Initial commit
This commit is contained in:
2
engines/tot/POTFILES
Normal file
2
engines/tot/POTFILES
Normal file
@@ -0,0 +1,2 @@
|
||||
engines/tot/metaengine.cpp
|
||||
engines/tot/saveload.cpp
|
||||
970
engines/tot/anims.cpp
Normal file
970
engines/tot/anims.cpp
Normal file
@@ -0,0 +1,970 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/substream.h"
|
||||
|
||||
#include "tot/anims.h"
|
||||
#include "tot/decoder/TotFlicDecoder.h"
|
||||
#include "tot/statics.h"
|
||||
#include "tot/tot.h"
|
||||
#include "tot/util.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
void drawText(uint x, uint y, const Common::String &str1, const Common::String &str2, const Common::String &str3, const Common::String &str4, const Common::String &str5, byte textColor, byte borderColor) {
|
||||
|
||||
littText(x, (y + 3), str1, borderColor);
|
||||
littText(x, (y + 13), str2, borderColor);
|
||||
littText(x, (y + 23), str3, borderColor);
|
||||
littText(x, (y + 33), str4, borderColor);
|
||||
littText(x, (y + 43), str5, borderColor);
|
||||
|
||||
littText(x, (y + 1), str1, borderColor);
|
||||
littText(x, (y + 11), str2, borderColor);
|
||||
littText(x, (y + 21), str3, borderColor);
|
||||
littText(x, (y + 31), str4, borderColor);
|
||||
littText(x, (y + 41), str5, borderColor);
|
||||
|
||||
g_engine->_screen->update();
|
||||
|
||||
littText(x + 1, (y + 2), str1, borderColor);
|
||||
littText(x + 1, (y + 12), str2, borderColor);
|
||||
littText(x + 1, (y + 22), str3, borderColor);
|
||||
littText(x + 1, (y + 32), str4, borderColor);
|
||||
littText(x + 1, (y + 42), str5, borderColor);
|
||||
|
||||
littText(x - 1, (y + 2), str1, borderColor);
|
||||
littText(x - 1, (y + 12), str2, borderColor);
|
||||
littText(x - 1, (y + 22), str3, borderColor);
|
||||
littText(x - 1, (y + 32), str4, borderColor);
|
||||
littText(x - 1, (y + 42), str5, borderColor);
|
||||
|
||||
littText(x, (y + 2), str1, textColor);
|
||||
littText(x, (y + 12), str2, textColor);
|
||||
littText(x, (y + 22), str3, textColor);
|
||||
littText(x, (y + 32), str4, textColor);
|
||||
littText(x, (y + 42), str5, textColor);
|
||||
g_engine->_screen->update();
|
||||
}
|
||||
|
||||
void removeText(uint xTextLine1, uint yTextLine1, uint xTextLine2, uint yTextLine2, byte fillColor) {
|
||||
|
||||
for (uint j = yTextLine1; j < yTextLine2 + 1; j++) {
|
||||
for (uint i = xTextLine1; i < xTextLine2 + 1; i++) {
|
||||
*((byte *)g_engine->_screen->getBasePtr(i, j)) = 0;
|
||||
}
|
||||
}
|
||||
g_engine->_screen->addDirtyRect(Common::Rect(xTextLine1, yTextLine1, xTextLine2, yTextLine2));
|
||||
}
|
||||
|
||||
void drawTvText(const Common::String &str1, const Common::String &str2, const Common::String &str3, const Common::String &str4, const Common::String &str5) {
|
||||
drawText(80, 0, str1, str2, str3, str4, str5, 253, 0);
|
||||
}
|
||||
|
||||
void clearTvText() {
|
||||
removeText(80, 0, 319, 54, 0);
|
||||
}
|
||||
|
||||
void drawCharacterText(const Common::String &str1, const Common::String &str2, const Common::String &str3, const Common::String &str4, const Common::String &str5) {
|
||||
drawText(2, 100, str1, str2, str3, str4, str5, 255, 0);
|
||||
}
|
||||
void clearCharacterText() {
|
||||
removeText(2, 100, 134, 199, 0);
|
||||
}
|
||||
|
||||
void handleFlcEvent(byte eventNumber, uint loopNumber, byte frameCount) {
|
||||
|
||||
const char *const *messages = getAnimMessagesByCurrentLanguage();
|
||||
bool isSpanish = isLanguageSpanish();
|
||||
bool isEnglish = !isSpanish;
|
||||
switch (eventNumber) {
|
||||
case 0:
|
||||
if (g_engine->_cpCounter > 103)
|
||||
showError(274);
|
||||
break;
|
||||
case 1:
|
||||
if (frameCount == 3)
|
||||
|
||||
switch (loopNumber) {
|
||||
case 2:
|
||||
drawTvText(messages[0], messages[1], messages[2], messages[3], messages[4]);
|
||||
break;
|
||||
case 13:
|
||||
clearTvText();
|
||||
break;
|
||||
case 14:
|
||||
drawTvText(messages[5], messages[6], messages[7], messages[8], messages[9]);
|
||||
break;
|
||||
case 25:
|
||||
clearTvText();
|
||||
break;
|
||||
case 26:
|
||||
drawTvText(messages[10], messages[11], messages[12], messages[13], messages[14]);
|
||||
break;
|
||||
case 35:
|
||||
clearTvText();
|
||||
break;
|
||||
case 36:
|
||||
drawCharacterText(messages[15], messages[16], messages[17], messages[18], messages[19]);
|
||||
break;
|
||||
// English only
|
||||
case 40:
|
||||
case 73:
|
||||
case 82:
|
||||
if (isEnglish) {
|
||||
clearCharacterText();
|
||||
}
|
||||
break;
|
||||
case 41:
|
||||
if (isEnglish) {
|
||||
drawCharacterText(messages[250], messages[251], messages[252], messages[253], messages[254]);
|
||||
}
|
||||
break;
|
||||
case 47:
|
||||
case 59:
|
||||
case 102:
|
||||
clearCharacterText();
|
||||
break;
|
||||
case 48:
|
||||
drawCharacterText(messages[20], messages[21], messages[22], messages[23], messages[24]);
|
||||
break;
|
||||
case 60:
|
||||
drawTvText(messages[25], messages[26], messages[27], messages[28], messages[29]);
|
||||
break;
|
||||
case 63:
|
||||
drawCharacterText(messages[30], messages[31], messages[32], messages[33], messages[34]);
|
||||
break;
|
||||
case 70:
|
||||
case 80:
|
||||
if (isEnglish) {
|
||||
clearTvText();
|
||||
}
|
||||
break;
|
||||
case 71:
|
||||
if (isEnglish) {
|
||||
drawTvText(messages[255], messages[256], messages[257], messages[258], messages[259]);
|
||||
}
|
||||
break;
|
||||
case 74:
|
||||
if (isEnglish) {
|
||||
debug(3, "Showing character text in English: %s\n", messages[35]);
|
||||
drawCharacterText(
|
||||
messages[35],
|
||||
messages[36],
|
||||
messages[37],
|
||||
messages[38],
|
||||
messages[39]);
|
||||
}
|
||||
break;
|
||||
case 75:
|
||||
case 89:
|
||||
if (isSpanish) {
|
||||
clearCharacterText();
|
||||
}
|
||||
break;
|
||||
case 76:
|
||||
if (isSpanish) {
|
||||
clearTvText();
|
||||
}
|
||||
break;
|
||||
case 77:
|
||||
if (isSpanish) {
|
||||
drawCharacterText(messages[35], messages[36], messages[37], messages[38], messages[39]);
|
||||
}
|
||||
break;
|
||||
case 83:
|
||||
if (isEnglish) {
|
||||
drawCharacterText(messages[260], messages[261], messages[262], messages[263], messages[264]);
|
||||
}
|
||||
break;
|
||||
case 90:
|
||||
if (isSpanish) {
|
||||
drawCharacterText(messages[40], messages[41], messages[42], messages[43], messages[44]);
|
||||
} else {
|
||||
clearCharacterText();
|
||||
}
|
||||
break;
|
||||
case 91:
|
||||
if (isEnglish) {
|
||||
drawCharacterText(messages[40], messages[41], messages[42], messages[43], messages[44]);
|
||||
}
|
||||
break;
|
||||
case 103:
|
||||
drawTvText(messages[45], messages[46], messages[47], messages[48], messages[49]);
|
||||
break;
|
||||
case 120:
|
||||
clearTvText();
|
||||
break;
|
||||
case 121:
|
||||
drawTvText(messages[50], messages[51], messages[52], messages[53], messages[54]);
|
||||
break;
|
||||
case 125:
|
||||
drawCharacterText(messages[55], messages[56], messages[57], messages[58], messages[59]);
|
||||
break;
|
||||
case 135: {
|
||||
clearTvText();
|
||||
clearCharacterText();
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (frameCount) {
|
||||
case 1: {
|
||||
clearCharacterText();
|
||||
clearTvText();
|
||||
} break;
|
||||
case 7:
|
||||
g_engine->_sound->playVoc("MANDO", 142001, 11469);
|
||||
break;
|
||||
case 20:
|
||||
drawCharacterText(messages[60], messages[61], messages[62], messages[63], messages[64]);
|
||||
break;
|
||||
case 58: {
|
||||
clearCharacterText();
|
||||
drawCharacterText(messages[65], messages[66], messages[67], messages[68], messages[69]);
|
||||
} break;
|
||||
case 74: {
|
||||
delay(1500);
|
||||
clearCharacterText();
|
||||
drawCharacterText(messages[70], messages[71], messages[72], messages[73], messages[74]);
|
||||
|
||||
delay(4000);
|
||||
clearCharacterText();
|
||||
drawTvText(messages[75], messages[76], messages[77], messages[78], messages[79]);
|
||||
|
||||
delay(7000);
|
||||
clearTvText();
|
||||
drawTvText(messages[80], messages[81], messages[82], messages[83], messages[84]);
|
||||
|
||||
if (isEnglish) {
|
||||
delay(5000);
|
||||
clearTvText();
|
||||
drawTvText(messages[265], messages[266], messages[267], messages[268], messages[269]);
|
||||
}
|
||||
|
||||
delay(7000);
|
||||
clearTvText();
|
||||
drawTvText(messages[85], messages[86], messages[87], messages[88], messages[89]);
|
||||
|
||||
delay(7000);
|
||||
clearTvText();
|
||||
drawCharacterText(messages[90], messages[91], messages[92], messages[93], messages[94]);
|
||||
|
||||
delay(6000);
|
||||
clearCharacterText();
|
||||
drawCharacterText(messages[95], messages[96], messages[97], messages[98], messages[99]);
|
||||
|
||||
if (isEnglish) {
|
||||
delay(6000);
|
||||
clearCharacterText();
|
||||
drawCharacterText(messages[95], messages[96], messages[97], messages[98], messages[99]);
|
||||
}
|
||||
|
||||
delay(6000);
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
switch (frameCount) {
|
||||
case 15:
|
||||
g_engine->_sound->playVoc("FRENAZO", 165322, 15073);
|
||||
break;
|
||||
case 26:
|
||||
delay(1000);
|
||||
break;
|
||||
case 43:
|
||||
g_engine->_sound->playVoc("PORTAZO", 434988, 932);
|
||||
break;
|
||||
case 60:
|
||||
g_engine->_graphics->getImg(0, 0, 319, 29, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (frameCount == 3)
|
||||
g_engine->_sound->playVoc("TIMBRAZO", 423775, 11213);
|
||||
break;
|
||||
case 5:
|
||||
if ((loopNumber == 1) && (frameCount == 2)) {
|
||||
|
||||
delay(2000);
|
||||
drawText(5, 1,
|
||||
messages[100],
|
||||
messages[101],
|
||||
messages[102],
|
||||
messages[103],
|
||||
messages[104],
|
||||
255, 249);
|
||||
delay(3500);
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
g_engine->_screen->update();
|
||||
drawText(5, 1,
|
||||
messages[105],
|
||||
messages[106],
|
||||
messages[107],
|
||||
messages[108],
|
||||
messages[109],
|
||||
255, 0);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if ((loopNumber == 1) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[110],
|
||||
messages[111],
|
||||
messages[112],
|
||||
messages[113],
|
||||
messages[114],
|
||||
255, 249);
|
||||
} else if ((loopNumber == 5) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[275],
|
||||
messages[276],
|
||||
messages[277],
|
||||
messages[278],
|
||||
messages[279],
|
||||
255, 249);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if ((loopNumber == 1) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[115],
|
||||
messages[116],
|
||||
messages[117],
|
||||
messages[118],
|
||||
messages[119],
|
||||
255, 0);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if ((loopNumber == 1) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[120],
|
||||
messages[121],
|
||||
messages[122],
|
||||
messages[123],
|
||||
messages[124],
|
||||
255, 249);
|
||||
} else if ((loopNumber == 5) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[280],
|
||||
messages[281],
|
||||
messages[282],
|
||||
messages[283],
|
||||
messages[284],
|
||||
255, 249);
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
if ((loopNumber == 1) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[125],
|
||||
messages[126],
|
||||
messages[127],
|
||||
messages[128],
|
||||
messages[129],
|
||||
255, 0);
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if ((loopNumber == 1) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[130],
|
||||
messages[131],
|
||||
messages[132],
|
||||
messages[133],
|
||||
messages[134],
|
||||
255, 249);
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
if ((loopNumber == 1) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[135],
|
||||
messages[136],
|
||||
messages[137],
|
||||
messages[138],
|
||||
messages[139],
|
||||
255, 0);
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
if ((loopNumber == 1) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[140],
|
||||
messages[141],
|
||||
messages[142],
|
||||
messages[143],
|
||||
messages[144],
|
||||
255, 249);
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
if ((loopNumber == 1) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[145],
|
||||
messages[146],
|
||||
messages[147],
|
||||
messages[148],
|
||||
messages[149],
|
||||
255, 0);
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
if ((loopNumber == 1) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[150],
|
||||
messages[151],
|
||||
messages[152],
|
||||
messages[153],
|
||||
messages[154],
|
||||
255, 249);
|
||||
} else if ((loopNumber == 5) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[285],
|
||||
messages[286],
|
||||
messages[287],
|
||||
messages[288],
|
||||
messages[289],
|
||||
255, 249);
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
if ((loopNumber == 1) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[155],
|
||||
messages[156],
|
||||
messages[157],
|
||||
messages[158],
|
||||
messages[159],
|
||||
255, 0);
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
if ((loopNumber == 1) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[160],
|
||||
messages[161],
|
||||
messages[162],
|
||||
messages[163],
|
||||
messages[164],
|
||||
255, 249);
|
||||
}
|
||||
break;
|
||||
case 17:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 17:
|
||||
delay(500);
|
||||
break;
|
||||
case 18:
|
||||
g_engine->_sound->playVoc("ACELERON", 30200, 42398);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 18:
|
||||
if ((loopNumber == 1) && (frameCount == 3)) {
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
drawText(5, 1,
|
||||
messages[165],
|
||||
messages[166],
|
||||
messages[167],
|
||||
messages[168],
|
||||
messages[169],
|
||||
255, 0);
|
||||
}
|
||||
break;
|
||||
case 19:
|
||||
if (frameCount == 1)
|
||||
drawText(5, 121,
|
||||
messages[170],
|
||||
messages[171],
|
||||
messages[172],
|
||||
messages[173],
|
||||
messages[174],
|
||||
253, 249);
|
||||
break;
|
||||
case 20:
|
||||
switch (loopNumber) {
|
||||
case 1:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->getImg(0, 0, 319, 69, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 3:
|
||||
drawText(15, 1,
|
||||
messages[175],
|
||||
messages[176],
|
||||
messages[177],
|
||||
messages[178],
|
||||
messages[179],
|
||||
255, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 3:
|
||||
drawText(15, 1,
|
||||
messages[180],
|
||||
messages[181],
|
||||
messages[182],
|
||||
messages[183],
|
||||
messages[184],
|
||||
230, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 3:
|
||||
drawText(15, 1,
|
||||
messages[185],
|
||||
messages[186],
|
||||
messages[187],
|
||||
messages[188],
|
||||
messages[189],
|
||||
230, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 3:
|
||||
drawText(15, 1,
|
||||
messages[190],
|
||||
messages[191],
|
||||
messages[192],
|
||||
messages[193],
|
||||
messages[194],
|
||||
230, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 3:
|
||||
drawText(15, 1,
|
||||
messages[195],
|
||||
messages[196],
|
||||
messages[197],
|
||||
messages[198],
|
||||
messages[199],
|
||||
230, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 3:
|
||||
drawText(15, 1,
|
||||
messages[200],
|
||||
messages[201],
|
||||
messages[202],
|
||||
messages[203],
|
||||
messages[204],
|
||||
230, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 18:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 3:
|
||||
drawText(15, 1,
|
||||
messages[205],
|
||||
messages[206],
|
||||
messages[207],
|
||||
messages[208],
|
||||
messages[209],
|
||||
230, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 21:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 3:
|
||||
drawText(15, 1,
|
||||
messages[210],
|
||||
messages[211],
|
||||
messages[212],
|
||||
messages[213],
|
||||
messages[214],
|
||||
230, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 3:
|
||||
drawText(15, 1,
|
||||
messages[215],
|
||||
messages[216],
|
||||
messages[217],
|
||||
messages[218],
|
||||
messages[219],
|
||||
230, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 3:
|
||||
drawText(15, 1,
|
||||
messages[220],
|
||||
messages[221],
|
||||
messages[222],
|
||||
messages[223],
|
||||
messages[224],
|
||||
230, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 30:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 3:
|
||||
drawText(15, 1,
|
||||
messages[225],
|
||||
messages[226],
|
||||
messages[227],
|
||||
messages[228],
|
||||
messages[229],
|
||||
230, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 33:
|
||||
if (frameCount == 17)
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 21:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_sound->playVoc("TRIDEN", 409405, 14370);
|
||||
break;
|
||||
case 5:
|
||||
g_engine->_sound->playVoc("PUFF", 191183, 18001);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 22:
|
||||
if (frameCount == 24)
|
||||
g_engine->_sound->playVoc("PUFF", 191183, 18001);
|
||||
break;
|
||||
case 23:
|
||||
switch (frameCount) {
|
||||
case 8:
|
||||
g_engine->_sound->playVoc("AFILAR", 0, 6433);
|
||||
break;
|
||||
case 18:
|
||||
g_engine->_sound->playVoc();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
if (frameCount == 8)
|
||||
g_engine->_sound->playVoc("DECAPITA", 354269, 1509);
|
||||
break;
|
||||
case 25:
|
||||
if (frameCount == 97)
|
||||
g_engine->_sound->playVoc("PUFF2", 209184, 14514);
|
||||
break;
|
||||
case 26:
|
||||
switch (loopNumber) {
|
||||
case 1:
|
||||
switch (frameCount) {
|
||||
case 2:
|
||||
g_engine->_graphics->getImg(0, 0, 319, 69, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 3:
|
||||
drawText(65, 1,
|
||||
messages[230],
|
||||
messages[231],
|
||||
messages[232],
|
||||
messages[233],
|
||||
messages[234],
|
||||
253, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 2:
|
||||
drawText(65, 1,
|
||||
messages[235],
|
||||
messages[236],
|
||||
messages[237],
|
||||
messages[238],
|
||||
messages[239],
|
||||
253, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 2:
|
||||
drawText(65, 1,
|
||||
messages[240],
|
||||
messages[241],
|
||||
messages[242],
|
||||
messages[243],
|
||||
messages[244],
|
||||
253, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
switch (frameCount) {
|
||||
case 1:
|
||||
g_engine->_graphics->putImg(0, 0, g_engine->_graphics->_textAreaBackground);
|
||||
break;
|
||||
case 2:
|
||||
drawText(65, 1,
|
||||
messages[245],
|
||||
messages[246],
|
||||
messages[247],
|
||||
messages[248],
|
||||
messages[249],
|
||||
253, 249);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
if (frameCount == 148)
|
||||
g_engine->_sound->playVoc("DECAPITA", 354269, 1509);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void exitProcedure(bool &exitLoop, bool isSkipAllowed) {
|
||||
exitLoop = false;
|
||||
g_engine->_events->pollEvent();
|
||||
if (isSkipAllowed && (g_engine->_events->_keyPressed || g_engine->_events->_leftMouseButton)) {
|
||||
exitLoop = true;
|
||||
}
|
||||
}
|
||||
|
||||
static FliHeader readHeader(Common::File *file) {
|
||||
FliHeader headerfile;
|
||||
|
||||
headerfile.size = file->readSint32LE();
|
||||
headerfile.magic = file->readSint16LE();
|
||||
headerfile.frames = file->readSint16LE();
|
||||
headerfile.width = file->readSint16LE();
|
||||
headerfile.height = file->readSint16LE();
|
||||
headerfile.depth = file->readSint16LE();
|
||||
headerfile.flags = file->readSint16LE();
|
||||
headerfile.speed = file->readSint32LE();
|
||||
headerfile.reserved1 = file->readSint16LE();
|
||||
headerfile.created = file->readSint32LE();
|
||||
file->read(headerfile.creator, 4);
|
||||
headerfile.updated = file->readSint32LE();
|
||||
file->read(headerfile.updator, 4);
|
||||
headerfile.aspectx = file->readSint16LE();
|
||||
headerfile.aspecty = file->readSint16LE();
|
||||
file->read(headerfile.reserved2, 19 * 2);
|
||||
headerfile.ofsframe1 = file->readSint32LE();
|
||||
headerfile.ofsframe2 = file->readSint32LE();
|
||||
file->read(headerfile.reserved3, 20 * 2);
|
||||
return headerfile;
|
||||
}
|
||||
|
||||
void blit(TotFlicDecoder *flic, const Graphics::Surface *src, Common::Rect bounds) {
|
||||
Graphics::Surface dest = g_engine->_screen->getSubArea(bounds);
|
||||
flic->copyDirtyRectsToBuffer((byte *)dest.getPixels(), dest.pitch);
|
||||
g_engine->_screen->addDirtyRect(bounds);
|
||||
g_engine->_screen->update();
|
||||
}
|
||||
|
||||
void drawFlc(
|
||||
uint x,
|
||||
uint y,
|
||||
int32 offset,
|
||||
uint loop,
|
||||
byte speed,
|
||||
byte eventNumber,
|
||||
bool fullPalette,
|
||||
bool isSkipAllowed,
|
||||
bool limitPaletteTo200,
|
||||
bool &exitAnim) {
|
||||
|
||||
uint loopNumber = 0;
|
||||
byte frameCount = 0;
|
||||
|
||||
Common::File animationsFile;
|
||||
Common::String fileName;
|
||||
if (loop == 60000)
|
||||
fileName = "OBJGIRO.DAT";
|
||||
else
|
||||
fileName = "FILMS.DAT";
|
||||
|
||||
if (!animationsFile.open(Common::Path(fileName))) {
|
||||
showError(272);
|
||||
}
|
||||
animationsFile.seek(offset, SEEK_SET);
|
||||
// Need to read header to get the total size of the FLIC file.
|
||||
FliHeader header = readHeader(&animationsFile);
|
||||
Common::SeekableSubReadStream *thisFlic = new Common::SeekableSubReadStream(
|
||||
&animationsFile,
|
||||
offset,
|
||||
offset + header.size);
|
||||
|
||||
TotFlicDecoder *flic = new TotFlicDecoder();
|
||||
|
||||
flic->loadStream(thisFlic);
|
||||
flic->start();
|
||||
bool skipFrame = false;
|
||||
do {
|
||||
exitProcedure(exitAnim, isSkipAllowed);
|
||||
loopNumber++;
|
||||
do {
|
||||
g_engine->_chrono->updateChrono();
|
||||
exitProcedure(exitAnim, isSkipAllowed);
|
||||
if (exitAnim) {
|
||||
goto Lexit_proc;
|
||||
}
|
||||
|
||||
if (g_engine->_chrono->_gameTick) {
|
||||
// Make sure we also update the palette animations! Esp. for part 2
|
||||
if (g_engine->_currentRoomData != nullptr && !g_engine->_shouldQuitGame) {
|
||||
g_engine->_graphics->advancePaletteAnim();
|
||||
}
|
||||
if(speed == 9) {
|
||||
skipFrame = !skipFrame;
|
||||
}
|
||||
if (!skipFrame) {
|
||||
handleFlcEvent(eventNumber, loopNumber, frameCount);
|
||||
const Graphics::Surface *frame = flic->decodeNextFrame();
|
||||
if (frame) {
|
||||
frameCount++;
|
||||
Common::Rect boundingBox = Common::Rect(x, y, x + flic->getWidth() + 1, y + flic->getHeight() + 1);
|
||||
blit(flic, frame, boundingBox);
|
||||
if (flic->hasDirtyPalette()) {
|
||||
|
||||
const byte *fliPalette = (const byte *)flic->getPalette();
|
||||
byte *palette = new byte[768];
|
||||
Common::copy(fliPalette, fliPalette + 768, palette);
|
||||
// game fixes background to 0
|
||||
palette[0] = 0;
|
||||
palette[1] = 0;
|
||||
palette[2] = 0;
|
||||
if (fullPalette) {
|
||||
byte *gamePalette = g_engine->_graphics->getPalette();
|
||||
g_engine->_graphics->fadePalettes(gamePalette, palette);
|
||||
free(gamePalette);
|
||||
g_engine->_graphics->copyPalette(palette, g_engine->_graphics->_pal);
|
||||
} else if (limitPaletteTo200) {
|
||||
g_engine->_graphics->setPalette(palette, 0, 200);
|
||||
for (int i = 0; i <= 200; i++) {
|
||||
if (g_engine->_gamePart == 2 && !g_engine->_shouldQuitGame && (i == 131 || i == 134 || i == 143 || i == 187)) {
|
||||
continue;
|
||||
}
|
||||
g_engine->_graphics->_pal[i * 3 + 0] = palette[i * 3 + 0];
|
||||
g_engine->_graphics->_pal[i * 3 + 1] = palette[i * 3 + 1];
|
||||
g_engine->_graphics->_pal[i * 3 + 2] = palette[i * 3 + 2];
|
||||
}
|
||||
|
||||
} else {
|
||||
g_engine->_graphics->setPalette(palette);
|
||||
g_engine->_graphics->copyPalette(palette, g_engine->_graphics->_pal);
|
||||
}
|
||||
delete[] palette;
|
||||
}
|
||||
g_engine->_chrono->_gameTick = false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_system->delayMillis(10);
|
||||
} while (!flic->endOfVideo() && !g_engine->shouldQuit());
|
||||
|
||||
if (flic->endOfVideo()) {
|
||||
if (flic->isRewindable()) {
|
||||
flic->rewind();
|
||||
}
|
||||
frameCount = 0;
|
||||
}
|
||||
} while (loopNumber <= loop && !g_engine->shouldQuit());
|
||||
flic->stop();
|
||||
Lexit_proc:
|
||||
animationsFile.close();
|
||||
delete flic;
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
58
engines/tot/anims.h
Normal file
58
engines/tot/anims.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef TOT_ANIMS_H
|
||||
#define TOT_ANIMS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
void drawFlc(uint x, uint y, int32 offset, uint loop,
|
||||
byte speed, byte eventNumber, bool fullPalette, bool isSkipAllowed,
|
||||
bool limitPaletteTo200, bool &exitAnim);
|
||||
|
||||
/**
|
||||
* Header of an Autodesk Animator FLIC file.
|
||||
*/
|
||||
struct FliHeader {
|
||||
int32 size; // file size
|
||||
uint magic, // format id
|
||||
frames, // number of animation frames
|
||||
width, // anim width
|
||||
height, // anim height
|
||||
depth, // 8 bits per pixel
|
||||
flags;
|
||||
int32 speed; // time delay between frames
|
||||
uint reserved1; // all set to zero
|
||||
int32 created; // creation date in DOS format
|
||||
byte creator[3]; // serial of creator program
|
||||
int32 updated; // update date in DOS format
|
||||
byte updator[3]; // serial of updating program
|
||||
uint aspectx, // aspect ratio
|
||||
aspecty; // aspect ratio
|
||||
uint reserved2[19]; // all zeroes
|
||||
int32 ofsframe1, // Offset to frame 1 (FLC only)
|
||||
ofsframe2; // Offset to frame 2 (FLC only)
|
||||
uint reserved3[20]; // All zeroes
|
||||
};
|
||||
|
||||
} // End of namespace Tot
|
||||
#endif
|
||||
70
engines/tot/chrono.cpp
Normal file
70
engines/tot/chrono.cpp
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
#include "tot/chrono.h"
|
||||
#include "tot/tot.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
ChronoManager::ChronoManager(/* args */) : _lastTick(0) {
|
||||
}
|
||||
|
||||
ChronoManager::~ChronoManager() {
|
||||
}
|
||||
|
||||
void ChronoManager::updateChrono() {
|
||||
uint32 currentTime = g_system->getMillis();
|
||||
|
||||
if ((currentTime - _lastTick) >= static_cast<uint32>(kTickMs / _speedMultiplier)) {
|
||||
_gameTick = true;
|
||||
_tickCount++;
|
||||
if (_tickCount == kHalfTickMultiplier) {
|
||||
_tickCount = 0;
|
||||
_gameTickHalfSpeed = true;
|
||||
} else {
|
||||
_gameTickHalfSpeed = false;
|
||||
}
|
||||
_lastTick = currentTime;
|
||||
} else {
|
||||
_gameTick = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ChronoManager::changeSpeed() {
|
||||
if (_speedMultiplier == 1)
|
||||
_speedMultiplier = 4;
|
||||
else
|
||||
_speedMultiplier = 1;
|
||||
}
|
||||
|
||||
void ChronoManager::delay(uint32 ms) {
|
||||
uint32 delayStart = g_system->getMillis();
|
||||
|
||||
ms = ms / _speedMultiplier;
|
||||
while ((g_system->getMillis() - delayStart) < ms && !g_engine->shouldQuit()) {
|
||||
g_engine->_events->pollEvent();
|
||||
g_engine->_screen->update();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
51
engines/tot/chrono.h
Normal file
51
engines/tot/chrono.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef TOT_CHRONO_H
|
||||
#define TOT_CHRONO_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
// const int kTickMs = 20;
|
||||
const int kTickMs = 50;
|
||||
const int kHalfTickMultiplier = 2;
|
||||
const int kFrameEffectMs = 10;
|
||||
|
||||
class ChronoManager {
|
||||
private:
|
||||
uint32 _lastTick = 0;
|
||||
byte _tickCount = 0;
|
||||
byte _speedMultiplier = 1;
|
||||
|
||||
public:
|
||||
ChronoManager();
|
||||
~ChronoManager();
|
||||
void updateChrono();
|
||||
void delay(uint32 ms);
|
||||
void changeSpeed();
|
||||
|
||||
bool _gameTick = false;
|
||||
bool _gameTickHalfSpeed = false;
|
||||
};
|
||||
|
||||
} // End of namespace Tot
|
||||
#endif
|
||||
3
engines/tot/configure.engine
Normal file
3
engines/tot/configure.engine
Normal file
@@ -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 tot "Tot" yes "" "" ""
|
||||
96
engines/tot/console.cpp
Normal file
96
engines/tot/console.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tot/console.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
TotConsole::TotConsole(TotEngine *engine) : _engine(engine) {
|
||||
registerCmd("jumpToPart2", WRAP_METHOD(TotConsole, cmdJumpToPart2));
|
||||
registerCmd("loadRoom", WRAP_METHOD(TotConsole, cmdLoadRoom));
|
||||
registerCmd("showMouseGrid", WRAP_METHOD(TotConsole, cmdShowMouseGrid));
|
||||
registerCmd("showGameGrid", WRAP_METHOD(TotConsole, cmdShowGameGrid));
|
||||
registerCmd("showScreenGrid", WRAP_METHOD(TotConsole, cmdShowScreenGrid));
|
||||
registerCmd("showObjectAreas", WRAP_METHOD(TotConsole, cmdShowObjectAreas));
|
||||
registerCmd("clearLayers", WRAP_METHOD(TotConsole, cmdClearLayers));
|
||||
}
|
||||
|
||||
TotConsole::~TotConsole() {
|
||||
}
|
||||
|
||||
bool TotConsole::cmdShowMouseGrid(int argc, const char **argv) {
|
||||
_engine->_showMouseGrid = true;
|
||||
debugPrintf("Enabled mouse hotspot grid");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TotConsole::cmdShowGameGrid(int argc, const char **argv) {
|
||||
_engine->_showGameGrid = true;
|
||||
debugPrintf("Enabled screen base grid");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TotConsole::cmdShowScreenGrid(int argc, const char **argv) {
|
||||
_engine->_showScreenGrid = true;
|
||||
debugPrintf("Enabled screen walk area grid");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TotConsole::cmdShowObjectAreas(int argc, const char **argv) {
|
||||
_engine->_drawObjectAreas = true;
|
||||
debugPrintf("Enabled room object area display");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TotConsole::cmdClearLayers(int argc, const char **argv) {
|
||||
_engine->_drawObjectAreas = false;
|
||||
_engine->_showScreenGrid = false;
|
||||
_engine->_showGameGrid = false;
|
||||
_engine->_showMouseGrid = false;
|
||||
g_engine->_graphics->drawScreen(g_engine->_sceneBackground);
|
||||
debugPrintf("Cleared all debug layers");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TotConsole::cmdLoadRoom(int argc, const char **argv) {
|
||||
|
||||
int roomID = atoi(argv[1]);
|
||||
|
||||
if (roomID < 0 || roomID > 24) {
|
||||
debugPrintf("Invalid RoomID %d!\n", roomID);
|
||||
return true;
|
||||
}
|
||||
g_engine->clearAnimation();
|
||||
g_engine->clearScreenLayers();
|
||||
g_engine->loadScreenData(roomID);
|
||||
g_engine->_graphics->drawScreen(g_engine->_sceneBackground);
|
||||
debugPrintf("Loaded screen %d", roomID);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TotConsole::cmdJumpToPart2(int argc, const char **argv) {
|
||||
g_engine->_list1Complete = true;
|
||||
g_engine->_list2Complete = true;
|
||||
debugPrintf("Moving on to part 2 of the game");
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
50
engines/tot/console.h
Normal file
50
engines/tot/console.h
Normal file
@@ -0,0 +1,50 @@
|
||||
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOT_CONSOLE_H
|
||||
#define TOT_CONSOLE_H
|
||||
|
||||
#include "gui/debugger.h"
|
||||
|
||||
#include "tot/tot.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
class TotConsole : public GUI::Debugger {
|
||||
private:
|
||||
TotEngine *_engine;
|
||||
bool cmdJumpToPart2(int argc, const char **argv);
|
||||
bool cmdLoadRoom(int argc, const char **argv);
|
||||
bool cmdShowMouseGrid(int argc, const char **argv);
|
||||
bool cmdShowScreenGrid(int argc, const char **argv);
|
||||
bool cmdShowGameGrid(int argc, const char **argv);
|
||||
bool cmdShowObjectAreas(int argc, const char **argv);
|
||||
bool cmdClearLayers(int argc, const char **argv);
|
||||
|
||||
public:
|
||||
TotConsole(TotEngine *engine);
|
||||
~TotConsole() override;
|
||||
};
|
||||
|
||||
} // End of namespace Tot
|
||||
|
||||
#endif // TOT_CONSOLE_H
|
||||
3
engines/tot/credits.pl
Normal file
3
engines/tot/credits.pl
Normal file
@@ -0,0 +1,3 @@
|
||||
begin_section("Tot");
|
||||
add_person("Gabriel Sanmartín", "kelmer", "");
|
||||
end_section();
|
||||
957
engines/tot/cutscenes.cpp
Normal file
957
engines/tot/cutscenes.cpp
Normal file
@@ -0,0 +1,957 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "tot/anims.h"
|
||||
#include "tot/tot.h"
|
||||
#include "tot/util.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
byte *drawCreditsScreen(uint &sizeAuxBG, byte *&auxBG) {
|
||||
Palette intermediatePalette, darkPalette;
|
||||
|
||||
Common::File ppFile;
|
||||
|
||||
if (!ppFile.open("DIPLOMA.PAN")) {
|
||||
showError(315);
|
||||
}
|
||||
byte *backgroundPointer = (byte *)malloc(320 * 200);
|
||||
ppFile.read(intermediatePalette, 256 * 3);
|
||||
ppFile.read(backgroundPointer, 320 * 200);
|
||||
ppFile.close();
|
||||
|
||||
g_engine->_graphics->drawFullScreen(backgroundPointer);
|
||||
|
||||
sizeAuxBG = imagesize(0, 0, 319, 59);
|
||||
|
||||
// Screen is now backgroundPointer so auxBG contains a 320x60 crop of backgroundPointer
|
||||
auxBG = (byte *)malloc(sizeAuxBG);
|
||||
g_engine->_graphics->getImg(0, 0, 319, 59, auxBG);
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
darkPalette[i * 3 + 0] = 0;
|
||||
darkPalette[i * 3 + 1] = 0;
|
||||
darkPalette[i * 3 + 2] = 0;
|
||||
// Adjust for 6-bit DAC color
|
||||
intermediatePalette[i * 3 + 0] <<= 2;
|
||||
intermediatePalette[i * 3 + 1] <<= 2;
|
||||
intermediatePalette[i * 3 + 2] <<= 2;
|
||||
}
|
||||
|
||||
g_engine->_graphics->fadePalettes(darkPalette, intermediatePalette);
|
||||
g_engine->_graphics->copyPalette(intermediatePalette, g_engine->_graphics->_pal);
|
||||
if (g_engine->_cpCounter2 > 9)
|
||||
showError(274);
|
||||
return backgroundPointer;
|
||||
}
|
||||
|
||||
void putCreditsImg(uint x, uint y, const byte *img1, const byte *img2, bool direct) {
|
||||
|
||||
uint16 wImg1, hImg1;
|
||||
uint horizontalAux;
|
||||
|
||||
wImg1 = READ_LE_UINT16(img1);
|
||||
hImg1 = READ_LE_UINT16(img1 + 2);
|
||||
|
||||
byte * step = (byte *)malloc((wImg1 + 1) * (hImg1 + 1) + 4);
|
||||
|
||||
horizontalAux = wImg1 + 1;
|
||||
uint yPos = hImg1 + y;
|
||||
|
||||
// makes sure that if the image is at the bottom of the screen we chop the bottom part
|
||||
for (int i = yPos; i >= 200; i--)
|
||||
hImg1 -= 1;
|
||||
|
||||
hImg1++;
|
||||
|
||||
// Copies the crop in the background corresponding to the current credit window in img1
|
||||
for (int i = 0; i < hImg1; i++) {
|
||||
const byte *src = img2 + (320 * (y + i)) + x;
|
||||
byte *dst = step + 4 + (horizontalAux * i);
|
||||
Common::copy(src, src + horizontalAux, dst);
|
||||
}
|
||||
|
||||
for (int kk = 0; kk < hImg1; kk++) {
|
||||
uint inc2 = (kk * wImg1) + 4;
|
||||
yPos = kk + y;
|
||||
for (int jj = 0; jj <= wImg1; jj++) {
|
||||
uint inc = inc2 + jj;
|
||||
if ((direct && img1[inc] > 0) || (img1[inc] > 16 && yPos >= 66 && yPos <= 192)) {
|
||||
step[inc] = img1[inc];
|
||||
} else if (img1[inc] > 16) {
|
||||
switch (yPos) {
|
||||
case 59:
|
||||
case 199:
|
||||
step[inc] = img1[inc] + 210;
|
||||
break;
|
||||
case 60:
|
||||
case 198:
|
||||
step[inc] = img1[inc] + 180;
|
||||
break;
|
||||
case 61:
|
||||
case 197:
|
||||
step[inc] = img1[inc] + 150;
|
||||
break;
|
||||
case 62:
|
||||
case 196:
|
||||
step[inc] = img1[inc] + 120;
|
||||
break;
|
||||
case 63:
|
||||
case 195:
|
||||
step[inc] = img1[inc] + 90;
|
||||
break;
|
||||
case 64:
|
||||
case 194:
|
||||
step[inc] = img1[inc] + 60;
|
||||
break;
|
||||
case 65:
|
||||
case 193:
|
||||
step[inc] = img1[inc] + 30;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Wait until render tick
|
||||
do {
|
||||
g_engine->_chrono->updateChrono();
|
||||
g_system->delayMillis(10);
|
||||
} while (!g_engine->_chrono->_gameTick && !g_engine->shouldQuit());
|
||||
g_engine->_chrono->_gameTick = false;
|
||||
|
||||
// Copies the credit window directly to the screen
|
||||
for (int i = 0; i < hImg1; i++) {
|
||||
const byte *src = step + 4 + (horizontalAux * i);
|
||||
byte *dst = ((byte *)g_engine->_screen->getPixels()) + (320 * (y + i)) + x;
|
||||
Common::copy(src, src + horizontalAux, dst);
|
||||
}
|
||||
g_engine->_screen->addDirtyRect(Common::Rect(x, y, x + wImg1 + 1, y + hImg1 + 1));
|
||||
free(step);
|
||||
}
|
||||
|
||||
void scrollCredit(
|
||||
int32 position,
|
||||
uint size,
|
||||
Palette &pal2,
|
||||
byte *&background,
|
||||
bool &exit,
|
||||
int minHeight,
|
||||
bool withFade,
|
||||
bool refresh) {
|
||||
Common::File creditFile;
|
||||
if (!creditFile.open("CREDITOS.DAT")) {
|
||||
showError(270);
|
||||
}
|
||||
creditFile.seek(position);
|
||||
creditFile.read(g_engine->_sceneBackground, size);
|
||||
creditFile.read(pal2, 768);
|
||||
creditFile.close();
|
||||
|
||||
for (int i = 16; i < 256; i++) {
|
||||
// Adjust for 6-bit DAC
|
||||
pal2[i * 3 + 0] <<= 2;
|
||||
pal2[i * 3 + 1] <<= 2;
|
||||
pal2[i * 3 + 2] <<= 2;
|
||||
|
||||
g_engine->_graphics->_pal[i * 3 + 0] = pal2[i * 3 + 0];
|
||||
g_engine->_graphics->_pal[i * 3 + 1] = pal2[i * 3 + 1];
|
||||
g_engine->_graphics->_pal[i * 3 + 2] = pal2[i * 3 + 2];
|
||||
}
|
||||
|
||||
g_engine->_graphics->setPalette(&g_engine->_graphics->_pal[16 * 3 + 0], 16, 240);
|
||||
// Loops an image from the bottom of the screen to the top
|
||||
for (int i = 199; i >= minHeight; i--) {
|
||||
g_engine->_events->pollEvent();
|
||||
|
||||
putCreditsImg(85, i, g_engine->_sceneBackground, background, !withFade);
|
||||
if (g_engine->_events->_keyPressed) {
|
||||
exit = true;
|
||||
break;
|
||||
}
|
||||
g_engine->_screen->update();
|
||||
g_system->delayMillis(10);
|
||||
if (g_engine->shouldQuit())
|
||||
break;
|
||||
}
|
||||
if (refresh) {
|
||||
g_engine->_graphics->copyFromScreen(background);
|
||||
}
|
||||
}
|
||||
|
||||
void scrollSingleCredit(
|
||||
int32 pos,
|
||||
uint size,
|
||||
Palette &pal2,
|
||||
byte *&background,
|
||||
bool &exit) {
|
||||
scrollCredit(
|
||||
pos,
|
||||
size,
|
||||
pal2,
|
||||
background,
|
||||
exit,
|
||||
8,
|
||||
true,
|
||||
false);
|
||||
}
|
||||
|
||||
void removeTitle(byte *&background2) {
|
||||
uint i2, j2;
|
||||
for (int i1 = 1; i1 <= 15000; i1++) {
|
||||
g_engine->_events->pollEvent();
|
||||
i2 = g_engine->getRandomNumber(318);
|
||||
j2 = getRandom(58);
|
||||
byte *src = background2 + 4 + (j2 * 320) + i2;
|
||||
byte *dest = ((byte *)g_engine->_screen->getPixels()) + (j2 * 320) + i2;
|
||||
Common::copy(src, src + 2, dest);
|
||||
|
||||
byte *src2 = background2 + 4 + ((j2 + 1) * 320) + i2;
|
||||
byte *dest2 = ((byte *)g_engine->_screen->getPixels()) + ((j2 + 1) * 320) + i2;
|
||||
|
||||
Common::copy(src2, src2 + 2, dest2);
|
||||
|
||||
i2 = getRandom(320);
|
||||
j2 = getRandom(60);
|
||||
|
||||
byte *src3 = background2 + 4 + (j2 * 320) + i2;
|
||||
byte *dest3 = ((byte *)g_engine->_screen->getPixels()) + (j2 * 320) + i2;
|
||||
Common::copy(src3, src3 + 1, dest3);
|
||||
if (i1 % 200 == 0) {
|
||||
g_engine->_screen->addDirtyRect(Common::Rect(0, 0, 320, 60));
|
||||
g_engine->_screen->update();
|
||||
}
|
||||
if (g_engine->shouldQuit()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_engine->_screen->addDirtyRect(Common::Rect(0, 0, 320, 60));
|
||||
g_engine->_screen->update();
|
||||
}
|
||||
|
||||
inline bool keyPressed() {
|
||||
|
||||
g_engine->_events->pollEvent();
|
||||
return g_engine->_events->_keyPressed;
|
||||
}
|
||||
|
||||
void TotEngine::credits() {
|
||||
_saveAllowed = true;
|
||||
Palette pal2;
|
||||
byte *background2;
|
||||
uint sizeBg2;
|
||||
bool shouldExit = false;
|
||||
|
||||
_mouse->hide();
|
||||
_graphics->totalFadeOut(0);
|
||||
_sound->fadeOutMusic();
|
||||
_screen->clear();
|
||||
_sound->playMidi("CREDITOS", true);
|
||||
_sound->fadeInMusic();
|
||||
byte *background = drawCreditsScreen(sizeBg2, background2);
|
||||
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
scrollCredit(0, 8004, pal2, background, shouldExit, 10, false, true);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
scrollSingleCredit(8772, 8004, pal2, background, shouldExit);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
scrollSingleCredit(17544, 8004, pal2, background, shouldExit);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
scrollSingleCredit(26316, 7504, pal2, background, shouldExit);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
scrollSingleCredit(34588, 7504, pal2, background, shouldExit);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
scrollSingleCredit(42860, 8004, pal2, background, shouldExit);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
scrollSingleCredit(51632, 7504, pal2, background, shouldExit);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
removeTitle(background2);
|
||||
if (keyPressed())
|
||||
goto Lexit;
|
||||
_graphics->putImg(0, 0, background2);
|
||||
if (keyPressed())
|
||||
goto Lexit;
|
||||
_graphics->copyFromScreen(background);
|
||||
if (keyPressed())
|
||||
goto Lexit;
|
||||
scrollCredit(59904, 8004, pal2, background, shouldExit, 10, false, true);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
scrollSingleCredit(68676, 8004, pal2, background, shouldExit);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
scrollSingleCredit(77448, 8004, pal2, background, shouldExit);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
scrollSingleCredit(86220, 8004, pal2, background, shouldExit);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
scrollSingleCredit(94992, 8004, pal2, background, shouldExit);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
scrollSingleCredit(103764, 8004, pal2, background, shouldExit);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
scrollSingleCredit(112536, 8004, pal2, background, shouldExit);
|
||||
if (keyPressed() || shouldExit)
|
||||
goto Lexit;
|
||||
removeTitle(background2);
|
||||
if (keyPressed())
|
||||
goto Lexit;
|
||||
_graphics->putImg(0, 0, background2);
|
||||
if (keyPressed())
|
||||
goto Lexit;
|
||||
_graphics->copyFromScreen(background);
|
||||
if (keyPressed())
|
||||
goto Lexit;
|
||||
scrollCredit(121308, 8004, pal2, background, shouldExit, 80, false, true);
|
||||
Lexit:
|
||||
delay(1000);
|
||||
_graphics->totalFadeOut(0);
|
||||
_sound->fadeOutMusic();
|
||||
_screen->clear();
|
||||
_sound->playMidi("INTRODUC", true);
|
||||
_sound->fadeInMusic();
|
||||
_mouse->show();
|
||||
free(background);
|
||||
free(background2);
|
||||
}
|
||||
|
||||
void TotEngine::introduction() {
|
||||
_saveAllowed = false;
|
||||
_mouse->hide();
|
||||
bool exitPressed;
|
||||
uint loopCount;
|
||||
bool isSpanish = isLanguageSpanish();
|
||||
const char *const *messages = getFullScreenMessagesByCurrentLanguage();
|
||||
const int32 *offsets = getOffsetsByCurrentLanguage();
|
||||
exitPressed = false;
|
||||
_graphics->totalFadeOut(0);
|
||||
|
||||
if (_cpCounter > 6)
|
||||
showError(270);
|
||||
_screen->clear();
|
||||
drawFlc(136, 53, offsets[2], 136, 9, 1, true, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(135, 54, offsets[3], 0, 9, 2, true, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
_graphics->totalFadeOut(0);
|
||||
_screen->clear();
|
||||
if (isSpanish) {
|
||||
littText(25, 20, messages[0], 253);
|
||||
littText(25, 35, messages[1], 253);
|
||||
littText(25, 50, messages[2], 253);
|
||||
littText(25, 65, messages[3], 253);
|
||||
littText(25, 80, messages[4], 253);
|
||||
littText(25, 95, messages[5], 253);
|
||||
littText(25, 120, messages[6], 253);
|
||||
littText(25, 140, messages[7], 253);
|
||||
littText(25, 155, messages[8], 253);
|
||||
} else {
|
||||
littText(25, 35, messages[0], 253);
|
||||
littText(25, 55, messages[1], 253);
|
||||
littText(25, 75, messages[2], 253);
|
||||
littText(25, 95, messages[3], 253);
|
||||
littText(25, 115, messages[4], 253);
|
||||
littText(25, 135, messages[5], 253);
|
||||
}
|
||||
if (shouldQuit()) {
|
||||
return;
|
||||
}
|
||||
_graphics->totalFadeIn(0, "DEFAULT");
|
||||
_screen->markAllDirty();
|
||||
_screen->update();
|
||||
loopCount = 0;
|
||||
|
||||
do {
|
||||
_chrono->updateChrono();
|
||||
g_engine->_events->pollEvent();
|
||||
if (g_engine->_events->_keyPressed || g_engine->_events->_leftMouseButton) {
|
||||
goto LexitIntro;
|
||||
}
|
||||
|
||||
if (g_engine->_chrono->_gameTick) {
|
||||
loopCount += 1;
|
||||
}
|
||||
g_system->delayMillis(10);
|
||||
} while (loopCount < 180 && !shouldQuit());
|
||||
|
||||
_graphics->totalFadeOut(0);
|
||||
_screen->clear();
|
||||
drawFlc(0, 0, offsets[4], 0, 9, 3, true, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(110, 30, offsets[5], 2, 9, 4, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(110, 30, offsets[6], 3, 9, 5, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(110, 30, offsets[7], 0, 9, 0, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(110, 30, offsets[8], isSpanish ? 4 : 8, 9, 6, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(110, 30, offsets[9], 3, 9, 7, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(110, 30, offsets[8], isSpanish ? 3 : 8, 9, 8, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(110, 30, offsets[9], 2, 9, 9, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(0, 0, offsets[10], 0, 9, 0, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(235, 100, offsets[11], 3, 9, 10, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(150, 40, offsets[12], 0, 9, 11, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(235, 100, offsets[11], 3, 9, 12, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(150, 40, offsets[12], isSpanish ? 0 : 2, 9, 13, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(235, 100, offsets[11], isSpanish ? 3 : 8, 9, 14, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(150, 40, offsets[12], 0, 9, 15, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(173, 98, offsets[13], 0, 9, 0, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(224, 100, offsets[14], 2, 9, 16, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(0, 0, offsets[15], 0, 18, 17, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
drawFlc(150, 40, offsets[16], 0, 9, 18, false, true, false, exitPressed);
|
||||
if (exitPressed)
|
||||
goto LexitIntro;
|
||||
delay(1000);
|
||||
LexitIntro:
|
||||
_graphics->totalFadeOut(0);
|
||||
_screen->clear();
|
||||
_mouse->show();
|
||||
}
|
||||
|
||||
void TotEngine::firstIntroduction() {
|
||||
if (!_firstTimeDone && !_isIntroSeen) {
|
||||
introduction();
|
||||
_firstTimeDone = true;
|
||||
ConfMan.setBool("introSeen", true);
|
||||
ConfMan.flushToDisk();
|
||||
}
|
||||
}
|
||||
|
||||
void TotEngine::initialLogo() {
|
||||
bool foobar = false;
|
||||
const int32 *offsets = getOffsetsByCurrentLanguage();
|
||||
drawFlc(0, 0, offsets[0], 0, 18, 25, false, false, false, foobar);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void TotEngine::sacrificeScene() {
|
||||
_saveAllowed = false;
|
||||
Palette palaux;
|
||||
|
||||
Common::File file;
|
||||
bool isSpanish = isLanguageSpanish();
|
||||
const char *const *messages = getFullScreenMessagesByCurrentLanguage();
|
||||
|
||||
const int32 *offsets = getOffsetsByCurrentLanguage();
|
||||
|
||||
_sound->stopVoc();
|
||||
bool exitPressed = _currentRoomData->paletteAnimationFlag;
|
||||
_currentRoomData->paletteAnimationFlag = false;
|
||||
|
||||
bar(0, 139, 319, 149, 0);
|
||||
bar(10, 10, 310, 120, 0);
|
||||
if (isSpanish) {
|
||||
littText(10, 10, messages[9], 200);
|
||||
littText(10, 30, messages[10], 200);
|
||||
littText(10, 50, messages[11], 200);
|
||||
littText(10, 70, messages[12], 200);
|
||||
littText(10, 90, messages[13], 200);
|
||||
} else {
|
||||
littText(10, 20, messages[9], 200);
|
||||
littText(10, 40, messages[10], 200);
|
||||
littText(10, 60, messages[11], 200);
|
||||
littText(10, 80, messages[12], 200);
|
||||
littText(10, 100, messages[13], 200);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= 28; i++)
|
||||
setRGBPalette(200, i * 2, i * 2, i * 2);
|
||||
|
||||
delay(10000);
|
||||
if (shouldQuit())
|
||||
return;
|
||||
|
||||
for (int i = 28; i >= 0; i--)
|
||||
setRGBPalette(200, i * 2, i * 2, i * 2);
|
||||
|
||||
bar(10, 10, 310, 120, 0);
|
||||
if (isSpanish) {
|
||||
littText(10, 10, messages[14], 200);
|
||||
littText(10, 30, messages[15], 200);
|
||||
littText(10, 50, messages[16], 200);
|
||||
littText(10, 70, messages[17], 200);
|
||||
littText(10, 90, messages[18], 200);
|
||||
} else {
|
||||
littText(10, 20, messages[14], 200);
|
||||
littText(10, 40, messages[15], 200);
|
||||
littText(10, 60, messages[16], 200);
|
||||
littText(10, 80, messages[17], 200);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= 28; i++)
|
||||
setRGBPalette(200, i * 2, i * 2, i * 2);
|
||||
delay(10000);
|
||||
if (shouldQuit())
|
||||
return;
|
||||
|
||||
for (int i = 28; i >= 0; i--)
|
||||
setRGBPalette(200, i * 2, i * 2, i * 2);
|
||||
|
||||
bar(10, 10, 310, 120, 0);
|
||||
if (isSpanish) {
|
||||
littText(10, 10, messages[19], 200);
|
||||
littText(10, 50, messages[20], 200);
|
||||
littText(10, 70, messages[21], 200);
|
||||
littText(10, 90, messages[22], 200);
|
||||
} else {
|
||||
littText(10, 30, messages[19], 200);
|
||||
littText(10, 60, messages[20], 200);
|
||||
littText(10, 80, messages[21], 200);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= 28; i++)
|
||||
setRGBPalette(200, i * 2, i * 2, i * 2);
|
||||
delay(10000);
|
||||
if (shouldQuit())
|
||||
return;
|
||||
|
||||
for (int i = 28; i >= 0; i--)
|
||||
setRGBPalette(200, i * 2, i * 2, i * 2);
|
||||
bar(10, 10, 310, 120, 0);
|
||||
|
||||
if (!file.open("SALONREC.PAN")) {
|
||||
showError(318);
|
||||
}
|
||||
file.read(palaux, 768);
|
||||
file.read(_sceneBackground, 44800);
|
||||
file.close();
|
||||
|
||||
g_engine->_graphics->_pal[0] = 0;
|
||||
g_engine->_graphics->_pal[1] = 0;
|
||||
g_engine->_graphics->_pal[2] = 0;
|
||||
for (int i = 1; i <= 234; i++) {
|
||||
g_engine->_graphics->_pal[i * 3 + 1] = palaux[i * 3 + 1] << 2;
|
||||
g_engine->_graphics->_pal[i * 3 + 2] = palaux[i * 3 + 2] << 2;
|
||||
g_engine->_graphics->_pal[i * 3 + 3] = palaux[i * 3 + 3] << 2;
|
||||
}
|
||||
|
||||
// We dont have the width and height here in the byte buffer
|
||||
_graphics->drawScreen(_sceneBackground, false);
|
||||
_graphics->partialFadeIn(234);
|
||||
_sound->stopVoc();
|
||||
|
||||
if (shouldQuit())
|
||||
return;
|
||||
|
||||
drawFlc(0, 0, offsets[17], 0, 9, 19, false, false, true, exitPressed);
|
||||
_graphics->totalFadeOut(128);
|
||||
_sound->stopVoc();
|
||||
delay(1000);
|
||||
if (shouldQuit())
|
||||
return;
|
||||
|
||||
_sound->fadeOutMusic();
|
||||
_sound->playMidi("SACRIFIC", true);
|
||||
_sound->fadeInMusic();
|
||||
_graphics->clear();
|
||||
|
||||
littText(10, 31, messages[23], 254);
|
||||
littText(10, 29, messages[23], 254);
|
||||
littText(11, 30, messages[23], 254);
|
||||
littText(9, 30, messages[23], 254);
|
||||
|
||||
littText(10, 51, messages[24], 254);
|
||||
littText(10, 49, messages[24], 254);
|
||||
littText(11, 50, messages[24], 254);
|
||||
littText(9, 50, messages[24], 254);
|
||||
|
||||
littText(10, 71, messages[25], 254);
|
||||
littText(10, 69, messages[25], 254);
|
||||
littText(11, 70, messages[25], 254);
|
||||
littText(9, 70, messages[25], 254);
|
||||
|
||||
littText(10, 30, messages[23], 255);
|
||||
littText(10, 50, messages[24], 255);
|
||||
littText(10, 70, messages[25], 255);
|
||||
|
||||
for (int i = 0; i <= 31; i++) {
|
||||
setRGBPalette(255, 32 + i, i * 2, i * 2);
|
||||
setRGBPalette(254, 32 - i, 0, 0);
|
||||
}
|
||||
|
||||
delay(10000);
|
||||
if (shouldQuit())
|
||||
return;
|
||||
|
||||
for (int i = 31; i >= 0; i--) {
|
||||
setRGBPalette(255, 63 - (32 - i), i * 2, i * 2);
|
||||
setRGBPalette(254, 32 - i, 0, 0);
|
||||
}
|
||||
delay(2000);
|
||||
|
||||
if (!file.open("SACRIFIC.PAN")) {
|
||||
showError(318);
|
||||
}
|
||||
file.read(palaux, 768);
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
palaux[i * 3 + 0] <<= 2;
|
||||
palaux[i * 3 + 1] <<= 2;
|
||||
palaux[i * 3 + 2] <<= 2;
|
||||
}
|
||||
|
||||
file.read(_sceneBackground, 64000);
|
||||
file.close();
|
||||
_graphics->drawFullScreen(_sceneBackground);
|
||||
|
||||
palaux[0] = 0;
|
||||
palaux[1] = 0;
|
||||
palaux[2] = 0;
|
||||
|
||||
_graphics->redFadeIn(palaux);
|
||||
|
||||
drawFlc(112, 57, offsets[18], 33, 9, 20, true, false, true, exitPressed);
|
||||
_sound->autoPlayVoc("REZOS", 0, 0);
|
||||
if (shouldQuit())
|
||||
return;
|
||||
|
||||
drawFlc(42, 30, offsets[19], 0, 9, 27, false, false, false, exitPressed);
|
||||
|
||||
if (shouldQuit())
|
||||
return;
|
||||
|
||||
_graphics->totalFadeOut(128);
|
||||
_sound->stopVoc();
|
||||
_graphics->clear();
|
||||
|
||||
littText(10, 21, messages[26], 254);
|
||||
littText(10, 19, messages[26], 254);
|
||||
littText(11, 20, messages[26], 254);
|
||||
littText(9, 20, messages[26], 254);
|
||||
|
||||
littText(10, 41, messages[27], 254);
|
||||
littText(10, 39, messages[27], 254);
|
||||
littText(11, 40, messages[27], 254);
|
||||
littText(9, 40, messages[27], 254);
|
||||
|
||||
littText(10, 61, messages[28], 254);
|
||||
littText(10, 59, messages[28], 254);
|
||||
littText(11, 60, messages[28], 254);
|
||||
littText(9, 60, messages[28], 254);
|
||||
|
||||
littText(10, 81, messages[29], 254);
|
||||
littText(10, 79, messages[29], 254);
|
||||
littText(11, 80, messages[29], 254);
|
||||
littText(9, 80, messages[29], 254);
|
||||
|
||||
littText(10, 101, messages[30], 254);
|
||||
littText(10, 99, messages[30], 254);
|
||||
littText(11, 100, messages[30], 254);
|
||||
littText(9, 100, messages[30], 254);
|
||||
|
||||
littText(10, 121, messages[31], 254);
|
||||
littText(10, 119, messages[31], 254);
|
||||
littText(11, 120, messages[31], 254);
|
||||
littText(9, 120, messages[31], 254);
|
||||
|
||||
littText(10, 141, messages[32], 254);
|
||||
littText(10, 139, messages[32], 254);
|
||||
littText(11, 140, messages[32], 254);
|
||||
littText(9, 140, messages[32], 254);
|
||||
|
||||
if (!isSpanish) {
|
||||
littText(10, 161, messages[56], 254);
|
||||
littText(10, 159, messages[56], 254);
|
||||
littText(11, 160, messages[56], 254);
|
||||
littText(9, 160, messages[56], 254);
|
||||
|
||||
littText(10, 181, messages[57], 254);
|
||||
littText(10, 179, messages[57], 254);
|
||||
littText(11, 180, messages[57], 254);
|
||||
littText(9, 180, messages[57], 254);
|
||||
}
|
||||
|
||||
littText(10, 20, messages[26], 255);
|
||||
littText(10, 40, messages[27], 255);
|
||||
littText(10, 60, messages[28], 255);
|
||||
littText(10, 80, messages[29], 255);
|
||||
littText(10, 100, messages[30], 255);
|
||||
littText(10, 120, messages[31], 255);
|
||||
littText(10, 140, messages[32], 255);
|
||||
|
||||
if (!isSpanish) {
|
||||
littText(10, 160, messages[56], 255);
|
||||
littText(10, 180, messages[57], 255);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= 31; i++) {
|
||||
setRGBPalette(255, 32 + i, i * 2, i * 2);
|
||||
setRGBPalette(254, 32 - i, 0, 0);
|
||||
}
|
||||
delay(16000);
|
||||
if (shouldQuit())
|
||||
return;
|
||||
|
||||
for (int i = 31; i >= 0; i--) {
|
||||
setRGBPalette(255, 63 - (32 - i), i * 2, i * 2);
|
||||
setRGBPalette(254, 32 - i, 0, 0);
|
||||
}
|
||||
delay(2000);
|
||||
if (shouldQuit())
|
||||
return;
|
||||
|
||||
_graphics->clear();
|
||||
|
||||
littText(10, 21, messages[33], 254);
|
||||
littText(10, 19, messages[33], 254);
|
||||
littText(11, 20, messages[33], 254);
|
||||
littText(9, 20, messages[33], 254);
|
||||
|
||||
littText(10, 41, messages[34], 254);
|
||||
littText(10, 39, messages[34], 254);
|
||||
littText(11, 40, messages[34], 254);
|
||||
littText(9, 40, messages[34], 254);
|
||||
|
||||
littText(10, 61, messages[35], 254);
|
||||
littText(10, 59, messages[35], 254);
|
||||
littText(11, 60, messages[35], 254);
|
||||
littText(9, 60, messages[35], 254);
|
||||
if (isSpanish) {
|
||||
littText(10, 81, messages[36], 254);
|
||||
littText(10, 79, messages[36], 254);
|
||||
littText(11, 80, messages[36], 254);
|
||||
littText(9, 80, messages[36], 254);
|
||||
|
||||
littText(10, 101, messages[37], 254);
|
||||
littText(10, 99, messages[37], 254);
|
||||
littText(11, 100, messages[37], 254);
|
||||
littText(9, 100, messages[37], 254);
|
||||
|
||||
littText(10, 121, messages[38], 254);
|
||||
littText(10, 119, messages[38], 254);
|
||||
littText(11, 120, messages[38], 254);
|
||||
littText(9, 120, messages[38], 254);
|
||||
|
||||
littText(10, 141, messages[39], 254);
|
||||
littText(10, 139, messages[39], 254);
|
||||
littText(11, 140, messages[39], 254);
|
||||
littText(9, 140, messages[39], 254);
|
||||
}
|
||||
|
||||
littText(10, 20, messages[33], 255);
|
||||
littText(10, 40, messages[34], 255);
|
||||
littText(10, 60, messages[35], 255);
|
||||
if (isSpanish) {
|
||||
littText(10, 80, messages[36], 255);
|
||||
littText(10, 100, messages[37], 255);
|
||||
littText(10, 120, messages[38], 255);
|
||||
littText(10, 140, messages[39], 255);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= 31; i++) {
|
||||
setRGBPalette(255, 32 + i, i * 2, i * 2);
|
||||
setRGBPalette(254, 32 - i, 0, 0);
|
||||
}
|
||||
delay(13000);
|
||||
if (shouldQuit())
|
||||
return;
|
||||
|
||||
for (int i = 31; i >= 0; i--) {
|
||||
setRGBPalette(255, 63 - (32 - i), i * 2, i * 2);
|
||||
setRGBPalette(254, 32 - i, 0, 0);
|
||||
}
|
||||
delay(2000);
|
||||
if (shouldQuit())
|
||||
return;
|
||||
_graphics->clear();
|
||||
|
||||
littText(10, 61, messages[40], 254);
|
||||
littText(10, 59, messages[40], 254);
|
||||
littText(11, 60, messages[40], 254);
|
||||
littText(9, 60, messages[40], 254);
|
||||
|
||||
littText(10, 81, messages[41], 254);
|
||||
littText(10, 79, messages[41], 254);
|
||||
littText(11, 80, messages[41], 254);
|
||||
littText(9, 80, messages[41], 254);
|
||||
|
||||
littText(10, 101, messages[42], 254);
|
||||
littText(10, 99, messages[42], 254);
|
||||
littText(11, 100, messages[42], 254);
|
||||
littText(9, 100, messages[42], 254);
|
||||
|
||||
littText(10, 60, messages[40], 255);
|
||||
littText(10, 80, messages[41], 255);
|
||||
littText(10, 100, messages[42], 255);
|
||||
|
||||
for (int i = 0; i <= 31; i++) {
|
||||
setRGBPalette(255, 32 + i, i * 2, i * 2);
|
||||
setRGBPalette(254, 32 - i, 0, 0);
|
||||
}
|
||||
delay(7000);
|
||||
if (shouldQuit())
|
||||
return;
|
||||
for (int i = 31; i >= 0; i--) {
|
||||
setRGBPalette(255, 63 - (32 - i), i * 2, i * 2);
|
||||
setRGBPalette(254, 32 - i, 0, 0);
|
||||
}
|
||||
delay(2000);
|
||||
_graphics->totalFadeOut(0);
|
||||
_currentRoomData->paletteAnimationFlag = exitPressed;
|
||||
_saveAllowed = true;
|
||||
}
|
||||
|
||||
void TotEngine::ending() {
|
||||
_saveAllowed = false;
|
||||
bool exitRequested;
|
||||
|
||||
const char *const *messages = getFullScreenMessagesByCurrentLanguage();
|
||||
const int32 *offsets = getOffsetsByCurrentLanguage();
|
||||
|
||||
littText(10, 41, messages[43], 249);
|
||||
littText(10, 39, messages[43], 249);
|
||||
littText(11, 40, messages[43], 249);
|
||||
littText(9, 40, messages[43], 249);
|
||||
|
||||
littText(10, 61, messages[44], 249);
|
||||
littText(10, 59, messages[44], 249);
|
||||
littText(11, 60, messages[44], 249);
|
||||
littText(9, 60, messages[44], 249);
|
||||
|
||||
littText(10, 40, messages[43], 253);
|
||||
littText(10, 60, messages[44], 253);
|
||||
if (shouldQuit()) {
|
||||
return;
|
||||
}
|
||||
delay(4000);
|
||||
_graphics->totalFadeOut(0);
|
||||
_graphics->clear();
|
||||
if (shouldQuit()) {
|
||||
return;
|
||||
}
|
||||
_sound->fadeOutMusic();
|
||||
_sound->playMidi("SACRIFIC", true);
|
||||
_sound->fadeInMusic();
|
||||
drawFlc(0, 0, offsets[30], 12, 9, 26, true, false, false, exitRequested);
|
||||
if (exitRequested) {
|
||||
return;
|
||||
}
|
||||
drawFlc(0, 0, offsets[31], 0, 9, 0, false, false, false, exitRequested);
|
||||
if (exitRequested) {
|
||||
return;
|
||||
}
|
||||
delay(1000);
|
||||
_sound->playVoc("NOOO", 0, 0);
|
||||
delay(3000);
|
||||
_saveAllowed = true;
|
||||
}
|
||||
|
||||
void TotEngine::wcScene() {
|
||||
Palette wcPalette;
|
||||
_currentZone = _currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount];
|
||||
goToObject(_currentZone, _targetZone);
|
||||
|
||||
_graphics->copyPalette(g_engine->_graphics->_pal, wcPalette);
|
||||
_mouse->hide();
|
||||
|
||||
_graphics->partialFadeOut(234);
|
||||
|
||||
const char *const *messages = getFullScreenMessagesByCurrentLanguage();
|
||||
|
||||
littText(10, 20, messages[45], 253);
|
||||
delay(1000);
|
||||
|
||||
bar(10, 20, 150, 30, 0);
|
||||
delay(2000);
|
||||
|
||||
littText(100, 50, messages[46], 255);
|
||||
delay(1000);
|
||||
|
||||
bar(100, 50, 250, 60, 0);
|
||||
delay(2000);
|
||||
|
||||
littText(30, 110, messages[47], 253);
|
||||
delay(1000);
|
||||
|
||||
bar(30, 110, 210, 120, 0);
|
||||
delay(3000);
|
||||
|
||||
littText(50, 90, messages[48], 248);
|
||||
delay(1000);
|
||||
|
||||
_sound->playVoc("WATER", 272050, 47062);
|
||||
bar(50, 90, 200, 100, 0);
|
||||
delay(4000);
|
||||
|
||||
_characterPosX = 76 - kCharacterCorrectionX;
|
||||
_characterPosY = 78 - kCharacerCorrectionY;
|
||||
_graphics->copyPalette(wcPalette, g_engine->_graphics->_pal);
|
||||
_graphics->restoreBackground();
|
||||
assembleScreen();
|
||||
_graphics->drawScreen(_sceneBackground);
|
||||
_graphics->partialFadeIn(234);
|
||||
_xframe2 = 0;
|
||||
_currentTrajectoryIndex = 0;
|
||||
_trajectoryLength = 1;
|
||||
_currentZone = 8;
|
||||
_targetZone = 8;
|
||||
_trajectory[0].x = _characterPosX;
|
||||
_trajectory[0].y = _characterPosY;
|
||||
|
||||
_mouse->show();
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
132
engines/tot/debug.cpp
Normal file
132
engines/tot/debug.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tot/debug.h"
|
||||
#include "tot/tot.h"
|
||||
#include "tot/util.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
// Debug
|
||||
void drawMouseGrid(RoomFileRegister *screen) {
|
||||
for (int i = 0; i < 39; i++) {
|
||||
for (int j = 0; j < 27; j++) {
|
||||
int color = screen->mouseGrid[i][j];
|
||||
if (color == 0) continue;
|
||||
int startX = i * kXGridCount + 7;
|
||||
int startY = j * kYGridCount;
|
||||
for (int i2 = 0; i2 < kXGridCount; i2 += 2) {
|
||||
for (int j2 = 0; j2 < kYGridCount; j2++) {
|
||||
int absPixel = startY + j2;
|
||||
int offsetX = (absPixel % 2 == 0) ? 1 : 0;
|
||||
*(byte *)g_engine->_screen->getBasePtr(startX + i2 + offsetX, startY + j2) = 255 - color;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
g_engine->_screen->markAllDirty();
|
||||
}
|
||||
|
||||
void drawScreenGrid(RoomFileRegister *screen) {
|
||||
for (int i = 0; i < 39; i++) {
|
||||
for (int j = 0; j < 27; j++) {
|
||||
int color = screen->walkAreasGrid[i][j];
|
||||
if (color == 0)
|
||||
continue;
|
||||
|
||||
int startX = i * kXGridCount + 7;
|
||||
int startY = j * kYGridCount;
|
||||
for (int i2 = 0; i2 < kXGridCount; i2 += 2) {
|
||||
for (int j2 = 0; j2 < kYGridCount; j2++) {
|
||||
int absPixel = startY + j2;
|
||||
int offsetX = (absPixel % 2 == 0) ? 1 : 0;
|
||||
*(byte *)g_engine->_screen->getBasePtr(startX + i2 + offsetX, startY + j2) = 255 - color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g_engine->_screen->markAllDirty();
|
||||
}
|
||||
|
||||
void drawPos(uint x, uint y, byte color) {
|
||||
if (x < 320 && x > 0 && y > 0 && y < 200)
|
||||
*(byte *)g_engine->_screen->getBasePtr(x, y) = color;
|
||||
|
||||
g_engine->_screen->addDirtyRect(Common::Rect(x, y, x + 1, y + 1));
|
||||
g_engine->_screen->markAllDirty();
|
||||
}
|
||||
|
||||
void drawLine(int x, int y, int x2, int y2, byte color) {
|
||||
g_engine->_screen->drawLine(x, y, x2, y2, color);
|
||||
}
|
||||
|
||||
void printNiches() {
|
||||
debug("| | %03d | %03d | %03d | %03d |", 0, 1, 2, 3);
|
||||
debug("| 0 | %03d | %03d | %03d | %03d |", g_engine->_niche[0][0], g_engine->_niche[0][1], g_engine->_niche[0][2], g_engine->_niche[0][3]);
|
||||
debug("| 1 | %03d | %03d | %03d | %03d |", g_engine->_niche[1][0], g_engine->_niche[1][1], g_engine->_niche[1][2], g_engine->_niche[1][3]);
|
||||
debug("niche[0][niche[0][3]] = %d", g_engine->_niche[0][g_engine->_niche[0][3]]);
|
||||
debug("niche[1][niche[1][3]] = %d", g_engine->_niche[1][g_engine->_niche[1][3]]);
|
||||
}
|
||||
|
||||
void drawX(int x, int y, byte color) {
|
||||
if (x > 0 && y > 0)
|
||||
*(byte *)g_engine->_screen->getBasePtr(x, y) = color;
|
||||
if (x - 1 > 0 && y - 1 > 0)
|
||||
*(byte *)g_engine->_screen->getBasePtr(x - 1, y - 1) = color;
|
||||
if (x - 1 > 0 && y + 1 < 140)
|
||||
*(byte *)g_engine->_screen->getBasePtr(x - 1, y + 1) = color;
|
||||
if (x + 1 < 320 && y + 1 < 140)
|
||||
*(byte *)g_engine->_screen->getBasePtr(x + 1, y + 1) = color;
|
||||
if (x + 1 < 320 && y - 1 > 0)
|
||||
*(byte *)g_engine->_screen->getBasePtr(x + 1, y - 1) = color;
|
||||
}
|
||||
|
||||
void drawCharacterPosition() {
|
||||
drawX(g_engine->_characterPosX, g_engine->_characterPosY, 210);
|
||||
drawX(g_engine->_characterPosX + kCharacterCorrectionX, g_engine->_characterPosY + kCharacerCorrectionY, 218);
|
||||
}
|
||||
|
||||
void drawRect(byte color, int x, int y, int x2, int y2) {
|
||||
rectangle(x, y, x2, y2, color);
|
||||
}
|
||||
|
||||
void printPos(int x, int y, int screenPosX, int screenPosY, const char *label) {
|
||||
g_engine->_graphics->restoreBackgroundArea(screenPosX, screenPosY, screenPosX + 100, screenPosY + 10);
|
||||
g_engine->_graphics->euroText(Common::String::format("%s: %d, %d", label, x, y), screenPosX, screenPosY, Graphics::kTextAlignLeft);
|
||||
}
|
||||
|
||||
void drawGrid() {
|
||||
int horizontal = 320 / kXGridCount;
|
||||
int vertical = 140 / kYGridCount;
|
||||
for (int i = 0; i < horizontal; i++) {
|
||||
int startX = i * kXGridCount;
|
||||
g_engine->_screen->drawLine(startX, 0, startX, 140, 200);
|
||||
}
|
||||
|
||||
for (int j = 0; j < vertical; j++) {
|
||||
int startY = j * kYGridCount;
|
||||
g_engine->_screen->drawLine(0, startY, 320, startY, 200);
|
||||
}
|
||||
g_engine->_screen->addDirtyRect(Common::Rect(0, 0, 320, 140));
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
43
engines/tot/debug.h
Normal file
43
engines/tot/debug.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOT_DEBUG_H
|
||||
#define TOT_DEBUG_H
|
||||
|
||||
#include "tot/tot.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
// Debug methods
|
||||
void drawMouseGrid(RoomFileRegister *screen);
|
||||
void drawScreenGrid(RoomFileRegister *screen);
|
||||
void drawCharacterPosition();
|
||||
void printPos(int x, int y, int screenPosX, int screenPosY, const char *label);
|
||||
void drawPos(uint x, uint y, byte color);
|
||||
void drawGrid();
|
||||
void drawRect(byte color, int x, int y, int x2, int y2);
|
||||
void drawX(int x, int y, byte color);
|
||||
void drawLine(int x, int y, int x2, int y2, byte color);
|
||||
void printNiches();
|
||||
|
||||
} // End of namespace Tot
|
||||
|
||||
#endif
|
||||
140
engines/tot/decoder/TotFlicDecoder.cpp
Normal file
140
engines/tot/decoder/TotFlicDecoder.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "common/stream.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "video/flic_decoder.h"
|
||||
|
||||
#include "tot/decoder/TotFlicDecoder.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
#define FLI_SETPAL 4
|
||||
#define FLI_SS2 7
|
||||
#define FLI_BLACK 13
|
||||
#define FLI_BRUN 15
|
||||
#define FLI_COPY 16
|
||||
#define PSTAMP 18
|
||||
#define FLC_FILE_HEADER 0x2420
|
||||
|
||||
bool TotFlicDecoder::loadStream(Common::SeekableReadStream *stream) {
|
||||
close();
|
||||
|
||||
/* uint32 frameSize = */ stream->readUint32LE();
|
||||
uint16 frameType = stream->readUint16LE();
|
||||
|
||||
// Check FLC magic number
|
||||
if (frameType != FLC_FILE_HEADER) {
|
||||
warning("FlicDecoder::loadStream(): attempted to load non-FLC data (type = 0x%04X)", frameType);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16 frameCount = stream->readUint16LE();
|
||||
uint16 width = stream->readUint16LE();
|
||||
uint16 height = stream->readUint16LE();
|
||||
uint16 colorDepth = stream->readUint16LE();
|
||||
if (colorDepth != 8) {
|
||||
warning("FlicDecoder::loadStream(): attempted to load an FLC with a palette of color depth %d. Only 8-bit color palettes are supported", colorDepth);
|
||||
return false;
|
||||
}
|
||||
|
||||
addTrack(new TotVideoTrack(stream, frameCount, width, height));
|
||||
return true;
|
||||
}
|
||||
|
||||
TotFlicDecoder::TotVideoTrack::TotVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height) : Video::FlicDecoder::FlicVideoTrack(stream, frameCount, width, height, true) {
|
||||
|
||||
FlicDecoder::FlicVideoTrack::readHeader();
|
||||
}
|
||||
|
||||
TotFlicDecoder::TotVideoTrack::~TotVideoTrack() {
|
||||
}
|
||||
|
||||
void TotFlicDecoder::TotVideoTrack::handleFrame() {
|
||||
uint16 chunkCount = _fileStream->readUint16LE();
|
||||
// Note: The overridden delay is a 16-bit integer (word), whereas the normal delay is a 32-bit integer (dword)
|
||||
// the frame delay is the FLIC "speed", in milliseconds.
|
||||
uint16 newFrameDelay = _fileStream->readUint16LE(); // "speed", in milliseconds
|
||||
if (newFrameDelay > 0)
|
||||
_frameDelay = newFrameDelay;
|
||||
|
||||
_fileStream->readUint16LE(); // reserved, always 0
|
||||
uint16 newWidth = _fileStream->readUint16LE();
|
||||
uint16 newHeight = _fileStream->readUint16LE();
|
||||
|
||||
if ((newWidth != 0) || (newHeight != 0)) {
|
||||
if (newWidth == 0)
|
||||
newWidth = _surface->w;
|
||||
if (newHeight == 0)
|
||||
newHeight = _surface->h;
|
||||
|
||||
_surface->free();
|
||||
delete _surface;
|
||||
_surface = new Graphics::Surface();
|
||||
_surface->create(newWidth, newHeight, Graphics::PixelFormat::createFormatCLUT8());
|
||||
}
|
||||
|
||||
// Read subchunks
|
||||
for (uint32 i = 0; i < chunkCount; ++i) {
|
||||
uint32 frameSize = _fileStream->readUint32LE();
|
||||
uint16 frameType = _fileStream->readUint16LE();
|
||||
uint8 *data;
|
||||
|
||||
if (frameType == FLI_COPY) {
|
||||
// data seems to be in a different format for COPY chunks so we adjust for that
|
||||
data = new uint8[frameSize - 4];
|
||||
_fileStream->read(data, frameSize - 4);
|
||||
} else {
|
||||
data = new uint8[frameSize - 6];
|
||||
_fileStream->read(data, frameSize - 6);
|
||||
}
|
||||
|
||||
switch (frameType) {
|
||||
case FLI_SETPAL:
|
||||
unpackPalette(data);
|
||||
_dirtyPalette = true;
|
||||
break;
|
||||
case FLI_SS2:
|
||||
decodeDeltaFLC(data);
|
||||
break;
|
||||
case FLI_BLACK:
|
||||
_surface->fillRect(Common::Rect(0, 0, getWidth(), getHeight()), 0);
|
||||
_dirtyRects.clear();
|
||||
_dirtyRects.push_back(Common::Rect(0, 0, getWidth(), getHeight()));
|
||||
break;
|
||||
case FLI_BRUN:
|
||||
decodeByteRun(data);
|
||||
break;
|
||||
case FLI_COPY:
|
||||
copyFrame(data);
|
||||
break;
|
||||
case PSTAMP:
|
||||
/* PSTAMP - skip for now */
|
||||
break;
|
||||
default:
|
||||
error("FlicDecoder::decodeNextFrame(): unknown subchunk type (type = 0x%02X)", frameType);
|
||||
break;
|
||||
}
|
||||
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
49
engines/tot/decoder/TotFlicDecoder.h
Normal file
49
engines/tot/decoder/TotFlicDecoder.h
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOT_FLICDECODER_H
|
||||
#define TOT_FLICDECODER_H
|
||||
|
||||
#include "video/flic_decoder.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
class TotFlicDecoder : public Video::FlicDecoder {
|
||||
public:
|
||||
TotFlicDecoder() : Video::FlicDecoder() {}
|
||||
~TotFlicDecoder() {}
|
||||
bool loadStream(Common::SeekableReadStream *stream) override;
|
||||
|
||||
private:
|
||||
class TotVideoTrack : public Video::FlicDecoder::FlicVideoTrack {
|
||||
public:
|
||||
TotVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height);
|
||||
~TotVideoTrack() override;
|
||||
|
||||
private:
|
||||
void handleFrame() override;
|
||||
};
|
||||
};
|
||||
|
||||
} // End namespace Tot
|
||||
|
||||
#endif
|
||||
38
engines/tot/detection.cpp
Normal file
38
engines/tot/detection.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tot/detection.h"
|
||||
#include "tot/detection_tables.h"
|
||||
|
||||
const DebugChannelDef TotMetaEngineDetection::debugFlagList[] = {
|
||||
{ Tot::kDebugGraphics, "Graphics", "Graphics debug level" },
|
||||
{ Tot::kDebugPath, "Path", "Pathfinding debug level" },
|
||||
{ Tot::kDebugFilePath, "FilePath", "File path debug level" },
|
||||
{ Tot::kDebugScan, "Scan", "Scan for unrecognised games" },
|
||||
{ Tot::kDebugScript, "Script", "Enable debug script dump" },
|
||||
DEBUG_CHANNEL_END
|
||||
};
|
||||
|
||||
TotMetaEngineDetection::TotMetaEngineDetection() : AdvancedMetaEngineDetection(
|
||||
Tot::gameDescriptions, Tot::totGames) {
|
||||
}
|
||||
|
||||
REGISTER_PLUGIN_STATIC(TOT_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, TotMetaEngineDetection);
|
||||
72
engines/tot/detection.h
Normal file
72
engines/tot/detection.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOT_DETECTION_H
|
||||
#define TOT_DETECTION_H
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
enum TotDebugChannels {
|
||||
kDebugGraphics = 1,
|
||||
kDebugPath,
|
||||
kDebugScan,
|
||||
kDebugFilePath,
|
||||
kDebugScript,
|
||||
};
|
||||
|
||||
extern const PlainGameDescriptor totGames[];
|
||||
|
||||
extern const ADGameDescription gameDescriptions[];
|
||||
|
||||
#define GAMEOPTION_COPY_PROTECTION GUIO_GAMEOPTIONS1
|
||||
#define GAMEOPTION_NO_TRANSITIONS GUIO_GAMEOPTIONS2
|
||||
#define GAMEOPTION_ORIGINAL_SAVELOAD_DIALOG GUIO_GAMEOPTIONS3
|
||||
#define GAMEOPTION_OPL3_MODE GUIO_GAMEOPTIONS4
|
||||
|
||||
} // End of namespace Tot
|
||||
|
||||
class TotMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
|
||||
static const DebugChannelDef debugFlagList[];
|
||||
|
||||
public:
|
||||
TotMetaEngineDetection();
|
||||
~TotMetaEngineDetection() override {}
|
||||
|
||||
const char *getName() const override {
|
||||
return "tot";
|
||||
}
|
||||
|
||||
const char *getEngineName() const override {
|
||||
return "Trick or Treat";
|
||||
}
|
||||
|
||||
const char *getOriginalCopyright() const override {
|
||||
return "(C) Todos los derechos reservados. ACA Soft. S.L. Granada Octubre de 1994";
|
||||
}
|
||||
|
||||
const DebugChannelDef *getDebugChannels() const override {
|
||||
return debugFlagList;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // TOT_DETECTION_H
|
||||
75
engines/tot/detection_tables.h
Normal file
75
engines/tot/detection_tables.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "tot/detection.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
const PlainGameDescriptor totGames[] = {
|
||||
{ "tot", "Trick or Treat" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
const ADGameDescription gameDescriptions[] = {
|
||||
{
|
||||
"tot",
|
||||
nullptr,
|
||||
AD_ENTRY3s(
|
||||
"AZCCOG.DAT", "2f66724fcd7f51c5b4a715b30f088581", 79916,
|
||||
"CREDITOS.DAT", "6885c1fadd25a0c0da1c88f071a30e63", 130080,
|
||||
"TOT.EXE", "cf3a34941be45d3207e38f8f5d66ba00", 209520
|
||||
),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO5(GUIO_NOSPEECH, GAMEOPTION_COPY_PROTECTION, GAMEOPTION_NO_TRANSITIONS, GAMEOPTION_ORIGINAL_SAVELOAD_DIALOG, GAMEOPTION_OPL3_MODE)
|
||||
},
|
||||
{
|
||||
"tot",
|
||||
nullptr,
|
||||
AD_ENTRY3s(
|
||||
"AZCCOG.DAT", "2f66724fcd7f51c5b4a715b30f088581", 79916,
|
||||
"CREDITOS.DAT", "bca1c63cfee9ec8b722f7715e21b5e8e", 130080,
|
||||
"TOT.EXE", "e711989e516bd33d0da6c278c82a0493", 207280
|
||||
),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO5(GUIO_NOSPEECH, GAMEOPTION_COPY_PROTECTION, GAMEOPTION_NO_TRANSITIONS, GAMEOPTION_ORIGINAL_SAVELOAD_DIALOG, GAMEOPTION_OPL3_MODE)
|
||||
},
|
||||
{
|
||||
"tot",
|
||||
"Demo",
|
||||
AD_ENTRY3s(
|
||||
"CREDITOS.DAT", "6885c1fadd25a0c0da1c88f071a30e63", 130080,
|
||||
"PERSONAJ.SPT", "e5e1a2caa4ba3439fa0492cff772a318", 326050,
|
||||
"ANIMA.EXE", "08b1495d89ef7f05990541edf8754d94", 212880
|
||||
),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_DEMO,
|
||||
GUIO4(GUIO_NOSPEECH, GAMEOPTION_NO_TRANSITIONS, GAMEOPTION_ORIGINAL_SAVELOAD_DIALOG, GAMEOPTION_OPL3_MODE)
|
||||
},
|
||||
AD_TABLE_END_MARKER
|
||||
};
|
||||
|
||||
} // End of namespace Tot
|
||||
|
||||
|
||||
651
engines/tot/dialog.cpp
Normal file
651
engines/tot/dialog.cpp
Normal file
@@ -0,0 +1,651 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tot/dialog.h"
|
||||
#include "tot/tot.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
Common::String decrypt(Common::String encryptedText) {
|
||||
for (uint i = 0; i < encryptedText.size(); i++) {
|
||||
encryptedText.setChar(g_engine->_decryptionKey[i] ^ (char)encryptedText[i], i);
|
||||
}
|
||||
return encryptedText;
|
||||
}
|
||||
|
||||
Common::List<uint>* findDialogue(Tree tree, byte characterIndex);
|
||||
|
||||
static void findDownwards(Tree curTree, bool &descend) {
|
||||
if (curTree != nullptr) {
|
||||
if (curTree->element.spoken != '1') {
|
||||
descend = true;
|
||||
return;
|
||||
} else {
|
||||
findDownwards(leftChild(curTree), descend);
|
||||
findDownwards(rightSibling(curTree), descend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Common::List<uint>* findDialogue(Tree tree, byte characterIndex) {
|
||||
bool speak = false, ascend = false, descend = false, border = false, forward = false, done = false;
|
||||
|
||||
Tree auxTree = tree->child;
|
||||
Common::List<uint> *linkedList = new Common::List<uint>();
|
||||
Tree step;
|
||||
do {
|
||||
switch (auxTree->element.spoken) {
|
||||
case '0':
|
||||
case '2':
|
||||
case 'H':
|
||||
speak = true;
|
||||
break;
|
||||
case '1': {
|
||||
speak = false;
|
||||
step = auxTree->child;
|
||||
descend = false;
|
||||
findDownwards(step, descend);
|
||||
if (!(descend))
|
||||
ascend = true;
|
||||
step = nullptr;
|
||||
} break;
|
||||
case '3':
|
||||
if (g_engine->_bookTopic[0] && (characterIndex == 3)) {
|
||||
speak = false;
|
||||
ascend = true;
|
||||
} else
|
||||
speak = true;
|
||||
break;
|
||||
case '4':
|
||||
if (g_engine->_firstTimeTopicA[characterIndex - 1]) {
|
||||
speak = false;
|
||||
ascend = true;
|
||||
} else
|
||||
speak = true;
|
||||
break;
|
||||
case '5':
|
||||
if (g_engine->_bookTopic[characterIndex - 1] && g_engine->_firstTimeTopicB[characterIndex - 1])
|
||||
speak = true;
|
||||
else {
|
||||
speak = false;
|
||||
ascend = true;
|
||||
}
|
||||
break;
|
||||
case '6':
|
||||
if (g_engine->_bookTopic[characterIndex - 1] && !g_engine->_firstTimeTopicB[characterIndex - 1])
|
||||
speak = true;
|
||||
else {
|
||||
speak = false;
|
||||
ascend = true;
|
||||
}
|
||||
break;
|
||||
case '7':
|
||||
if (g_engine->_bookTopic[characterIndex - 1]) {
|
||||
speak = false;
|
||||
ascend = true;
|
||||
} else if (!g_engine->_firstTimeTopicA[characterIndex - 1])
|
||||
speak = true;
|
||||
else {
|
||||
speak = false;
|
||||
ascend = true;
|
||||
}
|
||||
break;
|
||||
case '8':
|
||||
if (g_engine->_mintTopic[characterIndex - 1] && g_engine->_firstTimeTopicC[characterIndex - 1])
|
||||
speak = true;
|
||||
else {
|
||||
speak = false;
|
||||
ascend = true;
|
||||
}
|
||||
break;
|
||||
case '9':
|
||||
if (g_engine->_mintTopic[characterIndex - 1] && !g_engine->_firstTimeTopicC[characterIndex - 1])
|
||||
speak = true;
|
||||
else {
|
||||
speak = false;
|
||||
ascend = true;
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
if (!g_engine->_mintTopic[characterIndex - 1] && !g_engine->_firstTimeTopicA[characterIndex - 1])
|
||||
speak = true;
|
||||
else {
|
||||
speak = false;
|
||||
ascend = true;
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
if (g_engine->_caves[0] && !g_engine->_firstTimeTopicA[8])
|
||||
speak = true;
|
||||
else
|
||||
speak = false;
|
||||
break;
|
||||
case 'C':
|
||||
if (g_engine->_caves[1] && !g_engine->_firstTimeTopicA[8])
|
||||
speak = true;
|
||||
else
|
||||
speak = false;
|
||||
break;
|
||||
case 'D':
|
||||
if ((g_engine->_caves[0] && g_engine->_caves[1]) && !g_engine->_firstTimeTopicA[8])
|
||||
speak = true;
|
||||
else
|
||||
speak = false;
|
||||
break;
|
||||
case 'E':
|
||||
if ((g_engine->_caves[0] && !g_engine->_caves[2]) && !g_engine->_firstTimeTopicA[8])
|
||||
speak = true;
|
||||
else
|
||||
speak = false;
|
||||
break;
|
||||
case 'F':
|
||||
if (!g_engine->_caves[3])
|
||||
speak = true;
|
||||
else
|
||||
speak = false;
|
||||
break;
|
||||
case 'G':
|
||||
if (!g_engine->_caves[4])
|
||||
speak = true;
|
||||
else
|
||||
speak = false;
|
||||
break;
|
||||
case 'I':
|
||||
if (!g_engine->_isSealRemoved)
|
||||
speak = true;
|
||||
else
|
||||
speak = false;
|
||||
break;
|
||||
case 'Z':
|
||||
speak = false;
|
||||
break;
|
||||
}
|
||||
if (speak) {
|
||||
if (auxTree->element.spoken == '2') {
|
||||
if (!border) {
|
||||
border = true;
|
||||
switch (characterIndex) {
|
||||
case 1:
|
||||
if (g_engine->_firstTimeTopicA[characterIndex - 1]) {
|
||||
linkedList->push_back(12);
|
||||
forward = true;
|
||||
} else if (g_engine->_bookTopic[characterIndex - 1]) {
|
||||
forward = true;
|
||||
linkedList->push_back(33);
|
||||
} else {
|
||||
linkedList->push_back(21);
|
||||
forward = true;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (g_engine->_firstTimeTopicA[characterIndex - 1]) {
|
||||
linkedList->push_back(103);
|
||||
forward = true;
|
||||
} else {
|
||||
linkedList->push_back(112);
|
||||
forward = true;
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
linkedList->push_back(auxTree->element.index);
|
||||
forward = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
linkedList->push_back(auxTree->element.index);
|
||||
forward = true;
|
||||
}
|
||||
if (forward) {
|
||||
forward = false;
|
||||
}
|
||||
if (rightSibling(auxTree) != nullptr)
|
||||
auxTree = rightSibling(auxTree);
|
||||
else {
|
||||
do {
|
||||
if (!isRoot(parent(auxTree)))
|
||||
auxTree = parent(auxTree);
|
||||
else
|
||||
break;
|
||||
} while (!(auxTree->element.spoken == '1' && rightSibling(auxTree) != nullptr));
|
||||
if (rightSibling(auxTree) != nullptr)
|
||||
auxTree = rightSibling(auxTree);
|
||||
else
|
||||
done = true;
|
||||
}
|
||||
} else if (ascend) {
|
||||
ascend = false;
|
||||
if (rightSibling(auxTree) != nullptr)
|
||||
auxTree = rightSibling(auxTree);
|
||||
else {
|
||||
do {
|
||||
if (!isRoot(parent(auxTree)))
|
||||
auxTree = parent(auxTree);
|
||||
else
|
||||
break;
|
||||
} while (!((auxTree->element.spoken == '1') && (rightSibling(auxTree) != nullptr)));
|
||||
if (rightSibling(auxTree) != nullptr)
|
||||
auxTree = rightSibling(auxTree);
|
||||
else
|
||||
done = true;
|
||||
}
|
||||
} else if (leftChild(auxTree) != nullptr)
|
||||
auxTree = leftChild(auxTree);
|
||||
else if (rightSibling(auxTree) != nullptr)
|
||||
auxTree = rightSibling(auxTree);
|
||||
else {
|
||||
auxTree = parent(auxTree);
|
||||
if (rightSibling(auxTree) != nullptr)
|
||||
auxTree = rightSibling(auxTree);
|
||||
else {
|
||||
do {
|
||||
auxTree = parent(auxTree);
|
||||
} while (!(isRoot(auxTree) || rightSibling(auxTree) != nullptr));
|
||||
if (isRoot(auxTree))
|
||||
done = true;
|
||||
else
|
||||
auxTree = rightSibling(auxTree);
|
||||
}
|
||||
}
|
||||
} while (!done);
|
||||
auxTree = nullptr;
|
||||
step = nullptr;
|
||||
return linkedList;
|
||||
}
|
||||
|
||||
void modifyTree(Tree tree, uint node) {
|
||||
|
||||
bool found = false;
|
||||
Tree auxTree = tree->child;
|
||||
do {
|
||||
if (auxTree->element.index == node) {
|
||||
|
||||
if ((auxTree->element.spoken != '2') && (auxTree->element.spoken != 'H'))
|
||||
auxTree->element.spoken = '1';
|
||||
else if (auxTree->element.spoken != 'H')
|
||||
auxTree->element.spoken = 'Z';
|
||||
found = true;
|
||||
} else {
|
||||
if (leftChild(auxTree) != nullptr)
|
||||
auxTree = leftChild(auxTree);
|
||||
else if (rightSibling(auxTree) != nullptr)
|
||||
auxTree = rightSibling(auxTree);
|
||||
else {
|
||||
do {
|
||||
auxTree = parent(auxTree);
|
||||
} while (!(rightSibling(auxTree) != nullptr));
|
||||
auxTree = rightSibling(auxTree);
|
||||
}
|
||||
}
|
||||
} while (!found);
|
||||
}
|
||||
|
||||
void drawTalkMenu() {
|
||||
byte auxTextY;
|
||||
g_engine->_mouse->hide();
|
||||
for (auxTextY = 25; auxTextY >= 1; auxTextY--)
|
||||
rectangle(0, 175 - auxTextY, 319, 174 + auxTextY, 0);
|
||||
for (auxTextY = 1; auxTextY <= 25; auxTextY++)
|
||||
g_engine->buttonBorder(0, 175 - auxTextY, 319, 174 + auxTextY, 253, 253, 253, 253, 0);
|
||||
g_engine->drawMenu(5);
|
||||
g_engine->_mouse->show();
|
||||
}
|
||||
|
||||
void fixTree(Tree tree) {
|
||||
if (tree != nullptr) {
|
||||
if (tree->element.spoken == 'Z')
|
||||
tree->element.spoken = '2';
|
||||
else {
|
||||
fixTree(leftChild(tree));
|
||||
fixTree(rightSibling(tree));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void showDialogOptions(
|
||||
Common::String conversationMatrix[16],
|
||||
uint &chosenTopic,
|
||||
byte conversationIndex,
|
||||
Common::ListInternal::Iterator<uint> l1,
|
||||
bool &endOfConversation) {
|
||||
|
||||
byte firstChat = 1;
|
||||
byte selectedConv = 0;
|
||||
g_engine->_mouse->hide();
|
||||
|
||||
g_engine->drawMenu(5);
|
||||
euroText(6, 151, conversationMatrix[1], 255);
|
||||
euroText(6, 162, conversationMatrix[2], 255);
|
||||
euroText(6, 173, conversationMatrix[3], 255);
|
||||
euroText(6, 184, conversationMatrix[4], 255);
|
||||
g_engine->_mouse->show();
|
||||
|
||||
do {
|
||||
bool lMouseClicked = false;
|
||||
bool rMouseClicked = false;
|
||||
do {
|
||||
g_engine->_chrono->updateChrono();
|
||||
g_engine->_mouse->animateMouseIfNeeded();
|
||||
g_engine->_events->pollEvent();
|
||||
|
||||
if (g_engine->_events->_leftMouseButton) {
|
||||
lMouseClicked = true;
|
||||
} else if (g_engine->_events->_rightMouseButton) {
|
||||
rMouseClicked = true;
|
||||
}
|
||||
|
||||
if (g_engine->_chrono->_gameTick) {
|
||||
g_engine->_graphics->advancePaletteAnim();
|
||||
}
|
||||
g_system->delayMillis(10);
|
||||
g_engine->_screen->update();
|
||||
} while (!lMouseClicked && !rMouseClicked && !g_engine->shouldQuit());
|
||||
|
||||
if (lMouseClicked) {
|
||||
if (g_engine->_mouse->mouseClickY < 143)
|
||||
selectedConv = 0;
|
||||
else {
|
||||
if (g_engine->_mouse->mouseClickX <= 280) {
|
||||
if (g_engine->_mouse->mouseClickY <= 155) {
|
||||
selectedConv = firstChat;
|
||||
} else if (g_engine->_mouse->mouseClickY <= 166) {
|
||||
selectedConv = firstChat + 1;
|
||||
} else if (g_engine->_mouse->mouseClickY <= 177) {
|
||||
selectedConv = firstChat + 2;
|
||||
} else if (g_engine->_mouse->mouseClickY <= 186) {
|
||||
selectedConv = firstChat + 3;
|
||||
}
|
||||
} else if (g_engine->_mouse->mouseClickX <= 319) {
|
||||
if (g_engine->_mouse->mouseClickY <= 165) {
|
||||
if (firstChat > 1) {
|
||||
selectedConv = 0;
|
||||
firstChat -= 1;
|
||||
g_engine->_mouse->hide();
|
||||
g_engine->drawMenu(5);
|
||||
euroText(6, 151, conversationMatrix[firstChat], 255);
|
||||
euroText(6, 162, conversationMatrix[firstChat + 1], 255);
|
||||
euroText(6, 173, conversationMatrix[firstChat + 2], 255);
|
||||
euroText(6, 184, conversationMatrix[firstChat + 3], 255);
|
||||
g_engine->_mouse->show();
|
||||
}
|
||||
} else if (g_engine->_mouse->mouseClickY >= 167 && g_engine->_mouse->mouseClickY <= 186) {
|
||||
if (firstChat < 12) {
|
||||
selectedConv = 0;
|
||||
firstChat += 1;
|
||||
g_engine->_mouse->hide();
|
||||
g_engine->drawMenu(5);
|
||||
euroText(6, 151, conversationMatrix[firstChat], 255);
|
||||
euroText(6, 162, conversationMatrix[firstChat + 1], 255);
|
||||
euroText(6, 173, conversationMatrix[firstChat + 2], 255);
|
||||
euroText(6, 184, conversationMatrix[firstChat + 3], 255);
|
||||
g_engine->_mouse->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (rMouseClicked)
|
||||
selectedConv = conversationIndex;
|
||||
} while (!((selectedConv > 0) && (selectedConv <= conversationIndex)) && !g_engine->shouldQuit());
|
||||
|
||||
if (selectedConv == conversationIndex)
|
||||
endOfConversation = true;
|
||||
for (int i = 1; i <= (selectedConv - 1); i++)
|
||||
l1++;
|
||||
chosenTopic = *l1;
|
||||
}
|
||||
|
||||
void talk(byte characterIndex) {
|
||||
debug("Talking to person: %d", characterIndex);
|
||||
uint response, newNode;
|
||||
TextEntry text;
|
||||
byte stringAux, insertName, invIndex;
|
||||
|
||||
Common::String conversationMatrix[16];
|
||||
drawTalkMenu();
|
||||
bool endOfConversation = false;
|
||||
g_engine->readTextFile();
|
||||
// The original game makes a copy of the file upon starting a new game. .007 is the current game (the game
|
||||
// that resumes when clicking "continue game" in the main menu. Part of the savegame data is this 007
|
||||
// conversation file which marks conversatino topics as already gone through or not.
|
||||
Tree tree;
|
||||
readTree(*g_engine->_conversationData, tree, characterIndex - 1);
|
||||
loadTalkAnimations();
|
||||
Common::ListInternal::Iterator<uint> l1;
|
||||
do {
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
conversationMatrix[i] = "";
|
||||
}
|
||||
|
||||
Common::List<uint> *linkedList = findDialogue(tree, characterIndex);
|
||||
byte conversationIndex = 0;
|
||||
l1 = linkedList->begin();
|
||||
while (l1 != linkedList->end() && !g_engine->shouldQuit() && conversationIndex < 15) {
|
||||
g_engine->_verbFile.seek(kVerbRegSize * (*l1));
|
||||
conversationIndex += 1;
|
||||
text = g_engine->readTextRegister();
|
||||
insertName = 0;
|
||||
conversationMatrix[conversationIndex] = decrypt(text.text);
|
||||
|
||||
for (uint i = 0; i < conversationMatrix[conversationIndex].size(); i++) {
|
||||
if (conversationMatrix[conversationIndex][i] == '@')
|
||||
insertName = i;
|
||||
}
|
||||
if (insertName > 0) {
|
||||
conversationMatrix[conversationIndex].deleteChar(insertName);
|
||||
conversationMatrix[conversationIndex].insertString(g_engine->_characterName, insertName);
|
||||
}
|
||||
if (conversationMatrix[conversationIndex].size() > 45) {
|
||||
stringAux = 45;
|
||||
do {
|
||||
stringAux -= 1;
|
||||
} while (conversationMatrix[conversationIndex][stringAux] != ' ');
|
||||
conversationMatrix[conversationIndex] = conversationMatrix[conversationIndex].substr(0, stringAux);
|
||||
conversationMatrix[conversationIndex].insertString(" ...", stringAux);
|
||||
}
|
||||
l1++;
|
||||
};
|
||||
l1 = linkedList->begin();
|
||||
showDialogOptions(conversationMatrix, newNode, conversationIndex, l1, endOfConversation);
|
||||
delete linkedList;
|
||||
g_engine->sayLine(newNode, 255, 0, response, true);
|
||||
stringAux = 0;
|
||||
modifyTree(tree, newNode);
|
||||
while (response > 0 && !g_engine->shouldQuit()) {
|
||||
newNode = response;
|
||||
stringAux += 1;
|
||||
if (odd(stringAux))
|
||||
g_engine->sayLine(newNode, 253, 249, response, true);
|
||||
else
|
||||
g_engine->sayLine(newNode, 255, 0, response, true);
|
||||
switch (newNode) {
|
||||
case 9: {
|
||||
g_engine->_obtainedList1 = true;
|
||||
invIndex = 0;
|
||||
while (g_engine->_inventory[invIndex].code != 0) {
|
||||
invIndex += 1;
|
||||
}
|
||||
g_engine->_inventory[invIndex].bitmapIndex = kList1Index;
|
||||
g_engine->_inventory[invIndex].code = kList1code;
|
||||
g_engine->_inventory[invIndex].objectName = getObjectName(0);
|
||||
} break;
|
||||
case 25: {
|
||||
g_engine->_obtainedList2 = true;
|
||||
invIndex = 0;
|
||||
while (g_engine->_inventory[invIndex].code != 0) {
|
||||
invIndex += 1;
|
||||
}
|
||||
g_engine->_inventory[invIndex].bitmapIndex = kList2Index;
|
||||
g_engine->_inventory[invIndex].code = kList2code;
|
||||
g_engine->_inventory[invIndex].objectName = getObjectName(1);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
g_system->delayMillis(10);
|
||||
} while (!endOfConversation && !g_engine->shouldQuit());
|
||||
|
||||
unloadTalkAnimations();
|
||||
Tree step = tree;
|
||||
fixTree(step);
|
||||
saveConversations(g_engine->_conversationData, tree, characterIndex - 1);
|
||||
|
||||
g_engine->_verbFile.close();
|
||||
if (g_engine->shouldQuit()) {
|
||||
return;
|
||||
}
|
||||
delete tree;
|
||||
|
||||
g_engine->_mouse->hide();
|
||||
|
||||
for (int i = 25; i >= 1; i--)
|
||||
rectangle(0, 175 - i, 319, 174 + i, 0);
|
||||
g_engine->drawInventoryMask();
|
||||
g_engine->drawInventory();
|
||||
g_engine->_mouse->show();
|
||||
|
||||
if (characterIndex < 5) {
|
||||
if (g_engine->_firstTimeTopicA[characterIndex - 1])
|
||||
g_engine->_firstTimeTopicA[characterIndex - 1] = false;
|
||||
if (g_engine->_firstTimeTopicB[characterIndex - 1])
|
||||
g_engine->_firstTimeTopicB[characterIndex - 1] = false;
|
||||
if (g_engine->_firstTimeTopicC[characterIndex - 1])
|
||||
g_engine->_firstTimeTopicC[characterIndex - 1] = false;
|
||||
} else if (characterIndex == 8)
|
||||
g_engine->_firstTimeTopicA[8] = false;
|
||||
}
|
||||
|
||||
void talkToSceneObject() {
|
||||
Common::Point p = g_engine->_mouse->getClickCoordsWithinGrid();
|
||||
int correctedMouseX = p.x;
|
||||
int correctedMouseY = p.y;
|
||||
uint sceneObject = g_engine->_currentRoomData->screenObjectIndex[g_engine->_currentRoomData->mouseGrid[correctedMouseX][correctedMouseY]]->fileIndex;
|
||||
if (sceneObject == 0)
|
||||
return;
|
||||
|
||||
g_engine->readObject(sceneObject);
|
||||
g_engine->goToObject(g_engine->_currentRoomData->walkAreasGrid[(g_engine->_characterPosX + kCharacterCorrectionX) / kXGridCount][(g_engine->_characterPosY + kCharacerCorrectionY) / kYGridCount],
|
||||
g_engine->_currentRoomData->walkAreasGrid[correctedMouseX][correctedMouseY]);
|
||||
|
||||
if (g_engine->_curObject->speaking > 0) {
|
||||
talk(g_engine->_curObject->speaking);
|
||||
} else {
|
||||
g_engine->readTextFile();
|
||||
uint foo = 0;
|
||||
g_engine->sayLine((getRandom(10) + 1039), 255, 0, foo, false);
|
||||
g_engine->_verbFile.close();
|
||||
if (g_engine->_cpCounter > 198)
|
||||
showError(274);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads talking animation of main and secondary character
|
||||
*/
|
||||
void loadTalkAnimations() {
|
||||
Common::File animFile;
|
||||
|
||||
if (!animFile.open("TIOHABLA.SEC")) {
|
||||
showError(265);
|
||||
}
|
||||
g_engine->_mainCharFrameSize = animFile.readUint16LE();
|
||||
|
||||
int32 offset = g_engine->_mainCharFrameSize * 16;
|
||||
offset = (offset * g_engine->_charFacingDirection) + 2;
|
||||
animFile.seek(offset);
|
||||
// Will load talking anim always in the upwards direction of the walk cycle array
|
||||
for (int i = 0; i < 16; i++) {
|
||||
free(g_engine->_mainCharAnimation.bitmap[0][i]);
|
||||
g_engine->_mainCharAnimation.bitmap[0][i] = (byte *)malloc(g_engine->_mainCharFrameSize);
|
||||
animFile.read(g_engine->_mainCharAnimation.bitmap[0][i], g_engine->_mainCharFrameSize);
|
||||
}
|
||||
animFile.close();
|
||||
|
||||
if ((g_engine->_currentRoomData->animationName != "PETER") && (g_engine->_currentRoomData->animationName != "ARZCAEL")) {
|
||||
g_engine->_iframe2 = 0;
|
||||
bool result;
|
||||
switch (g_engine->_curObject->speaking) {
|
||||
case 1:
|
||||
result = animFile.open("JOHN.SEC");
|
||||
break;
|
||||
case 5:
|
||||
result = animFile.open("ALFRED.SEC");
|
||||
break;
|
||||
default:
|
||||
result = animFile.open(Common::Path(g_engine->_currentRoomData->animationName + Common::String(".SEC")));
|
||||
}
|
||||
|
||||
if (!result)
|
||||
showError(265);
|
||||
g_engine->_secondaryAnimFrameSize = animFile.readUint16LE();
|
||||
g_engine->_secondaryAnimationFrameCount = animFile.readByte();
|
||||
g_engine->_secondaryAnimDirCount = animFile.readByte();
|
||||
|
||||
newSecondaryAnimationFrame();
|
||||
if (g_engine->_secondaryAnimDirCount != 0) {
|
||||
g_engine->_secondaryAnimationFrameCount = g_engine->_secondaryAnimationFrameCount / 4;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
g_engine->loadAnimationForDirection(&animFile, i);
|
||||
}
|
||||
} else {
|
||||
g_engine->loadAnimationForDirection(&animFile, 0);
|
||||
}
|
||||
animFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void unloadTalkAnimations() {
|
||||
|
||||
Common::File animFile;
|
||||
if (!animFile.open("PERSONAJ.SPT")) {
|
||||
showError(265);
|
||||
}
|
||||
g_engine->_mainCharFrameSize = animFile.readUint16LE();
|
||||
|
||||
for (int i = 0; i < kWalkFrameCount; i++) {
|
||||
free(g_engine->_mainCharAnimation.bitmap[0][i]);
|
||||
g_engine->_mainCharAnimation.bitmap[0][i] = (byte *)malloc(g_engine->_mainCharFrameSize);
|
||||
animFile.read(g_engine->_mainCharAnimation.bitmap[0][i], g_engine->_mainCharFrameSize);
|
||||
}
|
||||
animFile.close();
|
||||
|
||||
if ((g_engine->_currentRoomData->animationName != "PETER") && (g_engine->_currentRoomData->animationName != "ARZCAEL")) {
|
||||
if (!animFile.open(Common::Path(g_engine->_currentRoomData->animationName + ".DAT"))) {
|
||||
showError(265);
|
||||
}
|
||||
g_engine->_secondaryAnimFrameSize = animFile.readUint16LE();
|
||||
g_engine->_secondaryAnimationFrameCount = animFile.readByte();
|
||||
g_engine->_secondaryAnimDirCount = animFile.readByte();
|
||||
newSecondaryAnimationFrame();
|
||||
if (g_engine->_secondaryAnimDirCount != 0) {
|
||||
|
||||
g_engine->_secondaryAnimationFrameCount = g_engine->_secondaryAnimationFrameCount / 4;
|
||||
for (int i = 0; i <= 3; i++) {
|
||||
g_engine->loadAnimationForDirection(&animFile, i);
|
||||
}
|
||||
} else {
|
||||
g_engine->loadAnimationForDirection(&animFile, 0);
|
||||
}
|
||||
animFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Tot
|
||||
36
engines/tot/dialog.h
Normal file
36
engines/tot/dialog.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef TOT_DIALOG_H
|
||||
#define TOT_DIALOG_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#include "tot/forest.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
void talkToSceneObject();
|
||||
void loadTalkAnimations();
|
||||
void unloadTalkAnimations();
|
||||
|
||||
} // End of namespace Tot
|
||||
|
||||
#endif
|
||||
5552
engines/tot/engine.cpp
Normal file
5552
engines/tot/engine.cpp
Normal file
File diff suppressed because it is too large
Load Diff
138
engines/tot/events.cpp
Normal file
138
engines/tot/events.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tot/events.h"
|
||||
#include "events.h"
|
||||
#include "tot/util.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
TotEventManager::TotEventManager() {
|
||||
}
|
||||
|
||||
void TotEventManager::pollEvent(bool allowDrag) {
|
||||
|
||||
Common::EventManager *eventMan = g_engine->_system->getEventManager();
|
||||
|
||||
zeroEvents(allowDrag);
|
||||
while (eventMan->pollEvent(_event)) {
|
||||
if (isMouseEvent(_event)) {
|
||||
g_engine->_mouse->warpMouse(_event.mouse);
|
||||
g_engine->_mouse->mouseX = _event.mouse.x;
|
||||
g_engine->_mouse->mouseY = _event.mouse.y;
|
||||
}
|
||||
switch (_event.type) {
|
||||
case Common::EVENT_QUIT:
|
||||
case Common::EVENT_RETURN_TO_LAUNCHER:
|
||||
return;
|
||||
|
||||
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
|
||||
// handle action
|
||||
handleKey(_event);
|
||||
break;
|
||||
|
||||
case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
|
||||
break;
|
||||
case Common::EVENT_KEYDOWN:
|
||||
changeGameSpeed(_event);
|
||||
_keyPressed = true;
|
||||
_lastKeyEvent = _event;
|
||||
return;
|
||||
case Common::EVENT_KEYUP:
|
||||
return;
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
_mouseX = _event.mouse.x;
|
||||
_mouseY = _event.mouse.y;
|
||||
break;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
_leftMouseButton = 1;
|
||||
g_engine->_mouse->mouseClickX = _event.mouse.x;
|
||||
g_engine->_mouse->mouseClickY = _event.mouse.y;
|
||||
break;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
_leftMouseButton = 0;
|
||||
break;
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
_rightMouseButton = 0;
|
||||
g_engine->_mouse->mouseClickX = _event.mouse.x;
|
||||
g_engine->_mouse->mouseClickY = _event.mouse.y;
|
||||
break;
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
_rightMouseButton = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TotEventManager::zeroEvents(bool allowDrag) {
|
||||
if (!allowDrag) {
|
||||
_leftMouseButton = 0;
|
||||
_rightMouseButton = 0;
|
||||
}
|
||||
_escKeyFl = false;
|
||||
_gameKey = KEY_NONE;
|
||||
_keyPressed = 0;
|
||||
_lastKeyEvent = Common::Event();
|
||||
}
|
||||
|
||||
void TotEventManager::waitForPress() {
|
||||
bool waitForKey = false;
|
||||
while (!waitForKey && !g_engine->shouldQuit()) {
|
||||
g_engine->_events->pollEvent();
|
||||
if (g_engine->_events->_keyPressed) {
|
||||
waitForKey = true;
|
||||
}
|
||||
|
||||
g_engine->_screen->update();
|
||||
g_system->delayMillis(10);
|
||||
}
|
||||
}
|
||||
|
||||
void TotEventManager::handleKey(const Common::Event &event) {
|
||||
if (event.customType == kActionVolume)
|
||||
_gameKey = KEY_VOLUME;
|
||||
else if (event.customType == kActionSaveLoad)
|
||||
_gameKey = KEY_SAVELOAD;
|
||||
else if (event.customType == kActionTalk)
|
||||
_gameKey = KEY_TALK;
|
||||
else if (event.customType == kActionPickup)
|
||||
_gameKey = KEY_PICKUP;
|
||||
else if (event.customType == kActionLookAt)
|
||||
_gameKey = KEY_LOOKAT;
|
||||
else if (event.customType == kActionUse)
|
||||
_gameKey = KEY_USE;
|
||||
else if (event.customType == kActionOpen)
|
||||
_gameKey = KEY_OPEN;
|
||||
else if (event.customType == kActionClose)
|
||||
_gameKey = KEY_CLOSE;
|
||||
else if (event.customType == kActionYes)
|
||||
_gameKey = KEY_YES;
|
||||
else if (event.customType == kActionNo)
|
||||
_gameKey = KEY_NO;
|
||||
else if (event.customType == kActionEscape) {
|
||||
_gameKey = KEY_ESCAPE;
|
||||
_escKeyFl = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
68
engines/tot/events.h
Normal file
68
engines/tot/events.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef TOT_EVENTS_H
|
||||
#define TOT_EVENTS_H
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
enum GAME_KEY {
|
||||
KEY_TALK = 0,
|
||||
KEY_PICKUP = 1,
|
||||
KEY_LOOKAT = 2,
|
||||
KEY_USE = 3,
|
||||
KEY_OPEN = 4,
|
||||
KEY_CLOSE = 5,
|
||||
KEY_YES = 6,
|
||||
KEY_NO = 7,
|
||||
KEY_SAVELOAD = 8,
|
||||
KEY_VOLUME = 9,
|
||||
KEY_ESCAPE = 10,
|
||||
KEY_NONE = -1
|
||||
};
|
||||
|
||||
class TotEventManager {
|
||||
private:
|
||||
Common::Event _event;
|
||||
|
||||
void handleKey(const Common::Event &event);
|
||||
public:
|
||||
bool _escKeyFl = false;
|
||||
bool _keyPressed = false;
|
||||
GAME_KEY _gameKey = KEY_NONE;
|
||||
bool _leftMouseButton = 0;
|
||||
bool _rightMouseButton = 0;
|
||||
int16 _mouseX = 0;
|
||||
int16 _mouseY = 0;
|
||||
Common::Event _lastKeyEvent;
|
||||
|
||||
TotEventManager();
|
||||
|
||||
void pollEvent(bool allowDrag = false);
|
||||
void zeroEvents(bool allowDrag = false);
|
||||
void waitForPress();
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Tot
|
||||
#endif
|
||||
193
engines/tot/forest.cpp
Normal file
193
engines/tot/forest.cpp
Normal file
@@ -0,0 +1,193 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tot/forest.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
void initTree(Tree &a, nodeElement data) {
|
||||
a = new TreeDef;
|
||||
a->element = data;
|
||||
a->parent = nullptr;
|
||||
a->sibling = nullptr;
|
||||
a->child = nullptr;
|
||||
}
|
||||
|
||||
bool isRoot(Tree node) {
|
||||
bool root;
|
||||
if (node->parent == nullptr)
|
||||
root = true;
|
||||
else
|
||||
root = false;
|
||||
return root;
|
||||
}
|
||||
|
||||
Tree rightSibling(Tree node) {
|
||||
Tree rightSibling;
|
||||
rightSibling = node->sibling;
|
||||
return rightSibling;
|
||||
}
|
||||
|
||||
Tree parent(Tree node) {
|
||||
Tree parent;
|
||||
parent = node->parent;
|
||||
return parent;
|
||||
}
|
||||
|
||||
Tree leftChild(Tree node) {
|
||||
Tree leftChild;
|
||||
leftChild = node->child;
|
||||
return leftChild;
|
||||
}
|
||||
|
||||
int depth(Tree node) {
|
||||
Tree aux;
|
||||
int depthCount = 0;
|
||||
aux = node;
|
||||
while (aux->parent != nullptr) {
|
||||
depthCount += 1;
|
||||
aux = parent(aux);
|
||||
}
|
||||
return depthCount;
|
||||
}
|
||||
|
||||
void expandNode(Tree &node, nodeElement data) {
|
||||
Tree aux = node;
|
||||
if (aux->child != nullptr) {
|
||||
|
||||
aux = leftChild(aux);
|
||||
while (aux->sibling != nullptr)
|
||||
aux = rightSibling(aux);
|
||||
;
|
||||
aux->sibling = new TreeDef;
|
||||
aux = aux->sibling;
|
||||
aux->element = data;
|
||||
aux->sibling = nullptr;
|
||||
aux->child = nullptr;
|
||||
aux->parent = node;
|
||||
} else {
|
||||
|
||||
aux->child = new TreeDef;
|
||||
aux = aux->child;
|
||||
aux->element = data;
|
||||
aux->sibling = nullptr;
|
||||
aux->child = nullptr;
|
||||
aux->parent = node;
|
||||
}
|
||||
}
|
||||
|
||||
void preOrder(Tree a, Common::String &encodedString) {
|
||||
if (a != nullptr) {
|
||||
encodedString = Common::String::format("%s%d%cN%d@", encodedString.c_str(), a->element.index, a->element.spoken, depth(a));
|
||||
preOrder(leftChild(a), encodedString);
|
||||
preOrder(rightSibling(a), encodedString);
|
||||
}
|
||||
}
|
||||
|
||||
void saveExpression(Common::SeekableWriteStream *s, Common::String expression) {
|
||||
s->writeByte(expression.size());
|
||||
s->writeString(expression);
|
||||
int paddingSize = 255 - expression.size();
|
||||
if (paddingSize > 0) {
|
||||
debug("Writing padding of %d", paddingSize);
|
||||
char *padding = new char[paddingSize];
|
||||
memset(padding, '\0', paddingSize);
|
||||
// 8 max char name
|
||||
s->write(padding, paddingSize);
|
||||
delete[] padding;
|
||||
}
|
||||
}
|
||||
|
||||
const int chatRegSize = 256;
|
||||
|
||||
void saveConversations(Common::SeekableWriteStream *s, Tree a, uint offset) {
|
||||
Common::String expression = "";
|
||||
preOrder(a, expression);
|
||||
s->seek(offset * chatRegSize, SEEK_SET);
|
||||
saveExpression(s, expression);
|
||||
}
|
||||
|
||||
void readTree(Common::SeekableReadStream &stream, Tree &a, uint position) {
|
||||
|
||||
const nodeElement empty = {'0', 0};
|
||||
nodeElement data;
|
||||
|
||||
Common::String strInd, tmpExpression;
|
||||
byte level;
|
||||
Common::String levelAsString;
|
||||
|
||||
stream.seek(chatRegSize * position);
|
||||
|
||||
Common::String expresion = stream.readPascalString();
|
||||
initTree(a, empty);
|
||||
Tree aux = a;
|
||||
byte pos = 0;
|
||||
byte currentLevel = 0;
|
||||
do {
|
||||
|
||||
tmpExpression = "";
|
||||
do {
|
||||
tmpExpression = tmpExpression + expresion[pos];
|
||||
} while (expresion[pos++] != '@');
|
||||
|
||||
int nIndex = tmpExpression.find('N');
|
||||
if (nIndex < 0)
|
||||
break;
|
||||
strInd = tmpExpression.substr(0, nIndex - 1);
|
||||
|
||||
data.spoken = tmpExpression[nIndex - 1];
|
||||
data.index = atoi(strInd.c_str());
|
||||
|
||||
levelAsString = tmpExpression.substr(nIndex + 1, tmpExpression.size() - nIndex - 2);
|
||||
level = atoi(levelAsString.c_str());
|
||||
|
||||
if (level == 0)
|
||||
aux->element = data;
|
||||
else if (level == (currentLevel + 1))
|
||||
expandNode(aux, data);
|
||||
else if (level > (currentLevel + 1)) {
|
||||
aux = leftChild(aux);
|
||||
currentLevel += 1;
|
||||
while (rightSibling(aux) != nullptr)
|
||||
aux = rightSibling(aux);
|
||||
expandNode(aux, data);
|
||||
} else {
|
||||
do {
|
||||
currentLevel -= 1;
|
||||
aux = parent(aux);
|
||||
} while (!(currentLevel < level));
|
||||
expandNode(aux, data);
|
||||
}
|
||||
|
||||
} while (pos != expresion.size());
|
||||
}
|
||||
|
||||
void readTree(Common::String f, Tree &a, uint offset) {
|
||||
|
||||
Common::File treeFile;
|
||||
if (!treeFile.open(Common::Path(f))) {
|
||||
showError(314);
|
||||
}
|
||||
readTree(treeFile, a, offset);
|
||||
treeFile.close();
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
67
engines/tot/forest.h
Normal file
67
engines/tot/forest.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef TOT_FOREST_H
|
||||
#define TOT_FOREST_H
|
||||
|
||||
#include "tot/util.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
struct nodeElement {
|
||||
char spoken;
|
||||
uint index;
|
||||
};
|
||||
|
||||
typedef struct TreeDef *Tree;
|
||||
|
||||
struct TreeDef {
|
||||
nodeElement element;
|
||||
Tree parent, sibling, child;
|
||||
|
||||
~TreeDef() {
|
||||
delete sibling;
|
||||
delete child;
|
||||
}
|
||||
};
|
||||
|
||||
void initTree(Tree &a, nodeElement data);
|
||||
|
||||
bool isRoot(Tree node);
|
||||
|
||||
Tree rightSibling(Tree node);
|
||||
|
||||
Tree parent(Tree node);
|
||||
|
||||
Tree leftChild(Tree node);
|
||||
|
||||
int depth(Tree node);
|
||||
|
||||
void expandNode(Tree &node, nodeElement data);
|
||||
|
||||
void preOrder(Tree a, Common::String &string_);
|
||||
|
||||
void saveConversations(Common::SeekableWriteStream *s, Tree a, uint location);
|
||||
|
||||
void readTree(Common::SeekableReadStream &f, Tree &a, uint location);
|
||||
void readTree(Common::String f, Tree &a, uint location);
|
||||
|
||||
} // End of namespace Tot
|
||||
#endif
|
||||
1050
engines/tot/graphics.cpp
Normal file
1050
engines/tot/graphics.cpp
Normal file
File diff suppressed because it is too large
Load Diff
110
engines/tot/graphics.h
Normal file
110
engines/tot/graphics.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef TOT_GRAPHICS_H
|
||||
#define TOT_GRAPHICS_H
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
#include "graphics/fonts/bgifont.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
const int kTextAreaSize = 320 * 70 + 4;
|
||||
|
||||
class GraphicsManager {
|
||||
public:
|
||||
GraphicsManager();
|
||||
~GraphicsManager();
|
||||
|
||||
void init();
|
||||
void fixPalette(byte *palette, uint num = 768);
|
||||
byte *getPalette();
|
||||
void setPalette(byte palette[768], uint start = 0, uint num = 256);
|
||||
void loadPaletteFromFile(Common::String image);
|
||||
void turnLightOn();
|
||||
void totalFadeOut(byte red);
|
||||
void partialFadeOut(byte numCol);
|
||||
void totalFadeIn(uint paletteNumber, Common::String paletteName);
|
||||
void redFadeIn(byte *palette);
|
||||
void partialFadeIn(byte numCol);
|
||||
void updatePalette(byte paletteIndex);
|
||||
void fadePalettes(byte *fromPalette, byte *toPalette);
|
||||
void copyPalette(byte *from, byte *to);
|
||||
|
||||
void putImg(uint coordx, uint coordy, byte *image, bool transparency = false);
|
||||
void getImg(uint coordx1, uint coordy1, uint coordx2, uint coordy2, byte *image);
|
||||
void putShape(uint coordx, uint coordy, byte *image);
|
||||
void putImageArea(uint putcoordx, uint putcoordy, byte *backgroundScreen, byte *image);
|
||||
void getImageArea(uint getcoordx1, uint getcoordy1, uint getcoordx2, uint getcoordy2, byte *backgroundScreen, byte *image);
|
||||
|
||||
void littText(const Common::String &str, int x, int y, uint32 color, Graphics::TextAlign align = Graphics::kTextAlignLeft, bool alignCenterY = false);
|
||||
void euroText(const Common::String &str, int x, int y, uint32 color, Graphics::TextAlign align = Graphics::kTextAlignLeft, bool alignCenterY = false);
|
||||
int euroTextWidth(const Common::String &str);
|
||||
void biosText(const Common::String &str, int x, int y, uint32 color);
|
||||
|
||||
void clear();
|
||||
|
||||
void clearActionLine();
|
||||
void writeActionLine(const Common::String &str);
|
||||
|
||||
void drawFullScreen(byte *screen);
|
||||
void copyFromScreen(byte *&screen);
|
||||
void drawScreen(byte *screen, bool offsetSize = true);
|
||||
void restoreBackground();
|
||||
void restoreBackgroundArea(uint x, uint y, uint x2, uint y2);
|
||||
|
||||
void sceneTransition(bool fadeToBlack, byte *screen, byte effectNumber);
|
||||
void sceneTransition(bool fadeToBlack, byte *screen);
|
||||
|
||||
void advancePaletteAnim();
|
||||
void printColor(int x, int y, int color);
|
||||
void updateSceneArea(int speed = 1);
|
||||
|
||||
/**
|
||||
* Aux for palette animation
|
||||
*/
|
||||
byte _paletteAnimFrame = 0;
|
||||
/**
|
||||
* Delay of palette animation
|
||||
*/
|
||||
byte _palAnimStep = 0;
|
||||
/**
|
||||
* 54 color palette slice.
|
||||
*/
|
||||
byte _palAnimSlice[768] = { 0 };
|
||||
/**
|
||||
* General palette
|
||||
*/
|
||||
byte _pal[768] = { 0 };
|
||||
|
||||
/**
|
||||
* TextArea for animations text
|
||||
*/
|
||||
byte *_textAreaBackground = (byte *)malloc(kTextAreaSize);
|
||||
private:
|
||||
signed char fadeData[256][256];
|
||||
Graphics::BgiFont *_litt;
|
||||
Graphics::BgiFont *_euro;
|
||||
Graphics::Font *_dosFont;
|
||||
};
|
||||
|
||||
} // End of namespace Tot
|
||||
#endif
|
||||
194
engines/tot/metaengine.cpp
Normal file
194
engines/tot/metaengine.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "backends/keymapper/action.h"
|
||||
#include "backends/keymapper/keymapper.h"
|
||||
#include "backends/keymapper/standard-actions.h"
|
||||
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "tot/metaengine.h"
|
||||
#include "tot/detection.h"
|
||||
#include "tot/statics.h"
|
||||
#include "tot/tot.h"
|
||||
|
||||
static const ADExtraGuiOptionsMap optionsList[] = {
|
||||
{
|
||||
GAMEOPTION_COPY_PROTECTION,
|
||||
{
|
||||
_s("Copy protection"),
|
||||
_s("Enable copy protection"),
|
||||
"copy_protection",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
{
|
||||
GAMEOPTION_NO_TRANSITIONS,
|
||||
{
|
||||
_s("Disable scene transitions"),
|
||||
_s("Disable original transition effects between scenes"),
|
||||
"transitions_disable",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
{
|
||||
GAMEOPTION_ORIGINAL_SAVELOAD_DIALOG,
|
||||
{
|
||||
_s("Original save/load dialog"),
|
||||
_s("Use original save and load dialogs"),
|
||||
"originalsaveload",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
{
|
||||
GAMEOPTION_OPL3_MODE,
|
||||
{
|
||||
_s("AdLib OPL3 mode"),
|
||||
_s("When AdLib is selected, OPL3 features will be used. Depending on the game, this will prevent cut-off notes, add extra notes or instruments and/or add stereo."),
|
||||
"opl3_mode",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
AD_EXTRA_GUI_OPTIONS_TERMINATOR
|
||||
};
|
||||
|
||||
const char *TotMetaEngine::getName() const {
|
||||
return "tot";
|
||||
}
|
||||
|
||||
Common::Error TotMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
|
||||
*engine = new Tot::TotEngine(syst, desc);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool TotMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
return checkExtendedSaves(f) ||
|
||||
(f == kSupportsLoadingDuringStartup);
|
||||
}
|
||||
|
||||
const ADExtraGuiOptionsMap *TotMetaEngine::getAdvancedExtraGuiOptions() const {
|
||||
return optionsList;
|
||||
}
|
||||
|
||||
Common::KeymapArray TotMetaEngine::initKeymaps(const char *target) const {
|
||||
using namespace Common;
|
||||
using namespace Tot;
|
||||
|
||||
Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "tot-default", _("Default keymappings"));
|
||||
Keymap *gameKeyMap = new Keymap(Keymap::kKeymapTypeGame, "game-shortcuts", _("Game keymappings"));
|
||||
Keymap *quitDialogKeyMap = new Keymap(Keymap::kKeymapTypeGame, "quit-dialog", _("Quit dialog keymappings"));
|
||||
|
||||
Common::Language lang = Common::parseLanguage(ConfMan.get("language", target));
|
||||
|
||||
static const char *const *defaultTotKeys = (lang == ES_ESP) ? keys[0] : keys[1];
|
||||
|
||||
Action *act;
|
||||
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Default action"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action("TALK", _("Talk"));
|
||||
act->setCustomEngineActionEvent(kActionTalk);
|
||||
act->addDefaultInputMapping(defaultTotKeys[KEY_TALK]);
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("PICK", _("Pick"));
|
||||
act->setCustomEngineActionEvent(kActionPickup);
|
||||
act->addDefaultInputMapping(defaultTotKeys[KEY_PICKUP]);
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("LOOK", _("Look"));
|
||||
act->setCustomEngineActionEvent(kActionLookAt);
|
||||
act->addDefaultInputMapping(defaultTotKeys[KEY_LOOKAT]);
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("USE", _("Use"));
|
||||
act->setCustomEngineActionEvent(kActionUse);
|
||||
act->addDefaultInputMapping(defaultTotKeys[KEY_USE]);
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("OPEN", _("Open"));
|
||||
act->setCustomEngineActionEvent(kActionOpen);
|
||||
act->addDefaultInputMapping(defaultTotKeys[KEY_OPEN]);
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("CLOSE", _("Close"));
|
||||
act->setCustomEngineActionEvent(kActionClose);
|
||||
act->addDefaultInputMapping(defaultTotKeys[KEY_CLOSE]);
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SAVELOAD", _("Save and load game"));
|
||||
act->setCustomEngineActionEvent(kActionSaveLoad);
|
||||
act->addDefaultInputMapping("F2");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("VOLCONTROLS", _("Volume controls"));
|
||||
act->setCustomEngineActionEvent(kActionVolume);
|
||||
act->addDefaultInputMapping("F1");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("MAINMENU", _("Main menu/Exit"));
|
||||
act->setCustomEngineActionEvent(kActionEscape);
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("QUITCONFIRM", _("Confirm quit"));
|
||||
act->setCustomEngineActionEvent(kActionYes);
|
||||
act->addDefaultInputMapping(defaultTotKeys[KEY_YES]);
|
||||
act->addDefaultInputMapping("JOY_RIGHT_TRIGGER");
|
||||
quitDialogKeyMap->addAction(act);
|
||||
|
||||
act = new Action("QUITCANCEL", _("Cancel quit"));
|
||||
act->setCustomEngineActionEvent(kActionNo);
|
||||
act->addDefaultInputMapping(defaultTotKeys[KEY_NO]);
|
||||
act->addDefaultInputMapping("JOY_KEFT_TRIGGER");
|
||||
quitDialogKeyMap->addAction(act);
|
||||
|
||||
KeymapArray keymaps(3);
|
||||
|
||||
keymaps[0] = engineKeyMap;
|
||||
keymaps[1] = gameKeyMap;
|
||||
keymaps[2] = quitDialogKeyMap;
|
||||
|
||||
return keymaps;
|
||||
}
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(TOT)
|
||||
REGISTER_PLUGIN_DYNAMIC(TOT, PLUGIN_TYPE_ENGINE, TotMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(TOT, PLUGIN_TYPE_ENGINE, TotMetaEngine);
|
||||
#endif
|
||||
43
engines/tot/metaengine.h
Normal file
43
engines/tot/metaengine.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOT_METAENGINE_H
|
||||
#define TOT_METAENGINE_H
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
class TotMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
|
||||
public:
|
||||
const char *getName() const override;
|
||||
|
||||
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
|
||||
|
||||
/**
|
||||
* Determine whether the engine supports the specified MetaEngine feature.
|
||||
*
|
||||
* Used by e.g. the launcher to determine whether to enable the Load button.
|
||||
*/
|
||||
bool hasFeature(MetaEngineFeature f) const override;
|
||||
const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override;
|
||||
Common::KeymapArray initKeymaps(const char *target) const override;
|
||||
};
|
||||
|
||||
#endif // TOT_METAENGINE_H
|
||||
194
engines/tot/midi.cpp
Normal file
194
engines/tot/midi.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "audio/midiparser.h"
|
||||
#include "audio/adlib_ctmidi.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "tot/midi.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
MidiPlayer::MidiPlayer() {
|
||||
_driver = nullptr;
|
||||
|
||||
_paused = false;
|
||||
_musicData = nullptr;
|
||||
_parserMusic = nullptr;
|
||||
}
|
||||
|
||||
MidiPlayer::~MidiPlayer() {
|
||||
stop();
|
||||
|
||||
if (_driver) {
|
||||
_driver->setTimerCallback(nullptr, nullptr);
|
||||
_driver->close();
|
||||
}
|
||||
if (_parserMusic)
|
||||
delete _parserMusic;
|
||||
if (_driver) {
|
||||
delete _driver;
|
||||
_driver = nullptr;
|
||||
}
|
||||
}
|
||||
int MidiPlayer::open() {
|
||||
|
||||
// Don't call open() twice!
|
||||
assert(!_driver);
|
||||
|
||||
OPL::Config::OplType oplType =
|
||||
(MidiDriver_ADLIB_Multisource::detectOplType(OPL::Config::kOpl3) && ConfMan.getBool("opl3_mode")) ?
|
||||
OPL::Config::kOpl3 : OPL::Config::kOpl2;
|
||||
|
||||
_driver = new MidiDriver_ADLIB_CTMIDI(oplType);
|
||||
|
||||
_parserMusic = MidiParser::createParser_SMF(0);
|
||||
|
||||
_driver->property(MidiDriver::PROP_USER_VOLUME_SCALING, true);
|
||||
_driver->setControllerDefault(MidiDriver_Multisource::CONTROLLER_DEFAULT_PITCH_BEND);
|
||||
_driver->setControllerDefault(MidiDriver_Multisource::CONTROLLER_DEFAULT_PANNING);
|
||||
|
||||
int returnCode = _driver->open();
|
||||
if (returnCode != 0)
|
||||
error("MidiPlayer::open - Failed to open MIDI music driver - error code %d.", returnCode);
|
||||
|
||||
syncSoundSettings();
|
||||
// Connect the driver(s) and the parser(s).
|
||||
_parserMusic->setMidiDriver(_driver);
|
||||
_parserMusic->setTimerRate(_driver->getBaseTempo());
|
||||
_driver->setTimerCallback(this, &onTimer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MidiPlayer::onTimer(void *data) {
|
||||
MidiPlayer *p = (MidiPlayer *)data;
|
||||
if (p->_parserMusic) {
|
||||
p->_parserMusic->onTimer();
|
||||
}
|
||||
}
|
||||
|
||||
bool MidiPlayer::isPlaying() {
|
||||
return _parserMusic->isPlaying();
|
||||
}
|
||||
|
||||
void MidiPlayer::stop() {
|
||||
if (_parserMusic) {
|
||||
_parserMusic->stopPlaying();
|
||||
if (_driver)
|
||||
_driver->deinitSource(0);
|
||||
}
|
||||
}
|
||||
|
||||
void MidiPlayer::pause(bool b) {
|
||||
if (_paused == b || !_driver)
|
||||
return;
|
||||
|
||||
_paused = b;
|
||||
if (_paused) {
|
||||
if (_parserMusic)
|
||||
_parserMusic->pausePlaying();
|
||||
} else {
|
||||
if (_parserMusic)
|
||||
_parserMusic->resumePlaying();
|
||||
}
|
||||
}
|
||||
|
||||
void MidiPlayer::syncSoundSettings() {
|
||||
if (_driver)
|
||||
_driver->syncSoundSettings();
|
||||
}
|
||||
|
||||
void MidiPlayer::setLoop(bool loop) {
|
||||
if (_parserMusic)
|
||||
_parserMusic->property(MidiParser::mpAutoLoop, loop);
|
||||
}
|
||||
|
||||
void MidiPlayer::setSourceVolume(uint8 volume) {
|
||||
if (_driver)
|
||||
_driver->setSourceVolume(0, volume);
|
||||
}
|
||||
|
||||
void MidiPlayer::startFadeOut() {
|
||||
if (_driver)
|
||||
// Note: 40 ms is almost imperceptibly short
|
||||
_driver->startFade(40, 0);
|
||||
}
|
||||
|
||||
void MidiPlayer::startFadeIn() {
|
||||
if (_driver)
|
||||
_driver->startFade(40, 255);
|
||||
}
|
||||
|
||||
bool MidiPlayer::isFading() {
|
||||
return _driver ? _driver->isFading() : false;
|
||||
}
|
||||
|
||||
void MidiPlayer::load(Common::SeekableReadStream *in, int32 size) {
|
||||
|
||||
MidiParser *parser = _parserMusic;
|
||||
if (!parser)
|
||||
return;
|
||||
|
||||
if (size < 0) {
|
||||
// Use the parser to determine the size of the MIDI data.
|
||||
int64 startPos = in->pos();
|
||||
size = parser->determineDataSize(in);
|
||||
if (size < 0) {
|
||||
warning("MidiPlayer::load - Could not determine size of music data");
|
||||
return;
|
||||
}
|
||||
// determineDataSize might move the stream position, so return it to
|
||||
// the original position.
|
||||
in->seek(startPos);
|
||||
}
|
||||
|
||||
if (isPlaying())
|
||||
stop();
|
||||
parser->unloadMusic();
|
||||
|
||||
byte **dataPtr = &_musicData;
|
||||
if (*dataPtr) {
|
||||
delete[] *dataPtr;
|
||||
}
|
||||
|
||||
*dataPtr = new byte[size];
|
||||
in->read(*dataPtr, size);
|
||||
|
||||
parser->loadMusic(*dataPtr, size);
|
||||
}
|
||||
|
||||
void MidiPlayer::play(int track) {
|
||||
MidiParser *parser = _parserMusic;
|
||||
if (!parser)
|
||||
return;
|
||||
if (parser->setTrack(track)) {
|
||||
if (_driver)
|
||||
// Reset the source volume to neutral (in case the previous track
|
||||
// was faded out).
|
||||
_driver->resetSourceVolume(0);
|
||||
parser->startPlaying();
|
||||
} else {
|
||||
parser->stopPlaying();
|
||||
warning("MidiPlayer::play - Could not play %s track %i", "music", track);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
66
engines/tot/midi.h
Normal file
66
engines/tot/midi.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOT_MIDI_H
|
||||
#define TOT_MIDI_H
|
||||
|
||||
#include "audio/mididrv_ms.h"
|
||||
#include "audio/midiparser.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
class MidiPlayer {
|
||||
protected:
|
||||
MidiDriver_Multisource *_driver;
|
||||
MidiParser *_parserMusic;
|
||||
byte *_musicData;
|
||||
|
||||
bool _paused;
|
||||
|
||||
static void onTimer(void *data);
|
||||
|
||||
public:
|
||||
MidiPlayer();
|
||||
~MidiPlayer();
|
||||
|
||||
// Creates and opens the relevant parsers and drivers
|
||||
int open();
|
||||
// Loads music or SFX data supported by the MidiParser
|
||||
void load(Common::SeekableReadStream *in, int32 size = -1);
|
||||
|
||||
void play(int track);
|
||||
|
||||
void setLoop(bool loop);
|
||||
|
||||
bool isPlaying();
|
||||
void stop();
|
||||
void pause(bool b);
|
||||
void syncSoundSettings();
|
||||
|
||||
void setSourceVolume(uint8 volume);
|
||||
void startFadeOut();
|
||||
void startFadeIn();
|
||||
bool isFading();
|
||||
};
|
||||
|
||||
} // End of namespace Tot
|
||||
|
||||
#endif
|
||||
33
engines/tot/module.mk
Normal file
33
engines/tot/module.mk
Normal file
@@ -0,0 +1,33 @@
|
||||
MODULE := engines/tot
|
||||
|
||||
MODULE_OBJS = \
|
||||
anims.o \
|
||||
chrono.o \
|
||||
console.o \
|
||||
cutscenes.o \
|
||||
debug.o \
|
||||
decoder/TotFlicDecoder.o \
|
||||
dialog.o \
|
||||
engine.o \
|
||||
events.o \
|
||||
forest.o \
|
||||
graphics.o \
|
||||
metaengine.o \
|
||||
midi.o \
|
||||
mouse.o \
|
||||
resources.o \
|
||||
saveload.o \
|
||||
sound.o \
|
||||
tot.o \
|
||||
util.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_TOT), DYNAMIC_PLUGIN)
|
||||
PLUGIN := 1
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
||||
# Detection objects
|
||||
DETECT_OBJS += $(MODULE)/detection.o
|
||||
121
engines/tot/mouse.cpp
Normal file
121
engines/tot/mouse.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "graphics/cursorman.h"
|
||||
|
||||
#include "tot/mouse.h"
|
||||
#include "tot/tot.h"
|
||||
#include "tot/util.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
MouseManager::MouseManager() {
|
||||
_mouseArea = Common::Rect(0, 0, 320, 200);
|
||||
loadMasks();
|
||||
mouseX = 160;
|
||||
mouseY = 100;
|
||||
mouseClickX = mouseX;
|
||||
mouseClickY = mouseY;
|
||||
mouseMaskIndex = 1;
|
||||
}
|
||||
|
||||
MouseManager::~MouseManager() {
|
||||
}
|
||||
|
||||
void MouseManager::drawMask(int idx) {
|
||||
CursorMan.replaceCursor(_mouseMasks[idx].mask, 15, 15, 0, 0, 0);
|
||||
}
|
||||
|
||||
void MouseManager::animateMouseIfNeeded() {
|
||||
if (g_engine->_chrono->_gameTick) {
|
||||
setMouseMask(_currentMouseMask);
|
||||
if (_currentMouseMask < 7) {
|
||||
// sync this with frame time
|
||||
_currentMouseMask++;
|
||||
} else
|
||||
_currentMouseMask = 0;
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MouseManager::hide() {
|
||||
CursorMan.showMouse(false);
|
||||
}
|
||||
|
||||
void MouseManager::show() {
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
|
||||
void MouseManager::setMouseArea(Common::Rect rect) {
|
||||
_mouseArea = rect;
|
||||
}
|
||||
|
||||
void MouseManager::warpMouse(Common::Point p) {
|
||||
p.x = CLIP<int16>(p.x, _mouseArea.left, _mouseArea.right);
|
||||
p.y = CLIP<int16>(p.y, _mouseArea.top, _mouseArea.bottom);
|
||||
|
||||
g_system->warpMouse(p.x, p.y);
|
||||
}
|
||||
|
||||
void MouseManager::printPos(int x, int y, int screenPosX, int screenPosY) {
|
||||
g_engine->_graphics->restoreBackgroundArea(screenPosX, screenPosY, screenPosX + 100, screenPosY + 10);
|
||||
g_engine->_graphics->euroText(Common::String::format("MousePos: %d, %d", x + 7, y + 7), screenPosX, screenPosY, Graphics::kTextAlignLeft);
|
||||
}
|
||||
|
||||
Common::Point MouseManager::getClickCoordsWithinGrid() {
|
||||
int correctedMouseX = (mouseClickX + 7) / kXGridCount;
|
||||
int correctedMouseY = (mouseClickY + 7) / kYGridCount;
|
||||
return Common::Point(correctedMouseX, correctedMouseY);
|
||||
}
|
||||
|
||||
Common::Point MouseManager::getMouseCoordsWithinGrid() {
|
||||
int correctedMouseX = (mouseX + 7) / kXGridCount;
|
||||
int correctedMouseY = (mouseY + 7) / kYGridCount;
|
||||
return Common::Point(correctedMouseX, correctedMouseY);
|
||||
}
|
||||
|
||||
void MouseManager::warpMouse(int mask, int x, int y) {
|
||||
setMouseMask(_currentMouseMask);
|
||||
g_system->warpMouse(x, y);
|
||||
}
|
||||
|
||||
void MouseManager::loadMasks() {
|
||||
Common::File mouseMaskFile;
|
||||
if (!mouseMaskFile.open(Common::Path("RATON.ACA")))
|
||||
showError(317);
|
||||
|
||||
int numMouseMasks = mouseMaskFile.readByte();
|
||||
int mouseMaskSize = mouseMaskFile.readUint16LE();
|
||||
|
||||
for (int i = 0; i < numMouseMasks; i++) {
|
||||
_mouseMasks[i].width = mouseMaskFile.readUint16LE();
|
||||
_mouseMasks[i].height = mouseMaskFile.readUint16LE();
|
||||
_mouseMasks[i].mask = (byte *)malloc(mouseMaskSize - 4);
|
||||
mouseMaskFile.read(_mouseMasks[i].mask, mouseMaskSize - 4);
|
||||
}
|
||||
mouseMaskFile.close();
|
||||
}
|
||||
|
||||
void MouseManager::setMouseMask(int numMask) {
|
||||
drawMask(numMask);
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
62
engines/tot/mouse.h
Normal file
62
engines/tot/mouse.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef TOT_MOUSE_H
|
||||
#define TOT_MOUSE_H
|
||||
|
||||
namespace Tot {
|
||||
|
||||
struct MouseMask {
|
||||
void *mask;
|
||||
uint width;
|
||||
uint height;
|
||||
};
|
||||
|
||||
class MouseManager {
|
||||
public:
|
||||
MouseManager();
|
||||
~MouseManager();
|
||||
void drawMask(int idx);
|
||||
void warpMouse(int mask, int x, int y);
|
||||
void setMask(int maskNum);
|
||||
void animateMouseIfNeeded();
|
||||
void hide();
|
||||
void show();
|
||||
void setMouseArea(Common::Rect rect);
|
||||
void warpMouse(Common::Point p);
|
||||
void printPos(int x, int y, int screenPosX, int screenPosY);
|
||||
Common::Point getClickCoordsWithinGrid();
|
||||
Common::Point getMouseCoordsWithinGrid();
|
||||
|
||||
uint mouseX, mouseY; // Coords of the mouse sprite
|
||||
uint mouseClickX, mouseClickY; // Coords of mouse clicks
|
||||
byte mouseMaskIndex; // Frame index of the mouse mask
|
||||
|
||||
private:
|
||||
Common::Rect _mouseArea;
|
||||
int _currentMouseMask = 0;
|
||||
MouseMask _mouseMasks[8];
|
||||
void loadMasks();
|
||||
void setMouseMask(int numMask);
|
||||
};
|
||||
|
||||
} // End of namespace Tot
|
||||
|
||||
#endif
|
||||
393
engines/tot/resources.cpp
Normal file
393
engines/tot/resources.cpp
Normal file
@@ -0,0 +1,393 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tot/tot.h"
|
||||
#include "tot/util.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
void TotEngine::readBitmap(int32 bitmapPosition, byte *buf, uint bitmapSize, uint error) {
|
||||
Common::File bitmapFile;
|
||||
if (!bitmapFile.open("BITMAPS.DAT")) {
|
||||
showError(error);
|
||||
}
|
||||
bitmapFile.seek(bitmapPosition);
|
||||
bitmapFile.read(buf, bitmapSize);
|
||||
|
||||
bitmapFile.close();
|
||||
}
|
||||
|
||||
void TotEngine::loadCharAnimation() {
|
||||
Common::File characterFile;
|
||||
_cpCounter = _cpCounter2;
|
||||
if (!characterFile.open("PERSONAJ.SPT"))
|
||||
showError(265);
|
||||
|
||||
_mainCharFrameSize = characterFile.readUint16LE();
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int j = 0; j < kWalkFrameCount; j++) {
|
||||
if (g_engine->_mainCharAnimation.bitmap[i][j])
|
||||
free(g_engine->_mainCharAnimation.bitmap[i][j]);
|
||||
_mainCharAnimation.bitmap[i][j] = (byte *)malloc(_mainCharFrameSize);
|
||||
characterFile.read(_mainCharAnimation.bitmap[i][j], _mainCharFrameSize);
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int j = kWalkFrameCount; j < (kWalkFrameCount + 10 * 3); j++) {
|
||||
if (g_engine->_mainCharAnimation.bitmap[i][j])
|
||||
free(g_engine->_mainCharAnimation.bitmap[i][j]);
|
||||
_mainCharAnimation.bitmap[i][j] = (byte *)malloc(_mainCharFrameSize);
|
||||
characterFile.read(_mainCharAnimation.bitmap[i][j], _mainCharFrameSize);
|
||||
}
|
||||
characterFile.close();
|
||||
}
|
||||
|
||||
void TotEngine::readTextFile() {
|
||||
if (!_verbFile.open("CONVERSA.TXT")) {
|
||||
showError(313);
|
||||
}
|
||||
}
|
||||
|
||||
TextEntry TotEngine::readTextRegister(uint numRegister) {
|
||||
_verbFile.seek(numRegister * kVerbRegSize);
|
||||
return readTextRegister();
|
||||
}
|
||||
|
||||
TextEntry TotEngine::readTextRegister() {
|
||||
TextEntry regmht;
|
||||
// Since the text is encrypted it's safer to save the size as reported by
|
||||
// the pascal string, because the encrypter character might be the termination
|
||||
// character
|
||||
byte size = _verbFile.readByte();
|
||||
_verbFile.seek(-1, SEEK_CUR);
|
||||
regmht.text = _verbFile.readPascalString(false);
|
||||
_verbFile.skip(255 - size);
|
||||
regmht.continued = _verbFile.readByte();
|
||||
regmht.response = _verbFile.readUint16LE();
|
||||
regmht.pointer = _verbFile.readSint32LE();
|
||||
return regmht;
|
||||
}
|
||||
|
||||
void TotEngine::readConversationFile() {
|
||||
Common::File conversationFile;
|
||||
if (!conversationFile.open(Common::Path(Common::String("CONVERSA.TRE")))) {
|
||||
showError(314);
|
||||
}
|
||||
int64 fileSize = conversationFile.size();
|
||||
byte *buf = (byte *)malloc(fileSize);
|
||||
conversationFile.read(buf, fileSize);
|
||||
|
||||
_conversationData = new Common::MemorySeekableReadWriteStream(buf, fileSize, DisposeAfterUse::YES);
|
||||
conversationFile.close();
|
||||
}
|
||||
|
||||
void saveDoorMetadata(DoorRegistry doors, Common::SeekableWriteStream *out) {
|
||||
out->writeUint16LE(doors.nextScene);
|
||||
out->writeUint16LE(doors.exitPosX);
|
||||
out->writeUint16LE(doors.exitPosY);
|
||||
out->writeByte(doors.openclosed);
|
||||
out->writeByte(doors.doorcode);
|
||||
}
|
||||
|
||||
void savePoint(Common::Point point, Common::SeekableWriteStream *out) {
|
||||
out->writeUint16LE(point.x);
|
||||
out->writeUint16LE(point.y);
|
||||
}
|
||||
|
||||
void saveBitmapRegister(RoomBitmapRegister bitmap, Common::SeekableWriteStream *out) {
|
||||
out->writeSint32LE(bitmap.bitmapPointer);
|
||||
out->writeUint16LE(bitmap.bitmapSize);
|
||||
out->writeUint16LE(bitmap.coordx);
|
||||
out->writeUint16LE(bitmap.coordy);
|
||||
out->writeUint16LE(bitmap.depth);
|
||||
}
|
||||
|
||||
void saveRoomObjectList(RoomObjectListEntry objectList, Common::SeekableWriteStream *out) {
|
||||
|
||||
out->writeUint16LE(objectList.fileIndex);
|
||||
out->writeByte(objectList.objectName.size());
|
||||
int paddingSize = 20 - objectList.objectName.size();
|
||||
if (paddingSize < 20) {
|
||||
out->writeString(objectList.objectName);
|
||||
}
|
||||
if (paddingSize > 0) {
|
||||
char *padding = (char *)calloc(paddingSize, 1);
|
||||
out->write(padding, paddingSize);
|
||||
|
||||
free(padding);
|
||||
}
|
||||
}
|
||||
|
||||
void saveRoom(RoomFileRegister *room, Common::SeekableWriteStream *out) {
|
||||
out->writeUint16LE(room->code);
|
||||
out->writeUint32LE(room->roomImagePointer);
|
||||
out->writeUint16LE(room->roomImageSize);
|
||||
out->write(room->walkAreasGrid, 40 * 28);
|
||||
out->write(room->mouseGrid, 40 * 28);
|
||||
|
||||
// read puntos
|
||||
for (int i = 0; i < 9; i++) {
|
||||
for (int j = 0; j < 30; j++) {
|
||||
for (int k = 0; k < 5; k++) {
|
||||
savePoint(room->trajectories[i][j][k], out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
saveDoorMetadata(room->doors[i], out);
|
||||
}
|
||||
for (int i = 0; i < 15; i++) {
|
||||
saveBitmapRegister(room->screenLayers[i], out);
|
||||
}
|
||||
for (int i = 0; i < 51; i++) {
|
||||
saveRoomObjectList(*room->screenObjectIndex[i], out);
|
||||
}
|
||||
out->writeByte(room->animationFlag);
|
||||
|
||||
out->writeByte(room->animationName.size());
|
||||
out->writeString(room->animationName);
|
||||
int paddingSize = 8 - room->animationName.size();
|
||||
if (paddingSize > 0) {
|
||||
char *padding = (char *)calloc(paddingSize, 1);
|
||||
// 8 max char name
|
||||
out->write(padding, paddingSize);
|
||||
|
||||
free(padding);
|
||||
}
|
||||
out->writeByte(room->paletteAnimationFlag);
|
||||
out->writeUint16LE(room->palettePointer);
|
||||
for (int i = 0; i < 300; i++) {
|
||||
savePoint(room->secondaryAnimTrajectory[i], out);
|
||||
}
|
||||
out->write(room->secondaryAnimDirections, 600);
|
||||
out->writeUint16LE(room->secondaryTrajectoryLength);
|
||||
}
|
||||
|
||||
void TotEngine::saveRoomData(RoomFileRegister *room, Common::SeekableWriteStream *out) {
|
||||
_rooms->seek(room->code * kRoomRegSize, SEEK_SET);
|
||||
saveRoom(room, out);
|
||||
}
|
||||
|
||||
void TotEngine::readObject(Common::SeekableReadStream *stream, uint itemPos, ScreenObject *thisRegObj) {
|
||||
stream->seek(itemPos * kItemRegSize);
|
||||
thisRegObj->code = stream->readUint16LE();
|
||||
thisRegObj->height = stream->readByte();
|
||||
|
||||
thisRegObj->name = stream->readPascalString();
|
||||
|
||||
stream->skip(kObjectNameLength - thisRegObj->name.size());
|
||||
|
||||
thisRegObj->lookAtTextRef = stream->readUint16LE();
|
||||
thisRegObj->beforeUseTextRef = stream->readUint16LE();
|
||||
thisRegObj->afterUseTextRef = stream->readUint16LE();
|
||||
thisRegObj->pickTextRef = stream->readUint16LE();
|
||||
thisRegObj->useTextRef = stream->readUint16LE();
|
||||
thisRegObj->speaking = stream->readByte();
|
||||
thisRegObj->openable = stream->readByte();
|
||||
thisRegObj->closeable = stream->readByte();
|
||||
|
||||
stream->read(thisRegObj->used, 8);
|
||||
|
||||
thisRegObj->pickupable = stream->readByte();
|
||||
thisRegObj->useWith = stream->readUint16LE();
|
||||
thisRegObj->replaceWith = stream->readUint16LE();
|
||||
thisRegObj->depth = stream->readByte();
|
||||
thisRegObj->bitmapPointer = stream->readUint32LE();
|
||||
thisRegObj->bitmapSize = stream->readUint16LE();
|
||||
thisRegObj->rotatingObjectAnimation = stream->readUint32LE();
|
||||
thisRegObj->rotatingObjectPalette = stream->readUint16LE();
|
||||
thisRegObj->dropOverlayX = stream->readUint16LE();
|
||||
thisRegObj->dropOverlayY = stream->readUint16LE();
|
||||
thisRegObj->dropOverlay = stream->readUint32LE();
|
||||
thisRegObj->dropOverlaySize = stream->readUint16LE();
|
||||
thisRegObj->objectIconBitmap = stream->readUint16LE();
|
||||
thisRegObj->xgrid1 = stream->readByte();
|
||||
thisRegObj->ygrid1 = stream->readByte();
|
||||
thisRegObj->xgrid2 = stream->readByte();
|
||||
thisRegObj->ygrid2 = stream->readByte();
|
||||
stream->read(thisRegObj->walkAreasPatch, 100);
|
||||
stream->read(thisRegObj->mouseGridPatch, 100);
|
||||
}
|
||||
|
||||
void TotEngine::readObject(uint itemPosition) {
|
||||
if(_curObject != nullptr) {
|
||||
delete _curObject;
|
||||
_curObject = nullptr;
|
||||
}
|
||||
_curObject = new ScreenObject();
|
||||
|
||||
readObject(_sceneObjectsData, itemPosition, _curObject);
|
||||
}
|
||||
|
||||
void TotEngine::updateObject(uint itemPosition) {
|
||||
_curObject->used[0] = 9;
|
||||
_sceneObjectsData->seek(itemPosition);
|
||||
saveObject(_curObject, _sceneObjectsData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Object files contain a single register per object, with a set of 8 flags, to mark them as used in each save.
|
||||
*/
|
||||
void TotEngine::initializeObjectFile() {
|
||||
Common::File objFile;
|
||||
if (!objFile.open(Common::Path("OBJETOS.DAT"))) {
|
||||
showError(261);
|
||||
}
|
||||
delete (_sceneObjectsData);
|
||||
byte *objectData = (byte *)malloc(objFile.size());
|
||||
objFile.read(objectData, objFile.size());
|
||||
_sceneObjectsData = new Common::MemorySeekableReadWriteStream(objectData, objFile.size(), DisposeAfterUse::NO);
|
||||
objFile.close();
|
||||
}
|
||||
|
||||
void TotEngine::saveObjectsData(ScreenObject *object, Common::SeekableWriteStream *out) {
|
||||
out->writeUint16LE(object->code);
|
||||
out->writeByte(object->height);
|
||||
|
||||
out->writeByte(object->name.size());
|
||||
out->writeString(object->name);
|
||||
int paddingSize = kObjectNameLength - object->name.size();
|
||||
if (paddingSize > 0) {
|
||||
char *padding = (char *)calloc(paddingSize, 1);
|
||||
// 8 max char name
|
||||
out->write(padding, paddingSize);
|
||||
free(padding);
|
||||
}
|
||||
|
||||
out->writeUint16LE(object->lookAtTextRef);
|
||||
out->writeUint16LE(object->beforeUseTextRef);
|
||||
out->writeUint16LE(object->afterUseTextRef);
|
||||
out->writeUint16LE(object->pickTextRef);
|
||||
out->writeUint16LE(object->useTextRef);
|
||||
|
||||
out->writeByte(object->speaking);
|
||||
out->writeByte(object->openable);
|
||||
out->writeByte(object->closeable);
|
||||
|
||||
out->write(object->used, 8);
|
||||
|
||||
out->writeByte(object->pickupable);
|
||||
|
||||
out->writeUint16LE(object->useWith);
|
||||
out->writeUint16LE(object->replaceWith);
|
||||
out->writeByte(object->depth);
|
||||
out->writeUint32LE(object->bitmapPointer);
|
||||
out->writeUint16LE(object->bitmapSize);
|
||||
out->writeUint16LE(object->rotatingObjectAnimation);
|
||||
out->writeUint16LE(object->rotatingObjectPalette);
|
||||
out->writeUint16LE(object->dropOverlayX);
|
||||
out->writeUint16LE(object->dropOverlayY);
|
||||
out->writeUint32LE(object->dropOverlay);
|
||||
out->writeUint16LE(object->dropOverlaySize);
|
||||
out->writeUint16LE(object->objectIconBitmap);
|
||||
|
||||
out->writeByte(object->xgrid1);
|
||||
out->writeByte(object->ygrid1);
|
||||
out->writeByte(object->xgrid2);
|
||||
out->writeByte(object->ygrid2);
|
||||
|
||||
out->write(object->walkAreasPatch, 100);
|
||||
out->write(object->mouseGridPatch, 100);
|
||||
}
|
||||
|
||||
void TotEngine::saveObject(ScreenObject *object, Common::SeekableWriteStream *out) {
|
||||
_sceneObjectsData->seek(object->code * kItemRegSize, SEEK_SET);
|
||||
saveObjectsData(object, out);
|
||||
}
|
||||
|
||||
DoorRegistry readDoorMetadata(Common::SeekableReadStream *in) {
|
||||
DoorRegistry doorMetadata;
|
||||
doorMetadata.nextScene = in->readUint16LE();
|
||||
doorMetadata.exitPosX = in->readUint16LE();
|
||||
doorMetadata.exitPosY = in->readUint16LE();
|
||||
doorMetadata.openclosed = in->readByte();
|
||||
doorMetadata.doorcode = in->readByte();
|
||||
|
||||
return doorMetadata;
|
||||
}
|
||||
|
||||
Common::Point readPoint(Common::SeekableReadStream *in) {
|
||||
Common::Point point;
|
||||
point.x = in->readUint16LE();
|
||||
point.y = in->readUint16LE();
|
||||
return point;
|
||||
}
|
||||
|
||||
RoomBitmapRegister readAuxBitmaps(Common::SeekableReadStream *in) {
|
||||
RoomBitmapRegister bitmapMetadata = RoomBitmapRegister();
|
||||
bitmapMetadata.bitmapPointer = in->readSint32LE();
|
||||
bitmapMetadata.bitmapSize = in->readUint16LE();
|
||||
bitmapMetadata.coordx = in->readUint16LE();
|
||||
bitmapMetadata.coordy = in->readUint16LE();
|
||||
bitmapMetadata.depth = in->readUint16LE();
|
||||
return bitmapMetadata;
|
||||
}
|
||||
|
||||
RoomObjectListEntry *readRoomObjects(Common::SeekableReadStream *in) {
|
||||
RoomObjectListEntry *objectMetadata = new RoomObjectListEntry();
|
||||
objectMetadata->fileIndex = in->readUint16LE();
|
||||
objectMetadata->objectName = in->readPascalString();
|
||||
|
||||
in->skip(20 - objectMetadata->objectName.size());
|
||||
|
||||
return objectMetadata;
|
||||
}
|
||||
|
||||
RoomFileRegister *TotEngine::readScreenDataFile(Common::SeekableReadStream *in) {
|
||||
RoomFileRegister *screenData = new RoomFileRegister();
|
||||
screenData->code = in->readUint16LE();
|
||||
screenData->roomImagePointer = in->readUint32LE();
|
||||
screenData->roomImageSize = in->readUint16LE();
|
||||
in->read(screenData->walkAreasGrid, 40 * 28);
|
||||
in->read(screenData->mouseGrid, 40 * 28);
|
||||
for (int i = 0; i < 9; i++) {
|
||||
for (int j = 0; j < 30; j++) {
|
||||
for (int k = 0; k < 5; k++) {
|
||||
screenData->trajectories[i][j][k] = readPoint(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
screenData->doors[i] = readDoorMetadata(in);
|
||||
}
|
||||
for (int i = 0; i < 15; i++) {
|
||||
screenData->screenLayers[i] = readAuxBitmaps(in);
|
||||
}
|
||||
for (int i = 0; i < 51; i++) {
|
||||
screenData->screenObjectIndex[i] = readRoomObjects(in);
|
||||
}
|
||||
|
||||
screenData->animationFlag = in->readByte();
|
||||
screenData->animationName = in->readPascalString();
|
||||
in->skip(8 - screenData->animationName.size());
|
||||
screenData->paletteAnimationFlag = in->readByte();
|
||||
screenData->palettePointer = in->readUint16LE();
|
||||
for (int i = 0; i < 300; i++) {
|
||||
screenData->secondaryAnimTrajectory[i] = readPoint(in);
|
||||
}
|
||||
in->read(screenData->secondaryAnimDirections, 600);
|
||||
screenData->secondaryTrajectoryLength = in->readUint16LE();
|
||||
return screenData;
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
815
engines/tot/saveload.cpp
Normal file
815
engines/tot/saveload.cpp
Normal file
@@ -0,0 +1,815 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "common/hashmap.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/translation.h"
|
||||
#include "graphics/thumbnail.h"
|
||||
#include "gui/message.h"
|
||||
|
||||
#include "tot/forest.h"
|
||||
#include "tot/tot.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
#define SAVEGAME_CURRENT_VERSION 1
|
||||
|
||||
bool syncGeneralData(Common::Serializer &s, SavedGame *game) {
|
||||
// Uint16
|
||||
s.syncAsUint16LE(game->roomCode);
|
||||
s.syncAsUint16LE(game->trajectoryLength);
|
||||
s.syncAsUint16LE(game->currentTrajectoryIndex);
|
||||
s.syncAsUint16LE(game->backpackObjectCode);
|
||||
s.syncAsUint16LE(game->rightSfxVol);
|
||||
s.syncAsUint16LE(game->leftSfxVol);
|
||||
s.syncAsUint16LE(game->musicVolRight);
|
||||
s.syncAsUint16LE(game->musicVolLeft);
|
||||
s.syncAsUint16LE(game->oldGridX);
|
||||
s.syncAsUint16LE(game->oldGridY);
|
||||
s.syncAsUint16LE(game->secAnimDepth);
|
||||
s.syncAsUint16LE(game->secAnimDir);
|
||||
s.syncAsUint16LE(game->secAnimX);
|
||||
s.syncAsUint16LE(game->secAnimY);
|
||||
s.syncAsUint16LE(game->secAnimIFrame);
|
||||
// Bytes
|
||||
s.syncAsByte(game->currentZone);
|
||||
s.syncAsByte(game->targetZone);
|
||||
s.syncAsByte(game->oldTargetZone);
|
||||
s.syncAsByte(game->inventoryPosition);
|
||||
s.syncAsByte(game->actionCode);
|
||||
s.syncAsByte(game->oldActionCode);
|
||||
s.syncAsByte(game->steps);
|
||||
s.syncAsByte(game->doorIndex);
|
||||
s.syncAsByte(game->characterFacingDir);
|
||||
s.syncAsByte(game->iframe);
|
||||
s.syncAsByte(game->gamePart);
|
||||
|
||||
// Booleans
|
||||
s.syncAsByte(game->isSealRemoved);
|
||||
s.syncAsByte(game->obtainedList1);
|
||||
s.syncAsByte(game->obtainedList2);
|
||||
s.syncAsByte(game->list1Complete);
|
||||
s.syncAsByte(game->list2Complete);
|
||||
s.syncAsByte(game->isVasePlaced);
|
||||
s.syncAsByte(game->isScytheTaken);
|
||||
s.syncAsByte(game->isTridentTaken);
|
||||
s.syncAsByte(game->isPottersWheelDelivered);
|
||||
s.syncAsByte(game->isMudDelivered);
|
||||
s.syncAsByte(game->isGreenDevilDelivered);
|
||||
s.syncAsByte(game->isRedDevilCaptured);
|
||||
s.syncAsByte(game->isPottersManualDelivered);
|
||||
s.syncAsByte(game->isCupboardOpen);
|
||||
s.syncAsByte(game->isChestOpen);
|
||||
s.syncAsByte(game->isTVOn);
|
||||
s.syncAsByte(game->isTrapSet);
|
||||
|
||||
for (int i = 0; i < kInventoryIconCount; i++) {
|
||||
s.syncAsUint16LE(game->mobj[i].bitmapIndex);
|
||||
s.syncAsUint16LE(game->mobj[i].code);
|
||||
s.syncString(game->mobj[i].objectName);
|
||||
}
|
||||
|
||||
// integers
|
||||
s.syncAsSint32LE(game->element1);
|
||||
s.syncAsSint32LE(game->element2);
|
||||
s.syncAsSint32LE(game->characterPosX);
|
||||
s.syncAsSint32LE(game->characterPosY);
|
||||
s.syncAsSint32LE(game->xframe2);
|
||||
s.syncAsSint32LE(game->yframe2);
|
||||
|
||||
// Strings
|
||||
s.syncString(game->oldInventoryObjectName);
|
||||
s.syncString(game->objetomoinventoryObjectNamehila);
|
||||
s.syncString(game->characterName);
|
||||
|
||||
for (int i = 0; i < kRoutePointCount; i++) {
|
||||
s.syncAsSint16LE(game->mainRoute[i].x);
|
||||
s.syncAsSint16LE(game->mainRoute[i].y);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 300; i++) {
|
||||
s.syncAsSint16LE(game->trajectory[i].x);
|
||||
s.syncAsSint16LE(game->trajectory[i].y);
|
||||
}
|
||||
|
||||
for (int indiaux = 0; indiaux < kCharacterCount; indiaux++) {
|
||||
// interleave them just to avoid creating many loops
|
||||
s.syncAsByte(game->firstTimeTopicA[indiaux]);
|
||||
s.syncAsByte(game->firstTimeTopicB[indiaux]);
|
||||
s.syncAsByte(game->firstTimeTopicC[indiaux]);
|
||||
s.syncAsByte(game->bookTopic[indiaux]);
|
||||
s.syncAsByte(game->mintTopic[indiaux]);
|
||||
}
|
||||
|
||||
for (int indiaux = 0; indiaux < 5; indiaux++) {
|
||||
s.syncAsByte(game->caves[indiaux]);
|
||||
s.syncAsUint16LE(game->firstList[indiaux]);
|
||||
s.syncAsUint16LE(game->secondList[indiaux]);
|
||||
}
|
||||
|
||||
for (int indiaux = 0; indiaux < 4; indiaux++) {
|
||||
s.syncAsUint16LE(game->niche[0][indiaux]);
|
||||
s.syncAsUint16LE(game->niche[1][indiaux]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool syncRoomData(Common::Serializer &s, Common::MemorySeekableReadWriteStream *roomStream) {
|
||||
if (s.isSaving()) {
|
||||
|
||||
// Restore trajectory
|
||||
g_engine->setRoomTrajectories(g_engine->_secondaryAnimHeight, g_engine->_secondaryAnimWidth, RESTORE);
|
||||
// Make sure to save any unsaved changes in the room
|
||||
g_engine->saveRoomData(g_engine->_currentRoomData, g_engine->_rooms);
|
||||
|
||||
// Do not fix screen grids, they will be fixed differently below
|
||||
g_engine->setRoomTrajectories(g_engine->_secondaryAnimHeight, g_engine->_secondaryAnimWidth, SET_WITH_ANIM);
|
||||
|
||||
int size = roomStream->size();
|
||||
byte *roomBuf = (byte *)malloc(size);
|
||||
roomStream->seek(0, 0);
|
||||
roomStream->read(roomBuf, size);
|
||||
s.syncBytes(roomBuf, size);
|
||||
free(roomBuf);
|
||||
}
|
||||
if (s.isLoading()) {
|
||||
int size = g_engine->_rooms->size();
|
||||
delete (g_engine->_rooms);
|
||||
byte *roomBuf = (byte *)malloc(size);
|
||||
s.syncBytes(roomBuf, size);
|
||||
|
||||
g_engine->_rooms = new Common::MemorySeekableReadWriteStream(roomBuf, size, DisposeAfterUse::NO);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool syncConversationData(Common::Serializer &s, Common::MemorySeekableReadWriteStream *conversations) {
|
||||
|
||||
int size = conversations->size();
|
||||
if (s.isSaving()) {
|
||||
|
||||
byte *convBuf = (byte *)malloc(size);
|
||||
conversations->seek(0, 0);
|
||||
conversations->read(convBuf, size);
|
||||
s.syncBytes(convBuf, size);
|
||||
free(convBuf);
|
||||
}
|
||||
if (s.isLoading()) {
|
||||
delete (g_engine->_conversationData);
|
||||
byte *convBuf = (byte *)malloc(size);
|
||||
s.syncBytes(convBuf, size);
|
||||
g_engine->_conversationData = new Common::MemorySeekableReadWriteStream(convBuf, size, DisposeAfterUse::NO);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool syncItemData(Common::Serializer &s, Common::MemorySeekableReadWriteStream *sceneObjects) {
|
||||
int size = sceneObjects->size();
|
||||
if (s.isSaving()) {
|
||||
byte *objBuf = (byte *)malloc(size);
|
||||
sceneObjects->seek(0, 0);
|
||||
sceneObjects->read(objBuf, size);
|
||||
s.syncBytes(objBuf, size);
|
||||
free(objBuf);
|
||||
}
|
||||
if (s.isLoading()) {
|
||||
delete (g_engine->_sceneObjectsData);
|
||||
byte *objBuf = (byte *)malloc(size);
|
||||
s.syncBytes(objBuf, size);
|
||||
g_engine->_sceneObjectsData = new Common::MemorySeekableReadWriteStream(objBuf, size, DisposeAfterUse::NO);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Common::Error syncSaveData(Common::Serializer &ser, SavedGame *game) {
|
||||
if (!syncGeneralData(ser, game)) {
|
||||
warning("Error while synchronizing general data");
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
if (!syncRoomData(ser, g_engine->_rooms)) {
|
||||
warning("Error while synchronizing room data");
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
if (!syncItemData(ser, g_engine->_sceneObjectsData)) {
|
||||
warning("Error while syncrhonizing object data");
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
if (!syncConversationData(ser, g_engine->_conversationData)) {
|
||||
warning("Error while syncrhonizing conversation data");
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
if (ser.err()) {
|
||||
warning("Error while synchronizing");
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::Error TotEngine::syncGame(Common::Serializer &s) {
|
||||
Common::Error result;
|
||||
|
||||
if (s.isLoading()) {
|
||||
SavedGame *loadedGame = new SavedGame();
|
||||
// Means we are loading from before the game has started
|
||||
// if(rooms == nullptr) {
|
||||
_graphics->clear();
|
||||
displayLoading();
|
||||
|
||||
loadCharAnimation();
|
||||
loadInventory();
|
||||
|
||||
_graphics->loadPaletteFromFile("DEFAULT");
|
||||
initScreenPointers();
|
||||
|
||||
_graphics->totalFadeOut(0);
|
||||
_graphics->clear();
|
||||
initializeScreenFile();
|
||||
initializeObjectFile();
|
||||
readConversationFile();
|
||||
|
||||
result = syncSaveData(s, loadedGame);
|
||||
loadGame(loadedGame);
|
||||
} else {
|
||||
SavedGame *saveGame = saveGameToRegister();
|
||||
result = syncSaveData(s, saveGame);
|
||||
free(saveGame);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Common::Error TotEngine::saveGameStream(Common::WriteStream *stream, bool isAutosave) {
|
||||
const byte version = SAVEGAME_CURRENT_VERSION;
|
||||
Common::Serializer s(nullptr, stream);
|
||||
s.setVersion(version);
|
||||
stream->writeByte(version);
|
||||
|
||||
return syncGame(s);
|
||||
}
|
||||
Common::Error TotEngine::loadGameStream(Common::SeekableReadStream *stream) {
|
||||
byte version = stream->readByte();
|
||||
if (version > SAVEGAME_CURRENT_VERSION) {
|
||||
GUI::MessageDialog dialog(_("Saved game was created with a newer version of ScummVM. Unable to load."));
|
||||
dialog.runModal();
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
|
||||
Common::Serializer s(stream, nullptr);
|
||||
s.setVersion(version);
|
||||
|
||||
return syncGame(s);
|
||||
}
|
||||
|
||||
bool TotEngine::canLoadGameStateCurrently(Common::U32String *msg) {
|
||||
return true;
|
||||
}
|
||||
bool TotEngine::canSaveGameStateCurrently(Common::U32String *msg) {
|
||||
return _inGame && _saveAllowed;
|
||||
}
|
||||
|
||||
SavedGame *TotEngine::saveGameToRegister() {
|
||||
SavedGame *_savedGame = new SavedGame();
|
||||
_savedGame->roomCode = _currentRoomData->code;
|
||||
_savedGame->trajectoryLength = _trajectoryLength;
|
||||
_savedGame->currentTrajectoryIndex = _currentTrajectoryIndex;
|
||||
_savedGame->backpackObjectCode = _backpackObjectCode;
|
||||
_savedGame->rightSfxVol = _sound->_rightSfxVol;
|
||||
_savedGame->leftSfxVol = _sound->_leftSfxVol;
|
||||
_savedGame->musicVolRight = _sound->_musicVolRight;
|
||||
_savedGame->musicVolLeft = _sound->_musicVolLeft;
|
||||
_savedGame->oldGridX = _oldGridX;
|
||||
_savedGame->oldGridY = _oldGridY;
|
||||
_savedGame->secAnimDepth = _secondaryAnimation.depth;
|
||||
_savedGame->secAnimDir = _secondaryAnimation.dir;
|
||||
_savedGame->secAnimX = _secondaryAnimation.posx;
|
||||
_savedGame->secAnimY = _secondaryAnimation.posy;
|
||||
_savedGame->secAnimIFrame = _iframe2;
|
||||
|
||||
_savedGame->currentZone = _currentZone;
|
||||
_savedGame->targetZone = _targetZone;
|
||||
_savedGame->oldTargetZone = _oldTargetZone;
|
||||
_savedGame->inventoryPosition = _inventoryPosition;
|
||||
_savedGame->actionCode = _actionCode;
|
||||
_savedGame->oldActionCode = _oldActionCode;
|
||||
_savedGame->steps = _trajectorySteps;
|
||||
_savedGame->doorIndex = _doorIndex;
|
||||
_savedGame->characterFacingDir = _charFacingDirection;
|
||||
_savedGame->iframe = _iframe;
|
||||
_savedGame->gamePart = _gamePart;
|
||||
|
||||
_savedGame->isSealRemoved = _isSealRemoved;
|
||||
_savedGame->obtainedList1 = _obtainedList1;
|
||||
_savedGame->obtainedList2 = _obtainedList2;
|
||||
_savedGame->list1Complete = _list1Complete;
|
||||
_savedGame->list2Complete = _list2Complete;
|
||||
_savedGame->isVasePlaced = _isVasePlaced;
|
||||
_savedGame->isScytheTaken = _isScytheTaken;
|
||||
_savedGame->isTridentTaken = _isTridentTaken;
|
||||
_savedGame->isPottersWheelDelivered = _isPottersWheelDelivered;
|
||||
_savedGame->isMudDelivered = _isMudDelivered;
|
||||
_savedGame->isGreenDevilDelivered = _isGreenDevilDelivered;
|
||||
_savedGame->isRedDevilCaptured = _isRedDevilCaptured;
|
||||
_savedGame->isPottersManualDelivered = _isPottersManualDelivered;
|
||||
_savedGame->isCupboardOpen = _isCupboardOpen;
|
||||
_savedGame->isChestOpen = _isChestOpen;
|
||||
_savedGame->isTVOn = _isTVOn;
|
||||
_savedGame->isTrapSet = _isTrapSet;
|
||||
|
||||
for (int i = 0; i < kInventoryIconCount; i++) {
|
||||
_savedGame->mobj[i].bitmapIndex = _inventory[i].bitmapIndex;
|
||||
_savedGame->mobj[i].code = _inventory[i].code;
|
||||
_savedGame->mobj[i].objectName = _inventory[i].objectName;
|
||||
}
|
||||
|
||||
_savedGame->element1 = _element1;
|
||||
_savedGame->element2 = _element2;
|
||||
_savedGame->characterPosX = _characterPosX;
|
||||
_savedGame->characterPosY = _characterPosY;
|
||||
_savedGame->xframe2 = _xframe2;
|
||||
_savedGame->yframe2 = _yframe2;
|
||||
|
||||
_savedGame->oldInventoryObjectName = _oldInventoryObjectName;
|
||||
_savedGame->objetomoinventoryObjectNamehila = _inventoryObjectName;
|
||||
_savedGame->characterName = _characterName;
|
||||
|
||||
for (int i = 0; i < kRoutePointCount; i++) {
|
||||
_savedGame->mainRoute[i].x = _mainRoute[i].x;
|
||||
_savedGame->mainRoute[i].y = _mainRoute[i].y;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 300; i++) {
|
||||
_savedGame->trajectory[i].x = _trajectory[i].x;
|
||||
_savedGame->trajectory[i].y = _trajectory[i].y;
|
||||
}
|
||||
|
||||
for (int i = 0; i < kCharacterCount; i++) {
|
||||
_savedGame->firstTimeTopicA[i] = _firstTimeTopicA[i];
|
||||
_savedGame->firstTimeTopicB[i] = _firstTimeTopicB[i];
|
||||
_savedGame->firstTimeTopicC[i] = _firstTimeTopicC[i];
|
||||
_savedGame->bookTopic[i] = _bookTopic[i];
|
||||
_savedGame->mintTopic[i] = _mintTopic[i];
|
||||
}
|
||||
for (int i = 0; i < 5; i++) {
|
||||
_savedGame->caves[i] = _caves[i];
|
||||
_savedGame->firstList[i] = _firstList[i];
|
||||
_savedGame->secondList[i] = _secondList[i];
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_savedGame->niche[0][i] = _niche[0][i];
|
||||
_savedGame->niche[1][i] = _niche[1][i];
|
||||
}
|
||||
return _savedGame;
|
||||
}
|
||||
|
||||
void TotEngine::loadGame(SavedGame *game) {
|
||||
clearAnimation();
|
||||
clearScreenLayers();
|
||||
|
||||
_trajectoryLength = game->trajectoryLength;
|
||||
_currentTrajectoryIndex = game->currentTrajectoryIndex;
|
||||
_backpackObjectCode = game->backpackObjectCode;
|
||||
_sound->_rightSfxVol = game->rightSfxVol;
|
||||
_sound->_leftSfxVol = game->leftSfxVol;
|
||||
_sound->_musicVolRight = game->musicVolRight;
|
||||
_sound->_musicVolLeft = game->musicVolLeft;
|
||||
_oldGridX = game->oldGridX;
|
||||
_oldGridY = game->oldGridY;
|
||||
_secondaryAnimation.depth = game->secAnimDepth;
|
||||
_secondaryAnimation.dir = game->secAnimDir;
|
||||
_secondaryAnimation.posx = game->secAnimX;
|
||||
_secondaryAnimation.posy = game->secAnimY;
|
||||
_iframe2 = game->secAnimIFrame;
|
||||
_currentZone = game->currentZone;
|
||||
_targetZone = game->targetZone;
|
||||
_oldTargetZone = game->oldTargetZone;
|
||||
_inventoryPosition = game->inventoryPosition;
|
||||
_actionCode = game->actionCode;
|
||||
_oldActionCode = game->oldActionCode;
|
||||
_trajectorySteps = game->steps;
|
||||
_doorIndex = game->doorIndex;
|
||||
_charFacingDirection = game->characterFacingDir;
|
||||
_iframe = game->iframe;
|
||||
if (game->gamePart != _gamePart) {
|
||||
_gamePart = game->gamePart;
|
||||
for (int i = 0; i < kInventoryIconCount; i++) {
|
||||
free(_inventoryIconBitmaps[i]);
|
||||
}
|
||||
loadInventory();
|
||||
}
|
||||
_isSealRemoved = game->isSealRemoved;
|
||||
_obtainedList1 = game->obtainedList1;
|
||||
_obtainedList2 = game->obtainedList2;
|
||||
_list1Complete = game->list1Complete;
|
||||
_list2Complete = game->list2Complete;
|
||||
_isVasePlaced = game->isVasePlaced;
|
||||
_isScytheTaken = game->isScytheTaken;
|
||||
if (_cpCounter > 24)
|
||||
showError(274);
|
||||
_isTridentTaken = game->isTridentTaken;
|
||||
_isPottersWheelDelivered = game->isPottersWheelDelivered;
|
||||
_isMudDelivered = game->isMudDelivered;
|
||||
_isGreenDevilDelivered = game->isGreenDevilDelivered;
|
||||
_isRedDevilCaptured = game->isRedDevilCaptured;
|
||||
_isPottersManualDelivered = game->isPottersManualDelivered;
|
||||
_isCupboardOpen = game->isCupboardOpen;
|
||||
_isChestOpen = game->isChestOpen;
|
||||
_isTVOn = game->isTVOn;
|
||||
_isTrapSet = game->isTrapSet;
|
||||
for (int i = 0; i < kInventoryIconCount; i++) {
|
||||
_inventory[i].bitmapIndex = game->mobj[i].bitmapIndex;
|
||||
_inventory[i].code = game->mobj[i].code;
|
||||
_inventory[i].objectName = game->mobj[i].objectName;
|
||||
}
|
||||
_element1 = game->element1;
|
||||
_element2 = game->element2;
|
||||
_characterPosX = game->characterPosX;
|
||||
_characterPosY = game->characterPosY;
|
||||
_xframe2 = game->xframe2;
|
||||
_yframe2 = game->yframe2;
|
||||
_oldInventoryObjectName = game->oldInventoryObjectName;
|
||||
_inventoryObjectName = game->objetomoinventoryObjectNamehila;
|
||||
_characterName = game->characterName;
|
||||
for (int i = 0; i < kRoutePointCount; i++) {
|
||||
_mainRoute[i].x = game->mainRoute[i].x;
|
||||
_mainRoute[i].y = game->mainRoute[i].y;
|
||||
}
|
||||
for (int indiaux = 0; indiaux < 300; indiaux++) {
|
||||
_trajectory[indiaux].x = game->trajectory[indiaux].x;
|
||||
_trajectory[indiaux].y = game->trajectory[indiaux].y;
|
||||
}
|
||||
for (int i = 0; i < kCharacterCount; i++) {
|
||||
_firstTimeTopicA[i] = game->firstTimeTopicA[i];
|
||||
_firstTimeTopicB[i] = game->firstTimeTopicB[i];
|
||||
_firstTimeTopicC[i] = game->firstTimeTopicC[i];
|
||||
_bookTopic[i] = game->bookTopic[i];
|
||||
_mintTopic[i] = game->mintTopic[i];
|
||||
}
|
||||
for (int i = 0; i < 5; i++) {
|
||||
_caves[i] = game->caves[i];
|
||||
_firstList[i] = game->firstList[i];
|
||||
_secondList[i] = game->secondList[i];
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_niche[0][i] = game->niche[0][i];
|
||||
_niche[1][i] = game->niche[1][i];
|
||||
}
|
||||
|
||||
_graphics->totalFadeOut(0);
|
||||
_screen->clear();
|
||||
_graphics->loadPaletteFromFile("DEFAULT");
|
||||
loadScreenData(game->roomCode);
|
||||
|
||||
switch (_currentRoomData->code) {
|
||||
case 2: {
|
||||
if (_isTVOn)
|
||||
_sound->autoPlayVoc("PARASITO", 355778, 20129);
|
||||
else
|
||||
loadTV();
|
||||
_sound->setSfxVolume(_sound->_leftSfxVol, _sound->_rightSfxVol);
|
||||
} break;
|
||||
case 4: {
|
||||
_sound->loadVoc("GOTA", 140972, 1029);
|
||||
_sound->setSfxVolume(_sound->_leftSfxVol, _sound->_rightSfxVol);
|
||||
} break;
|
||||
case 5: {
|
||||
_sound->setSfxVolume(_sound->_leftSfxVol, 0);
|
||||
_sound->autoPlayVoc("CALDERA", 6433, 15386);
|
||||
} break;
|
||||
case 6: {
|
||||
_sound->setSfxVolume(_sound->_leftSfxVol, _sound->_rightSfxVol);
|
||||
_sound->autoPlayVoc("CALDERA", 6433, 15386);
|
||||
} break;
|
||||
case 17: {
|
||||
if (_bookTopic[0] == true && _currentRoomData->animationFlag)
|
||||
disableSecondAnimation();
|
||||
} break;
|
||||
case 20: {
|
||||
switch (_niche[0][_niche[0][3]]) {
|
||||
case 0:
|
||||
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(4);
|
||||
break;
|
||||
case 561:
|
||||
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(5);
|
||||
break;
|
||||
case 563:
|
||||
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(6);
|
||||
break;
|
||||
case 615:
|
||||
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(7);
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
case 23: {
|
||||
_sound->autoPlayVoc("Fuente", 0, 0);
|
||||
_sound->setSfxVolume(_sound->_leftSfxVol, _sound->_rightSfxVol);
|
||||
} break;
|
||||
case 24: {
|
||||
switch (_niche[1][_niche[1][3]]) {
|
||||
case 0:
|
||||
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(4);
|
||||
break;
|
||||
case 561:
|
||||
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(5);
|
||||
break;
|
||||
case 615:
|
||||
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(7);
|
||||
break;
|
||||
case 622:
|
||||
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(8);
|
||||
break;
|
||||
case 623:
|
||||
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(9);
|
||||
break;
|
||||
}
|
||||
if (_isTrapSet) {
|
||||
_currentRoomData->animationFlag = true;
|
||||
loadAnimation(_currentRoomData->animationName);
|
||||
_iframe2 = 0;
|
||||
_currentSecondaryTrajectoryIndex = 1;
|
||||
_currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x = 214 - 15;
|
||||
_currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y = 115 - 42;
|
||||
_secondaryAnimation.dir = _currentRoomData->secondaryAnimDirections[_currentSecondaryTrajectoryIndex - 1];
|
||||
_secondaryAnimation.posx = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x;
|
||||
_secondaryAnimation.posy = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y;
|
||||
_secondaryAnimation.depth = 14;
|
||||
|
||||
for (int i = 0; i < _maxXGrid; i++)
|
||||
for (int j = 0; j < _maxYGrid; j++) {
|
||||
if (_maskGridSecondaryAnim[i][j] > 0)
|
||||
_currentRoomData->walkAreasGrid[_oldposx + i][_oldposy + j] = _maskGridSecondaryAnim[i][j];
|
||||
if (_maskMouseSecondaryAnim[i][j] > 0)
|
||||
_currentRoomData->mouseGrid[_oldposx + i][_oldposy + j] = _maskMouseSecondaryAnim[i][j];
|
||||
}
|
||||
}
|
||||
assembleScreen();
|
||||
} break;
|
||||
}
|
||||
|
||||
drawInventoryMask();
|
||||
_inventoryPosition = 0;
|
||||
drawInventory();
|
||||
if (_isRedDevilCaptured == false && _currentRoomData->code == 24 && _isTrapSet == false)
|
||||
runaroundRed();
|
||||
_graphics->sceneTransition(false, _sceneBackground);
|
||||
|
||||
_saveAllowed = true;
|
||||
}
|
||||
|
||||
const int kMaxSaveSlots = 100;
|
||||
|
||||
Common::String drawAndSelectSaves(int pageNumber, const Common::HashMap<int, SaveStateDescriptor> &saveMap, uint selectedSlot) {
|
||||
g_engine->_mouse->hide();
|
||||
const char *availableText = getHardcodedTextsByCurrentLanguage()[11];
|
||||
ExtendedSavegameHeader header;
|
||||
int selectedGame = selectedSlot + pageNumber * 6;
|
||||
Common::String selectedGameDesc = "";
|
||||
for (uint i = 0; i < 6; i++) {
|
||||
int saveSlot = i + pageNumber * 6;
|
||||
int color = saveSlot == selectedGame ? 255 : 253;
|
||||
bar(60, 31 + (i * 15), 259, 39 + (i * 15), 251);
|
||||
if (saveSlot >= kMaxSaveSlots) {
|
||||
continue;
|
||||
;
|
||||
}
|
||||
Common::String desc = "";
|
||||
if (saveMap.contains(saveSlot)) {
|
||||
desc = saveMap[saveSlot].getDescription();
|
||||
if (saveSlot == selectedGame) {
|
||||
selectedGameDesc = saveMap[saveSlot].getDescription();
|
||||
}
|
||||
}
|
||||
if (desc.empty() == false) {
|
||||
euroText(65, 29 + (i * 15), desc, color);
|
||||
} else {
|
||||
euroText(65, 29 + (i * 15), Common::String::format(availableText, saveSlot), color);
|
||||
}
|
||||
}
|
||||
|
||||
g_engine->_mouse->show();
|
||||
return selectedGameDesc;
|
||||
}
|
||||
|
||||
void TotEngine::originalSaveLoadScreen() {
|
||||
uint oldMouseX, oldMouseY;
|
||||
int selectedSlot = 1;
|
||||
bool modified = false;
|
||||
Common::String saveName = "";
|
||||
|
||||
bool exitSaveLoadMenu = false;
|
||||
oldMouseX = _mouse->mouseX;
|
||||
oldMouseY = _mouse->mouseY;
|
||||
_mouse->hide();
|
||||
|
||||
uint menuBgSize = imagesize(20, 10, 300, 120);
|
||||
byte *menuBgPointer = (byte *)malloc(menuBgSize);
|
||||
_graphics->getImg(20, 10, 300, 120, menuBgPointer);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
uint textY = i + 1;
|
||||
buttonBorder((120 - (textY * 10)), (80 - (textY * 10)), (200 + (textY * 10)), (60 + (textY * 10)), 251, 251, 251, 251, 0);
|
||||
}
|
||||
drawMenu(2); // 220 x 110 at xmenu = 50;ymenu = 10;
|
||||
// 50, 10, 270, 120
|
||||
// Arrows are 20, 18
|
||||
drawLeftArrow(20, 65);
|
||||
line(20, 65, 39, 65, 255);
|
||||
line(20, 65, 20, 80, 255);
|
||||
line(40, 66, 40, 82, 249);
|
||||
line(40, 82, 21, 82, 249);
|
||||
drawRightArrow(280, 65);
|
||||
line(280, 65, 299, 65, 255);
|
||||
line(280, 65, 280, 80, 255);
|
||||
line(300, 66, 300, 82, 249);
|
||||
line(300, 82, 292, 82, 249);
|
||||
|
||||
if (!_saveAllowed) {
|
||||
bar(61, 15, 122, 23, 253);
|
||||
bar(201, 15, 259, 23, 253);
|
||||
}
|
||||
|
||||
int pageNumber = 0;
|
||||
SaveStateList listSaves = getMetaEngine()->listSaves(_targetName.c_str());
|
||||
|
||||
Common::HashMap<int, SaveStateDescriptor> saveMap;
|
||||
|
||||
// Iterate and populate
|
||||
for (const SaveStateDescriptor &desc : listSaves) {
|
||||
int slot = desc.getSaveSlot();
|
||||
saveMap[slot] = desc;
|
||||
}
|
||||
|
||||
saveName = drawAndSelectSaves(pageNumber, saveMap, selectedSlot);
|
||||
|
||||
if (_cpCounter2 > 17)
|
||||
showError(274);
|
||||
_mouse->mouseX = 150;
|
||||
_mouse->mouseY = 60;
|
||||
_mouse->mouseMaskIndex = 1;
|
||||
_mouse->setMouseArea(Common::Rect(13, 13, 293, 105));
|
||||
_mouse->warpMouse(1, 150, 60);
|
||||
|
||||
do {
|
||||
bool mouseClicked = false;
|
||||
bool keyPressed = false;
|
||||
Common::Event lastKeyboardEvent = Common::Event();
|
||||
do {
|
||||
_chrono->updateChrono();
|
||||
if (_chrono->_gameTick) {
|
||||
_mouse->animateMouseIfNeeded();
|
||||
}
|
||||
_events->pollEvent();
|
||||
if (_events->_leftMouseButton || _events->_rightMouseButton) {
|
||||
mouseClicked = true;
|
||||
} else if (_events->_keyPressed) {
|
||||
keyPressed = true;
|
||||
lastKeyboardEvent = _events->_lastKeyEvent;
|
||||
}
|
||||
|
||||
_screen->update();
|
||||
g_system->delayMillis(10);
|
||||
} while (!keyPressed && !mouseClicked && !shouldQuit());
|
||||
|
||||
if (mouseClicked) {
|
||||
if (_mouse->mouseX > 13 && _mouse->mouseX < 33 && _mouse->mouseY >= 58 && _mouse->mouseY <= 73) { // Left arrow
|
||||
|
||||
if (pageNumber > 0)
|
||||
pageNumber--;
|
||||
else
|
||||
_sound->beep(100, 300);
|
||||
saveName = drawAndSelectSaves(pageNumber, saveMap, selectedSlot);
|
||||
} else if (_mouse->mouseX > 273 && _mouse->mouseX < 293 && _mouse->mouseY >= 58 && _mouse->mouseY <= 73) { // Right arrow
|
||||
|
||||
if (pageNumber < kMaxSaveSlots / 6)
|
||||
pageNumber++;
|
||||
else
|
||||
_sound->beep(100, 300);
|
||||
saveName = drawAndSelectSaves(pageNumber, saveMap, selectedSlot);
|
||||
} else if (_mouse->mouseY >= 13 && _mouse->mouseY <= 16) {
|
||||
if (_mouse->mouseX >= 54 && _mouse->mouseX <= 124) { // Save
|
||||
if (selectedSlot > 0 && _saveAllowed && saveName != "") {
|
||||
saveGameState(selectedSlot + pageNumber * 6, saveName, false);
|
||||
_graphics->putImg(20, 10, menuBgPointer);
|
||||
exitSaveLoadMenu = true;
|
||||
selectedSlot = -1;
|
||||
} else {
|
||||
_sound->beep(100, 300);
|
||||
}
|
||||
} else if (_mouse->mouseX >= 130 && _mouse->mouseX <= 194) {
|
||||
if (selectedSlot >= 0 && !modified) { // Load
|
||||
if (selectedSlot < (int)listSaves.size()) {
|
||||
_mouse->hide();
|
||||
_graphics->putImg(20, 10, menuBgPointer);
|
||||
free(menuBgPointer);
|
||||
if (_saveAllowed) {
|
||||
clearAnimation();
|
||||
clearScreenLayers();
|
||||
}
|
||||
loadGameState(selectedSlot + pageNumber * 6);
|
||||
_mouse->mouseX = oldMouseX;
|
||||
_mouse->mouseY = oldMouseY;
|
||||
|
||||
_mouse->show();
|
||||
_mouse->setMouseArea(Common::Rect(0, 0, 305, 185));
|
||||
exitSaveLoadMenu = true;
|
||||
selectedSlot = -1;
|
||||
|
||||
return;
|
||||
} else {
|
||||
_sound->beep(100, 300);
|
||||
}
|
||||
} else {
|
||||
_sound->beep(100, 300);
|
||||
saveName = drawAndSelectSaves(pageNumber, saveMap, selectedSlot);
|
||||
_mouse->show();
|
||||
}
|
||||
} else if (_mouse->mouseClickX >= 200 && _mouse->mouseClickX <= 250) { // Exit
|
||||
if (_inGame && _saveAllowed) {
|
||||
_graphics->putImg(20, 10, menuBgPointer);
|
||||
exitSaveLoadMenu = true;
|
||||
selectedSlot = -1;
|
||||
} else {
|
||||
_sound->beep(100, 300);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_mouse->mouseClickY >= 24 && _mouse->mouseClickY <= 32) {
|
||||
if (0 + pageNumber * 6 >= kMaxSaveSlots) {
|
||||
_sound->beep(100, 300);
|
||||
} else {
|
||||
selectedSlot = 0;
|
||||
modified = false;
|
||||
}
|
||||
} else if (_mouse->mouseClickY >= 39 && _mouse->mouseClickY <= 47) {
|
||||
if (1 + pageNumber * 6 >= kMaxSaveSlots) {
|
||||
_sound->beep(100, 300);
|
||||
} else {
|
||||
selectedSlot = 1;
|
||||
modified = false;
|
||||
}
|
||||
} else if (_mouse->mouseClickY >= 54 && _mouse->mouseClickY <= 62) {
|
||||
if (2 + pageNumber * 6 >= kMaxSaveSlots) {
|
||||
_sound->beep(100, 300);
|
||||
} else {
|
||||
selectedSlot = 2;
|
||||
modified = false;
|
||||
}
|
||||
} else if (_mouse->mouseClickY >= 69 && _mouse->mouseClickY <= 77) {
|
||||
if (3 + pageNumber * 6 >= kMaxSaveSlots) {
|
||||
_sound->beep(100, 300);
|
||||
} else {
|
||||
selectedSlot = 3;
|
||||
modified = false;
|
||||
}
|
||||
} else if (_mouse->mouseClickY >= 84 && _mouse->mouseClickY <= 92) {
|
||||
if (4 + pageNumber * 6 >= kMaxSaveSlots) {
|
||||
_sound->beep(100, 300);
|
||||
} else {
|
||||
selectedSlot = 4;
|
||||
modified = false;
|
||||
}
|
||||
} else if (_mouse->mouseClickY >= 99 && _mouse->mouseClickY <= 107) {
|
||||
if (5 + pageNumber * 6 >= kMaxSaveSlots) {
|
||||
_sound->beep(100, 300);
|
||||
} else {
|
||||
selectedSlot = 5;
|
||||
modified = false;
|
||||
}
|
||||
}
|
||||
saveName = drawAndSelectSaves(pageNumber, saveMap, selectedSlot);
|
||||
}
|
||||
}
|
||||
|
||||
if (keyPressed && _saveAllowed) {
|
||||
_mouse->hide();
|
||||
byte ytext = 29 + (selectedSlot * 15);
|
||||
readAlphaGraphSmall(saveName, 30, 65, ytext, 251, 254, lastKeyboardEvent);
|
||||
modified = true;
|
||||
_mouse->show();
|
||||
keyPressed = false;
|
||||
}
|
||||
} while (!exitSaveLoadMenu && !shouldQuit());
|
||||
_mouse->mouseX = oldMouseX;
|
||||
_mouse->mouseY = oldMouseY;
|
||||
_mouse->warpMouse(_mouse->mouseMaskIndex, _mouse->mouseX, _mouse->mouseY);
|
||||
free(menuBgPointer);
|
||||
_mouse->setMouseArea(Common::Rect(0, 0, 305, 185));
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
211
engines/tot/sound.cpp
Normal file
211
engines/tot/sound.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "audio/decoders/voc.h"
|
||||
#include "audio/mixer.h"
|
||||
#include "audio/softsynth/pcspk.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "tot/sound.h"
|
||||
#include "tot/tot.h"
|
||||
#include "tot/util.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
SoundManager::SoundManager(Audio::Mixer *mixer) : _mixer(mixer) {
|
||||
_rightSfxVol = 6;
|
||||
_leftSfxVol = 6;
|
||||
_musicVolRight = 3;
|
||||
_musicVolLeft = 3;
|
||||
|
||||
_midiPlayer = new MidiPlayer();
|
||||
_speaker = new Audio::PCSpeaker();
|
||||
}
|
||||
|
||||
SoundManager::~SoundManager() {
|
||||
if (_midiPlayer)
|
||||
delete _midiPlayer;
|
||||
delete _lastSrcStream;
|
||||
delete _audioStream;
|
||||
delete _speaker;
|
||||
}
|
||||
|
||||
void SoundManager::init() {
|
||||
_rightSfxVol = 6;
|
||||
_leftSfxVol = 6;
|
||||
_musicVolRight = 3;
|
||||
_musicVolLeft = 3;
|
||||
|
||||
_speaker->init();
|
||||
_midiPlayer->open();
|
||||
|
||||
setMidiVolume(3, 3);
|
||||
//playMidi("SILENT", false);
|
||||
setSfxVolume(6, 6);
|
||||
}
|
||||
|
||||
void SoundManager::syncSoundSettings() {
|
||||
_midiPlayer->syncSoundSettings();
|
||||
}
|
||||
|
||||
void SoundManager::loadVoc(Common::String vocFile, int32 startPos, int16 size) {
|
||||
Common::File vocResource;
|
||||
if(_lastSrcStream) {
|
||||
delete _lastSrcStream;
|
||||
_lastSrcStream = nullptr;
|
||||
}
|
||||
if (size == 0) {
|
||||
if (!vocResource.open(Common::Path(vocFile + ".VOC"))) {
|
||||
showError(266);
|
||||
}
|
||||
|
||||
_lastSrcStream = vocResource.readStream((uint32)vocResource.size());
|
||||
|
||||
} else {
|
||||
if (!vocResource.open("EFECTOS.DAT")) {
|
||||
showError(266);
|
||||
}
|
||||
vocResource.seek(startPos);
|
||||
_lastSrcStream = vocResource.readStream((uint32)size);
|
||||
}
|
||||
if(_audioStream) {
|
||||
delete _audioStream;
|
||||
_audioStream = nullptr;
|
||||
}
|
||||
_audioStream = Audio::makeVOCStream(_lastSrcStream, Audio::FLAG_UNSIGNED, DisposeAfterUse::NO);
|
||||
}
|
||||
|
||||
void SoundManager::autoPlayVoc(Common::String vocFile, int32 startPos, int16 vocSize) {
|
||||
loadVoc(vocFile, startPos, vocSize);
|
||||
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, Audio::makeLoopingAudioStream(_audioStream, 0), kSfxId, 255U, 0, DisposeAfterUse::NO);
|
||||
}
|
||||
|
||||
void SoundManager::playVoc() {
|
||||
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _audioStream, kSfxId, 255U, 0, DisposeAfterUse::NO);
|
||||
_lastSrcStream->seek(0);
|
||||
_audioStream->rewind();
|
||||
}
|
||||
|
||||
void SoundManager::playVoc(Common::String vocFile, int32 startPos, uint vocSize) {
|
||||
stopVoc();
|
||||
loadVoc(vocFile, startPos, vocSize);
|
||||
playVoc();
|
||||
}
|
||||
|
||||
void SoundManager::stopVoc() {
|
||||
_mixer->stopHandle(_soundHandle);
|
||||
}
|
||||
|
||||
void SoundManager::waitForSoundEnd() {
|
||||
do {
|
||||
g_engine->_events->pollEvent();
|
||||
g_engine->_chrono->updateChrono();
|
||||
g_engine->_screen->update();
|
||||
g_system->delayMillis(10);
|
||||
} while (g_engine->_sound->isVocPlaying());
|
||||
}
|
||||
|
||||
bool SoundManager::isVocPlaying() {
|
||||
return _mixer->isSoundIDActive(kSfxId);
|
||||
}
|
||||
|
||||
void SoundManager::playMidi(Common::String fileName, bool loop) {
|
||||
Common::File musicFile;
|
||||
musicFile.open(Common::Path(fileName + ".MUS"));
|
||||
if (!musicFile.isOpen()) {
|
||||
showError(267);
|
||||
return;
|
||||
}
|
||||
byte *curMidi = (byte *)malloc(musicFile.size());
|
||||
musicFile.read(curMidi, musicFile.size());
|
||||
playMidi(curMidi, musicFile.size(), loop);
|
||||
musicFile.close();
|
||||
free(curMidi);
|
||||
}
|
||||
|
||||
void SoundManager::playMidi(byte *data, int size, bool loop) {
|
||||
Common::MemoryReadStream stream = Common::MemoryReadStream(data, size);
|
||||
_midiPlayer->load(&stream, size);
|
||||
_midiPlayer->setLoop(loop);
|
||||
_midiPlayer->play(0);
|
||||
}
|
||||
|
||||
void SoundManager::toggleMusic() {
|
||||
}
|
||||
|
||||
void SoundManager::beep(int32 frequency, int32 ms) {
|
||||
_speaker->stop();
|
||||
_speaker->play(Audio::PCSpeaker::kWaveFormSquare, frequency, ms);
|
||||
}
|
||||
|
||||
void SoundManager::setSfxVolume(byte voll, byte volr) {
|
||||
|
||||
if (voll == volr) {
|
||||
int volume = (voll) / (float)7 * 255;
|
||||
setSfxVolume(volume);
|
||||
setSfxBalance(true, true);
|
||||
} else {
|
||||
if (voll == 0) {
|
||||
setSfxBalance(false, true);
|
||||
} else {
|
||||
setSfxBalance(true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::setMidiVolume(byte voll, byte volr) {
|
||||
if (voll != _musicVolLeft || volr != _musicVolRight) {
|
||||
_musicVolLeft = voll;
|
||||
_musicVolRight = volr;
|
||||
setMusicVolume(voll == 0 ? 0 : 255);
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::fadeOutMusic() {
|
||||
_midiPlayer->startFadeOut();
|
||||
while (_midiPlayer->isFading()) {
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::fadeInMusic() {
|
||||
_midiPlayer->startFadeIn();
|
||||
while (_midiPlayer->isFading()) {
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::setMasterVolume(byte voll, byte volr) {
|
||||
}
|
||||
|
||||
void SoundManager::setSfxVolume(byte volume) {
|
||||
_mixer->setChannelVolume(_soundHandle, volume);
|
||||
}
|
||||
|
||||
void SoundManager::setSfxBalance(bool left, bool right) {
|
||||
int balance = left ? -127 : 127;
|
||||
_mixer->setChannelBalance(_soundHandle, balance);
|
||||
}
|
||||
|
||||
void SoundManager::setMusicVolume(byte volume) {
|
||||
_midiPlayer->setSourceVolume(volume);
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
78
engines/tot/sound.h
Normal file
78
engines/tot/sound.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef TOT_SOUND_H
|
||||
#define TOT_SOUND_H
|
||||
|
||||
#include "audio/decoders/raw.h"
|
||||
#include "audio/softsynth/pcspk.h"
|
||||
#include "audio/mixer.h"
|
||||
#include "common/file.h"
|
||||
|
||||
#include "tot/midi.h"
|
||||
|
||||
namespace Tot {
|
||||
const int kSfxId = 1;
|
||||
|
||||
class SoundManager {
|
||||
public:
|
||||
SoundManager(Audio::Mixer *mixer);
|
||||
~SoundManager();
|
||||
|
||||
void init();
|
||||
void syncSoundSettings();
|
||||
void loadVoc(Common::String vocFile, int32 startPos, int16 vocSize);
|
||||
void autoPlayVoc(Common::String vocFile, int32 startPos, int16 vocSize);
|
||||
void playVoc(Common::String vocFile, int32 startPos, uint vocSize);
|
||||
void playVoc();
|
||||
void stopVoc();
|
||||
bool isVocPlaying();
|
||||
void playMidi(Common::String fileName, bool loop);
|
||||
void playMidi(byte *data, int size, bool loop);
|
||||
void toggleMusic();
|
||||
void beep(int32 frequency, int32 ms);
|
||||
void waitForSoundEnd();
|
||||
// Set game logic volume levels
|
||||
void setSfxVolume(byte leftVol, byte rightVol);
|
||||
void setMidiVolume(byte leftVol, byte rightVol);
|
||||
void fadeOutMusic();
|
||||
void fadeInMusic();
|
||||
void setMasterVolume(byte leftVol, byte rightVol);
|
||||
void setSfxBalance(bool left, bool right);
|
||||
// Game logic volume settings
|
||||
uint _rightSfxVol, _leftSfxVol;
|
||||
uint _musicVolRight, _musicVolLeft;
|
||||
|
||||
private:
|
||||
// Apply game logic volume levels
|
||||
void setSfxVolume(byte volume);
|
||||
void setMusicVolume(byte volume);
|
||||
|
||||
Audio::SoundHandle _soundHandle;
|
||||
Audio::Mixer *_mixer;
|
||||
MidiPlayer *_midiPlayer;
|
||||
Audio::PCSpeaker *_speaker;
|
||||
|
||||
Common::SeekableReadStream *_lastSrcStream = nullptr;
|
||||
Audio::SeekableAudioStream *_audioStream = nullptr;
|
||||
};
|
||||
|
||||
} // End of namespace Tot
|
||||
#endif
|
||||
1298
engines/tot/statics.h
Normal file
1298
engines/tot/statics.h
Normal file
File diff suppressed because it is too large
Load Diff
1333
engines/tot/tot.cpp
Normal file
1333
engines/tot/tot.cpp
Normal file
File diff suppressed because it is too large
Load Diff
531
engines/tot/tot.h
Normal file
531
engines/tot/tot.h
Normal file
@@ -0,0 +1,531 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOT_H
|
||||
#define TOT_H
|
||||
|
||||
#include "common/error.h"
|
||||
#include "common/events.h"
|
||||
#include "common/fs.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/random.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/serializer.h"
|
||||
#include "common/system.h"
|
||||
#include "common/util.h"
|
||||
#include "engines/engine.h"
|
||||
#include "engines/savestate.h"
|
||||
#include "graphics/screen.h"
|
||||
|
||||
#include "tot/chrono.h"
|
||||
#include "tot/detection.h"
|
||||
#include "tot/events.h"
|
||||
#include "tot/graphics.h"
|
||||
#include "tot/mouse.h"
|
||||
#include "tot/sound.h"
|
||||
#include "tot/types.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
struct TotGameDescription;
|
||||
|
||||
enum TotAction {
|
||||
kActionEscape,
|
||||
kActionVolume,
|
||||
kActionSaveLoad,
|
||||
kActionTalk,
|
||||
kActionPickup,
|
||||
kActionLookAt,
|
||||
kActionUse,
|
||||
kActionOpen,
|
||||
kActionClose,
|
||||
kActionYes,
|
||||
kActionNo
|
||||
};
|
||||
|
||||
class TotEngine : public Engine {
|
||||
|
||||
private:
|
||||
Common::RandomSource _randomSource;
|
||||
|
||||
void handleEvent(Common::Event e);
|
||||
/**
|
||||
* Uses a serializer to allow implementing savegame
|
||||
* loading and saving using a single method
|
||||
*/
|
||||
Common::Error syncGame(Common::Serializer &s);
|
||||
|
||||
int engineStart();
|
||||
int startGame();
|
||||
void newGame();
|
||||
void resumeGame();
|
||||
|
||||
void changeRoom();
|
||||
void loadScrollData(uint roomCode, bool rightScroll, uint horizontalPos, int scrollCorrection);
|
||||
void drawText(uint number);
|
||||
void displayLoading();
|
||||
void runaroundRed();
|
||||
void sprites(bool drawCharacter);
|
||||
SavedGame *saveGameToRegister();
|
||||
void originalSaveLoadScreen();
|
||||
void loadGame(SavedGame *game);
|
||||
|
||||
RoomFileRegister *readScreenDataFile(Common::SeekableReadStream *screenDataFile);
|
||||
void lookAtObject(byte objectNumber);
|
||||
void useInventoryObjectWithInventoryObject(int16 obj1, int16 obj2);
|
||||
void pickupScreenObject();
|
||||
void useScreenObject();
|
||||
void openScreenObject();
|
||||
void closeScreenObject();
|
||||
void action();
|
||||
void handleAction(byte invPos);
|
||||
void loadInventory();
|
||||
void obtainName(Common::String &playerName);
|
||||
void calculateRoute(byte zone1, byte zone2, bool extraCorrection = false, bool zonavedada = false);
|
||||
void wcScene();
|
||||
void advanceAnimations(bool barredZone, bool animateMouse);
|
||||
void updateSecondaryAnimationDepth();
|
||||
void updateMainCharacterDepth();
|
||||
void actionLineText(const Common::String &actionLine);
|
||||
void initializeObjectFile();
|
||||
void saveObjectsData(ScreenObject *object, Common::SeekableWriteStream *out);
|
||||
void scrollLeft(uint horizontalPos);
|
||||
void scrollRight(uint horizontalPos);
|
||||
TextEntry readTextRegister(uint numRegister);
|
||||
|
||||
void readConversationFile();
|
||||
|
||||
void adjustKey();
|
||||
void adjustKey2();
|
||||
void animateBat();
|
||||
void updateVideo();
|
||||
void nicheAnimation(byte nicheDir, int32 bitmap);
|
||||
void replaceBackpack(byte obj1, uint obj2);
|
||||
void dropObjectInScreen(ScreenObject *replacementObject);
|
||||
void calculateTrajectory(uint finalX, uint finalY);
|
||||
void animatedSequence(uint numSequence);
|
||||
void initScreenPointers();
|
||||
|
||||
void loadAnimation(const Common::String &animation);
|
||||
void loadCharAnimation();
|
||||
void animateGive(uint dir, uint height);
|
||||
void animatePickup1(uint dir, uint height);
|
||||
void animatePickup2(uint dir, uint height);
|
||||
void animateOpen2(uint dir, uint height);
|
||||
|
||||
void loadTV();
|
||||
void loadScreen();
|
||||
void loadScreenLayerWithDepth(uint coordx, uint coordy, uint bitmapSize, int32 bitmapIndex, uint depth);
|
||||
void loadScreenLayer(uint coordx, uint coordy, uint picSize, int32 pic, uint prof);
|
||||
void readBitmap(int32 bitmapOffset, byte *bitmap, uint bitmapSize, uint errorCode);
|
||||
void updateAltScreen(byte altScreenNumber);
|
||||
|
||||
void freeInventory();
|
||||
void updateInventory(byte index);
|
||||
void updateObject(uint filePos);
|
||||
void readObject(Common::SeekableReadStream *stream, uint objPos, ScreenObject *thisRegObj);
|
||||
void saveObject(ScreenObject *object, Common::SeekableWriteStream *stream);
|
||||
void saveItemRegister();
|
||||
|
||||
void saveTemporaryGame();
|
||||
void drawLookAtItem(RoomObjectListEntry obj);
|
||||
void putIcon(uint posX, uint posY, uint iconNumber);
|
||||
void drawInventory(byte direction, byte limit);
|
||||
void generateDiploma(Common::String &photoName);
|
||||
void credits();
|
||||
void checkMouseGrid();
|
||||
void introduction();
|
||||
void firstIntroduction();
|
||||
void readAlphaGraph(Common::String &data, int length, int x, int y, byte barColor);
|
||||
void readAlphaGraphSmall(Common::String &data, int length, int x, int y, byte barColor, byte textColor, Common::Event startEvent);
|
||||
void displayObjectDescription(const Common::String &text);
|
||||
void copyProtection();
|
||||
void initialLogo();
|
||||
void mainMenu(bool fade);
|
||||
void exitToDOS();
|
||||
void soundControls();
|
||||
void sacrificeScene();
|
||||
void ending();
|
||||
void loadBat();
|
||||
void loadDevil();
|
||||
void assembleCompleteBackground(byte *image, uint coordx, uint coordy);
|
||||
void assembleScreen(bool scroll = false);
|
||||
void disableSecondAnimation();
|
||||
void clearGame();
|
||||
|
||||
// vars
|
||||
void initVars();
|
||||
void resetGameState();
|
||||
void clearVars();
|
||||
|
||||
void processEvents(bool &escapePressed);
|
||||
void oldProcessEvents(bool &escapePressed);
|
||||
protected:
|
||||
// Engine APIs
|
||||
Common::Error run() override;
|
||||
void syncSoundSettings() override;
|
||||
|
||||
public:
|
||||
Graphics::Screen *_screen = nullptr;
|
||||
GraphicsManager *_graphics = nullptr;
|
||||
SoundManager *_sound = nullptr;
|
||||
MouseManager *_mouse = nullptr;
|
||||
ChronoManager *_chrono = nullptr;
|
||||
Tot::TotEventManager *_events = nullptr;
|
||||
const ADGameDescription *_gameDescription;
|
||||
|
||||
bool _showMouseGrid = false;
|
||||
bool _showScreenGrid = false;
|
||||
bool _showGameGrid = false;
|
||||
bool _drawObjectAreas = false;
|
||||
|
||||
Common::Language _lang = Common::ES_ESP;
|
||||
|
||||
Common::MemorySeekableReadWriteStream *_conversationData = nullptr;
|
||||
Common::MemorySeekableReadWriteStream *_rooms = nullptr;
|
||||
Common::MemorySeekableReadWriteStream *_sceneObjectsData = nullptr;
|
||||
|
||||
bool _roomChange = false;
|
||||
bool _isTVOn = false;
|
||||
bool _isVasePlaced = false;
|
||||
bool _isScytheTaken = false;
|
||||
bool _isTridentTaken = false;
|
||||
bool _isPottersWheelDelivered = false;
|
||||
bool _isMudDelivered = false;
|
||||
bool _isGreenDevilDelivered = false;
|
||||
bool _isRedDevilCaptured = false;
|
||||
bool _isPottersManualDelivered = false;
|
||||
bool _isCupboardOpen = false;
|
||||
bool _isChestOpen = false;
|
||||
bool _isTrapSet = false;
|
||||
bool _isPeterCoughing = false;
|
||||
|
||||
bool _isSealRemoved = false;
|
||||
bool _inGame = false;
|
||||
bool _firstTimeDone = false; // Flag for first time run of the game.
|
||||
bool _isIntroSeen = false;
|
||||
bool _shouldQuitGame = false;
|
||||
bool _startNewGame = false; // Flag to initialize game
|
||||
bool _continueGame = false; // Flag to resume game
|
||||
bool _isSavingDisabled = false;
|
||||
bool _isDrawingEnabled = false; // true if sprites should be drawn
|
||||
bool _isSecondaryAnimationEnabled = false; // Whether room has secondary animation
|
||||
|
||||
InventoryEntry _inventory[kInventoryIconCount]; // These are the icons currnetly in the inventory
|
||||
/**
|
||||
* Keeps an array of all inventory icon bitmaps
|
||||
*/
|
||||
byte *_inventoryIconBitmaps[kInventoryIconCount] = { nullptr };
|
||||
/**
|
||||
* Position within inventory
|
||||
*/
|
||||
byte _inventoryPosition = 0;
|
||||
/**
|
||||
* Animation sequences
|
||||
*/
|
||||
CharacterAnim _mainCharAnimation;
|
||||
uint _mainCharFrameSize = 0;
|
||||
SecondaryAnim _secondaryAnimation;
|
||||
uint _secondaryAnimFrameSize = 0;
|
||||
/**
|
||||
* Currently selected action.
|
||||
*/
|
||||
byte _actionCode = 0;
|
||||
/**
|
||||
* Previously selected action.
|
||||
*/
|
||||
byte _oldActionCode = 0;
|
||||
/**
|
||||
* Number of trajectory changes
|
||||
*/
|
||||
byte _trajectorySteps = 0;
|
||||
/**
|
||||
* index of currently selected door.
|
||||
*/
|
||||
byte _doorIndex = 0;
|
||||
/**
|
||||
* 1 first part, 2 second part
|
||||
*/
|
||||
byte _gamePart = 1;
|
||||
/**
|
||||
* Number of frames of secondary animation
|
||||
*/
|
||||
byte _secondaryAnimationFrameCount = 0;
|
||||
/**
|
||||
* Number of directions of the secondary animation
|
||||
*/
|
||||
byte _secondaryAnimDirCount = 0;
|
||||
/**
|
||||
* Data protection control
|
||||
*/
|
||||
byte _cpCounter = 0, _cpCounter2 = 0;
|
||||
/**
|
||||
* Coordinates of target step
|
||||
*/
|
||||
byte _destinationX = 0, _destinationY = 0;
|
||||
/**
|
||||
* Current character facing direction
|
||||
* 0: upwards
|
||||
* 1: right
|
||||
* 2: downwards
|
||||
* 3: left
|
||||
*/
|
||||
byte _charFacingDirection = 0;
|
||||
|
||||
/**
|
||||
* Width and height of secondary animation
|
||||
*/
|
||||
uint _secondaryAnimWidth = 0, _secondaryAnimHeight = 0;
|
||||
/**
|
||||
* Code of selected object in the backpack
|
||||
*/
|
||||
uint _backpackObjectCode = 0;
|
||||
/**
|
||||
* Auxiliary vars for grid update
|
||||
*/
|
||||
uint _oldposx = 0, _oldposy = 0;
|
||||
|
||||
/**
|
||||
* Amplitude of movement
|
||||
*/
|
||||
int _element1 = 0, _element2 = 0;
|
||||
/**
|
||||
* Current position of the main character
|
||||
*/
|
||||
uint16 _characterPosX = 0, _characterPosY = 0;
|
||||
/**
|
||||
* Target position of the main character?
|
||||
*/
|
||||
int _xframe2 = 0, _yframe2 = 0;
|
||||
|
||||
/**
|
||||
* Text map
|
||||
*/
|
||||
Common::File _verbFile;
|
||||
/**
|
||||
* Auxiliary vars with current inventory object name.
|
||||
*/
|
||||
Common::String _oldInventoryObjectName, _inventoryObjectName;
|
||||
|
||||
/**
|
||||
* Name of player
|
||||
*/
|
||||
Common::String _characterName = "";
|
||||
|
||||
Common::String _decryptionKey;
|
||||
|
||||
/**
|
||||
* State of the niches in part 2
|
||||
*/
|
||||
uint _niche[2][4];
|
||||
|
||||
RoomFileRegister *_currentRoomData = nullptr;
|
||||
|
||||
ScreenObject *_curObject = nullptr; // Currently selected object in the screen
|
||||
/**
|
||||
* New movement to execute.
|
||||
*/
|
||||
Route _mainRoute;
|
||||
|
||||
/**
|
||||
* Matrix of positions for a trajectory between two points
|
||||
*/
|
||||
Common::Point _trajectory[300];
|
||||
|
||||
/**
|
||||
* Longitude of the trajectory matrix.
|
||||
*/
|
||||
uint _trajectoryLength = 0;
|
||||
/**
|
||||
* Position within the trajectory matrix
|
||||
*/
|
||||
uint _currentTrajectoryIndex = 0;
|
||||
/**
|
||||
* Position within the trajectory matrix for secondary animation
|
||||
*/
|
||||
uint _currentSecondaryTrajectoryIndex = 0;
|
||||
/**
|
||||
* Screen areas
|
||||
*/
|
||||
byte _currentZone = 0, _targetZone = 0, _oldTargetZone = 0;
|
||||
|
||||
/**
|
||||
* Amplitude of grid slices
|
||||
*/
|
||||
byte _maxXGrid = 0, _maxYGrid = 0;
|
||||
|
||||
/**
|
||||
* capture of movement grid of secondary animation
|
||||
*/
|
||||
byte _movementGridForSecondaryAnim[10][10];
|
||||
/**
|
||||
* capture of mouse grid of secondary animation
|
||||
*/
|
||||
byte _mouseGridForSecondaryAnim[10][10];
|
||||
/**
|
||||
* movement mask for grid of secondary animation
|
||||
*/
|
||||
byte _maskGridSecondaryAnim[10][10];
|
||||
/**
|
||||
* mouse mask for grid of secondary animation
|
||||
*/
|
||||
byte _maskMouseSecondaryAnim[10][10];
|
||||
|
||||
bool _list1Complete = false,
|
||||
_list2Complete = false,
|
||||
_obtainedList1 = false, // whether we've been given list 1
|
||||
_obtainedList2 = false; // whether we've been given list 2
|
||||
|
||||
/** Conversation topic unlocks */
|
||||
bool _firstTimeTopicA[kCharacterCount] = { false },
|
||||
_firstTimeTopicB[kCharacterCount] = { false },
|
||||
_firstTimeTopicC[kCharacterCount] = { false },
|
||||
_bookTopic[kCharacterCount] = { false },
|
||||
_mintTopic[kCharacterCount] = { false };
|
||||
|
||||
bool _caves[5] = { false };
|
||||
|
||||
/**
|
||||
* First and second lists of objects to retrieve in the game
|
||||
*/
|
||||
uint16 _firstList[5] = { 0 }, _secondList[5] = { 0 };
|
||||
|
||||
int32 _screenSize = 65520;
|
||||
|
||||
/**
|
||||
* Frame number for the animations
|
||||
*/
|
||||
byte _iframe = 0, _iframe2 = 0;
|
||||
|
||||
/**
|
||||
* Depth of screenobjects
|
||||
*/
|
||||
ObjectInfo _depthMap[kNumScreenOverlays];
|
||||
/**
|
||||
* Bitmaps of screenobjects
|
||||
*/
|
||||
byte *_screenLayers[kNumScreenOverlays] = { nullptr };
|
||||
/**
|
||||
* Current frame of main character
|
||||
*/
|
||||
byte *_curCharacterAnimationFrame = nullptr;
|
||||
/**
|
||||
* Current frame of secondary animation
|
||||
*/
|
||||
byte *_curSecondaryAnimationFrame = nullptr;
|
||||
|
||||
/**
|
||||
* Pointer storing the screen as it displays on the game
|
||||
*/
|
||||
byte *_sceneBackground = nullptr;
|
||||
|
||||
/**
|
||||
* Dirty patch of screen to repaint on every frame
|
||||
*/
|
||||
byte *_characterDirtyRect = nullptr;
|
||||
/**
|
||||
* Stores a copy of the background bitmap
|
||||
*/
|
||||
byte *_backgroundCopy = nullptr;
|
||||
|
||||
uint _currentRoomNumber = 0;
|
||||
|
||||
bool _isLoadingFromLauncher = false;
|
||||
|
||||
bool _saveAllowed = false;
|
||||
|
||||
/**
|
||||
* Previous positions of the mouse within the screen grid
|
||||
*/
|
||||
uint _oldGridX = 0, _oldGridY = 0;
|
||||
|
||||
uint _curDepth = 0;
|
||||
/**
|
||||
* Point of origin of the area surrounding the main character.
|
||||
* Calculated using the position of the character.
|
||||
*/
|
||||
uint16 _dirtyMainSpriteX = 0, _dirtyMainSpriteY = 0;
|
||||
/**
|
||||
* End point of origin of the area surrounding the main character.
|
||||
* Calculated using the position of the character + dimension
|
||||
*/
|
||||
uint _dirtyMainSpriteX2 = 0, _dirtyMainSpriteY2 = 0;
|
||||
byte *_spriteBackground = nullptr;
|
||||
public:
|
||||
TotEngine(OSystem *syst, const ADGameDescription *gameDesc);
|
||||
~TotEngine() override;
|
||||
|
||||
uint32 getFeatures() const;
|
||||
|
||||
/**
|
||||
* Returns the game Id
|
||||
*/
|
||||
Common::String getGameId() const;
|
||||
|
||||
/**
|
||||
* Gets a random number
|
||||
*/
|
||||
uint32 getRandomNumber(uint maxNum) {
|
||||
return _randomSource.getRandomNumber(maxNum);
|
||||
}
|
||||
|
||||
bool hasFeature(EngineFeature f) const override {
|
||||
return (f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime) ||
|
||||
(f == kSupportsReturnToLauncher);
|
||||
};
|
||||
|
||||
void drawFontSurface(Graphics::BgiFont &litt);
|
||||
|
||||
// Save/Load
|
||||
Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
|
||||
Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
|
||||
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
|
||||
void loadScreenData(uint screenNumber);
|
||||
void clearScreenLayers();
|
||||
void clearAnimation();
|
||||
void buttonBorder(uint x1, uint y1, uint x2, uint y2, byte color1, byte color2, byte color3, byte color4, byte color5);
|
||||
void drawMenu(byte menuNumber);
|
||||
void drawLeftArrow(uint x, uint y);
|
||||
void drawRightArrow(uint x, uint y);
|
||||
void readTextFile();
|
||||
void loadAnimationForDirection(Common::SeekableReadStream *stream, int direction);
|
||||
void sayLine(uint textRef, byte textColor, byte shadowColor, uint &responseNumber, bool isWithinConversation);
|
||||
void goToObject(byte zone1, byte zone2);
|
||||
void readObject(uint objPos);
|
||||
TextEntry readTextRegister();
|
||||
void drawInventory();
|
||||
void drawInventoryMask();
|
||||
void setRoomTrajectories(int height, int width, TRAJECTORIES_OP op, bool fixGrids = true);
|
||||
void saveRoomData(RoomFileRegister *room, Common::SeekableWriteStream *stream);
|
||||
//vars
|
||||
void initializeScreenFile();
|
||||
};
|
||||
|
||||
extern TotEngine *g_engine;
|
||||
#define SHOULD_QUIT ::Tot::g_engine->shouldQuit()
|
||||
|
||||
} // End of namespace Tot
|
||||
|
||||
#endif // TOT_H
|
||||
290
engines/tot/types.h
Normal file
290
engines/tot/types.h
Normal file
@@ -0,0 +1,290 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef TOT_TYPES_H
|
||||
#define TOT_TYPES_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
const int kVerbRegSize = 263;
|
||||
const int kRoomRegSize = 10856;
|
||||
const int kItemRegSize = 279;
|
||||
|
||||
const int kList1Index = 19;
|
||||
const int kList2Index = 20;
|
||||
const int kList1code = 149;
|
||||
const int kList2code = 150;
|
||||
/**
|
||||
* Num of icons in the inventory
|
||||
*/
|
||||
const int kInventoryIconCount = 34;
|
||||
const int kNumScreenOverlays = 15;
|
||||
/**
|
||||
* Num of depth levels
|
||||
*/
|
||||
const int kDepthLevelCount = 15;
|
||||
/**
|
||||
* Num of frames of the main character in a single direction
|
||||
*/
|
||||
const int kWalkFrameCount = 16;
|
||||
/**
|
||||
* Num of frames in the secondary animation
|
||||
*/
|
||||
const int kSecAnimationFrameCount = 50;
|
||||
/**
|
||||
* X factor of the screen grid
|
||||
* This results in 320/8 = 40 quadrants.
|
||||
*/
|
||||
const int kXGridCount = 8;
|
||||
/**
|
||||
* Y factor of the screen grid
|
||||
* This results in 140/5 = 28 quadrants.
|
||||
*/
|
||||
const int kYGridCount = 5;
|
||||
/**
|
||||
* Y offset of feet within character sprite (for adjustment of path finding)
|
||||
*/
|
||||
const int kCharacerCorrectionY = 49;
|
||||
/**
|
||||
* X offset of feet within character sprite (for adjustment of path finding)
|
||||
*/
|
||||
const int kCharacterCorrectionX = 14;
|
||||
const int kObjectNameLength = 20;
|
||||
const int kCharacterCount = 9;
|
||||
/**
|
||||
* Size of an inventory icon (39x26)
|
||||
*/
|
||||
const int kInventoryIconSize = 1018;
|
||||
/**
|
||||
* Number of points in a
|
||||
*/
|
||||
const int kRoutePointCount = 7;
|
||||
|
||||
/**
|
||||
* Trajectory changes
|
||||
*/
|
||||
typedef Common::Point Route[kRoutePointCount];
|
||||
|
||||
|
||||
enum TRAJECTORIES_OP {
|
||||
// Subtracts the animation dimensions to the trajectory coordinates to adjust movement
|
||||
SET_WITH_ANIM = false,
|
||||
// Adds the animation dimensions to the trajectory coordinates to restore
|
||||
RESTORE = true
|
||||
};
|
||||
|
||||
struct ObjectInfo {
|
||||
uint16 code = 0, posx = 0, posy = 0, posx2 = 0, posy2 = 0;
|
||||
};
|
||||
|
||||
struct CharacterAnim {
|
||||
uint16 depth = 0;
|
||||
byte *bitmap[4][kWalkFrameCount + 30]; // 30 = 3 actions * 10 frames each
|
||||
};
|
||||
|
||||
struct SecondaryAnim {
|
||||
uint16 depth = 0, dir = 1, posx = 0, posy = 0;
|
||||
byte *bitmap[4][kSecAnimationFrameCount];
|
||||
};
|
||||
|
||||
struct InventoryEntry {
|
||||
int16 bitmapIndex = -1;
|
||||
int16 code = -1;
|
||||
Common::String objectName = "";
|
||||
};
|
||||
|
||||
/**
|
||||
* Hypertext struct
|
||||
*/
|
||||
struct TextEntry {
|
||||
Common::String text; // string
|
||||
bool continued = false; // true if the next entry is a continuation of this one
|
||||
uint16 response = 0; // entry number of reply
|
||||
int32 pointer = 0;
|
||||
};
|
||||
|
||||
struct ScreenObject {
|
||||
/**
|
||||
* registry number
|
||||
*/
|
||||
uint16 code;
|
||||
byte height; /* 0 top 1 middle 2 bottom, determines character anim on use/pick*/
|
||||
Common::String name; /* name for mouseover*/
|
||||
uint16 lookAtTextRef; /* Text reference when looking at object */
|
||||
uint16 beforeUseTextRef; /* Text reference before using object */
|
||||
uint16 afterUseTextRef; /* Text reference after using object */
|
||||
uint16 pickTextRef; /* Text reference when picking up object */
|
||||
uint16 useTextRef; /* Text reference when using object */
|
||||
byte speaking; /* whether the object talks or not */
|
||||
bool openable; /* true if it can be opened */
|
||||
bool closeable; /* true if it can be closed*/
|
||||
byte used[8]; /* flags (one per original savegame) on whether the object has been used */
|
||||
bool pickupable;
|
||||
uint16 useWith,
|
||||
replaceWith; /* Code of the object it should be replaced with in case a replacement is due.*/
|
||||
byte depth;
|
||||
uint32 bitmapPointer; /* reference to the objects bitmap in the bitmap resource file */
|
||||
uint16 bitmapSize;
|
||||
uint32 rotatingObjectAnimation; /* Pointer to the FLC animation of the rotatin object */
|
||||
uint16 rotatingObjectPalette; /* Pointer to the palette of the above FLC animation*/
|
||||
uint16 dropOverlayX, dropOverlayY; /* coords when the object requires placing an overlay on the screen */
|
||||
uint32 dropOverlay; /* pointer to such overlay */
|
||||
uint16 dropOverlaySize;
|
||||
uint16 objectIconBitmap; /* Icon on the inventory */
|
||||
|
||||
byte xgrid1, ygrid1, xgrid2, ygrid2; /* position of patches below*/
|
||||
|
||||
byte walkAreasPatch[10][10]; /* patch on the scene's walking area (e.g. object prevents character from walking */
|
||||
byte mouseGridPatch[10][10]; /* patch on the mouse grid area (i.e. selectable area of the object */
|
||||
};
|
||||
|
||||
struct DoorRegistry {
|
||||
uint16 nextScene,
|
||||
exitPosX,
|
||||
exitPosY;
|
||||
byte openclosed,
|
||||
doorcode;
|
||||
};
|
||||
|
||||
struct RoomObjectListEntry {
|
||||
uint16 fileIndex;
|
||||
Common::String objectName;
|
||||
};
|
||||
|
||||
struct RoomBitmapRegister {
|
||||
uint32 bitmapPointer;
|
||||
uint16 bitmapSize;
|
||||
uint16 coordx, coordy, depth;
|
||||
};
|
||||
|
||||
struct RoomFileRegister {
|
||||
uint16 code;
|
||||
uint32 roomImagePointer;
|
||||
uint16 roomImageSize;
|
||||
byte walkAreasGrid[40][28]; /* movement grid */
|
||||
byte mouseGrid[40][28]; /* mousegrid with index to indexadoObjetos */
|
||||
/**
|
||||
* This is a preset matrix of trajectories from different areas of the game.action
|
||||
* Each room is divided into a number of areas according to the screen grid [rejapantalla].action
|
||||
*
|
||||
* A given coordinate in the game (x,y) is mapped into a grid position by dividing the x with factorx (8)
|
||||
* and the y coordinate by factory (5). With each room being 320x140 this results in
|
||||
* 40 horizontal divisions and 28 vertical divisions which matches the [rejapantalla] matrix.action
|
||||
*
|
||||
* When obtaining the grid position a given (x,y) coordinate matches to, [rejapantalla] returns an
|
||||
* area number.action
|
||||
*
|
||||
* trayectorias then has a precalculated route from each possible combination of two areas in the game.
|
||||
* pixel by pixel translation within the area is done by bresenham algorithm in the trajectory function.
|
||||
*/
|
||||
Common::Point trajectories[9][30][5];
|
||||
DoorRegistry doors[5]; /* doors in the room */
|
||||
RoomBitmapRegister screenLayers[15];
|
||||
RoomObjectListEntry *screenObjectIndex[51] = { nullptr }; /* includes name of objects for mouseover + index to object file*/
|
||||
bool animationFlag; /* true if there is a secondary animation */
|
||||
Common::String animationName; /* name of the secondary animation, 8 chars*/
|
||||
bool paletteAnimationFlag; /* true if there exist palette animation */
|
||||
uint16 palettePointer; /* points to the screen palette */
|
||||
Common::Point secondaryAnimTrajectory[300]; /* trajectory of the secondary animation */
|
||||
uint16 secondaryAnimDirections[300]; /* directions of the secondary trajectory. Pos 300 reflects object code. */
|
||||
uint16 secondaryTrajectoryLength; /* length of the trajectory of the secondary animation */
|
||||
~RoomFileRegister() {
|
||||
for (int i = 0; i < 51; i++) {
|
||||
delete screenObjectIndex[i];
|
||||
screenObjectIndex[i] = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct SavedGame {
|
||||
uint roomCode,
|
||||
trajectoryLength,
|
||||
currentTrajectoryIndex,
|
||||
backpackObjectCode,
|
||||
rightSfxVol,
|
||||
leftSfxVol,
|
||||
musicVolRight,
|
||||
musicVolLeft,
|
||||
oldGridX,
|
||||
oldGridY,
|
||||
secAnimDepth,
|
||||
secAnimDir,
|
||||
secAnimX,
|
||||
secAnimY,
|
||||
secAnimIFrame;
|
||||
byte currentZone,
|
||||
targetZone,
|
||||
oldTargetZone,
|
||||
inventoryPosition,
|
||||
actionCode,
|
||||
oldActionCode,
|
||||
steps,
|
||||
doorIndex,
|
||||
characterFacingDir,
|
||||
iframe,
|
||||
gamePart;
|
||||
bool isSealRemoved,
|
||||
isPottersManualDelivered,
|
||||
obtainedList1,
|
||||
obtainedList2,
|
||||
list1Complete,
|
||||
list2Complete,
|
||||
isVasePlaced,
|
||||
isScytheTaken,
|
||||
isTridentTaken,
|
||||
isPottersWheelDelivered,
|
||||
isMudDelivered,
|
||||
isGreenDevilDelivered,
|
||||
isCupboardOpen,
|
||||
isChestOpen,
|
||||
isTVOn,
|
||||
isTrapSet,
|
||||
isRedDevilCaptured;
|
||||
InventoryEntry mobj[kInventoryIconCount];
|
||||
int element1,
|
||||
element2,
|
||||
characterPosX,
|
||||
characterPosY,
|
||||
xframe2,
|
||||
yframe2;
|
||||
Common::String oldInventoryObjectName,
|
||||
objetomoinventoryObjectNamehila;
|
||||
Common::String characterName;
|
||||
Route mainRoute;
|
||||
uint16 firstList[5], secondList[5];
|
||||
Common::Point trajectory[300];
|
||||
// Conversation topic unlocks
|
||||
bool firstTimeTopicA[kCharacterCount],
|
||||
firstTimeTopicB[kCharacterCount],
|
||||
firstTimeTopicC[kCharacterCount],
|
||||
bookTopic[kCharacterCount],
|
||||
mintTopic[kCharacterCount];
|
||||
|
||||
bool caves[5];
|
||||
uint niche[2][4];
|
||||
};
|
||||
|
||||
typedef byte Palette[768];
|
||||
|
||||
} // End of namespace Tot
|
||||
|
||||
#endif
|
||||
524
engines/tot/util.cpp
Normal file
524
engines/tot/util.cpp
Normal file
@@ -0,0 +1,524 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "common/textconsole.h"
|
||||
#include "graphics/paletteman.h"
|
||||
|
||||
#include "tot/statics.h"
|
||||
#include "tot/tot.h"
|
||||
#include "tot/util.h"
|
||||
#include "util.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
// Enforces a small delay when text reveal is supposed to happen
|
||||
const int kEnforcedTextAnimDelay = 0;
|
||||
|
||||
void showError(int code) {
|
||||
const char *const *messages = (isLanguageSpanish()) ? errorMessages[0] : errorMessages[1];
|
||||
switch (code) {
|
||||
case 1:
|
||||
error("%s", messages[0]);
|
||||
break;
|
||||
case 2:
|
||||
error("%s", messages[1]);
|
||||
break;
|
||||
case 3:
|
||||
error("%s", messages[2]);
|
||||
break;
|
||||
case 4:
|
||||
error("%s", messages[3]);
|
||||
break;
|
||||
case 5:
|
||||
error("%s", messages[4]);
|
||||
break;
|
||||
case 6:
|
||||
error("%s", messages[5]);
|
||||
break;
|
||||
case 12:
|
||||
error("%s", messages[6]);
|
||||
break;
|
||||
case 13:
|
||||
case 14:
|
||||
error(messages[7], code);
|
||||
break;
|
||||
case 15:
|
||||
error("%s", messages[8]);
|
||||
break;
|
||||
case 16:
|
||||
error("%s", messages[9]);
|
||||
break;
|
||||
case 17:
|
||||
error("%s", messages[10]);
|
||||
break;
|
||||
case 18:
|
||||
error("%s", messages[11]);
|
||||
break;
|
||||
case 100:
|
||||
error("%s", messages[12]);
|
||||
break;
|
||||
case 101:
|
||||
error("%s", messages[13]);
|
||||
break;
|
||||
case 102:
|
||||
error("%s", messages[14]);
|
||||
break;
|
||||
case 103:
|
||||
error("%s", messages[15]);
|
||||
break;
|
||||
case 104:
|
||||
error("%s", messages[16]);
|
||||
break;
|
||||
case 105:
|
||||
error("%s", messages[17]);
|
||||
break;
|
||||
case 106:
|
||||
error("%s", messages[18]);
|
||||
break;
|
||||
case 150:
|
||||
error("%s", messages[19]);
|
||||
break;
|
||||
case 151:
|
||||
error("%s", messages[20]);
|
||||
break;
|
||||
case 152:
|
||||
error("%s", messages[21]);
|
||||
break;
|
||||
case 153:
|
||||
error("%s", messages[22]);
|
||||
break;
|
||||
case 154:
|
||||
error("%s", messages[23]);
|
||||
break;
|
||||
case 155:
|
||||
error(messages[24], code);
|
||||
break;
|
||||
case 156:
|
||||
error("%s", messages[25]);
|
||||
break;
|
||||
case 157:
|
||||
error("%s", messages[26]);
|
||||
break;
|
||||
case 158:
|
||||
error("%s", messages[27]);
|
||||
break;
|
||||
case 159:
|
||||
error("%s", messages[28]);
|
||||
break;
|
||||
case 160:
|
||||
error("%s", messages[29]);
|
||||
break;
|
||||
case 161:
|
||||
error("%s", messages[30]);
|
||||
break;
|
||||
case 162:
|
||||
error("%s", messages[31]);
|
||||
break;
|
||||
case 200:
|
||||
error("%s", messages[32]);
|
||||
break;
|
||||
case 201:
|
||||
error("%s", messages[33]);
|
||||
break;
|
||||
case 202:
|
||||
error("%s", messages[34]);
|
||||
break;
|
||||
case 203:
|
||||
error("%s", messages[35]);
|
||||
break;
|
||||
case 204:
|
||||
error("%s", messages[36]);
|
||||
break;
|
||||
case 205:
|
||||
error("%s", messages[37]);
|
||||
break;
|
||||
case 206:
|
||||
error("%s", messages[38]);
|
||||
break;
|
||||
case 207:
|
||||
error("%s", messages[39]);
|
||||
break;
|
||||
case 208:
|
||||
error("%s", messages[40]);
|
||||
break;
|
||||
case 209:
|
||||
error("%s", messages[41]);
|
||||
break;
|
||||
case 210:
|
||||
error("%s", messages[42]);
|
||||
break;
|
||||
case 211:
|
||||
error("%s", messages[43]);
|
||||
break;
|
||||
case 212:
|
||||
error("%s", messages[44]);
|
||||
break;
|
||||
case 213:
|
||||
error("%s", messages[45]);
|
||||
break;
|
||||
case 214:
|
||||
error("%s", messages[46]);
|
||||
break;
|
||||
case 215:
|
||||
error("%s", messages[47]);
|
||||
break;
|
||||
case 216:
|
||||
error("%s", messages[48]);
|
||||
break;
|
||||
case 250:
|
||||
error("%s", messages[49]);
|
||||
break;
|
||||
case 251:
|
||||
error("%s", messages[50]);
|
||||
break;
|
||||
case 252:
|
||||
error("%s", messages[51]);
|
||||
break;
|
||||
case 253:
|
||||
error("%s", messages[52]);
|
||||
break;
|
||||
case 254:
|
||||
error("%s", messages[53]);
|
||||
break;
|
||||
case 255:
|
||||
error("%s", messages[54]);
|
||||
break;
|
||||
case 256:
|
||||
error("%s", messages[55]);
|
||||
break;
|
||||
case 257:
|
||||
error("%s", messages[56]);
|
||||
break;
|
||||
case 258:
|
||||
error("%s", messages[57]);
|
||||
break;
|
||||
case 259:
|
||||
error("%s", messages[58]);
|
||||
break;
|
||||
case 260:
|
||||
error("%s", messages[59]);
|
||||
break;
|
||||
case 261:
|
||||
error("%s", messages[60]);
|
||||
break;
|
||||
case 262:
|
||||
error("%s", messages[61]);
|
||||
break;
|
||||
case 263:
|
||||
error("%s", messages[62]);
|
||||
break;
|
||||
case 264:
|
||||
error("%s", messages[63]);
|
||||
break;
|
||||
case 265:
|
||||
error("%s", messages[64]);
|
||||
break;
|
||||
case 266:
|
||||
error("%s", messages[65]);
|
||||
break;
|
||||
case 267:
|
||||
error("%s", messages[66]);
|
||||
break;
|
||||
case 268:
|
||||
error("%s", messages[67]);
|
||||
break;
|
||||
case 269:
|
||||
error("%s", messages[68]);
|
||||
break;
|
||||
case 270:
|
||||
error("%s", messages[69]);
|
||||
break;
|
||||
case 271:
|
||||
error("%s", messages[70]);
|
||||
break;
|
||||
case 272:
|
||||
error("%s", messages[71]);
|
||||
break;
|
||||
case 273:
|
||||
error("%s", messages[72]);
|
||||
break;
|
||||
case 274:
|
||||
error("%s", messages[73]);
|
||||
break;
|
||||
case 275:
|
||||
error("%s", messages[74]);
|
||||
break;
|
||||
case 276:
|
||||
error("%s", messages[75]);
|
||||
break;
|
||||
case 277:
|
||||
error("%s", messages[76]);
|
||||
break;
|
||||
case 278:
|
||||
error("%s", messages[77]);
|
||||
break;
|
||||
case 279:
|
||||
error("%s", messages[78]);
|
||||
break;
|
||||
case 280:
|
||||
error("%s", messages[79]);
|
||||
break;
|
||||
case 281:
|
||||
error("%s", messages[80]);
|
||||
break;
|
||||
case 282:
|
||||
error("%s", messages[81]);
|
||||
break;
|
||||
case 299:
|
||||
error("%s", messages[82]);
|
||||
break;
|
||||
case 300:
|
||||
error("%s", messages[83]);
|
||||
break;
|
||||
case 301:
|
||||
error("%s", messages[84]);
|
||||
break;
|
||||
case 302:
|
||||
error("%s", messages[85]);
|
||||
break;
|
||||
case 303:
|
||||
error("%s", messages[86]);
|
||||
break;
|
||||
case 304:
|
||||
error("%s", messages[87]);
|
||||
break;
|
||||
case 305:
|
||||
error("%s", messages[88]);
|
||||
break;
|
||||
case 306:
|
||||
error("%s", messages[89]);
|
||||
break;
|
||||
case 307:
|
||||
error("%s", messages[90]);
|
||||
break;
|
||||
case 308:
|
||||
error("%s", messages[91]);
|
||||
break;
|
||||
case 309:
|
||||
error("%s", messages[92]);
|
||||
break;
|
||||
case 310:
|
||||
error("%s", messages[93]);
|
||||
break;
|
||||
case 311:
|
||||
error("%s", messages[94]);
|
||||
break;
|
||||
case 312:
|
||||
error("%s", messages[95]);
|
||||
break;
|
||||
case 313:
|
||||
error("%s", messages[96]);
|
||||
break;
|
||||
case 314:
|
||||
error("%s", messages[97]);
|
||||
break;
|
||||
case 315:
|
||||
error("%s", messages[98]);
|
||||
break;
|
||||
case 316:
|
||||
error("%s", messages[99]);
|
||||
break;
|
||||
case 317:
|
||||
error("%s", messages[100]);
|
||||
break;
|
||||
case 318:
|
||||
error("%s", messages[101]);
|
||||
break;
|
||||
case 319:
|
||||
error("%s", messages[102]);
|
||||
break;
|
||||
case 320:
|
||||
error("%s", messages[103]);
|
||||
break;
|
||||
case 321:
|
||||
error("%s", messages[104]);
|
||||
break;
|
||||
case 322:
|
||||
error("%s", messages[105]);
|
||||
break;
|
||||
case 323:
|
||||
error("%s", messages[106]);
|
||||
break;
|
||||
default: {
|
||||
if (code >= 7 && code <= 11) {
|
||||
error(messages[107], code);
|
||||
} else if (code >= 19 && code <= 99) {
|
||||
error(messages[108], code);
|
||||
} else if (code >= 107 && code <= 149) {
|
||||
error(messages[109],
|
||||
code);
|
||||
} else if (code >= 163 && code <= 199) {
|
||||
error(messages[110], code);
|
||||
} else if (code >= 217 && code <= 249) {
|
||||
error(messages[111], code);
|
||||
} else if (code >= 283 && code <= 298) {
|
||||
error(messages[112], code);
|
||||
} else {
|
||||
error(messages[113], code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void delay(uint16 ms) {
|
||||
g_engine->_chrono->delay(ms);
|
||||
}
|
||||
|
||||
/*
|
||||
Allows you to modify palette entries for the IBM
|
||||
8514 and the VGA drivers.
|
||||
*/
|
||||
void setRGBPalette(int color, int r, int g, int b) {
|
||||
// Take current palette
|
||||
byte palbuf[768];
|
||||
g_system->getPaletteManager()->grabPalette(palbuf, 0, 256);
|
||||
|
||||
palbuf[color * 3 + 0] = r << 2;
|
||||
palbuf[color * 3 + 1] = g << 2;
|
||||
palbuf[color * 3 + 2] = b << 2;
|
||||
|
||||
g_system->getPaletteManager()->setPalette(palbuf, 0, 256);
|
||||
}
|
||||
|
||||
void littText(int x, int y, const Common::String &text, byte color, Graphics::TextAlign align) {
|
||||
littText(x, y, text.c_str(), color, align);
|
||||
}
|
||||
|
||||
void littText(int x, int y, const char *text, byte color, Graphics::TextAlign align) {
|
||||
bool yAligned = (align == Graphics::kTextAlignCenter) ? true : false;
|
||||
x = (align == Graphics::kTextAlignCenter) ? 0 : x;
|
||||
y = y + 2;
|
||||
g_engine->_graphics->littText(text, x, y, color, align, yAligned);
|
||||
}
|
||||
|
||||
void euroText(int x, int y, const Common::String &text, byte color, Graphics::TextAlign align) {
|
||||
euroText(x, y, text.c_str(), color, align);
|
||||
}
|
||||
|
||||
void euroText(int x, int y, const char *text, byte color, Graphics::TextAlign align) {
|
||||
bool yAligned = (align == Graphics::kTextAlignCenter) ? true : false;
|
||||
x = (align == Graphics::kTextAlignCenter) ? 0 : x;
|
||||
y = y + 2;
|
||||
g_engine->_graphics->euroText(text, x, y, color, align, yAligned);
|
||||
}
|
||||
|
||||
void biosText(int x, int y, const Common::String &text, byte color) {
|
||||
g_engine->_graphics->biosText(text, x, y, color);
|
||||
}
|
||||
|
||||
uint imagesize(int x, int y, int x2, int y2) {
|
||||
int w = x2 - x + 1;
|
||||
int h = y2 - y + 1;
|
||||
return 4 + (w * h);
|
||||
}
|
||||
|
||||
void rectangle(int x1, int y1, int x2, int y2, byte color) {
|
||||
g_engine->_screen->drawLine(x1, y1, x2, y1, color);
|
||||
g_engine->_screen->drawLine(x2, y1, x2, y2, color);
|
||||
g_engine->_screen->drawLine(x1, y2, x2, y2, color);
|
||||
g_engine->_screen->drawLine(x1, y1, x1, y2, color);
|
||||
g_engine->_screen->addDirtyRect(Common::Rect(x1, y1, x2, y2));
|
||||
}
|
||||
|
||||
void bar(int x1, int y1, int x2, int y2, byte color) {
|
||||
x2 = x2 + 1;
|
||||
y2 = y2 + 1;
|
||||
for (int i = x1; i < x2; i++) {
|
||||
for (int j = y1; j < y2; j++) {
|
||||
*((byte *)g_engine->_screen->getBasePtr(i, j)) = color;
|
||||
}
|
||||
}
|
||||
g_engine->_screen->addDirtyRect(Common::Rect(x1, y1, x2, y2));
|
||||
}
|
||||
|
||||
void putpixel(int x, int y, byte color) {
|
||||
g_engine->_screen->setPixel(x, y, color);
|
||||
}
|
||||
|
||||
void line(uint x1, uint y1, uint x2, uint y2, byte color) {
|
||||
g_engine->_screen->drawLine(x1, y1, x2, y2, color);
|
||||
}
|
||||
|
||||
void changeGameSpeed(Common::Event e) {
|
||||
if (e.type == Common::EVENT_KEYDOWN) {
|
||||
if (e.kbd.hasFlags(Common::KBD_CTRL)) {
|
||||
if (e.kbd.keycode == Common::KEYCODE_f) {
|
||||
g_engine->_chrono->changeSpeed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void emptyLoop() {
|
||||
do {
|
||||
g_engine->_events->pollEvent();
|
||||
g_engine->_chrono->updateChrono();
|
||||
g_engine->_screen->update();
|
||||
} while (!g_engine->_chrono->_gameTick && !g_engine->shouldQuit());
|
||||
}
|
||||
|
||||
void emptyLoop2() {
|
||||
do {
|
||||
g_engine->_chrono->updateChrono();
|
||||
g_engine->_screen->update();
|
||||
} while (!g_engine->_chrono->_gameTickHalfSpeed);
|
||||
}
|
||||
|
||||
int getRandom(int range) { return g_engine->getRandomNumber(range - 1); }
|
||||
|
||||
Common::String getObjectName(int idx) {
|
||||
return g_engine->_lang == Common::ES_ESP ? hardcodedTexts_ES[idx] : hardcodedTexts_EN[idx];
|
||||
}
|
||||
|
||||
Common::String getActionLineText(int idx) {
|
||||
return g_engine->_lang == Common::ES_ESP ? actionLine_ES[idx] : actionLine_EN[idx];
|
||||
}
|
||||
|
||||
const char *const *getFullScreenMessagesByCurrentLanguage() {
|
||||
return (g_engine->_lang == Common::ES_ESP) ? fullScreenMessages[0] : fullScreenMessages[1];
|
||||
}
|
||||
|
||||
const char *const *getAnimMessagesByCurrentLanguage() {
|
||||
return (g_engine->_lang == Common::ES_ESP) ? animMessages[0] : animMessages[1];
|
||||
}
|
||||
|
||||
const char *const *getHardcodedTextsByCurrentLanguage() {
|
||||
return (g_engine->_lang == Common::ES_ESP) ? hardcodedTexts_ES : hardcodedTexts_EN;
|
||||
}
|
||||
|
||||
const int32 *getOffsetsByCurrentLanguage() {
|
||||
return (g_engine->_lang == Common::ES_ESP) ? flcOffsets[0] : flcOffsets[1];
|
||||
}
|
||||
|
||||
void newSecondaryAnimationFrame() {
|
||||
if (g_engine->_curSecondaryAnimationFrame != nullptr) {
|
||||
free(g_engine->_curSecondaryAnimationFrame);
|
||||
}
|
||||
g_engine->_curSecondaryAnimationFrame = (byte *)malloc(g_engine->_secondaryAnimFrameSize);
|
||||
}
|
||||
|
||||
void clearScreenLayer(uint pos) {
|
||||
if (g_engine->_screenLayers[pos]) {
|
||||
free(g_engine->_screenLayers[pos]);
|
||||
}
|
||||
g_engine->_screenLayers[pos] = nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
93
engines/tot/util.h
Normal file
93
engines/tot/util.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef TOT_UTIL_H
|
||||
#define TOT_UTIL_H
|
||||
|
||||
#include "tot/tot.h"
|
||||
|
||||
namespace Tot {
|
||||
|
||||
extern const int kEnforcedTextAnimDelay;
|
||||
|
||||
void showError(int code);
|
||||
|
||||
// Delays a specified number of milliseconds.
|
||||
void delay(uint16 ms);
|
||||
|
||||
int engine_start();
|
||||
|
||||
void setRGBPalette(int color, int r, int g, int b);
|
||||
|
||||
void littText(int x, int y, const Common::String &text, byte color, Graphics::TextAlign align = Graphics::kTextAlignStart);
|
||||
void littText(int x, int y, const char *text, byte color, Graphics::TextAlign align = Graphics::kTextAlignStart);
|
||||
|
||||
void euroText(int x, int y, const Common::String &text, byte color, Graphics::TextAlign align = Graphics::kTextAlignStart);
|
||||
void euroText(int x, int y, const char *text, byte color, Graphics::TextAlign align = Graphics::kTextAlignStart);
|
||||
|
||||
void biosText(int x, int y, const Common::String &text, byte color);
|
||||
|
||||
uint imagesize(int x, int y, int x2, int y2);
|
||||
|
||||
void rectangle(int x1, int y1, int x2, int y2, byte color);
|
||||
|
||||
void line(uint x1, uint y1, uint x2, uint y2, byte color);
|
||||
|
||||
void bar(int x1, int y1, int x2, int y2, byte color);
|
||||
|
||||
void putpixel(int x, int y, byte color);
|
||||
|
||||
void emptyLoop();
|
||||
|
||||
void emptyLoop2();
|
||||
|
||||
void changeGameSpeed(Common::Event e);
|
||||
|
||||
inline bool odd(int32 i) { return i % 2 != 0; }
|
||||
|
||||
int getRandom(int range);
|
||||
|
||||
Common::String getObjectName(int idx);
|
||||
|
||||
Common::String getActionLineText(int idx);
|
||||
|
||||
const char *const *getFullScreenMessagesByCurrentLanguage();
|
||||
|
||||
const char *const *getAnimMessagesByCurrentLanguage();
|
||||
|
||||
const char *const *getHardcodedTextsByCurrentLanguage();
|
||||
|
||||
const int32 *getOffsetsByCurrentLanguage();
|
||||
|
||||
void newSecondaryAnimationFrame();
|
||||
|
||||
void clearScreenLayer(uint pos);
|
||||
|
||||
inline bool isLanguageSpanish() {
|
||||
return g_engine->_lang == Common::ES_ESP;
|
||||
}
|
||||
|
||||
inline bool isDemo() {
|
||||
return g_engine->_gameDescription->flags & ADGF_DEMO;
|
||||
}
|
||||
|
||||
} // End of namespace Tot
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user