1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 /*
24 * This code is based on Labyrinth of Time code with assistance of
25 *
26 * Copyright (c) 1993 Terra Nova Development
27 * Copyright (c) 2004 The Wyrmkeep Entertainment Co.
28 *
29 */
30
31 #include "common/file.h"
32
33 #include "lab/lab.h"
34
35 #include "lab/anim.h"
36 #include "lab/dispman.h"
37 #include "lab/eventman.h"
38 #include "lab/image.h"
39 #include "lab/interface.h"
40 #include "lab/labsets.h"
41 #include "lab/music.h"
42 #include "lab/processroom.h"
43 #include "lab/resource.h"
44 #include "lab/utils.h"
45
46 namespace Lab {
47
doNotes()48 void LabEngine::doNotes() {
49 TextFont *noteFont = _resource->getFont("F:Note.fon");
50 Common::String noteText = _resource->getText("Lab:Rooms/Notes");
51
52 Common::Rect textRect = Common::Rect(_utils->vgaScaleX(25) + _utils->svgaCord(15), _utils->vgaScaleY(50), _utils->vgaScaleX(295) - _utils->svgaCord(15), _utils->vgaScaleY(148));
53 _graphics->flowText(noteFont, -2 + _utils->svgaCord(1), 0, 0, false, false, true, true, textRect, noteText.c_str());
54 _graphics->setPalette(_anim->_diffPalette, 256);
55 _graphics->freeFont(¬eFont);
56 }
57
doWestPaper()58 void LabEngine::doWestPaper() {
59 TextFont *paperFont = _resource->getFont("F:News22.fon");
60 Common::String paperText = _resource->getText("Lab:Rooms/Date");
61
62 Common::Rect textRect = Common::Rect(_utils->vgaScaleX(57), _utils->vgaScaleY(77) + _utils->svgaCord(2), _utils->vgaScaleX(262), _utils->vgaScaleY(91));
63 _graphics->flowText(paperFont, 0, 0, 0, false, true, false, true, textRect, paperText.c_str());
64 _graphics->freeFont(&paperFont);
65
66 paperFont = _resource->getFont("F:News32.fon");
67 paperText = _resource->getText("Lab:Rooms/Headline");
68
69 int fileLen = paperText.size() - 1;
70 textRect = Common::Rect(_utils->vgaScaleX(57), _utils->vgaScaleY(86) - _utils->svgaCord(2), _utils->vgaScaleX(262), _utils->vgaScaleY(118));
71 int charsPrinted = _graphics->flowText(paperFont, -8, 0, 0, false, true, false, true, textRect, paperText.c_str());
72
73 uint16 y;
74
75 if (charsPrinted < fileLen) {
76 y = 130 - _utils->svgaCord(5);
77 textRect = Common::Rect(_utils->vgaScaleX(57), _utils->vgaScaleY(86) - _utils->svgaCord(2), _utils->vgaScaleX(262), _utils->vgaScaleY(132));
78 _graphics->flowText(paperFont, -8 - _utils->svgaCord(1), 0, 0, false, true, false, true, textRect, paperText.c_str());
79 } else
80 y = 115 - _utils->svgaCord(5);
81
82 _graphics->freeFont(&paperFont);
83
84 paperFont = _resource->getFont("F:Note.fon");
85 paperText = _resource->getText("Lab:Rooms/Col1");
86 _graphics->flowText(paperFont, -4, 0, 0, false, false, false, true, _utils->vgaRectScale(45, y, 158, 148), paperText.c_str());
87
88 paperText = _resource->getText("Lab:Rooms/Col2");
89 _graphics->flowText(paperFont, -4, 0, 0, false, false, false, true, _utils->vgaRectScale(162, y, 275, 148), paperText.c_str());
90
91 _graphics->freeFont(&paperFont);
92 _graphics->setPalette(_anim->_diffPalette, 256);
93 }
94
loadJournalData()95 void LabEngine::loadJournalData() {
96 if (_journalFont)
97 _graphics->freeFont(&_journalFont);
98
99 _journalFont = _resource->getFont("F:Journal.fon");
100 updateEvents();
101
102 Common::String filename = "Lab:Rooms/j";
103
104 bool bridge = _conditions->in(kCondBridge0) || _conditions->in(kCondBridge1);
105 bool dirty = _conditions->in(kCondDirty);
106 bool news = !_conditions->in(kCondNoNews);
107 bool clean = !_conditions->in(kCondNoClean);
108
109 if (bridge && clean && news)
110 filename += '8';
111 else if (clean && news)
112 filename += '9';
113 else if (bridge && clean)
114 filename += '6';
115 else if (clean)
116 filename += '7';
117 else if (bridge && dirty && news)
118 filename += '4';
119 else if (dirty && news)
120 filename += '5';
121 else if (bridge && dirty)
122 filename += '2';
123 else if (dirty)
124 filename += '3';
125 else if (bridge)
126 filename += '1';
127 else
128 filename += '0';
129
130 _journalText = _resource->getText(filename);
131 _journalTextTitle = _resource->getText("Lab:Rooms/jt");
132
133 Common::File *journalFile = _resource->openDataFile("P:JImage");
134 _journalButtonList.push_back(_interface->createButton( 80, _utils->vgaScaleY(162) + _utils->svgaCord(1), 0, Common::KEYCODE_LEFT, new Image(journalFile, this), new Image(journalFile, this))); // back
135 _journalButtonList.push_back(_interface->createButton(194, _utils->vgaScaleY(162) + _utils->svgaCord(1), 2, Common::KEYCODE_RIGHT, new Image(journalFile, this), new Image(journalFile, this))); // forward
136 _journalButtonList.push_back(_interface->createButton(144, _utils->vgaScaleY(164) - _utils->svgaCord(1), 1, Common::KEYCODE_ESCAPE, new Image(journalFile, this), new Image(journalFile, this))); // cancel
137 delete journalFile;
138
139 _anim->_noPalChange = true;
140 _journalBackImage->setData(new byte[_graphics->_screenBytesPerPage]);
141 _graphics->readPict("P:Journal.pic", true, false, _journalBackImage->_imageData);
142 _anim->_noPalChange = false;
143
144 // Keep a copy of the blank journal
145 _blankJournal = new byte[_graphics->_screenBytesPerPage];
146 memcpy(_blankJournal, _journalBackImage->_imageData, _graphics->_screenBytesPerPage);
147 }
148
drawJournalText()149 void LabEngine::drawJournalText() {
150 uint16 drawingToPage = 1;
151 const char *curText = _journalText.c_str();
152
153 assert((_journalPage & 1) == 0);
154
155 while (drawingToPage < _journalPage) {
156 updateEvents();
157
158 // flowText without output
159 curText += _graphics->flowText(_journalFont, -2, 2, 0, false, false, false, false, _utils->vgaRectScale(52, 32, 152, 148), curText);
160
161 _lastPage = (*curText == 0);
162
163 if (_lastPage) {
164 // Reset _journalPage to this page, in case it was set too high
165 _journalPage = (drawingToPage / 2) * 2;
166 break;
167 }
168
169 drawingToPage++;
170 }
171
172 if (_journalPage == 0) {
173 // draw title page centered
174 _graphics->flowText(_journalFont, -2, 2, 0, false, true, true, true, _utils->vgaRectScale(52, 32, 152, 148), _journalTextTitle.c_str(), _journalBackImage);
175 } else {
176 curText += _graphics->flowText(_journalFont, -2, 2, 0, false, false, false, true, _utils->vgaRectScale(52, 32, 152, 148), curText, _journalBackImage);
177 }
178
179 updateEvents();
180 curText += _graphics->flowText(_journalFont, -2, 2, 0, false, false, false, true, _utils->vgaRectScale(171, 32, 271, 148), curText, _journalBackImage);
181
182 _lastPage = (*curText == 0);
183 }
184
turnPage(bool fromLeft)185 void LabEngine::turnPage(bool fromLeft) {
186 if (fromLeft) {
187 for (int i = 0; i < _graphics->_screenWidth; i += 8) {
188 updateEvents();
189 waitTOF();
190 _journalBackImage->blitBitmap(i, 0, nullptr, i, 0, 8, _graphics->_screenHeight, false);
191 }
192 } else {
193 for (int i = (_graphics->_screenWidth - 8); i > 0; i -= 8) {
194 updateEvents();
195 waitTOF();
196 _journalBackImage->blitBitmap(i, 0, nullptr, i, 0, 8, _graphics->_screenHeight, false);
197 }
198 }
199 }
200
drawJournal(uint16 wipenum,bool needFade)201 void LabEngine::drawJournal(uint16 wipenum, bool needFade) {
202 _event->mouseHide();
203 updateEvents();
204 drawJournalText();
205 _graphics->loadBackPict("P:Journal.pic", _highPalette);
206
207 if (wipenum == 0)
208 _journalBackImage->blitBitmap(0, 0, nullptr, 0, 0, _graphics->_screenWidth, _graphics->_screenHeight, false);
209 else
210 turnPage((wipenum == 1));
211
212 _interface->toggleButton(_interface->getButton(0), 15, (_journalPage > 0)); // back button
213 _interface->toggleButton(_interface->getButton(2), 15, (!_lastPage)); // forward button
214
215 if (needFade)
216 _graphics->fade(true);
217
218 // Reset the journal background, so that all the text that has been blitted on it is erased
219 memcpy(_journalBackImage->_imageData, _blankJournal, _graphics->_screenBytesPerPage);
220
221 eatMessages();
222 _event->mouseShow();
223 }
224
processJournal()225 void LabEngine::processJournal() {
226 while (1) {
227 IntuiMessage *msg = _event->getMsg();
228 if (shouldQuit()) {
229 _quitLab = true;
230 return;
231 }
232
233 updateEvents();
234 _graphics->screenUpdate();
235 _system->delayMillis(10);
236
237 if (!msg)
238 continue;
239
240 MessageClass msgClass = msg->_msgClass;
241
242 if ((msgClass == kMessageRightClick) ||
243 ((msgClass == kMessageRawKey) && (msg->_code == Common::KEYCODE_ESCAPE)))
244 return;
245 else if (msgClass == kMessageButtonUp) {
246 uint16 buttonId = msg->_code;
247 if (buttonId == 0) {
248 if (_journalPage >= 2) {
249 _journalPage -= 2;
250 drawJournal(1, false);
251 }
252 } else if (buttonId == 1) {
253 return;
254 } else if (buttonId == 2) {
255 if (!_lastPage) {
256 _journalPage += 2;
257 drawJournal(2, false);
258 }
259 }
260 }
261 } // while
262 }
263
doJournal()264 void LabEngine::doJournal() {
265 _graphics->blackAllScreen();
266 _lastPage = false;
267
268 _journalBackImage->_width = _graphics->_screenWidth;
269 _journalBackImage->_height = _graphics->_screenHeight;
270 _journalBackImage->setData(nullptr, true);
271
272 updateEvents();
273 loadJournalData();
274 _interface->attachButtonList(&_journalButtonList);
275 drawJournal(0, true);
276 _event->mouseShow();
277 processJournal();
278 _interface->attachButtonList(nullptr);
279 _graphics->fade(false);
280 _event->mouseHide();
281
282 delete[] _blankJournal;
283 _blankJournal = nullptr;
284 _journalBackImage->setData(nullptr, true);
285
286 _interface->freeButtonList(&_journalButtonList);
287 _graphics->freeFont(&_journalFont);
288
289 _graphics->rectFill(0, 0, _graphics->_screenWidth - 1, _graphics->_screenHeight - 1, 0);
290 _graphics->blackScreen();
291 }
292
drawMonText(const char * text,TextFont * monitorFont,Common::Rect textRect,bool isinteractive)293 void LabEngine::drawMonText(const char *text, TextFont *monitorFont, Common::Rect textRect, bool isinteractive) {
294 uint16 drawingToPage = 0, yspacing = 0;
295
296 _event->mouseHide();
297
298 if (*text == '%') {
299 text++;
300 uint16 numlines = (*text - '0') * 10;
301 text++;
302 numlines += (*text - '0');
303 text += 2;
304
305 uint16 fheight = _graphics->textHeight(monitorFont);
306 textRect.left = _monitorButton->_width + _utils->vgaScaleX(3);
307 _monitorButtonHeight = _monitorButton->_height + _utils->vgaScaleY(3);
308
309 if (_monitorButtonHeight > fheight)
310 yspacing = _monitorButtonHeight - fheight;
311 else
312 _monitorButtonHeight = fheight;
313
314 _graphics->rectFill(0, 0, _graphics->_screenWidth - 1, textRect.bottom, 0);
315
316 for (int i = 0; i < numlines; i++)
317 _monitorButton->drawImage(0, i * _monitorButtonHeight);
318 } else if (isinteractive) {
319 _graphics->rectFill(0, 0, _graphics->_screenWidth - 1, textRect.bottom, 0);
320 } else {
321 _graphics->rectFill(textRect, 0);
322 }
323
324 const char *curText = text;
325 while (drawingToPage < _monitorPage) {
326 updateEvents();
327 curText += _graphics->flowText(monitorFont, yspacing, 0, 0, false, false, false, false, textRect, curText);
328 _lastPage = (*curText == 0);
329
330 if (_lastPage)
331 _monitorPage = drawingToPage;
332 else
333 drawingToPage++;
334 }
335
336 curText += _graphics->flowText(monitorFont, yspacing, 2, 0, false, false, false, true, textRect, curText);
337 _lastPage = (*curText == 0);
338 _event->mouseShow();
339 }
340
processMonitor(const Common::String & ntext,TextFont * monitorFont,bool isInteractive,Common::Rect textRect)341 void LabEngine::processMonitor(const Common::String &ntext, TextFont *monitorFont, bool isInteractive, Common::Rect textRect) {
342 Common::String startFileName = _monitorTextFilename;
343 const CloseData *startClosePtr = _closeDataPtr, *lastClosePtr[10];
344 uint16 depth = 0;
345 Common::String text = ntext;
346
347 lastClosePtr[0] = _closeDataPtr;
348
349 while (1) {
350 if (isInteractive) {
351 if (!_closeDataPtr)
352 _closeDataPtr = startClosePtr;
353
354 Common::String filename;
355 if (_closeDataPtr == startClosePtr)
356 filename = startFileName;
357 else
358 filename = _closeDataPtr->_graphicName;
359
360 if (filename != _monitorTextFilename) {
361 _monitorPage = 0;
362 _monitorTextFilename = filename;
363
364 text = _resource->getText(_monitorTextFilename);
365 _graphics->fade(false);
366 drawMonText(text.c_str(), monitorFont, textRect, isInteractive);
367 _graphics->fade(true);
368 }
369 }
370
371 IntuiMessage *msg = _event->getMsg();
372 if (shouldQuit()) {
373 _quitLab = true;
374 return;
375 }
376
377 updateEvents();
378 _graphics->screenUpdate();
379 _system->delayMillis(10);
380
381 if (!msg)
382 continue;
383
384 MessageClass msgClass = msg->_msgClass;
385
386 if ((msgClass == kMessageRightClick) ||
387 ((msgClass == kMessageRawKey) && (msg->_code == Common::KEYCODE_ESCAPE)))
388 return;
389
390 if (msgClass == kMessageLeftClick) {
391 int16 mouseX = msg->_mouse.x;
392 int16 mouseY = msg->_mouse.y;
393
394 // Check if mouse was in button bar
395 if ((mouseY >= _utils->vgaScaleY(171)) && (mouseY <= _utils->vgaScaleY(200))) {
396 if (mouseX <= _utils->vgaScaleX(31)) {
397 // Exit button
398 return;
399 }
400
401 if (mouseX <= _utils->vgaScaleX(59)) {
402 // Back button
403 if (isInteractive) {
404 _monitorPage = 0;
405
406 if (depth) {
407 depth--;
408 _closeDataPtr = lastClosePtr[depth];
409 }
410 } else if (_monitorPage > 0) {
411 _monitorPage = 0;
412 drawMonText(text.c_str(), monitorFont, textRect, isInteractive);
413 }
414 } else if (mouseX < _utils->vgaScaleX(259)) {
415 // empty region; ignore
416 } else if (mouseX <= _utils->vgaScaleX(289)) {
417 // Page down button
418 if (!_lastPage) {
419 _monitorPage += 1;
420 drawMonText(text.c_str(), monitorFont, textRect, isInteractive);
421 }
422 } else if (_monitorPage >= 1) {
423 // Page up button
424 _monitorPage -= 1;
425 drawMonText(text.c_str(), monitorFont, textRect, isInteractive);
426 }
427 } else if (isInteractive) {
428 const CloseData *tmpClosePtr = _closeDataPtr;
429 mouseY = 64 + (mouseY / _monitorButtonHeight) * 42;
430 mouseX = 101;
431 setCurrentClose(Common::Point(mouseX, mouseY), &_closeDataPtr, false);
432
433 if (tmpClosePtr != _closeDataPtr) {
434 lastClosePtr[depth] = tmpClosePtr;
435 depth++;
436 }
437 }
438 }
439 } // while
440 }
441
doMonitor(const Common::String background,const Common::String textfile,bool isinteractive,Common::Rect textRect)442 void LabEngine::doMonitor(const Common::String background, const Common::String textfile, bool isinteractive, Common::Rect textRect) {
443 Common::Rect scaledRect = _utils->vgaRectScale(textRect.left, textRect.top, textRect.right, textRect.bottom);
444 _monitorTextFilename = textfile;
445
446 _graphics->blackAllScreen();
447 _graphics->readPict("P:Mon/Monitor.1");
448 _graphics->readPict("P:Mon/NWD1");
449 _graphics->readPict("P:Mon/NWD2");
450 _graphics->readPict("P:Mon/NWD3");
451 _graphics->blackAllScreen();
452
453 _monitorPage = 0;
454 _lastPage = false;
455 _graphics->_fadePalette = _highPalette;
456
457 TextFont *monitorFont = _resource->getFont("F:Map.fon");
458 Common::File *buttonFile = _resource->openDataFile("P:MonImage");
459 _monitorButton = new Image(buttonFile, this);
460 delete buttonFile;
461
462 Common::String ntext = _resource->getText(textfile);
463 _graphics->loadBackPict(background, _highPalette);
464 drawMonText(ntext.c_str(), monitorFont, scaledRect, isinteractive);
465 _event->mouseShow();
466 _graphics->fade(true);
467 processMonitor(ntext, monitorFont, isinteractive, scaledRect);
468 _graphics->fade(false);
469 _event->mouseHide();
470 _graphics->freeFont(&monitorFont);
471
472 _graphics->rectFill(0, 0, _graphics->_screenWidth - 1, _graphics->_screenHeight - 1, 0);
473 _graphics->blackAllScreen();
474 _graphics->freePict();
475 }
476
477 } // End of namespace Lab
478