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