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 "agos/agos.h"
28 #include "agos/intern.h"
29 #include "agos/sound.h"
30 
31 namespace AGOS {
32 
setupVideoOpcodes(VgaOpcodeProc * op)33 void AGOSEngine_Feeble::setupVideoOpcodes(VgaOpcodeProc *op) {
34 	AGOSEngine_Simon2::setupVideoOpcodes(op);
35 
36 	op[75] = &AGOSEngine::vc75_setScale;
37 	op[76] = &AGOSEngine::vc76_setScaleXOffs;
38 	op[77] = &AGOSEngine::vc77_setScaleYOffs;
39 	op[78] = &AGOSEngine::vc78_computeXY;
40 	op[79] = &AGOSEngine::vc79_computePosNum;
41 	op[80] = &AGOSEngine::vc80_setOverlayImage;
42 	op[81] = &AGOSEngine::vc81_setRandom;
43 	op[82] = &AGOSEngine::vc82_getPathValue;
44 	op[83] = &AGOSEngine::vc83_playSoundLoop;
45 	op[84] = &AGOSEngine::vc84_stopSoundLoop;
46 }
47 
getScale(int16 y,int16 x)48 int AGOSEngine::getScale(int16 y, int16 x) {
49 	int16 z;
50 
51 	if (y > _baseY) {
52 		return((int16)(x * (1 + ((y - _baseY) * _scale))));
53 	} else {
54 		if (x == 0)
55 			return(0);
56 		if (x < 0) {
57 			z = ((int16)((x * (1 - ((_baseY - y)* _scale))) - 0.5));
58 			if (z >- 2)
59 				return(-2);
60 			return(z);
61 		}
62 
63 		z = ((int16)((x * (1 - ((_baseY - y) * _scale))) + 0.5));
64 		if (z < 2)
65 			return(2);
66 
67 		return(z);
68 	}
69 }
70 
vc36_setWindowImage()71 void AGOSEngine_Feeble::vc36_setWindowImage() {
72 	_displayFlag = 0;
73 	vcReadNextWord();
74 	vcReadNextWord();
75 	fillBackGroundFromFront();
76 }
77 
vc48_setPathFinder()78 void AGOSEngine_Feeble::vc48_setPathFinder() {
79 	uint16 a = (uint16)_variableArrayPtr[12];
80 	const uint16 *p = _pathFindArray[a - 1];
81 
82 	VgaSprite *vsp = findCurSprite();
83 	int16 x, y, ydiff;
84 	int16 x1, y1, x2, y2;
85 	uint pos = 0;
86 
87 	x = vsp->x;
88 	while (x >= (int16)readUint16Wrapper(p + 2)) {
89 		p += 2;
90 		pos++;
91 	}
92 
93 	x1 = readUint16Wrapper(p);
94 	y1 = readUint16Wrapper(p + 1);
95 	x2 = readUint16Wrapper(p + 2);
96 	y2 = readUint16Wrapper(p + 3);
97 
98 	if (x2 != 9999) {
99 		ydiff = y2 - y1;
100 		if (ydiff < 0) {
101 			ydiff = -ydiff;
102 			x = vsp->x & 7;
103 			ydiff *= x;
104 			ydiff /= 8;
105 			ydiff = -ydiff;
106 		} else {
107 			x = vsp->x & 7;
108 			ydiff *= x;
109 			ydiff /= 8;
110 		}
111 		y1 += ydiff;
112 	}
113 
114 	y = vsp->y;
115 	vsp->y = y1;
116 	checkScrollY(y1 - y, y1);
117 
118 	_variableArrayPtr[11] = x1;
119 	_variableArrayPtr[13] = pos;
120 }
121 
vc75_setScale()122 void AGOSEngine::vc75_setScale() {
123 	_baseY = vcReadNextWord();
124 	_scale = vcReadNextWord() / 1000000.0f;
125 }
126 
vc76_setScaleXOffs()127 void AGOSEngine::vc76_setScaleXOffs() {
128 	if (getGameType() == GType_PP && getBitFlag(120)) {
129 		VgaSprite *vsp1, *vsp2;
130 		uint16 old_file_1, tmp1, tmp2;
131 
132 		old_file_1 = _vgaCurSpriteId;
133 
134 		_vgaCurSpriteId = vcReadVar(vcReadNextWord());
135 		 vsp1 = findCurSprite();
136 		_vgaCurSpriteId = vcReadVar(vcReadNextWord());
137 		 vsp2 = findCurSprite();
138 
139 		tmp1 = vsp1->x;
140 		tmp2 = vsp2->x;
141 		vsp1->x = tmp2;
142 		vsp2->x = tmp1;
143 		tmp1 = vsp1->y;
144 		tmp2 = vsp2->y;
145 		vsp1->y = tmp2;
146 		vsp2->y = tmp1;
147 
148 		_vgaCurSpriteId = old_file_1;
149 		_vcPtr += 2;
150 	} else {
151 		VgaSprite *vsp = findCurSprite();
152 
153 		vsp->image = vcReadNextWord();
154 		int16 x = vcReadNextWord();
155 		uint16 var = vcReadNextWord();
156 
157 		vsp->x += getScale(vsp->y, x);
158 		_variableArrayPtr[var] = vsp->x;
159 
160 		checkScrollX(x, vsp->x);
161 
162 		vsp->flags = kDFScaled;
163 	}
164 }
165 
vc77_setScaleYOffs()166 void AGOSEngine::vc77_setScaleYOffs() {
167 	VgaSprite *vsp = findCurSprite();
168 
169 	vsp->image = vcReadNextWord();
170 	int16 y = vcReadNextWord();
171 	uint16 var = vcReadNextWord();
172 
173 	vsp->y += getScale(vsp->y, y);
174 	_variableArrayPtr[var] = vsp->y;
175 
176 	if (y != 0)
177 		checkScrollY(y, vsp->y);
178 
179 	vsp->flags = kDFScaled;
180 }
181 
vc78_computeXY()182 void AGOSEngine::vc78_computeXY() {
183 	VgaSprite *vsp = findCurSprite();
184 
185 	uint16 a = (uint16)_variableArrayPtr[12];
186 	uint16 b = (uint16)_variableArrayPtr[13];
187 
188 	const uint16 *p = _pathFindArray[a - 1];
189 	p += b * 2;
190 
191 	uint16 posx = readUint16Wrapper(p);
192 	_variableArrayPtr[15] = posx;
193 	vsp->x = posx;
194 
195 	uint16 posy = readUint16Wrapper(p + 1);
196 	_variableArrayPtr[16] = posy;
197 	vsp->y = posy;
198 
199 	if (getGameType() == GType_FF) {
200 		setBitFlag(85, false);
201 		if (getBitFlag(74)) {
202 			centerScroll();
203 		}
204 	}
205 }
206 
vc79_computePosNum()207 void AGOSEngine::vc79_computePosNum() {
208 	uint a = (uint16)_variableArrayPtr[12];
209 	const uint16 *p = _pathFindArray[a - 1];
210 	uint pos = 0;
211 
212 	int16 y = _variableArrayPtr[16];
213 	while (y >= (int16)readUint16Wrapper(p + 1)) {
214 		p += 2;
215 		pos++;
216 	}
217 
218 	_variableArrayPtr[13] = pos;
219 }
220 
vc80_setOverlayImage()221 void AGOSEngine::vc80_setOverlayImage() {
222 	VgaSprite *vsp = findCurSprite();
223 
224 	vsp->image = vcReadVarOrWord();
225 
226 	vsp->x += vcReadNextWord();
227 	vsp->y += vcReadNextWord();
228 	vsp->flags = kDFOverlayed;
229 
230 	_vgaSpriteChanged++;
231 }
232 
vc81_setRandom()233 void AGOSEngine::vc81_setRandom() {
234 	uint16 var = vcReadNextWord();
235 	uint16 value = vcReadNextWord();
236 
237 	_variableArray[var] = _rnd.getRandomNumber(value - 1);
238 }
239 
vc82_getPathValue()240 void AGOSEngine::vc82_getPathValue() {
241 	uint8 val;
242 
243 	uint16 var = vcReadNextWord();
244 
245 	if (getGameType() == GType_FF && getBitFlag(82)) {
246 		val = _pathValues1[_GPVCount1++];
247 	} else {
248 		val = _pathValues[_GPVCount++];
249 	}
250 
251 	vcWriteVar(var, val);
252 }
253 
vc83_playSoundLoop()254 void AGOSEngine::vc83_playSoundLoop() {
255 	uint16 sound = vcReadNextWord();
256 	int16 vol = vcReadNextWord();
257 	int16 pan = vcReadNextWord();
258 
259 	loadSound(sound, pan, vol, Sound::TYPE_SFX5);
260 }
261 
vc84_stopSoundLoop()262 void AGOSEngine::vc84_stopSoundLoop() {
263 	_sound->stopSfx5();
264 }
265 
266 // Scrolling functions for Feeble Files
checkScrollX(int16 x,int16 xpos)267 void AGOSEngine::checkScrollX(int16 x, int16 xpos) {
268 	if (_scrollXMax == 0 || x == 0)
269 		return;
270 
271 	if (getGameType() == GType_FF && (getBitFlag(80) || getBitFlag(82)))
272 		return;
273 
274 	int16 tmp;
275 	if (x > 0) {
276 		if (_scrollCount != 0) {
277 			if (_scrollCount >= 0)
278 				return;
279 			_scrollCount = 0;
280 		} else {
281 			if (_scrollFlag != 0)
282 				return;
283 		}
284 
285 		if (xpos - _scrollX >= 480) {
286 			_scrollCount = 320;
287 			tmp = _scrollXMax - _scrollX;
288 			if (tmp < 320)
289 				_scrollCount = tmp;
290 		}
291 	} else {
292 		if (_scrollCount != 0) {
293 			if (_scrollCount < 0)
294 				return;
295 			_scrollCount = 0;
296 		} else {
297 			if (_scrollFlag != 0)
298 				return;
299 		}
300 
301 		if (xpos - _scrollX < 161) {
302 			_scrollCount = -320;
303 			if (_scrollX < 320)
304 				_scrollCount = -_scrollX;
305 		}
306 	}
307 }
308 
checkScrollY(int16 y,int16 ypos)309 void AGOSEngine::checkScrollY(int16 y, int16 ypos) {
310 	if (_scrollYMax == 0)
311 		return;
312 
313 	if (getGameType() == GType_FF && getBitFlag(80))
314 		return;
315 
316 	int16 tmp;
317 	if (y >= 0) {
318 		if (_scrollCount != 0) {
319 			if (_scrollCount >= 0)
320 				return;
321 		} else {
322 			if (_scrollFlag != 0)
323 				return;
324 		}
325 
326 		if (ypos - _scrollY >= 440) {
327 			_scrollCount = 240;
328 			tmp = _scrollYMax - _scrollY;
329 			if (tmp < 240)
330 				_scrollCount = tmp;
331 		}
332 	} else {
333 		if (_scrollCount != 0) {
334 			if (_scrollCount < 0)
335 				return;
336 		} else {
337 			if (_scrollFlag != 0)
338 				return;
339 		}
340 
341 		if (ypos - _scrollY < 100) {
342 			_scrollCount = -240;
343 			if (_scrollY < 240)
344 				_scrollCount = -_scrollY;
345 		}
346 	}
347 }
348 
centerScroll()349 void AGOSEngine::centerScroll() {
350 	int16 x, y, tmp;
351 
352 	if (_scrollXMax != 0) {
353 		_scrollCount = 0;
354 		x = _variableArray[15] - _scrollX;
355 		if (x < 17 || (getBitFlag(85) && x < 320)) {
356 			x -= 320;
357 			if (_scrollX < -x)
358 				x = -_scrollX;
359 			_scrollCount = x;
360 		} else if ((getBitFlag(85) && x >= 320) || x >= 624) {
361 			x -= 320;
362 			tmp = _scrollXMax - _scrollX;
363 			if (tmp < x)
364 				x = tmp;
365 			_scrollCount = x;
366 		}
367 	} else if (_scrollYMax != 0) {
368 		_scrollCount = 0;
369 		y = _variableArray[16] - _scrollY;
370 		if (y < 30) {
371 			y -= 240;
372 			if (_scrollY < -y)
373 				y = -_scrollY;
374 			_scrollCount = y;
375 		} else if (y >= 460) {
376 			y -= 240;
377 			tmp = _scrollYMax - _scrollY;
378 			if (tmp < y)
379 				y = tmp;
380 			_scrollCount = y;
381 		}
382 	}
383 }
384 
385 // Puzzle Pack specific code
386 
vc3_loadSprite()387 void AGOSEngine_PuzzlePack::vc3_loadSprite() {
388 	if (getGameId() != GID_DIMP && getBitFlag(100)) {
389 		startAnOverlayAnim();
390 		return;
391 	}
392 
393 	AGOSEngine::vc3_loadSprite();
394 }
395 
vc63_fastFadeIn()396 void AGOSEngine_PuzzlePack::vc63_fastFadeIn() {
397 	_fastFadeInFlag = 256;
398 	_fastFadeOutFlag = false;
399 
400 	if (getGameId() == GID_DIMP)
401 		return;
402 
403 	if (getBitFlag(100)) {
404 		startOverlayAnims();
405 	} else if (getBitFlag(103)) {
406 		debug("vc63_fastFadeIn: NameAndTime");
407 	} else if (getBitFlag(104)) {
408 		debug("vc63_fastFadeIn: HiScoreTable");
409 	}
410 }
411 
startOverlayAnims()412 void AGOSEngine_PuzzlePack::startOverlayAnims() {
413 	VgaSprite *vsp = _vgaSprites;
414 	uint16 zoneNum;
415 	int i;
416 
417 	zoneNum = _variableArray[999];
418 
419 	for (i = 0; i < 600; i++) {
420 		if (_variableArray[1000 + i] < 100)
421 			continue;
422 
423 		while (vsp->id)
424 			vsp++;
425 
426 		vsp->windowNum = 4;
427 		vsp->priority = 4;
428 		vsp->flags = 0;
429 		vsp->palette = 0;
430 		vsp->image = _variableArray[1000 + i];
431 		if (i >= 300) {
432 			vsp->y = ((i - 300) / 20) * 32;
433 			vsp->x = ((i - 300) % 20) * 32;
434 		} else {
435 			vsp->y = (i / 20) * 32;
436 			vsp->x = (i % 20) * 32;
437 		}
438 		vsp->id = 1000 + i;
439 		vsp->zoneNum = zoneNum;
440 	}
441 }
442 
startAnOverlayAnim()443 void AGOSEngine_PuzzlePack::startAnOverlayAnim() {
444 	VgaSprite *vsp = _vgaSprites;
445 	const byte *vcPtrOrg;
446 	uint16 a, sprite, file, tmp, zoneNum;
447 	int16 x;
448 
449 	zoneNum = _variableArray[999];
450 
451 	_vcPtr += 4;
452 	a = vcReadNextWord();
453 	_vcPtr += 6;
454 
455 	while (vsp->id)
456 		vsp++;
457 
458 	vsp->windowNum = 4;
459 	vsp->priority = 20;
460 	vsp->flags = 0;
461 	vsp->palette = 0;
462 	vsp->image = vcReadVar(vcReadVar(a));
463 
464 	x = vcReadVar(a) - 1300;
465 	if (x < 0) {
466 		x += 300;
467 		vsp->priority = 10;
468 	}
469 
470 	vsp->y = x / 20 * 32;
471 	vsp->x = x % 20 * 32;
472 	vsp->id = vcReadVar(a);
473 	vsp->zoneNum = zoneNum;
474 
475 	sprite = _vgaCurSpriteId;
476 	file = _vgaCurZoneNum;
477 
478 	_vgaCurZoneNum = vsp->zoneNum;
479 	_vgaCurSpriteId = vsp->id;
480 
481 	tmp = to16Wrapper(vsp->priority);
482 
483 	vcPtrOrg = _vcPtr;
484 	_vcPtr = (byte *)&tmp;
485 	vc23_setPriority();
486 
487 	_vcPtr = vcPtrOrg;
488 	_vgaCurSpriteId = sprite;
489 	_vgaCurZoneNum = file;
490 }
491 
492 } // End of namespace AGOS
493 
494 #endif // ENABLE_AGOS2
495