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 
25 #ifdef ENABLE_AGOS2
26 
27 #include "common/savefile.h"
28 
29 #include "graphics/surface.h"
30 
31 #include "agos/agos.h"
32 #include "agos/intern.h"
33 #include "agos/vga.h"
34 
35 namespace AGOS {
36 
checkLinkBox()37 void AGOSEngine_Feeble::checkLinkBox() {	// Check for boxes spilling over to next row of text
38 	if (_hyperLink != 0) {
39 		_variableArray[52] = _textWindow->x + _textWindow->textColumn - _variableArray[50];
40 		if (_variableArray[52] != 0) {
41 			defineBox(_variableArray[53], _variableArray[50], _variableArray[51], _variableArray[52], 15, 145, 208, _dummyItem2);
42 			_variableArray[53]++;
43 		}
44 		_variableArray[50] = _textWindow->x;
45 		_variableArray[51] = _textWindow->textRow + _textWindow->y + (_oracleMaxScrollY-_textWindow->scrollY) * 15;
46 	}
47 }
48 
hyperLinkOn(uint16 x)49 void AGOSEngine_Feeble::hyperLinkOn(uint16 x) {
50 	if (!getBitFlag(51))
51 		return;
52 
53 	_hyperLink = x;
54 	_variableArray[50] = _textWindow->textColumn + _textWindow->x;
55 	_variableArray[51] = _textWindow->textRow + _textWindow->y + (_oracleMaxScrollY - _textWindow->scrollY) * 15;
56 }
57 
58 
hyperLinkOff()59 void AGOSEngine_Feeble::hyperLinkOff() {
60 	if (!getBitFlag(51))
61 		return;
62 
63 	_variableArray[52] = _textWindow->x + _textWindow->textColumn - _variableArray[50];
64 	defineBox(_variableArray[53], _variableArray[50], _variableArray[51], _variableArray[52], 15, 145, 208, _dummyItem2);
65 	_variableArray[53]++;
66 	_hyperLink = 0;
67 }
68 
linksUp()69 void AGOSEngine_Feeble::linksUp() {	// Scroll Oracle Links
70 	uint16 j;
71 	for (j = 700; j < _variableArray[53]; j++) {
72 		moveBox(j, 0, -15);
73 	}
74 }
75 
linksDown()76 void AGOSEngine_Feeble::linksDown() {
77 	uint16 i;
78 	for (i = 700; i < _variableArray[53]; i++) {
79 		moveBox(i,0, 15);
80 	}
81 }
82 
checkUp(WindowBlock * window)83 void AGOSEngine_Feeble::checkUp(WindowBlock *window) {
84 	uint16 j, k;
85 
86 	if (((_variableArray[31] - _variableArray[30]) == 40) && (_variableArray[31] > 52)) {
87 		k = (((_variableArray[31] / 52) - 2) % 3);
88 		j = k * 6;
89 		if (!isBoxDead(j + 201)) {
90 			uint index = getWindowNum(window);
91 			drawIconArray(index, window->iconPtr->itemRef, 0, window->iconPtr->classMask);
92 			animate(4, 9, k + 34, 0, 0, 0);
93 		}
94 	}
95 	if ((_variableArray[31] - _variableArray[30]) == 76) {
96 		k = ((_variableArray[31] / 52) % 3);
97 		j = k * 6;
98 		if (isBoxDead(j + 201)) {
99 			animate(4, 9, k + 31, 0, 0, 0);
100 			undefineBox(j + 201);
101 			undefineBox(j + 202);
102 			undefineBox(j + 203);
103 			undefineBox(j + 204);
104 			undefineBox(j + 205);
105 			undefineBox(j + 206);
106 		}
107 		_variableArray[31] -= 52;
108 		_iOverflow = 1;
109 	}
110 }
111 
inventoryUp(WindowBlock * window)112 void AGOSEngine_Feeble::inventoryUp(WindowBlock *window) {
113 	_marks = 0;
114 	checkUp(window);
115 	animate(4, 9, 21, 0 ,0, 0);
116 	while (_currentBoxNum == 0x7FFB && getBitFlag(89)) {
117 		checkUp(window);
118 		delay(1);
119 	}
120 	waitForMark(2);
121 	checkUp(window);
122 	sendSync(922);
123 	waitForMark(1);
124 	checkUp(window);
125 }
126 
127 
checkDown(WindowBlock * window)128 void AGOSEngine_Feeble::checkDown(WindowBlock *window) {
129 	uint16 j, k;
130 
131 	if (((_variableArray[31] - _variableArray[30]) == 24) && (_iOverflow == 1)) {
132 		uint index = getWindowNum(window);
133 		drawIconArray(index, window->iconPtr->itemRef, 0, window->iconPtr->classMask);
134 		k = ((_variableArray[31] / 52) % 3);
135 		animate(4, 9, k + 25, 0, 0, 0);
136 		_variableArray[31] += 52;
137 	}
138 	if (((_variableArray[31] - _variableArray[30]) == 40) && (_variableArray[30] > 52)) {
139 		k = (((_variableArray[31] / 52) + 1) % 3);
140 		j = k * 6;
141 		if (isBoxDead(j + 201)) {
142 			animate(4, 9, k + 28, 0, 0, 0);
143 			undefineBox(j + 201);
144 			undefineBox(j + 202);
145 			undefineBox(j + 203);
146 			undefineBox(j + 204);
147 			undefineBox(j + 205);
148 			undefineBox(j + 206);
149 		}
150 	}
151 }
152 
inventoryDown(WindowBlock * window)153 void AGOSEngine_Feeble::inventoryDown(WindowBlock *window) {
154 	_marks = 0;
155 	checkDown(window);
156 	animate(4, 9, 23, 0, 0, 0);
157 	while (_currentBoxNum == 0x7FFC && getBitFlag(89)) {
158 		checkDown(window);
159 		delay(1);
160 	}
161 	waitForMark(2);
162 	checkDown(window);
163 	sendSync(924);
164 	waitForMark(1);
165 	checkDown(window);
166 }
167 
scrollOracle()168 void AGOSEngine_Feeble::scrollOracle() {
169 	int i;
170 
171 	for (i = 0; i < 5; i++)
172 		scrollOracleUp();
173 }
174 
oracleTextUp()175 void AGOSEngine_Feeble::oracleTextUp() {
176 	Subroutine *sub;
177 	int i = 0;
178 	changeWindow(3);
179 	_noOracleScroll = 0;
180 
181 	if (_textWindow->scrollY > _oracleMaxScrollY)		// For scroll up
182 		_oracleMaxScrollY = _textWindow->scrollY;
183 	while (!shouldQuit()) {
184 		if (_textWindow->scrollY == _oracleMaxScrollY)
185 			break;
186 		_textWindow->textRow = 105;
187 		for (i = 0; i < 5; i++) {
188 			_newLines = 0;
189 			_textWindow->textColumn = 0;
190 			_textWindow->textRow -= 3;
191 			if (i == 2) {
192 				_textWindow->scrollY += 1;
193 				_textWindow->textRow += 15;
194 				linksUp();
195 			}
196 			scrollOracleUp();
197 			setBitFlag(94, true);
198 			sub = getSubroutineByID(_variableArray[104]);
199 			if (sub)
200 				startSubroutineEx(sub);
201 			setBitFlag(94, false);
202 		}
203 		if (_currentBoxNum != 601 || !getBitFlag(89))
204 			break;
205 		delay(100);
206 	}
207 }
208 
oracleTextDown()209 void AGOSEngine_Feeble::oracleTextDown() {
210 	Subroutine *sub;
211 	int i = 0;
212 	changeWindow(3);
213 	_noOracleScroll = 0;
214 
215 	if (_textWindow->scrollY > _oracleMaxScrollY)		// For scroll up
216 		_oracleMaxScrollY = _textWindow->scrollY;
217 	while (!shouldQuit()) {
218 		if (_textWindow->scrollY == 0)
219 			break;
220 
221 		for (i = 0; i < 5; i++) {
222 			_newLines = 0;
223 			_textWindow->textColumn = 0;
224 			_textWindow->textRow = (i + 1) * 3;
225 			if (i == 4) {
226 				_textWindow->scrollY -= 1;
227 				_textWindow->textRow = 0;
228 				linksDown();
229 			}
230 			scrollOracleDown();
231 			setBitFlag(93, true);
232 			sub = getSubroutineByID(_variableArray[104]);
233 			if (sub)
234 				startSubroutineEx(sub);
235 			setBitFlag(93, false);
236 		}
237 		if (_currentBoxNum != 600 || !getBitFlag(89))
238 			break;
239 		delay(100);
240 	}
241 }
242 
scrollOracleUp()243 void AGOSEngine_Feeble::scrollOracleUp() {
244 	byte *src, *dst;
245 	uint16 w, h;
246 
247 	dst = getBackGround() + 103 * _backGroundBuf->pitch + 136;
248 	src = getBackGround() + 106 * _backGroundBuf->pitch + 136;
249 
250 	for (h = 0; h < 21; h++) {
251 		for (w = 0; w < 360; w++) {
252 			if (dst[w] == 0 || dst[w] == 113 || dst[w] == 116 || dst[w] == 252)
253 				dst[w] = src[w];
254 		}
255 		dst += _backGroundBuf->pitch;
256 		src += _backGroundBuf->pitch;
257 	}
258 
259 	for (h = 0; h < 80; h++) {
260 		memcpy(dst, src, 360);
261 		dst += _backGroundBuf->pitch;
262 		src += _backGroundBuf->pitch;
263 	}
264 
265 	for (h = 0; h < 3; h++) {
266 		memset(dst, 0, 360);
267 		dst += _backGroundBuf->pitch;
268 		src += _backGroundBuf->pitch;
269 	}
270 }
271 
scrollOracleDown()272 void AGOSEngine_Feeble::scrollOracleDown() {
273 	byte *src, *dst;
274 	uint16 w, h;
275 
276 	src = getBackGround() + 203 * _backGroundBuf->pitch + 136;
277 	dst = getBackGround() + 206 * _backGroundBuf->pitch + 136;
278 
279 	for (h = 0; h < 77; h++) {
280 		memcpy(dst, src, 360);
281 		dst -= _backGroundBuf->pitch;
282 		src -= _backGroundBuf->pitch;
283 	}
284 
285 	for (h = 0; h < 24; h++) {
286 		for (w = 0; w < 360; w++) {
287 			if (src[w] == 0)
288 				dst[w] = src[w];
289 
290 			if (src[w] == 113 || src[w] == 116 || src[w] == 252) {
291 				dst[w] = src[w];
292 				src[w] = 0;
293 			}
294 		}
295 		dst -= _backGroundBuf->pitch;
296 		src -= _backGroundBuf->pitch;
297 	}
298 }
299 
oracleLogo()300 void AGOSEngine_Feeble::oracleLogo() {
301 	Common::Rect srcRect, dstRect;
302 	byte *src, *dst;
303 	uint16 w, h;
304 
305 	dstRect.left = 16;
306 	dstRect.top = 16;
307 	dstRect.right = 58;
308 	dstRect.bottom = 59;
309 
310 	srcRect.left = 0;
311 	srcRect.top = 0;
312 	srcRect.right = 42;
313 	srcRect.bottom = 43;
314 
315 	src = _iconFilePtr;
316 	dst = getBackBuf() + _backBuf->pitch * dstRect.top + dstRect.left;
317 
318 	for (h = 0; h < dstRect.height(); h++) {
319 		for (w = 0; w < dstRect.width(); w++) {
320 			if (src[w])
321 				dst[w] = src[w];
322 		}
323 		src += 336;
324 		dst += _backBuf->pitch;
325 	}
326 }
327 
swapCharacterLogo()328 void AGOSEngine_Feeble::swapCharacterLogo() {
329 	Common::Rect srcRect, dstRect;
330 	byte *src, *dst;
331 	uint16 w, h;
332 	int x;
333 
334 	dstRect.left = 64;
335 	dstRect.top = 16;
336 	dstRect.right = 106;
337 	dstRect.bottom = 59;
338 
339 	srcRect.top = 0;
340 	srcRect.bottom = 43;
341 
342 	x = _variableArray[91];
343 	if (x > _variableArray[90])
344 		x--;
345 	if (x < _variableArray[90])
346 		x++;
347 	_variableArray[91] = x;
348 
349 	x++;
350 	x *= 42;
351 
352 	srcRect.left = x;
353 	srcRect.right = srcRect.left + 42;
354 
355 	src = _iconFilePtr + srcRect.top * 336 + srcRect.left;
356 	dst = getBackBuf() + _backBuf->pitch * dstRect.top + dstRect.left;
357 
358 	for (h = 0; h < dstRect.height(); h++) {
359 		for (w = 0; w < dstRect.width(); w++) {
360 			if (src[w])
361 				dst[w] = src[w];
362 		}
363 		src += 336;
364 		dst += _backBuf->pitch;
365 	}
366 }
367 
listSaveGamesFeeble()368 void AGOSEngine_Feeble::listSaveGamesFeeble() {
369 	char b[108];
370 	Common::InSaveFile *in;
371 	uint16 j, k, z, maxFiles;
372 	int OK;
373 	memset(b, 0, 108);
374 
375 	maxFiles = countSaveGames() - 1;
376 	j = maxFiles;
377 	k = 1;
378 	z = maxFiles;
379 	if (getBitFlag(95)) {
380 		j++;
381 		z++;
382 	}
383 
384 	while (!shouldQuit()) {
385 		OK = 1;
386 		if (getBitFlag(93) || getBitFlag(94)) {
387 			OK = 0;
388 			if (j > z)
389 				break;
390 		}
391 
392 		if (getBitFlag(93)) {
393 			if (((_newLines + 1) >= _textWindow->scrollY) && ((_newLines + 1) < (_textWindow->scrollY + 3)))
394 				OK = 1;
395 		}
396 
397 		if (getBitFlag(94)) {
398 			if ((_newLines + 1) == (_textWindow->scrollY + 7))
399 				OK = 1;
400 		}
401 
402 
403 		if (OK == 1) {
404 			if (j == maxFiles + 1) {
405 				showMessageFormat("\n");
406 				hyperLinkOn(j + 400);
407 				setTextColor(116);
408 				showMessageFormat(" %d. ", 1);
409 				hyperLinkOff();
410 				setTextColor(113);
411 				k++;
412 				j--;
413 			}
414 
415 			if (!(in = _saveFileMan->openForLoading(genSaveName(j))))
416 				break;
417 			in->read(b, 100);
418 			delete in;
419 		}
420 
421 		showMessageFormat("\n");
422 		hyperLinkOn(j + 400);
423 		setTextColor(116);
424 		if (k < 10)
425 			showMessageFormat(" ");
426 		showMessageFormat("%d. ", k);
427 		setTextColor(113);
428 		showMessageFormat("%s ", b);
429 		hyperLinkOff();
430 		j--;
431 		k++;
432 	}
433 }
434 
saveUserGame(int slot)435 void AGOSEngine_Feeble::saveUserGame(int slot) {
436 	WindowBlock *window;
437 	Common::InSaveFile *in;
438 	char name[108];
439 	int len;
440 	memset(name, 0, 108);
441 
442 	window = _windowArray[3];
443 
444 	window->textRow = (slot + 1 - window->scrollY) * 15;
445 	window->textColumn = 26;
446 
447 	if ((in = _saveFileMan->openForLoading(genSaveName(readVariable(55))))) {
448 		in->read(name, 100);
449 		delete in;
450 	}
451 
452 	len = 0;
453 	while (name[len]) {
454 		byte chr = name[len];
455 		window->textColumn += getFeebleFontSize(chr);
456 		len++;
457 	}
458 
459 	windowPutChar(window, 0x7f);
460 	while (!shouldQuit()) {
461 		_keyPressed.reset();
462 		delay(1);
463 
464 		if (_keyPressed.ascii == 0 || _keyPressed.ascii >= 127)
465 			continue;
466 
467 		window->textColumn -= getFeebleFontSize(127);
468 		name[len] = 0;
469 		windowBackSpace(_windowArray[3]);
470 
471 		if (_keyPressed.keycode == Common::KEYCODE_ESCAPE) {
472 			_variableArray[55] = 27;
473 			break;
474 		}
475 		if (_keyPressed.keycode == Common::KEYCODE_KP_ENTER || _keyPressed.keycode == Common::KEYCODE_RETURN) {
476 			if (!saveGame(readVariable(55), name))
477 				_variableArray[55] = (int16)0xFFFF;
478 			else
479 				_variableArray[55] = 0;
480 			break;
481 		}
482 		if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE && len != 0) {
483 			len--;
484 			byte chr = name[len];
485 			window->textColumn -= getFeebleFontSize(chr);
486 			name[len] = 0;
487 			windowBackSpace(_windowArray[3]);
488 		}
489 		if (_keyPressed.ascii >= 32 && window->textColumn + 26 <= window->width) {
490 			name[len++] = _keyPressed.ascii;
491 			windowPutChar(_windowArray[3], _keyPressed.ascii);
492 		}
493 
494 		windowPutChar(window, 0x7f);
495 	}
496 }
497 
windowBackSpace(WindowBlock * window)498 void AGOSEngine_Feeble::windowBackSpace(WindowBlock *window) {
499 	byte *dst;
500 	uint x, y, h, w;
501 
502 	_videoLockOut |= 0x8000;
503 
504 	x = window->x + window->textColumn;
505 	y = window->y + window->textRow;
506 
507 	dst = getBackGround() + _backGroundBuf->pitch * y + x;
508 
509 	for (h = 0; h < 13; h++) {
510 		for (w = 0; w < 8; w++) {
511 			if (dst[w] == 113 || dst[w] == 116 || dst[w] == 252)
512 				dst[w] = 0;
513 		}
514 		dst += _backGroundBuf->pitch;
515 	}
516 
517 	_videoLockOut &= ~0x8000;
518 }
519 
520 } // End of namespace AGOS
521 
522 #endif // ENABLE_AGOS2
523