scummvm/engines/mortevielle/outtext.cpp
2015-01-26 22:16:31 +01:00

333 lines
8.1 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on original Mortville Manor DOS source code
* Copyright (c) 1987-1989 Lankhor
*/
#include "mortevielle/mortevielle.h"
#include "mortevielle/mouse.h"
#include "mortevielle/outtext.h"
#include "mortevielle/graphics.h"
#include "common/file.h"
#include "common/str.h"
namespace Mortevielle {
TextHandler::TextHandler(MortevielleEngine *vm) {
_vm = vm;
}
/**
* Next word
* @remarks Originally called 'l_motsuiv'
*/
int TextHandler::nextWord(int p, const char *ch, int &tab) {
int c = p;
while ((ch[p] != ' ') && (ch[p] != '$') && (ch[p] != '@'))
++p;
return tab * (p - c);
}
/**
* Engine function - Display Text
* @remarks Originally called 'afftex'
*/
void TextHandler::displayStr(Common::String inputStr, int x, int y, int dx, int dy, int typ) {
Common::String s;
int i, j;
// Safeguard: add $ just in case
inputStr += '$';
_vm->_screenSurface->putxy(x, y);
int tab = 6;
dx *= 6;
dy *= 6;
int xc = x;
int yc = y;
int xf = x + dx;
int yf = y + dy;
int p = 0;
bool stringParsed = (inputStr[p] == '$');
s = "";
while (!stringParsed) {
switch (inputStr[p]) {
case '@':
_vm->_screenSurface->drawString(s, typ);
s = "";
++p;
xc = x;
yc += 6;
_vm->_screenSurface->putxy(xc, yc);
break;
case ' ':
s += ' ';
xc += tab;
++p;
if (nextWord(p, inputStr.c_str(), tab) + xc > xf) {
_vm->_screenSurface->drawString(s, typ);
s = "";
xc = x;
yc += 6;
if (yc > yf) {
while (!_vm->keyPressed())
;
i = y;
do {
j = x;
do {
_vm->_screenSurface->putxy(j, i);
_vm->_screenSurface->drawString(" ", 0);
j += 6;
} while (j <= xf);
i += 6;
} while (i <= yf);
yc = y;
}
_vm->_screenSurface->putxy(xc, yc);
}
break;
case '$':
stringParsed = true;
_vm->_screenSurface->drawString(s, typ);
break;
default:
s += inputStr[p];
++p;
xc += tab;
break;
}
}
}
/**
* Load DES (picture container) file
* @remarks Originally called 'chardes'
*/
void TextHandler::loadPictureFile(Common::String filename, Common::String altFilename, int32 skipSize, int length) {
Common::File f;
if (!f.open(filename)) {
if (!f.open(altFilename))
error("Missing file: Either %s or %s", filename.c_str(), altFilename.c_str());
}
// HACK: The original game contains a bug in the 2nd intro screen, in German DOS version.
// The size specified in the fxx array is wrong (too short). In order to fix it, we are using
// the value -1 to force a variable read length.
if (length == -1)
length = f.size() - skipSize;
assert(skipSize + length <= f.size());
free(_vm->_curPict);
_vm->_curPict = (byte *)malloc(sizeof(byte) * length);
f.seek(skipSize);
f.read(_vm->_curPict, length);
f.close();
}
/**
* Load ANI file
* @remarks Originally called 'charani'
*/
void TextHandler::loadAniFile(Common::String filename, int32 skipSize, int length) {
Common::File f;
if (!f.open(filename))
error("Missing file - %s", filename.c_str());
assert(skipSize + length <= f.size());
free(_vm->_curAnim);
_vm->_curAnim = (byte *)malloc(sizeof(byte) * length);
f.seek(skipSize);
f.read(_vm->_curAnim, length);
f.close();
}
void TextHandler::taffich() {
static const byte tran1[] = { 121, 121, 138, 139, 120 };
static const byte tran2[] = { 150, 150, 152, 152, 100, 110, 159, 100, 100 };
int cx, drawingSize, npal;
int32 drawingStartPos;
int a = _vm->_caff;
if ((a >= 153) && (a <= 161))
a = tran2[a - 153];
else if ((a >= 136) && (a <= 140))
a = tran1[a - 136];
int b = a;
if (_vm->_maff == a)
return;
switch (a) {
case 16:
_vm->_coreVar._pctHintFound[9] = '*';
_vm->_coreVar._availableQuestion[42] = '*';
break;
case 20:
_vm->_coreVar._availableQuestion[39] = '*';
if (_vm->_coreVar._availableQuestion[36] == '*') {
_vm->_coreVar._pctHintFound[3] = '*';
_vm->_coreVar._availableQuestion[38] = '*';
}
break;
case 24:
_vm->_coreVar._availableQuestion[37] = '*';
break;
case 30:
_vm->_coreVar._availableQuestion[9] = '*';
break;
case 31: // Coat of arms
_vm->_coreVar._pctHintFound[4] = '*';
_vm->_coreVar._availableQuestion[35] = '*';
break;
case 118:
_vm->_coreVar._availableQuestion[41] = '*';
break;
case 143:
_vm->_coreVar._pctHintFound[1] = '*';
break;
case 150:
_vm->_coreVar._availableQuestion[34] = '*';
break;
case 151:
_vm->_coreVar._pctHintFound[2] = '*';
break;
default:
break;
}
_vm->_destinationOk = true;
_vm->_mouse->hideMouse();
drawingStartPos = 0;
Common::String filename, altFilename;
if ((a != 50) && (a != 51)) {
int m = a + 2000;
if ((m > 2001) && (m < 2010))
m = 2001;
else if (m == 2011)
m = 2010;
if (a == 32)
m = 2034;
else if ((a == 17) && (_vm->_maff == 14))
m = 2018;
else if (a > 99) {
if ((_vm->_is == 1) || (_vm->_is == 0))
m = 2031;
else
m = 2032;
}
if ( ((a > 69) && (a < 80)) || (a == 30) || (a == 31) || (a == 144) || (a == 147) || (a == 149) )
m = 2030;
else if ( ((a < 27) && ( ((_vm->_maff > 69) && (!_vm->_coreVar._alreadyEnteredManor)) || (_vm->_maff > 99) )) || ((_vm->_maff > 29) && (_vm->_maff < 33)) )
m = 2033;
_vm->displayInterScreenMessage(m);
_vm->_maff = a;
if (a == 159)
a = 86;
else if (a > 140)
a -= 67;
else if (a > 137)
a -= 66;
else if (a > 99)
a -= 64;
else if (a > 69)
a -= 42;
else if (a > 29)
a -= 5;
else if (a == 26)
a = 24;
else if (a > 18)
--a;
npal = a;
for (cx = 0; cx <= (a - 1); ++cx)
drawingStartPos += _vm->_drawingSizeArr[cx];
drawingSize = _vm->_drawingSizeArr[a];
altFilename = filename = "DXX.mor";
} else {
filename = "DZZ.mor";
altFilename = "DZZALL";
if (a == 50) {
// First intro screen
drawingStartPos = 0;
drawingSize = _vm->_drawingSizeArr[87];
} else { // a == 51
// Second intro screen
drawingStartPos = _vm->_drawingSizeArr[87];
// HACK: Force a variable size in order to fix the wrong size used by the German version
drawingSize = -1;
}
_vm->_maff = a;
npal = a + 37;
}
loadPictureFile(filename, altFilename, drawingStartPos, drawingSize);
_vm->_numpal = npal;
_vm->setPal(npal);
if ((b < 15) || (b == 16) || (b == 17) || (b == 24) || (b == 26) || (b == 50)) {
drawingStartPos = 0;
if ((b < 15) || (b == 16) || (b == 17) || (b == 24) || (b == 26)) {
if (b == 26)
b = 18;
else if (b == 24)
b = 17;
else if (b > 15)
--b;
for (cx = 0; cx <= (b - 1); ++cx)
drawingStartPos += _vm->_drawingSizeArr[cx + 89];
drawingSize = _vm->_drawingSizeArr[b + 89];
filename = "AXX.mor";
} else { // b == 50
// CHECKME: the size of AZZ.mor is 1280 for the DOS version
// and 1260 for the Amiga version. Maybe the 20 bytes
// are a filler (to get 10 blocks of 128 bytes),
// or the size should be variable.
drawingSize = 1260;
filename = "AZZ.mor";
}
loadAniFile(filename, drawingStartPos, drawingSize);
}
_vm->_mouse->showMouse();
if ((a < COAT_ARMS) && ((_vm->_maff < COAT_ARMS) || (_vm->_coreVar._currPlace == LANDING)) && (_vm->_currAction != _vm->_menu->_opcodeEnter)) {
if ((a == ATTIC) || (a == CELLAR))
_vm->displayAloneText();
else if (!_vm->_outsideOnlyFl)
_vm->getPresence(_vm->_coreVar._currPlace);
_vm->_savedBitIndex = 0;
}
}
} // End of namespace Mortevielle