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 #include "ags/lib/allegro.h"
24 #include "ags/plugins/ags_pal_render/ags_pal_render.h"
25 #include "ags/plugins/ags_pal_render/pal_render.h"
26 #include "ags/plugins/ags_pal_render/raycast.h"
27 #include "ags/ags.h"
28
29 namespace AGS3 {
30 namespace Plugins {
31 namespace AGSPalRender {
32
33 #define MAX_OVERLAYS 128
34 #define MAX_STARS 1024
35 #define MAX_DEPTH 64
36
37 #define PI (3.1415926535f)
38 #define HALF_PI (0.5f * PI)
39 #define TWO_PI (2.0f * PI)
40 #define TWO_PI_INV (1.0f / TWO_PI)
41
42 const float halfpi = (0.5f * PI);
43 const float twopi = (2.0f * PI);
44 const float twopi_inv = (1.0f / TWO_PI);
45 const float pisquared = PI * PI;
46 const float picubed = PI * PI * PI;
47
48 IAGSEngine *engine;
49 //unsigned char clut[256][256];
50 unsigned char clut[65536];
51
52 struct transoverlaytype {
53 int sprite;
54 int spritemask;
55 int blendtype;
56 int x;
57 int y;
58 int trans;
59 int level;
60 bool enabled;
61 } overlay[MAX_OVERLAYS];
62
63 int clutslot;
64 int drawreflections;
65 byte cycle_remap[256];
66
67 struct starstype {
68 float x;
69 float y;
70 float z;
71 unsigned char color;
72 long sprite;
73 int maxrad;
74 int scaleboost;
75 };
76 starstype *stars;
77
78 struct starsoptions {
79 float speed;
80 int maxstars;
81 int depthmultiplier;
82 int originx;
83 int originy;
84 int overscan;
85 } Starfield;
86 long *reflectionmap;
87 BITMAP *rcolormap;
88 BITMAP *ralphamap;
89
90 struct charrefopt {
91 int8 reflect;
92 int replaceview;
93 };
94
95 struct objrefopt {
96 int8 reflect;
97 int8 ignorescaling;
98 };
99
100 struct reflectionopt {
101 charrefopt *Characters;
102 objrefopt *Objects;
103 int blendslot;
104 int blendamount;
105 } Reflection;
106
107 int dummy;
108
109 #define LENS_WIDTH 150
110
111 struct LensDistort {
112 int xoffset;
113 int yoffset;
114 };
115
116 LensDistort *lens;
117 struct LensOpt {
118 bool draw;
119 int lenswidth;
120 int lenszoom;
121 int level;
122 int x;
123 int y;
124 int clampoffset;
125 } LensOption;
126
127 const int alphamultiply [4096] = {
128 //#include "alphamultiply.txt"
129 };
130 float rot_sine_LUT[360];
131 float rot_cos_LUT[360];
132
133 BITMAP *backgroundimage;
134
135 PALSTRUCT objectivepal[256];
136 int bgimgspr;
137
WriteObjectivePalette(ScriptMethodParams & params)138 void AGSPalRender::WriteObjectivePalette(ScriptMethodParams ¶ms) {
139 PARAMS4(unsigned char, index, unsigned char, r, unsigned char, b, unsigned char, g);
140 objectivepal[index].r = r;
141 objectivepal[index].b = b;
142 objectivepal[index].g = g;
143 }
144
ReadObjectivePaletteR(ScriptMethodParams & params)145 void AGSPalRender::ReadObjectivePaletteR(ScriptMethodParams ¶ms) {
146 PARAMS1(unsigned char, index);
147 params._result = (int)objectivepal[index].r;
148 }
149
ReadObjectivePaletteB(ScriptMethodParams & params)150 void AGSPalRender::ReadObjectivePaletteB(ScriptMethodParams ¶ms) {
151 PARAMS1(unsigned char, index);
152 params._result = (int)objectivepal[index].b;
153 }
ReadObjectivePaletteG(ScriptMethodParams & params)154 void AGSPalRender::ReadObjectivePaletteG(ScriptMethodParams ¶ms) {
155 PARAMS1(unsigned char, index);
156 params._result = (int)objectivepal[index].g;
157 }
158
159
160 #define SQRT_MAGIC_F 0x5f3759df
q3sqrt(const float x)161 float q3sqrt(const float x) {
162 const float xhalf = 0.5f * x;
163
164 union { // get bits for floating value
165 float x;
166 int i;
167 } u;
168 u.x = x;
169 u.i = SQRT_MAGIC_F - (u.i >> 1); // gives initial guess y0
170 return x * u.x * (1.5f - xhalf * u.x * u.x); // Newton step, repeating increases accuracy
171 }
172
Make_Sin_Lut()173 void Make_Sin_Lut() {
174 for (int angle = 0; angle < 360; angle++) {
175 double rad = (angle * PI) / 180.0;
176 rot_sine_LUT [angle] = static_cast<float>(sin(rad));
177 rot_cos_LUT [angle] = static_cast<float>(cos(rad));
178 }
179 }
180
181 /*
182 void PreMultiply_Alphas () //Ha ha, this isn't the kind of premultiplcation you're thinking of.
183 {
184 for (int y=0;y<64;y++)
185 for (int x=0;x<64;x++)
186 alphamultiply [y*64+x] = y*x;
187 }
188 */
189
GetModifiedBackgroundImage(ScriptMethodParams & params)190 void AGSPalRender::GetModifiedBackgroundImage(ScriptMethodParams ¶ms) {
191 params._result = bgimgspr;
192 }
193
root(unsigned short x)194 unsigned short root(unsigned short x) {
195 unsigned short a, b;
196 b = x;
197 a = x = 0x3f;
198 x = b / x;
199 a = x = (x + a) >> 1;
200 x = b / x;
201 a = x = (x + a) >> 1;
202 x = b / x;
203 x = (x + a) >> 1;
204 return (x);
205 }
206
207
Hill(float x)208 float Hill(float x) {
209 const float a0 = 1.0f;
210 const float a2 = 2.0f / PI - 12.0f / (pisquared);
211 const float a3 = 16.0f / (picubed) - 4.0f / (pisquared);
212 const float xx = x * x;
213 const float xxx = xx * x;
214
215 return a0 + a2 * xx + a3 * xxx;
216 }
217
FastSin(float x)218 float FastSin(float x) {
219 // wrap x within [0, TWO_PI)
220 const float a = x * twopi_inv;
221 x -= static_cast<int>(a) * twopi;
222 if (x < 0.0f)
223 x += twopi;
224
225 // 4 pieces of hills
226 if (x < halfpi)
227 return Hill(halfpi - x);
228 else if (x < PI)
229 return Hill(x - halfpi);
230 else if (x < 3.0f * halfpi)
231 return -Hill(3.0f * halfpi - x);
232 else
233 return -Hill(x - 3.0f * halfpi);
234 }
235
FastCos(float x)236 float FastCos(float x) {
237 return FastSin(x + halfpi);
238 }
239
AGSFastRoot(ScriptMethodParams & params)240 void AGSPalRender::AGSFastRoot(ScriptMethodParams ¶ms) {
241 PARAMS1(unsigned short, x);
242 x = root(x);
243 params._result = (int)x;
244 }
245
AGSFastSin(ScriptMethodParams & params)246 void AGSPalRender::AGSFastSin(ScriptMethodParams ¶ms) {
247 PARAMS1(int32, xi);
248 float x = PARAM_TO_FLOAT(xi);
249 x = FastSin(x);
250 params._result = PARAM_FROM_FLOAT(x);
251 }
252
AGSFastCos(ScriptMethodParams & params)253 void AGSPalRender::AGSFastCos(ScriptMethodParams ¶ms) {
254 PARAMS1(int32, xi);
255 float x = PARAM_TO_FLOAT(xi);
256 x = FastSin(x + halfpi);
257 params._result = PARAM_FROM_FLOAT(x);
258 }
259
260
DrawLens(int ox,int oy)261 void DrawLens(int ox, int oy) {
262 int32 sh, sw = 0;
263 engine->GetScreenDimensions(&sw, &sh, nullptr);
264 BITMAP *virtsc = engine->GetVirtualScreen();
265 if (!virtsc) engine->AbortGame("DrawLens: Cannot get virtual screen.");
266 BITMAP *lenswrite = engine->CreateBlankBitmap(LensOption.lenswidth, LensOption.lenswidth, 8);
267 uint8 *vScreen = engine->GetRawBitmapSurface(virtsc);
268 uint8 *lensarray = engine->GetRawBitmapSurface(lenswrite);
269 int virtscPitch = engine->GetBitmapPitch(virtsc);
270 int lenswritePitch = engine->GetBitmapPitch(lenswrite);
271 int radius = LensOption.lenswidth >> 1;
272 for (int y = 0, lensy = 0; y < LensOption.lenswidth; y++, lensy += lenswritePitch) {
273 int ypos = y * LensOption.lenswidth;
274 for (int x = 0; x < LensOption.lenswidth; x++) {
275 int lenspos = ypos + x;
276 int coffx = lens[lenspos].xoffset;
277 int coffy = lens[lenspos].yoffset;
278 if (oy + coffy > 0 && oy + coffy < sh && ox + coffx > 0 && ox + coffx < sw) {
279 lensarray[lensy + x] = vScreen[(oy + coffy) * virtscPitch + ox + coffx];
280 //vScreen[(oy + coffy) * virtscPitch + ox + coffx] = ABS(coffy);
281 }
282 }
283 }
284 /*
285 for (int y=0, lensy = 0;y<LensOption.lenswidth;y++, lensy += lenswritePitch)
286 {
287 int ypos = y*LensOption.lenswidth;
288 for (int x=0;x<LensOption.lenswidth;x++)
289 {
290 if (oy+y > 0 && oy+y < sh && ox+x > 0 && ox+x < sw)
291 {
292 vScreen[(oy+y) * virtscPitch + ox+x] = lensarray[lensy + x];
293 }
294 }
295 }
296 */
297 int radsq = radius * radius;
298 for (int cy = -radius, lensy = 0; cy <= radius; cy++, lensy += lenswritePitch) { //Draw a circle around the point, for the mask.
299 int cysq = cy * cy;
300 for (int cx = -radius; cx <= radius; cx++) {
301 int cxsq = cx * cx;
302 int dx = cx + ox;
303 int dy = cy + oy;
304 if ((cxsq + cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0 && cy + radius < LensOption.lenswidth - 1 && cx + radius < LensOption.lenswidth - 1) {
305 //if (cy+radius < 0 || cx+radius < 0) engine->AbortGame ("I did something wrong");
306 vScreen[dy * virtscPitch + dx] = lensarray[lensy + cx + radius];
307 }
308 }
309 }
310
311 engine->ReleaseBitmapSurface(lenswrite);
312 engine->ReleaseBitmapSurface(virtsc);
313 engine->FreeBitmap(lenswrite);
314 }
315
SetLensPos(ScriptMethodParams & params)316 void AGSPalRender::SetLensPos(ScriptMethodParams ¶ms) {
317 PARAMS2(int, x, int, y);
318 LensOption.x = x;
319 LensOption.y = y;
320 }
321
GetLensX(ScriptMethodParams & params)322 void AGSPalRender::GetLensX(ScriptMethodParams ¶ms) {
323 params._result = LensOption.x;
324 }
325
GetLensY(ScriptMethodParams & params)326 void AGSPalRender::GetLensY(ScriptMethodParams ¶ms) {
327 params._result = LensOption.y;
328 }
329
SetLensDrawn(ScriptMethodParams & params)330 void AGSPalRender::SetLensDrawn(ScriptMethodParams ¶ms) {
331 PARAMS1(int, toggle);
332 if (toggle > 0) LensOption.draw = 1;
333 else LensOption.draw = 0;
334 }
335
GetLensDrawn(ScriptMethodParams & params)336 void AGSPalRender::GetLensDrawn(ScriptMethodParams ¶ms) {
337 params._result = LensOption.draw;
338 }
339
SetLensOffsetClamp(ScriptMethodParams & params)340 void AGSPalRender::SetLensOffsetClamp(ScriptMethodParams ¶ms) {
341 PARAMS1(int, clamp);
342 if (clamp < 0) LensOption.clampoffset = LensOption.lenswidth;
343 else LensOption.clampoffset = clamp;
344 }
345
GetLensOffsetClamp(ScriptMethodParams & params)346 void AGSPalRender::GetLensOffsetClamp(ScriptMethodParams ¶ms) {
347 params._result = LensOption.clampoffset;
348 }
349
GetLensLevel(ScriptMethodParams & params)350 void AGSPalRender::GetLensLevel(ScriptMethodParams ¶ms) {
351 params._result = LensOption.level;
352 }
353
SetLensLevel(ScriptMethodParams & params)354 void AGSPalRender::SetLensLevel(ScriptMethodParams ¶ms) {
355 PARAMS1(int, level);
356 if (level < 0 || level > 4) engine->AbortGame("SetLensLevel: Invalid level.");
357 else LensOption.level = level;
358 }
359
LensInitialize(ScriptMethodParams & params)360 void AGSPalRender::LensInitialize(ScriptMethodParams ¶ms) {
361 PARAMS5(int, width, int, zoom, int, lensx, int, lensy, int, level);
362 int clamp = -1;
363 if (params.size() > 5)
364 clamp = (int)params[5];
365
366 int32 sw, sh, radius;
367 if (width < 1) engine->AbortGame("Invalid lens dimension!");
368 radius = width >> 1;
369 lens = new LensDistort [width * width]();
370 engine->GetScreenDimensions(&sw, &sh, nullptr);
371 int radsq = radius * radius;
372 int zoomsq = zoom * zoom;
373 for (int y = 0; y < radius; y++) {
374 int ysq = y * y;
375 for (int x = 0; x < radius; x++) {
376 int lx, ly;
377 int xsq = x * x;
378 if ((xsq + ysq) < (radsq)) {
379 float shift = zoom / sqrt((float)(zoomsq - (xsq + ysq - radsq)));
380 lx = (int)(x * shift - x);
381 ly = (int)(y * shift - y);
382 } else {
383 lx = 0;
384 ly = 0;
385 }
386 lens[(radius - y)*width + (radius - x)].xoffset = lx;
387 lens[(radius - y)*width + (radius - x)].yoffset = ly;
388 lens[(radius + y)*width + (radius + x)].xoffset = -lx;
389 lens[(radius + y)*width + (radius + x)].yoffset = -ly;
390 lens[(radius + y)*width + (radius - x)].xoffset = lx;
391 lens[(radius + y)*width + (radius - x)].yoffset = -ly;
392 lens[(radius - y)*width + (radius + x)].xoffset = -lx;
393 lens[(radius - y)*width + (radius + x)].yoffset = ly;
394 }
395 }
396 LensOption.lenswidth = width;
397 LensOption.lenszoom = zoom;
398 if (clamp < 0) LensOption.clampoffset = width;
399 else LensOption.clampoffset = clamp;
400 LensOption.x = lensx;
401 LensOption.y = lensy;
402 if (level < 0 || level > 4) engine->AbortGame("SetLensLevel: Invalid level.");
403 else LensOption.level = level;
404 }
405
ResetRemapping(ScriptMethodParams &)406 void AGSPalRender::ResetRemapping(ScriptMethodParams &) {
407 for (int j = 0; j < 256; ++j) {
408 cycle_remap [j] = j;
409 }
410 }
411
412 #define MAX_PLASMA_COMPLEXITY 4
413 int plasmatype[MAX_PLASMA_COMPLEXITY];
414 int plasmadata [MAX_PLASMA_COMPLEXITY];
415 int plasmadata2 [MAX_PLASMA_COMPLEXITY];
416 int plasmadata3 [MAX_PLASMA_COMPLEXITY];
417 int plasmaroottype;
418
419
SetPlasmaRootType(ScriptMethodParams & params)420 void AGSPalRender::SetPlasmaRootType(ScriptMethodParams ¶ms) {
421 PARAMS1(int, real);
422 if (real) plasmaroottype = 1;
423 else plasmaroottype = 0;
424 }
425
GetPlasmaRootType(ScriptMethodParams & params)426 void AGSPalRender::GetPlasmaRootType(ScriptMethodParams ¶ms) {
427 params._result = plasmaroottype;
428 }
429
SetPlasmaType(ScriptMethodParams & params)430 void AGSPalRender::SetPlasmaType(ScriptMethodParams ¶ms) {
431 PARAMS5(int, component, int, type, int, data, int, data2, int, data3);
432 if (component >= MAX_PLASMA_COMPLEXITY) engine->AbortGame("Plasma too complex!");
433 else {
434 plasmatype [component] = type;
435 plasmadata [component] = data;
436 plasmadata2[component] = data2;
437 plasmadata3[component] = data3;
438 }
439
440 //0 = None.
441 //1 = Horizontal Bars (data=width)
442 //2 = Vertical Bars (data=width)
443 //3 = Circle (data=x,data2=y,data3=width)
444 //4 = Diagonal Bars (data=width)
445 }
446
ResetPlasmaSettings(ScriptMethodParams &)447 void AGSPalRender::ResetPlasmaSettings(ScriptMethodParams &) {
448 int i = 0;
449 while (i < MAX_PLASMA_COMPLEXITY) {
450 plasmatype [i] = 0;
451 plasmadata [i] = 0;
452 plasmadata2[i] = 0;
453 plasmadata3[i] = 0;
454 i++;
455 }
456 }
457
DrawPlasma(ScriptMethodParams & params)458 void AGSPalRender::DrawPlasma(ScriptMethodParams ¶ms) {
459 PARAMS3(int, slot, int, palstart, int, palend);
460 BITMAP *plasmaspr = engine->GetSpriteGraphic(slot);
461 if (!plasmaspr) engine->AbortGame("Plasma: Not a sprite I can load.");
462 int32 w, h, basecol, range = 0;
463 if (palend > palstart) {
464 range = palend - palstart;
465 basecol = palstart;
466 } else {
467 range = palstart - palend;
468 basecol = palend;
469 }
470 engine->GetBitmapDimensions(plasmaspr, &w, &h, nullptr);
471 uint8 *plasmarray = engine->GetRawBitmapSurface(plasmaspr);
472 int plasmapitch = engine->GetBitmapPitch(plasmaspr);
473 double frange = range / 2.0;
474 int complex = 0;
475 int color = 0;
476 int i = 0;
477 while (i < MAX_PLASMA_COMPLEXITY) {
478 if (plasmatype[i] > 0) complex++;
479 i++;
480 }
481 for (int x = 0; x < w; x++) {
482 for (int y = 0, plasmay = 0; y < h; y++, plasmay += plasmapitch) {
483 color = 0;
484 for (int p = 0; p < MAX_PLASMA_COMPLEXITY; p++) {
485 if (plasmatype[p] == 1) { //1 = Horizontal Bars (data=width)
486 color += int(frange + (frange * FastSin(y / (float)plasmadata[p])));
487 } else if (plasmatype[p] == 2) { //2 = Vertical Bars (data=width)
488 color += int(frange + (frange * FastSin(x / (float)plasmadata[p])));
489 } else if (plasmatype[p] == 3) { //3 = Circle (data=x,data2=y,data3=width)
490 int cx, cy = 0;
491 cx = plasmadata [p];
492 cy = plasmadata2 [p];
493 if (plasmaroottype == 1) color += int(frange + (frange * FastSin(q3sqrt((float)((x - cx) * (x - cx) + (y - cy) * (y - cy)) / plasmadata3[p]))));
494 else color += int(frange + (frange * FastSin(root(((x - cx) * (x - cx) + (y - cy) * (y - cy)) / plasmadata3[p]))));
495 } else if (plasmatype[p] == 4) { //4 = Diagonal Bars (data=width)
496 color += int(frange + (frange * FastSin((x + y) / (float)plasmadata[p])));
497 }
498 }
499 if (color > 0 && complex > 0) color = color / complex;
500 plasmarray[plasmay + x] = static_cast<unsigned char>(basecol + color);
501 }
502 }
503 engine->ReleaseBitmapSurface(plasmaspr);
504 engine->NotifySpriteUpdated(slot);
505 }
506
DoFire(ScriptMethodParams & params)507 void AGSPalRender::DoFire(ScriptMethodParams ¶ms) {
508 PARAMS8(int, spriteId, int, masksprite, int, palstart, int, palend, int, strength, int, seed, int, cutoff, int, windspeed);
509 BITMAP *firespr = engine->GetSpriteGraphic(masksprite);
510 BITMAP *firecolorspr = engine->GetSpriteGraphic(spriteId);
511 BITMAP *seedspr;
512 int32 w, h = 0;
513 int range, basecol, dir = 0;
514 if (palend > palstart) {
515 range = palend - palstart;
516 basecol = palstart;
517 dir = 1;
518 } else {
519 range = palstart - palend;
520 basecol = palend;
521 dir = -1;
522 }
523 int divider = 256 / range;
524 engine->GetBitmapDimensions(firespr, &w, &h, nullptr);
525 uint8 *fire = engine->GetRawBitmapSurface(firespr);
526 uint8 *color = engine->GetRawBitmapSurface(firecolorspr);
527 int firePitch = engine->GetBitmapPitch(firespr);
528 int colorPitch = engine->GetBitmapPitch(firecolorspr);
529 int sparky = 0;
530 //srand(time(NULL));
531 for (int y = 0, firey = 0; y < h - 1; y++, firey += firePitch) {
532 if ((int)::AGS::g_vm->getRandomNumber(9) > 7 - windspeed) { //Wind right
533 for (int x = w - 1; x > 1; x--) {
534 fire[firey + x] = fire[firey + x - 1];
535 }
536 } else if ((int)::AGS::g_vm->getRandomNumber(9) > 7 + windspeed) { // wind left
537 for (int x = 0; x < w - 1; x++) {
538 fire[firey + x] = fire[firey + x + 1];
539 }
540 }
541 }
542 for (int x = 0; x < w; x++) {
543 sparky = ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % (h - 2));
544 int firexy = (h - sparky) * firePitch + x;
545 if (sparky < h && sparky > 0 && fire[firexy] > cutoff &&
546 ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % 10) > 7)
547 fire[firexy] = 255;
548 sparky = ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % (h - 2));
549 firexy = (h - sparky) * firePitch + x;
550 if (sparky < h && sparky > 0 && fire[firexy] > cutoff &&
551 ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % 10) > 7)
552 fire[firexy] = 0;
553 }
554 if (seed == 0) {
555 int firey = (h - 1) * firePitch;
556 for (int x = 0; x < w; x++)
557 fire[firey + x] = 255;
558 firey = (h - 2) * firePitch;
559 for (int x = 0; x < w; x++)
560 fire[firey + x] = ::AGS::g_vm->getRandomNumber(255);
561 } else if (seed > 0) {
562 seedspr = engine->GetSpriteGraphic(seed);
563 BITMAP *virtsc = engine->GetVirtualScreen();
564 engine->SetVirtualScreen(firespr);
565 engine->BlitBitmap(0, 0, seedspr, 1);
566 engine->SetVirtualScreen(virtsc);
567 engine->ReleaseBitmapSurface(virtsc);
568 engine->ReleaseBitmapSurface(seedspr);
569 engine->NotifySpriteUpdated(spriteId);
570 engine->NotifySpriteUpdated(masksprite);
571 }
572
573 for (int y = 0, firey = 0, colory = 0; y < h - 1; y++, firey += firePitch, colory += colorPitch) {
574 for (int x = 0; x < w; x++) {
575 fire[firey + x] =
576 ((fire[((y + 1) % h) * firePitch + ((x - 1 + w) % w)]
577 + fire[((y + 1) % h) * firePitch + ((x) % w)]
578 + fire[((y + 1) % h) * firePitch + ((x + 1) % w)]
579 + fire[((y + 2) % h) * firePitch + ((x) % w)])
580 * 100) / (400 + (100 - strength));
581 if (fire[firey + x] < cutoff) fire[firey + x] = 0;
582 //if (fire[firey + x] ==255) color [colory + x] = palend;
583 else color [colory + x] = static_cast<uint8>(basecol + (fire[firey + x] / divider) * dir);
584 }
585 }
586 engine->ReleaseBitmapSurface(firespr);
587 engine->ReleaseBitmapSurface(firecolorspr);
588 engine->NotifySpriteUpdated(spriteId);
589 engine->NotifySpriteUpdated(masksprite);
590 }
591
592 /*
593 unsigned char MixColorAlpha (unsigned char fg,unsigned char bg,unsigned char alpha)
594 {
595 //unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
596 //unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
597 //BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
598 //if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
599 //uint8 *clutarray = engine->GetRawBitmapSurface (clutspr);
600 AGSColor *palette = engine->GetPalette ();
601 int i=0;
602 int out_r = (palette[fg].r>>1) * alpha + (palette[bg].r>>1) * (255 - alpha);
603 int out_g = palette[fg].g * alpha + palette[bg].g * (255 - alpha);
604 int out_b = (palette[fg].b>>1) * alpha + (palette[bg].b>>1) * (255 - alpha);
605 //unsigned char ralpha = alpha>>2;
606 //unsigned char invralpha = 64-ralpha;
607 //if (ralpha > alpha) engine->AbortGame ("wtf");
608 //int out_r = alphamultiply[(palette[fg].r>>1)][ralpha] + alphamultiply[(palette[bg].r>>1)][(invralpha)];
609 //int out_g = alphamultiply[(palette[fg].g)][ralpha] + alphamultiply[(palette[bg].g)][(invralpha)];
610 //int out_b = alphamultiply[(palette[fg].b>>1)][ralpha] + alphamultiply[(palette[bg].b>>1)][(invralpha)];
611 out_r = (out_r + 1 + (out_r >> 8)) >> 8;
612 out_g = (out_g + 1 + (out_g >> 8)) >> 8;
613 out_b = (out_b + 1 + (out_b >> 8)) >> 8;
614 i = ((out_r << 11) | (out_g << 5) | out_b);
615 unsigned char (*clutp) = clut;
616 //unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
617 unsigned char result = cycle_remap [*(clutp+i)]; //Once again, to make sure that the palette slot used is the right one.
618 //engine->ReleaseBitmapSurface (clutspr);
619 return result;
620 }
621
622 unsigned char MixColorAdditive (unsigned char fg,unsigned char bg,unsigned char alpha)
623 {
624 //unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
625 //unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
626 //BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
627 //if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
628 //uint8 *clutarray = engine->GetRawBitmapSurface (clutspr);
629 AGSColor *palette = engine->GetPalette ();
630 int i=0;
631 int add_r,add_b,add_g = 0;
632 char ralpha = alpha>>2;
633 //if (ralpha > alpha) engine->AbortGame ("wtf");
634 //add_r = (((palette[fg].r>>1) * (alpha))>>8);
635 //add_b = (((palette[fg].b>>1) * (alpha))>>8);
636 //add_g = (((palette[fg].g) * (alpha))>>8);
637 add_r = ((alphamultiply[(palette[fg].r>>1)*64+ralpha])>>6);
638 add_b = ((alphamultiply[(palette[fg].b>>1)*64+ralpha])>>6);
639 add_g = ((alphamultiply[(palette[fg].g )*64+ralpha])>>6);
640 int out_r = min(31,(palette[bg].r>>1) + add_r);
641 int out_g = min(63, palette[bg].g + add_g);
642 int out_b = min(31,(palette[bg].b>>1) + add_b);
643 i = ((out_r << 11) | (out_g << 5) | out_b);
644 unsigned char (*clutp) = clut;
645 unsigned char result = cycle_remap [*(clutp+i)]; //Once again, to make sure that the palette slot used is the right one.
646 //unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
647 //engine->ReleaseBitmapSurface (clutspr);
648 return result;
649 }
650 */
GetColor565(ScriptMethodParams & params)651 void AGSPalRender::GetColor565(ScriptMethodParams ¶ms) {
652 PARAMS3(unsigned char, r, unsigned char, g, unsigned char, b);
653 //BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
654 //if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
655 //uint8 *clutarray = engine->GetRawBitmapSurface (clutspr);
656 int i = ((r << 11) | (g << 5) | b);
657 unsigned char *clutp = clut;
658 unsigned char result = *(clutp + i);
659 result = cycle_remap [result]; //Once again, to make sure that the palette slot used is the right one.
660 //engine->ReleaseBitmapSurface (clutspr);
661 params._result = (int)result;
662 }
663
CycleRemap(ScriptMethodParams & params)664 void AGSPalRender::CycleRemap(ScriptMethodParams ¶ms) {
665 PARAMS2(int, start, int, end);
666 if (end > start) {
667 // Rotate left
668 int wraparound = cycle_remap [start];
669 for (; start < end; ++start) {
670 cycle_remap [start] = cycle_remap [start + 1];
671 }
672 cycle_remap [end] = wraparound;
673 } else if (end < start) {
674 // Rotate right
675 int wraparound = cycle_remap [start];
676 for (; start > end; --start) {
677 cycle_remap [start] = cycle_remap [start - 1];
678 }
679 cycle_remap [end] = wraparound;
680
681 }
682 }
683
GetRemappedSlot(ScriptMethodParams & params)684 void AGSPalRender::GetRemappedSlot(ScriptMethodParams ¶ms) {
685 PARAMS1(unsigned char, slot);
686 params._result = cycle_remap [slot];
687 }
688
LoadCLUT(ScriptMethodParams & params)689 void AGSPalRender::LoadCLUT(ScriptMethodParams ¶ms) {
690 PARAMS1(int, slot);
691 if (engine->GetSpriteWidth(slot) != 256 || engine->GetSpriteHeight(slot) != 256) {
692 params._result = 1;
693 return;
694 };
695 BITMAP *clutimage = engine->GetSpriteGraphic(slot);
696 uint8 *clutarray = engine->GetRawBitmapSurface(clutimage);
697 int pitch = engine->GetBitmapPitch(clutimage);
698 for (int y = 0, arrayy = 0, cluty = 0; y < 256; y++, arrayy += pitch, cluty += 256) {
699 for (int x = 0; x < 256; x++) {
700 clut[cluty + x] = clutarray[arrayy + x];
701 }
702 }
703 clutslot = slot;
704 engine->ReleaseBitmapSurface(clutimage);
705 params._result = 0;
706 }
707
SetReflections(ScriptMethodParams & params)708 void AGSPalRender::SetReflections(ScriptMethodParams ¶ms) {
709 PARAMS1(int, toggle);
710 drawreflections = toggle;
711 }
712
IsReflectionsOn(ScriptMethodParams & params)713 void AGSPalRender::IsReflectionsOn(ScriptMethodParams ¶ms) {
714 params._result = drawreflections;
715 }
716
GetLuminosityFromPalette(ScriptMethodParams & params)717 void AGSPalRender::GetLuminosityFromPalette(ScriptMethodParams ¶ms) {
718 PARAMS1(int, slot);
719 AGSColor *pal = engine->GetPalette();
720 int lum = (pal[slot].r +
721 pal[slot].r +
722 pal[slot].r +
723 pal[slot].g +
724 pal[slot].g +
725 pal[slot].g +
726 pal[slot].g +
727 pal[slot].b) >> 3;
728 params._result = lum;
729 }
730
731
732
SetStarsOriginPoint(ScriptMethodParams & params)733 void AGSPalRender::SetStarsOriginPoint(ScriptMethodParams ¶ms) {
734 PARAMS2(int, x, int, y);
735 Starfield.originx = x;
736 Starfield.originy = y;
737 }
InitializeStars(ScriptMethodParams & params)738 void AGSPalRender::InitializeStars(ScriptMethodParams ¶ms) {
739 PARAMS2(int, slot, int, maxstars);
740 int32 sw, sh = 0;
741 BITMAP *canvas = engine->GetSpriteGraphic(slot);
742 engine->GetBitmapDimensions(canvas, &sw, &sh, nullptr);
743 Starfield.maxstars = maxstars;
744 Starfield.overscan = 20;
745 stars = new starstype [Starfield.maxstars];
746 for (int i = 0; i < Starfield.maxstars; i++) {
747 stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
748 if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
749 stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
750 if (stars[i].y < 1.0 && stars[i].y > -1.0) stars[i].y = (float)sh;
751 stars[i].z = (float)(MAX_DEPTH);
752 stars[i].color = (::AGS::g_vm->getRandomNumber(0x7fffffff) % 240);
753 stars[i].sprite = 0;
754 stars[i].maxrad = (::AGS::g_vm->getRandomNumber(0x7fffffff) % 5);
755 }
756 }
757
IterateStars(ScriptMethodParams & params)758 void AGSPalRender::IterateStars(ScriptMethodParams ¶ms) {
759 PARAMS1(int, slot);
760 long sw, sh = 0;
761 sw = engine->GetSpriteWidth(slot);
762 sh = engine->GetSpriteHeight(slot);
763 for (int i = 0; i < Starfield.maxstars; i++) {
764 stars[i].z -= Starfield.speed;
765 //if (stars[i].z < 1.0) stars[i].z = (double)MAX_DEPTH;
766 float k = Starfield.depthmultiplier / stars[i].z;
767 int px = static_cast<int>(stars[i].x * k + Starfield.originx);
768 int py = static_cast<int>(stars[i].y * k + Starfield.originy);
769 if (px >= sw + Starfield.overscan || px < 0 - Starfield.overscan || py >= sh + Starfield.overscan || py < 0 - Starfield.overscan) {
770 stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
771 if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
772 stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
773 if (stars[i].y < 1.0 && stars[i].y > 1.0) stars[i].y = (float)sh;
774 stars[i].z = (float)MAX_DEPTH;
775 //stars[i].color = (rand () %240);
776 }
777 }
778 }
GetStarfieldOverscan(ScriptMethodParams & params)779 void AGSPalRender::GetStarfieldOverscan(ScriptMethodParams ¶ms) {
780 params._result = Starfield.overscan;
781 }
SetStarfieldOverscan(ScriptMethodParams & params)782 void AGSPalRender::SetStarfieldOverscan(ScriptMethodParams ¶ms) {
783 PARAMS1(int, overscan);
784 Starfield.overscan = overscan;
785 }
786
GetStarfieldOriginX(ScriptMethodParams & params)787 void AGSPalRender::GetStarfieldOriginX(ScriptMethodParams ¶ms) {
788 params._result = Starfield.originx;
789 }
790
GetStarfieldOriginY(ScriptMethodParams & params)791 void AGSPalRender::GetStarfieldOriginY(ScriptMethodParams ¶ms) {
792 params._result = Starfield.originy;
793 }
794
SetStarfieldDepthMultiplier(ScriptMethodParams & params)795 void AGSPalRender::SetStarfieldDepthMultiplier(ScriptMethodParams ¶ms) {
796 PARAMS1(int, multi);
797 Starfield.depthmultiplier = multi;
798 }
799
GetStarfieldDepthMultiplier(ScriptMethodParams & params)800 void AGSPalRender::GetStarfieldDepthMultiplier(ScriptMethodParams ¶ms) {
801 params._result = Starfield.depthmultiplier;
802 }
803
GetStarfieldMaxStars(ScriptMethodParams & params)804 void AGSPalRender::GetStarfieldMaxStars(ScriptMethodParams ¶ms) {
805 params._result = Starfield.maxstars;
806 }
807
SetStarSpriteScaleBoost(ScriptMethodParams & params)808 void AGSPalRender::SetStarSpriteScaleBoost(ScriptMethodParams ¶ms) {
809 PARAMS2(int, star, int, boost);
810 stars[star].scaleboost = boost;
811 }
812
GetStarSpriteScaleBoost(ScriptMethodParams & params)813 void AGSPalRender::GetStarSpriteScaleBoost(ScriptMethodParams ¶ms) {
814 PARAMS1(int, star);
815 params._result = stars[star].scaleboost;
816 }
817
SetStarMaxRadius(ScriptMethodParams & params)818 void AGSPalRender::SetStarMaxRadius(ScriptMethodParams ¶ms) {
819 PARAMS2(int, star, int, radius);
820 stars[star].maxrad = radius;
821 }
822
GetStarMaxRadius(ScriptMethodParams & params)823 void AGSPalRender::GetStarMaxRadius(ScriptMethodParams ¶ms) {
824 PARAMS1(int, star);
825 params._result = stars[star].maxrad;
826 }
827
RotateStar(ScriptMethodParams & params)828 void AGSPalRender::RotateStar(ScriptMethodParams ¶ms) {
829 PARAMS4(int, star, int, angle, int, px, int, py);
830 float rsin = rot_sine_LUT[angle];
831 float rcos = rot_cos_LUT[angle];
832 float fPx = (float)px;
833 float fPy = (float)py;
834 float x1 = 0, y1 = 0, xRot = 0, yRot = 0;
835 int i = star;
836 x1 = stars[i].x;
837 y1 = stars[i].y;
838 xRot = fPx + rcos * (x1 - fPx) - rsin * (y1 - fPy);
839 yRot = fPy + rsin * (x1 - fPx) + rcos * (y1 - fPy);
840 stars[i].x = xRot;
841 stars[i].y = yRot;
842 i++;
843 }
844
GetStarX(ScriptMethodParams & params)845 void AGSPalRender::GetStarX(ScriptMethodParams ¶ms) {
846 PARAMS1(int, i);
847 float starx = (float)stars[i].x;
848 params._result = PARAM_FROM_FLOAT(starx);
849 }
850
GetStarY(ScriptMethodParams & params)851 void AGSPalRender::GetStarY(ScriptMethodParams ¶ms) {
852 PARAMS1(int, i);
853 float stary = (float)stars[i].y;
854 params._result = PARAM_FROM_FLOAT(stary);
855 }
856
GetStarZ(ScriptMethodParams & params)857 void AGSPalRender::GetStarZ(ScriptMethodParams ¶ms) {
858 PARAMS1(int, i);
859 float starz = (float)stars[i].z;
860 params._result = PARAM_FROM_FLOAT(starz);
861 }
862
SetStarPosition(ScriptMethodParams & params)863 void AGSPalRender::SetStarPosition(ScriptMethodParams ¶ms) {
864 PARAMS4(int, star, int32, xi, int32, yi, int32, zi);
865 float x = PARAM_TO_FLOAT(xi);
866 float y = PARAM_TO_FLOAT(yi);
867 float z = PARAM_TO_FLOAT(zi);
868 stars[star].x = x;
869 stars[star].y = y;
870 stars[star].z = z;
871 }
872
SetStarColor(ScriptMethodParams & params)873 void AGSPalRender::SetStarColor(ScriptMethodParams ¶ms) {
874 PARAMS2(int, star, unsigned char, color);
875 stars[star].color = color;
876 }
877
GetStarColor(ScriptMethodParams & params)878 void AGSPalRender::GetStarColor(ScriptMethodParams ¶ms) {
879 PARAMS1(int, star);
880 params._result = (int)stars[star].color;
881 }
882
SetStarSprite(ScriptMethodParams & params)883 void AGSPalRender::SetStarSprite(ScriptMethodParams ¶ms) {
884 PARAMS2(int, star, int, slot);
885 stars[star].sprite = slot;
886 }
887
GetStarSprite(ScriptMethodParams & params)888 void AGSPalRender::GetStarSprite(ScriptMethodParams ¶ms) {
889 PARAMS1(int, star);
890 params._result = stars[star].sprite;
891 }
892
SetStarSpriteRange(ScriptMethodParams & params)893 void AGSPalRender::SetStarSpriteRange(ScriptMethodParams ¶ms) {
894 PARAMS3(int, start, int, end, int, slot);
895 int sfix = start;
896 int efix = end;
897 if (start > Starfield.maxstars) sfix = Starfield.maxstars - 1;
898 if (end > Starfield.maxstars) efix = Starfield.maxstars;
899 for (int i = sfix; i < efix; i++)
900 stars[i].sprite = slot;
901 }
902
DrawStars(ScriptMethodParams & params)903 void AGSPalRender::DrawStars(ScriptMethodParams ¶ms) {
904 PARAMS2(int, slot, int, maskslot);
905 int32 sw, sh = 0;
906 BITMAP *canvas = engine->GetSpriteGraphic(slot);
907 if (!canvas) engine->AbortGame("DrawStars: Can't load sprite slot.");
908 BITMAP *maskcanvas = engine->GetSpriteGraphic(maskslot);
909 if (!maskcanvas) engine->AbortGame("DrawStars: Can't load mask slot.");
910 engine->GetBitmapDimensions(canvas, &sw, &sh, nullptr);
911 uint8 *screenarray = engine->GetRawBitmapSurface(canvas);
912 uint8 *maskarray = engine->GetRawBitmapSurface(maskcanvas);
913 int screenPitch = engine->GetBitmapPitch(canvas);
914 int maskPitch = engine->GetBitmapPitch(maskcanvas);
915 for (int i = 0; i < Starfield.maxstars; i++) {
916 //stars[i].z-= 0.5;
917 //if (stars[i].z < 1.0) stars[i].z = (double)MAX_DEPTH;
918 float k = (float)Starfield.depthmultiplier / stars[i].z;
919 int px = static_cast<int>(stars[i].x * k + Starfield.originx);
920 int py = static_cast<int>(stars[i].y * k + Starfield.originy);
921 if (px >= sw + Starfield.overscan || px < 0 - Starfield.overscan || py >= sh + Starfield.overscan || py < 0 - Starfield.overscan) {
922 stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
923 if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
924 stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
925 if (stars[i].y < 1.0 && stars[i].y > 1.0) stars[i].y = (float)sh;
926 stars[i].z = (float)MAX_DEPTH;
927 //stars[i].color = (rand () %240);
928 } else if (stars[i].z > 0) {
929 int ivalue = (63 - (int)stars[i].z);
930 if (ivalue > 63) ivalue = 63;
931 else if (ivalue < 0) ivalue = 0;
932 unsigned char value = (unsigned char)(ivalue);
933 unsigned char maskcolor = value << 2;
934 if (stars[i].sprite > 0) {
935 BITMAP *origspr = engine->GetSpriteGraphic(stars[i].sprite);
936 int scale = (ivalue + 1) * 100 >> 6;
937 //int scale = 50;
938 if (scale < 1) scale = 1;
939 /*
940 if (scale != 100)
941 {
942 uint8 * orig = engine->GetRawBitmapSurface (origspr);
943 int origPitch = engine->GetBitmapPitch(origspr);
944 int32 h1,h2,w1,w2=0;
945 double fw2,fh2;
946 engine->GetBitmapDimensions (origspr,&w1,&h1,NULL);
947 fh2 = h1 * (scale / 100.0);
948 fw2 = w1 * (scale / 100.0);
949 h2 = static_cast<int>(fh2);
950 w2 = static_cast<int>(fw2);
951 if (w2 < 1) w2 = 1;
952 if (h2 < 1) h2 = 1;
953 resizspr = engine->CreateBlankBitmap (w2,h2,8);
954 uint8 * resized = engine->GetRawBitmapSurface (resizspr);
955 int resizePitch = engine->GetBitmapPitch(resizspr);
956 int x_ratio = (int)((w1<<16)/w2) +1;
957 int y_ratio = (int)((h1<<16)/h2) +1;
958 int x2, y2 ;
959 for (int i=0;i<h2;i++)
960 {
961 for (int j=0;j<w2;j++)
962 {
963 x2 = ((j*x_ratio)>>16) ;
964 y2 = ((i*y_ratio)>>16) ;
965 resized [i * resizePitch + j] = orig [y2 * origPitch + x2];
966 }
967 }
968 engine->ReleaseBitmapSurface (resizspr);
969 }
970 //resizspr = origspr;
971 int32 w,h=0;
972 engine->GetBitmapDimensions (resizspr,&w,&h,NULL);
973 uint8 *imagemap = engine->GetRawBitmapSurface (resizspr);
974 int imagePitch = engine->GetBitmapPitch(resizspr);
975 int ox = px - (w>>1);
976 int oy = py - (h>>1);
977 for (int dy=0;dy<h;dy++)
978 {
979 for (int dx=0;dx<w;dx++)
980 {
981 int ex = ox+dx;
982 int ey = oy+dy;
983 if (ex < sw && ex >= 0 && ey < sh && ey >= 0)
984 {
985 if (maskcolor > maskarray [ey * maskPitch + ex] && imagemap[dy * imagePitch + dx] > 0)
986 {
987 maskarray [ey * maskPitch + ex] = maskcolor;
988 screenarray [ey * screenPitch + ex] = imagemap[dy][dx];
989 }
990 }
991 }
992 }
993 */
994
995 uint8 *orig = engine->GetRawBitmapSurface(origspr);
996 int origPitch = engine->GetBitmapPitch(origspr);
997 int32 h1, h2, w1, w2 = 0;
998 double fw2, fh2;
999 engine->GetBitmapDimensions(origspr, &w1, &h1, nullptr);
1000 fh2 = h1 * (scale / 100.0);
1001 fw2 = w1 * (scale / 100.0);
1002 h2 = static_cast<int>(fh2);
1003 w2 = static_cast<int>(fw2);
1004 if (w2 < 1) w2 = 1;
1005 if (h2 < 1) h2 = 1;
1006 int x_ratio = (int)((w1 << 16) / w2) + 1;
1007 int y_ratio = (int)((h1 << 16) / h2) + 1;
1008 int x2, y2 ;
1009 int ox = px - (w2 >> 1);
1010 int oy = py - (h2 >> 1);
1011 for (int ii = 0; ii < h2; ii++) {
1012 int temprzy = ii * y_ratio;
1013 int ey = oy + ii;
1014 for (int j = 0; j < w2; j++) {
1015 x2 = ((j * x_ratio) >> 16);
1016 y2 = ((temprzy) >> 16);
1017 int ex = ox + j;
1018 if (ex < sw && ex >= 0 && ey < sh && ey >= 0) {
1019 if (maskcolor > maskarray [ey * maskPitch + ex] && orig[y2 * origPitch + x2] > 0) {
1020 maskarray [ey * maskPitch + ex] = maskcolor;
1021 screenarray [ey * screenPitch + ex] = orig[y2 * origPitch + x2];
1022 }
1023 }
1024 //resized [ii][j] = orig [y2 * origPitch + x2];
1025 }
1026 }
1027 engine->ReleaseBitmapSurface(origspr);
1028 } else if (stars[i].sprite == 0) {
1029 if (stars[i].maxrad == 1) {
1030 if (px < sw && px >= 0 && py < sh && py >= 0) {
1031 if (maskcolor > maskarray[py * maskPitch + px]) {
1032 maskarray[py * maskPitch + px] = maskcolor;
1033 screenarray[py * screenPitch + px] = stars[i].color;
1034 }
1035 }
1036 } else {
1037 int scale = ((((int)stars[i].z) * 100) / 63);
1038 if (scale < 1) scale = 1;
1039 int radius = (stars[i].maxrad * (100 - scale) / 100);
1040 int radsq = radius * radius;
1041 //unsigned char color = GetColor565 (value>>1,value,value>>1);
1042 unsigned char color = stars[i].color;
1043 for (int cy = -radius; cy <= radius; cy++) { //Draw a circle around the point, for the mask.
1044 int cysq = cy * cy;
1045 for (int cx = -radius; cx <= radius; cx++) {
1046 int cxsq = cx * cx;
1047 int dx = cx + px;
1048 int dy = cy + py;
1049 if ((cxsq + cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0) {
1050 if (maskcolor > maskarray [dy * maskPitch + dx]) {
1051 maskarray [dy * maskPitch + dx] = maskcolor;
1052 screenarray [dy * screenPitch + dx] = color;
1053 }
1054 }
1055 }
1056 }
1057 /*
1058 for(int cy=-radius; cy<=radius; cy++) //Draw a circle around the point, for the color.
1059 {
1060 int cysq = cy*cy;
1061 for(int cx=-radius; cx<=radius; cx++)
1062 {
1063 int cxsq = cx*cx;
1064 int dx = cx+px;
1065 int dy = cy+py;
1066 if((cxsq+cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0)
1067 {
1068 if (maskarray [dy * maskPitch + dx] == maskcolor)screenarray [dy * screenPitch + dx] = color;
1069 }
1070 }
1071 }
1072 */
1073 }
1074 }
1075 }
1076 }
1077 engine->ReleaseBitmapSurface(canvas);
1078 engine->ReleaseBitmapSurface(maskcanvas);
1079 engine->NotifySpriteUpdated(slot);
1080 engine->NotifySpriteUpdated(maskslot);
1081 }
1082
1083
CreateTranslucentOverlay(ScriptMethodParams & params)1084 void AGSPalRender::CreateTranslucentOverlay(ScriptMethodParams ¶ms) {
1085 PARAMS6(int, id, int, spriteId, int, alpha, int, level, int, ox, int, oy);
1086 int mask = 0, blendmode = 0;
1087 if (params.size() > 6)
1088 mask = params[6];
1089 if (params.size() > 7)
1090 blendmode = params[7];
1091 BITMAP *testspr = engine->GetSpriteGraphic(spriteId);
1092 if (testspr) overlay[id].sprite = spriteId;
1093 else engine->AbortGame("CreateTranslucentOverlay: Invalid spriteId.");
1094 engine->ReleaseBitmapSurface(testspr);
1095 overlay[id].level = MAX(0, MIN(level, 4));
1096 overlay[id].trans = MAX(0, MIN(alpha, 255));
1097 overlay[id].spritemask = mask;
1098 overlay[id].x = ox;
1099 overlay[id].y = oy;
1100 overlay[id].enabled = true;
1101 overlay[id].blendtype = blendmode;
1102 params._result = 0;
1103 }
1104
DeleteTranslucentOverlay(ScriptMethodParams & params)1105 void AGSPalRender::DeleteTranslucentOverlay(ScriptMethodParams ¶ms) {
1106 PARAMS1(int, id);
1107 overlay[id].enabled = false;
1108 overlay[id].sprite = 0;
1109 overlay[id].x = 0;
1110 overlay[id].y = 0;
1111 overlay[id].level = 0;
1112 overlay[id].trans = 0;
1113 params._result = 0;
1114 }
1115
MoveTranslucentOverlay(ScriptMethodParams & params)1116 void AGSPalRender::MoveTranslucentOverlay(ScriptMethodParams ¶ms) {
1117 PARAMS3(int, id, int, ox, int, oy);
1118 overlay[id].x = ox;
1119 overlay[id].y = oy;
1120 params._result = 0;
1121 }
1122
GetTranslucentOverlayX(ScriptMethodParams & params)1123 void AGSPalRender::GetTranslucentOverlayX(ScriptMethodParams ¶ms) {
1124 PARAMS1(int, id);
1125 params._result = overlay[id].x;
1126 }
1127
GetTranslucentOverlayY(ScriptMethodParams & params)1128 void AGSPalRender::GetTranslucentOverlayY(ScriptMethodParams ¶ms) {
1129 PARAMS1(int, id);
1130 params._result = overlay[id].y;
1131 }
1132
GetTranslucentOverlaySprite(ScriptMethodParams & params)1133 void AGSPalRender::GetTranslucentOverlaySprite(ScriptMethodParams ¶ms) {
1134 PARAMS1(int, id);
1135 params._result = overlay[id].sprite;
1136 }
1137
GetTranslucentOverlayLevel(ScriptMethodParams & params)1138 void AGSPalRender::GetTranslucentOverlayLevel(ScriptMethodParams ¶ms) {
1139 PARAMS1(int, id);
1140 params._result = overlay[id].level;
1141 }
1142
GetTranslucentOverlayEnabled(ScriptMethodParams & params)1143 void AGSPalRender::GetTranslucentOverlayEnabled(ScriptMethodParams ¶ms) {
1144 PARAMS1(int, id);
1145 params._result = overlay[id].enabled;
1146 }
1147
GetTranslucentOverlayAlpha(ScriptMethodParams & params)1148 void AGSPalRender::GetTranslucentOverlayAlpha(ScriptMethodParams ¶ms) {
1149 PARAMS1(int, id);
1150 params._result = overlay[id].trans;
1151 }
1152
SetTranslucentOverlayAlpha(ScriptMethodParams & params)1153 void AGSPalRender::SetTranslucentOverlayAlpha(ScriptMethodParams ¶ms) {
1154 PARAMS2(int, id, int, alpha);
1155 if (alpha >= 0 && alpha < 256)
1156 overlay[id].trans = alpha;
1157 else
1158 engine->AbortGame("CreateTranslucentOverlay: Invalid alpha selected.");
1159 params._result = 0;
1160 }
1161
SetTranslucentOverlayEnabled(ScriptMethodParams & params)1162 void AGSPalRender::SetTranslucentOverlayEnabled(ScriptMethodParams ¶ms) {
1163 PARAMS2(int, id, int, toggle);
1164 if (toggle > 0)
1165 overlay[id].enabled = true;
1166 else
1167 overlay[id].enabled = false;
1168 params._result = 0;
1169 }
1170
SetCharacterReflected(ScriptMethodParams & params)1171 void AGSPalRender::SetCharacterReflected(ScriptMethodParams ¶ms) {
1172 PARAMS2(int, id, int, refl);
1173 if (refl > 0) Reflection.Characters[id].reflect = 1;
1174 else Reflection.Characters[id].reflect = 0;
1175 }
1176
SetObjectReflected(ScriptMethodParams & params)1177 void AGSPalRender::SetObjectReflected(ScriptMethodParams ¶ms) {
1178 PARAMS2(int, id, int, refl);
1179 if (refl > 0)
1180 Reflection.Objects[id].reflect = 1;
1181 else
1182 Reflection.Objects[id].reflect = 0;
1183 }
1184
GetCharacterReflected(ScriptMethodParams & params)1185 void AGSPalRender::GetCharacterReflected(ScriptMethodParams ¶ms) {
1186 PARAMS1(int, id);
1187 params._result = Reflection.Characters[id].reflect;
1188 }
1189
GetObjectReflected(ScriptMethodParams & params)1190 void AGSPalRender::GetObjectReflected(ScriptMethodParams ¶ms) {
1191 PARAMS1(int, id);
1192 params._result = Reflection.Objects[id].reflect;
1193 }
1194
ReplaceCharacterReflectionView(ScriptMethodParams & params)1195 void AGSPalRender::ReplaceCharacterReflectionView(ScriptMethodParams ¶ms) {
1196 PARAMS2(int, id, int, view);
1197 Reflection.Characters[id].replaceview = view - 1;
1198 }
1199
SetObjectReflectionIgnoreScaling(ScriptMethodParams & params)1200 void AGSPalRender::SetObjectReflectionIgnoreScaling(ScriptMethodParams ¶ms) {
1201 PARAMS2(int, id, int, wb);
1202 if (wb) Reflection.Objects[id].ignorescaling = 1;
1203 else Reflection.Objects[id].ignorescaling = 0;
1204 }
1205
DrawReflections(int id,int charobj=0)1206 int DrawReflections(int id, int charobj = 0) {
1207 int32 screenw, screenh;
1208 int32 bgw, bgh;
1209 engine->GetScreenDimensions(&screenw, &screenh, nullptr);
1210 BITMAP *bgmask = engine->GetBackgroundScene(1);
1211 if (bgmask == nullptr) return 1;
1212 //BITMAP *virtsc = engine->GetVirtualScreen();
1213 BITMAP *walkbehind = engine->GetRoomMask(MASK_WALKBEHIND);
1214 //if (!virtsc) engine->AbortGame ("Can't load virtual screen.");
1215 if (!walkbehind) engine->AbortGame("DrawRelfections: Can't load Walkbehind into memory.");
1216 engine->GetBitmapDimensions(walkbehind, &bgw, &bgh, nullptr);
1217 if (!bgmask) engine->AbortGame("DrawReflections: Can't load reflection mask.");
1218 //unsigned char **charbuffer = engine->GetRawBitmapSurface (virtsc);
1219 uint8 *wbarray = engine->GetRawBitmapSurface(walkbehind);
1220 uint8 *maskarray = engine->GetRawBitmapSurface(bgmask);
1221 int wbPitch = engine->GetBitmapPitch(walkbehind);
1222 int maskPitch = engine->GetBitmapPitch(bgmask);
1223 //Initialize stuff
1224 BITMAP *charsprite = nullptr;
1225 BITMAP *charsprite2 = nullptr;
1226 AGSCharacter *currchar = nullptr;
1227 AGSObject *currobj;
1228 int cox = 0, coy = 0, coz = 0;
1229 int scale = 0;
1230 //Get character, and their sprite.
1231 if (charobj == 0) {
1232 currchar = engine->GetCharacter(id);
1233 /*int view = 0;
1234 if (Reflection.Characters[id].replaceview == 0) view = currchar->view + 1;
1235 else view = Reflection.Characters[id].replaceview;
1236 */
1237 AGSViewFrame *vf = engine->GetViewFrame(currchar->view + 1, currchar->loop, currchar->frame);
1238 charsprite = engine->GetSpriteGraphic(vf->pic);
1239 long scaling = currchar->flags & CHF_NOSCALING;
1240 if (!scaling)scale = engine->GetAreaScaling(currchar->x, currchar->y);
1241 else scale = 100;
1242 cox = currchar->x;
1243 coy = currchar->y;
1244 coz = currchar->z;
1245 } else if (charobj == 1) {
1246 currobj = engine->GetObject(id);
1247
1248 charsprite = engine->GetSpriteGraphic(currobj->num);
1249 if (Reflection.Objects[id].ignorescaling) scale = 100;
1250 else scale = engine->GetAreaScaling(currobj->x, currobj->y);
1251 cox = currobj->x;
1252 if (currobj->baseline < 0) coy = currobj->y;
1253 else coy = currobj->baseline;
1254 coz = 0;
1255 }
1256 bool scaled = false;
1257 int32 w, h;
1258 engine->GetBitmapDimensions(charsprite, &w, &h, nullptr);
1259 if (scale != 100) {
1260 uint8 *orig = engine->GetRawBitmapSurface(charsprite);
1261 int origPitch = engine->GetBitmapPitch(charsprite);
1262 int h1, h2, w1, w2;
1263 double fw2, fh2;
1264 h1 = h;
1265 w1 = w;
1266 fh2 = h1 * ((double)scale / 100.0);
1267 fw2 = w1 * ((double)scale / 100.0);
1268 h2 = static_cast<int>(fh2);
1269 w2 = static_cast<int>(fw2);
1270 charsprite2 = engine->CreateBlankBitmap(w2, h2, 8);
1271 uint8 *resized = engine->GetRawBitmapSurface(charsprite2);
1272 int resizedPitch = engine->GetBitmapPitch(charsprite2);
1273 int x_ratio = (int)((w1 << 16) / w2) + 1;
1274 int y_ratio = (int)((h1 << 16) / h2) + 1;
1275 int x2, y2 ;
1276 for (int i = 0; i < h2; i++) {
1277 for (int j = 0; j < w2; j++) {
1278 x2 = ((j * x_ratio) >> 16) ;
1279 y2 = ((i * y_ratio) >> 16) ;
1280 resized [i * resizedPitch + j] = orig [y2 * origPitch + x2];
1281 }
1282 }
1283 engine->ReleaseBitmapSurface(charsprite2);
1284 scaled = true;
1285 w = w2;
1286 h = h2;
1287 } else {
1288 charsprite2 = charsprite;
1289 }
1290 int transamount = 0;
1291 uint8 *spritearray = engine->GetRawBitmapSurface(charsprite2);
1292 uint8 *charbuffer = engine->GetRawBitmapSurface(rcolormap);
1293 uint8 *alphaarray = engine->GetRawBitmapSurface(ralphamap);
1294 int spritePitch = engine->GetBitmapPitch(charsprite2);
1295 int charPitch = engine->GetBitmapPitch(rcolormap);
1296 int alphaPitch = engine->GetBitmapPitch(ralphamap);
1297 int i = h - 1, j = 0;
1298 int32 ox = cox;
1299 if (charobj == 0) ox = ox - (w / 2);
1300 int32 oy = coy + coz - 1;
1301 engine->RoomToViewport(&ox, &oy);
1302 int yoffset = 0;
1303 int translevel = 7;
1304 //bool dither = false;
1305 //bool dodither = false;
1306 int counter = 0;
1307 int rowcount = 101 - (int)(50.0 * ((double)(scale) / 100.0));
1308 int delay = screenh / rowcount;
1309 int *obst;
1310 int flipped = 0;
1311 if (charobj == 0) {
1312 PluginMethod sfGetGameParameter = engine->GetScriptFunctionAddress("GetGameParameter");
1313 flipped = sfGetGameParameter(13, currchar->view + 1, currchar->loop, currchar->frame);
1314 } else flipped = 0;
1315 obst = new int [w];
1316 for (int k = 0; k < w; k++) {
1317 obst[k] = 0;
1318 }
1319 while (i > 0) {
1320 //if ((counter == delay/2-1 || counter == delay-1) && yoffset < 36) dodither = (!dodither);
1321 if (counter == delay) {
1322 counter = 0;
1323 if (translevel > 0) translevel--;
1324 } else counter++;
1325 yoffset++;
1326 while (j < w) {
1327 int xoffset;
1328 if (flipped == 1) xoffset = w - j - 1;
1329 else xoffset = j;
1330 int32 rx = ox + xoffset, ry = oy + yoffset;
1331 int wbb = 0;
1332 engine->ViewportToRoom(&rx, &ry);
1333 if (ry > 0 && ry < bgh && rx > 0 && rx < bgw) {
1334 if (wbarray [ry * wbPitch + rx] > 0) {
1335 wbb = engine->GetWalkbehindBaseline(wbarray[ry * wbPitch + rx]);
1336 }
1337 if (maskarray[ry * maskPitch + rx] == 21) obst[j] = 1;
1338 }
1339
1340 //dither = (!dither);
1341 transamount = 32 * translevel;
1342 if (spritearray [i * spritePitch + j] != 0 && oy + yoffset < screenh && ox + xoffset < screenw && oy + yoffset >= 0 && ox + xoffset >= 0) { // If the sprite isn't transparent, and isn't drawn off the edge of the bg.
1343 if (wbb < ry && obst[j] == 0 && (oy > reflectionmap[(ox + xoffset) + (screenw * (oy + yoffset))])) {
1344 //charbuffer[(oy+yoffset) * charPitch + ox+xoffset] = MixColorAlpha (spritearray [i * spritePitch + j],charbuffer[(oy+yoffset) * charPitch + ox+xoffset],transamount);
1345 charbuffer [(oy + yoffset) * charPitch + ox + xoffset] = spritearray [i * spritePitch + j];
1346 alphaarray [(oy + yoffset) * alphaPitch + ox + xoffset] = transamount;
1347 reflectionmap[(ox + xoffset) + (screenw * (oy + yoffset))] = oy;
1348 }
1349 }
1350 j++;
1351 }
1352 //if (w % 2 == 0) dither = (!dither);
1353 i--;
1354 j = 0;
1355 }
1356
1357 delete[] obst;
1358 if (scaled == true)engine->FreeBitmap(charsprite2);
1359 engine->ReleaseBitmapSurface(charsprite);
1360 //engine->ReleaseBitmapSurface (virtsc);
1361 //engine->ReleaseBitmapSurface (clutspr);
1362 engine->ReleaseBitmapSurface(bgmask);
1363 engine->ReleaseBitmapSurface(walkbehind);
1364 engine->ReleaseBitmapSurface(rcolormap);
1365 engine->ReleaseBitmapSurface(ralphamap);
1366 engine->MarkRegionDirty(ox, oy, ox + w, oy + h);
1367 return 0;
1368 }
1369
1370
DrawTransSprite(ScriptMethodParams & params)1371 void AGSPalRender::DrawTransSprite(ScriptMethodParams ¶ms) {
1372 PARAMS3(int, spriteId, int, bg, int, translevel);
1373 int mask = 0, blendmode = 0, use_objpal = 0;
1374 if (params.size() > 3)
1375 mask = params[3];
1376 if (params.size() > 4)
1377 blendmode = params[4];
1378 if (params.size() > 5)
1379 use_objpal = params[5];
1380
1381 BITMAP *maskspr = nullptr;
1382 if (mask > 0) maskspr = engine->GetSpriteGraphic(mask);
1383 if (!maskspr && mask > 0) {
1384 char maskerr [100];
1385 snprintf(maskerr, 100, "DrawTransSprite: Can't load mask from slot %d.", mask);
1386 engine->AbortGame(maskerr);
1387 }
1388 // Get a reference to the screen we'll draw onto
1389 BITMAP *bgspr = engine->GetSpriteGraphic(bg);
1390 //BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
1391 BITMAP *spritespr = engine->GetSpriteGraphic(spriteId);
1392 if (!bgspr) engine->AbortGame("DrawTransSprite: Can't load background");
1393 //if (!clutspr) engine->AbortGame ("Can't load CLUT spriteId into memory.");
1394 if (!spritespr) engine->AbortGame("DrawTransSprite: Can't load overlay spriteId into memory.");
1395 // Get its surface
1396 int32 sprw, sprh, coldepth;
1397 int32 bgw, bgh;
1398 engine->GetBitmapDimensions(bgspr, &bgw, &bgh, &coldepth);
1399 engine->GetBitmapDimensions(spritespr, &sprw, &sprh, &coldepth);
1400
1401 uint8 *bgarray = engine->GetRawBitmapSurface(bgspr);
1402 //uint8 *clutarray = engine->GetRawBitmapSurface (clutspr);
1403 uint8 *spritearray = engine->GetRawBitmapSurface(spritespr);
1404 int bgPitch = engine->GetBitmapPitch(bgspr);
1405 //int clutPitch = engine->GetBitmapPitch(clutspr);
1406 int spritePitch = engine->GetBitmapPitch(spritespr);
1407
1408 unsigned char *maskarray = nullptr;
1409 int maskPitch = 0;
1410 if (mask > 0) {
1411 maskarray = engine->GetRawBitmapSurface(maskspr);
1412 maskPitch = engine->GetBitmapPitch(maskspr);
1413 }
1414 int tloffset = 255 - translevel;
1415 int x = 0;
1416 int y = 0;
1417 //int transamount = 256 * translevel; //old
1418 while (y < sprh) {
1419 while (x < sprw) {
1420 if (spritearray [y * spritePitch + x] != 0 && y < bgh && x < bgw && y >= 0 && x >= 0) { // If the spriteId isn't transparent, and isn't drawn off the edge of the bg.
1421 if (mask > 0) {
1422 translevel = MAX(maskarray [y * maskPitch + x] - tloffset, 0);
1423 }
1424 //spritearray[y * spritePitch + x] = cycle_remap[clutarray [(cycle_remap[bgarray[y * bgPitch + x]]+transamount) * clutPitch + (cycle_remap[spritearray [y * spritePitch + x]])]; //old
1425 if (blendmode == 0) spritearray[y * spritePitch + x] = Mix::MixColorAlpha(spritearray [y * spritePitch + x], bgarray[y * bgPitch + x], translevel, use_objpal);
1426 else if (blendmode == 1) spritearray[y * spritePitch + x] = Mix::MixColorAdditive(spritearray [y * spritePitch + x], bgarray[y * bgPitch + x], translevel, use_objpal);
1427 }
1428 x++;
1429 }
1430 x = 0;
1431 y++;
1432 }
1433
1434 // Release the screen so that the engine can continue
1435 engine->ReleaseBitmapSurface(bgspr);
1436 //engine->ReleaseBitmapSurface (clutspr);
1437 engine->ReleaseBitmapSurface(spritespr);
1438 engine->NotifySpriteUpdated(spriteId);
1439 params._result = 0;
1440 }
1441
DrawTranslucentOverlay(int spriteId,int translevel,int ox,int oy,int mask=0,int blendmode=0)1442 int DrawTranslucentOverlay(int spriteId, int translevel, int ox, int oy, int mask = 0, int blendmode = 0) {
1443 if (translevel == 0) return 0;
1444 BITMAP *maskspr = nullptr;
1445 // Get a reference to the screen we'll draw onto
1446 BITMAP *virtsc = engine->GetVirtualScreen();
1447 //BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
1448 BITMAP *spritespr = engine->GetSpriteGraphic(spriteId);
1449 if (mask > 0) maskspr = engine->GetSpriteGraphic(mask);
1450 if (!virtsc) engine->AbortGame("DrawTranslucentOverlay: Can't load virtual screen.");
1451 //if (!clutspr) engine->AbortGame ("Can't load CLUT spriteId into memory.");
1452 if (!spritespr) engine->AbortGame("DrawTranslucentOverlay: Can't load overlay spriteId into memory.");
1453 // Get its surface
1454 int32 sprw, sprh, coldepth;
1455 int32 screenw, screenh;
1456 engine->GetScreenDimensions(&screenw, &screenh, &coldepth);
1457 engine->GetBitmapDimensions(spritespr, &sprw, &sprh, &coldepth);
1458 uint8 *charbuffer = engine->GetRawBitmapSurface(virtsc);
1459 uint8 *spritearray = engine->GetRawBitmapSurface(spritespr);
1460 int charPitch = engine->GetBitmapPitch(virtsc);
1461 int spritePitch = engine->GetBitmapPitch(spritespr);
1462 uint8 *maskarray = nullptr;
1463 int maskPitch = 0;
1464 if (mask > 0) {
1465 if (!maskspr && mask > 0) {
1466 char maskerr [100];
1467 snprintf(maskerr, 100, "DrawTransSprite: Can't load mask from slot %d.", mask);
1468 engine->AbortGame(maskerr);
1469 }
1470 maskarray = engine->GetRawBitmapSurface(maskspr);
1471 maskPitch = engine->GetBitmapPitch(maskspr);
1472 }
1473 int tloffset = 255 - translevel;
1474 int x = 0;
1475 int y = 0;
1476 //int transamount = 256 * translevel; //old
1477 while (y < sprh) {
1478 while (x < sprw) {
1479 if (spritearray [y * spritePitch + x] != 0 && y + oy < screenh && x + ox < screenw && y + oy >= 0 && x + ox >= 0) { // If the spriteId isn't transparent, and isn't drawn off the edge of the screen.
1480 //charbuffer[(y+oy) * charPitch + x+ox] = cycle_remap[clutarray ([cycle_remap[charbuffer[(y+oy) * charPitch + x+ox]]+transamount) * clutPitch + (cycle_remap[spritearray [y * spritePitch + x]])]; //old
1481 if (mask > 0) {
1482 translevel = MAX(maskarray [y * maskPitch + x] - tloffset, 0);
1483 }
1484 if (blendmode == 0) {
1485 if (translevel == 255) {
1486 charbuffer[(y + oy) * charPitch + x + ox] = spritearray [y * spritePitch + x];
1487 } else charbuffer[(y + oy) * charPitch + x + ox] = Mix::MixColorAlpha(spritearray [y * spritePitch + x], charbuffer[(y + oy) * charPitch + x + ox], translevel);
1488 } else if (blendmode == 1) charbuffer[(y + oy) * charPitch + x + ox] = Mix::MixColorAdditive(spritearray [y * spritePitch + x], charbuffer[(y + oy) * charPitch + x + ox], translevel);
1489 }
1490 x++;
1491 }
1492 x = 0;
1493 y++;
1494 }
1495
1496 // Release the screen so that the engine can continue
1497 long dirtywidth = ox + sprw;
1498 if (dirtywidth > screenw) dirtywidth = screenw - 1;
1499 long dirtyheight = oy + sprh;
1500 if (dirtyheight > screenh) dirtywidth = screenh - 1;
1501 engine->ReleaseBitmapSurface(virtsc);
1502 //engine->ReleaseBitmapSurface (clutspr);
1503 engine->ReleaseBitmapSurface(spritespr);
1504 if (mask > 0) engine->ReleaseBitmapSurface(maskspr);
1505 engine->MarkRegionDirty(ox, oy, dirtywidth, dirtyheight);
1506
1507 return 0;
1508 }
1509
1510 /*------------------------------------------------------------------*/
1511
AGS_GetPluginName()1512 const char *AGSPalRender::AGS_GetPluginName() {
1513 return "PALgorithms Translucent Overlay Renderer";
1514 }
1515
AGS_EngineStartup(IAGSEngine * lpEngine)1516 void AGSPalRender::AGS_EngineStartup(IAGSEngine *lpEngine) {
1517 PluginBase::AGS_EngineStartup(lpEngine);
1518 engine = lpEngine;
1519
1520 // Make sure it's got the version with the features we need
1521 if (engine->version < 3) {
1522 engine->AbortGame("Engine interface is too old, need newer version of AGS.");
1523 }
1524
1525 SCRIPT_METHOD(PALInternal::LoadCLUT^1, AGSPalRender::LoadCLUT);
1526 SCRIPT_METHOD(PALInternal::CycleRemap^2, AGSPalRender::CycleRemap);
1527 SCRIPT_METHOD(PALInternal::GetColor565^3, AGSPalRender::GetColor565);
1528 SCRIPT_METHOD(PALInternal::GetLuminosityFromPalette^1, AGSPalRender::GetLuminosityFromPalette);
1529 SCRIPT_METHOD(PALInternal::FastSin^1, AGSPalRender::AGSFastSin);
1530 SCRIPT_METHOD(PALInternal::FastCos^1, AGSPalRender::AGSFastCos);
1531 SCRIPT_METHOD(PALInternal::FastRoot^1, AGSPalRender::AGSFastRoot);
1532 SCRIPT_METHOD(PALInternal::GetRemappedSlot^1, AGSPalRender::GetRemappedSlot);
1533 SCRIPT_METHOD(PALInternal::ResetRemapping^0, AGSPalRender::ResetRemapping);
1534 SCRIPT_METHOD(PALInternal::GetModifiedBackgroundImage, AGSPalRender::GetModifiedBackgroundImage);
1535 SCRIPT_METHOD(PALInternal::WriteObjectivePalette^4, AGSPalRender::WriteObjectivePalette);
1536 SCRIPT_METHOD(PALInternal::ReadObjectivePaletteR^1, AGSPalRender::ReadObjectivePaletteR);
1537 SCRIPT_METHOD(PALInternal::ReadObjectivePaletteB^1, AGSPalRender::ReadObjectivePaletteB);
1538 SCRIPT_METHOD(PALInternal::ReadObjectivePaletteG^1, AGSPalRender::ReadObjectivePaletteG);
1539
1540 SCRIPT_METHOD(Raycast::Render^1, AGSPalRender::Raycast_Render);
1541 SCRIPT_METHOD(Raycast::LoadMap^4, AGSPalRender::LoadMap);
1542 SCRIPT_METHOD(Raycast::Initialize, AGSPalRender::Init_Raycaster);
1543 SCRIPT_METHOD(Raycast::MakeTextures^1, AGSPalRender::MakeTextures);
1544 SCRIPT_METHOD(Raycast::MoveForward^0, AGSPalRender::MoveForward);
1545 SCRIPT_METHOD(Raycast::MoveBackward^0, AGSPalRender::MoveBackward);
1546 SCRIPT_METHOD(Raycast::RotateLeft^0, AGSPalRender::RotateLeft);
1547 SCRIPT_METHOD(Raycast::RotateRight^0, AGSPalRender::RotateRight);
1548 SCRIPT_METHOD(Raycast::SetCameraPosition^2, AGSPalRender::Ray_SetPlayerPosition);
1549 SCRIPT_METHOD(Raycast::GetCameraX^0, AGSPalRender::Ray_GetPlayerX);
1550 SCRIPT_METHOD(Raycast::GetCameraY^0, AGSPalRender::Ray_GetPlayerY);
1551 SCRIPT_METHOD(Raycast::GetCameraAngle^0, AGSPalRender::Ray_GetPlayerAngle);
1552 SCRIPT_METHOD(Raycast::SetCameraAngle^1, AGSPalRender::Ray_SetPlayerAngle);
1553 SCRIPT_METHOD(Raycast::InitSprite^9, AGSPalRender::Ray_InitSprite);
1554 SCRIPT_METHOD(Raycast::UnloadEngine^0, AGSPalRender::QuitCleanup);
1555 SCRIPT_METHOD(Raycast::GetHotspotAtXY^2, AGSPalRender::Ray_GetHotspotAt);
1556 SCRIPT_METHOD(Raycast::GetObjectAtXY^2, AGSPalRender::Ray_GetObjectAt);
1557 SCRIPT_METHOD(Raycast::SetSpriteInteractObj^2, AGSPalRender::Ray_SetSpriteInteractObj);
1558 SCRIPT_METHOD(Raycast::GetSpriteInteractObj^1, AGSPalRender::Ray_GetSpriteInteractObj);
1559 SCRIPT_METHOD(Raycast::SetSpritePosition^3, AGSPalRender::Ray_SetSpritePosition);
1560 SCRIPT_METHOD(Raycast::SetSpriteVertOffset^2, AGSPalRender::Ray_SetSpriteVertOffset);
1561 SCRIPT_METHOD(Raycast::GetSpriteVertOffset^1, AGSPalRender::Ray_GetSpriteVertOffset);
1562 SCRIPT_METHOD(Raycast::GetSpriteX^1, AGSPalRender::Ray_GetSpriteX);
1563 SCRIPT_METHOD(Raycast::GetSpriteY^1, AGSPalRender::Ray_GetSpriteY);
1564 SCRIPT_METHOD(Raycast::SetWallHotspot^2, AGSPalRender::Ray_SetWallHotspot);
1565 SCRIPT_METHOD(Raycast::SetWallTextures^5, AGSPalRender::Ray_SetWallTextures);
1566 SCRIPT_METHOD(Raycast::SetWallSolid^5, AGSPalRender::Ray_SetWallSolid);
1567 SCRIPT_METHOD(Raycast::SetWallIgnoreLighting^5, AGSPalRender::Ray_SetWallIgnoreLighting);
1568 SCRIPT_METHOD(Raycast::SetWallAlpha^5, AGSPalRender::Ray_SetWallAlpha);
1569 SCRIPT_METHOD(Raycast::SetWallBlendType^5, AGSPalRender::Ray_SetWallBlendType);
1570 SCRIPT_METHOD(Raycast::GetMoveSpeed^0, AGSPalRender::Ray_GetMoveSpeed);
1571 SCRIPT_METHOD(Raycast::SetMoveSpeed^1, AGSPalRender::Ray_SetMoveSpeed);
1572 SCRIPT_METHOD(Raycast::GetRotSpeed^0, AGSPalRender::Ray_GetRotSpeed);
1573 SCRIPT_METHOD(Raycast::SetRotSpeed^1, AGSPalRender::Ray_SetRotSpeed);
1574 SCRIPT_METHOD(Raycast::GetWallAt^2, AGSPalRender::Ray_GetWallAt);
1575 SCRIPT_METHOD(Raycast::GetLightAt^2, AGSPalRender::Ray_GetLightAt);
1576 SCRIPT_METHOD(Raycast::SetLightAt^3, AGSPalRender::Ray_SetLightAt);
1577 SCRIPT_METHOD(Raycast::SetWallAt^3, AGSPalRender::Ray_SetWallAt);
1578 SCRIPT_METHOD(Raycast::SetPlaneY^1, AGSPalRender::Ray_SetPlaneY);
1579 SCRIPT_METHOD(Raycast::GetDistanceAt^2, AGSPalRender::Ray_GetDistanceAt);
1580 SCRIPT_METHOD(Raycast::GetSpriteAngle^1, AGSPalRender::Ray_GetSpriteAngle);
1581 SCRIPT_METHOD(Raycast::SetSpriteAngle^2, AGSPalRender::Ray_SetSpriteAngle);
1582 SCRIPT_METHOD(Raycast::SetSpriteView^2, AGSPalRender::Ray_SetSpriteView);
1583 SCRIPT_METHOD(Raycast::GetSpriteView^1, AGSPalRender::Ray_GetSpriteView);
1584 SCRIPT_METHOD(Raycast::SetSpriteFrame^2, AGSPalRender::Ray_SetSpriteFrame);
1585 SCRIPT_METHOD(Raycast::GetSpriteFrame^1, AGSPalRender::Ray_GetSpriteFrame);
1586 SCRIPT_METHOD(Raycast::SetSpritePic^2, AGSPalRender::Ray_SetSpritePic);
1587 SCRIPT_METHOD(Raycast::GetSpritePic^1, AGSPalRender::Ray_GetSpritePic);
1588 SCRIPT_METHOD(Raycast::SetSkyBox^1, AGSPalRender::Ray_SetSkyBox);
1589 SCRIPT_METHOD(Raycast::SetSpriteAlpha^2, AGSPalRender::Ray_SetSpriteAlpha);
1590 SCRIPT_METHOD(Raycast::GetSpriteAlpha^1, AGSPalRender::Ray_GetSpriteAlpha);
1591 SCRIPT_METHOD(Raycast::GetSkyBox^1, AGSPalRender::Ray_GetSkyBox);
1592 SCRIPT_METHOD(Raycast::SetAmbientLight^1, AGSPalRender::Ray_SetAmbientLight);
1593 SCRIPT_METHOD(Raycast::SetAmbientColor^2, AGSPalRender::Ray_SetAmbientColor);
1594 SCRIPT_METHOD(Raycast::GetAmbientLight^0, AGSPalRender::Ray_GetAmbientLight);
1595 SCRIPT_METHOD(Raycast::GetAmbientWeight^0, AGSPalRender::Ray_GetAmbientWeight);
1596 SCRIPT_METHOD(Raycast::GetTileX_At^2, AGSPalRender::Ray_GetTileX_At);
1597 SCRIPT_METHOD(Raycast::GetTileY_At^2, AGSPalRender::Ray_GetTileY_At);
1598 SCRIPT_METHOD(Raycast::DrawTile^2, AGSPalRender::Ray_DrawTile);
1599 SCRIPT_METHOD(Raycast::DrawOntoTile^2, AGSPalRender::Ray_DrawOntoTile);
1600 SCRIPT_METHOD(Raycast::SetNoClip^1, AGSPalRender::Ray_SetNoClip);
1601 SCRIPT_METHOD(Raycast::GetNoClip^0, AGSPalRender::Ray_GetNoClip);
1602 SCRIPT_METHOD(Raycast::GetSpriteScaleX^1, AGSPalRender::Ray_GetSpriteScaleX);
1603 SCRIPT_METHOD(Raycast::SetSpriteScaleX^2, AGSPalRender::Ray_SetSpriteScaleX);
1604 SCRIPT_METHOD(Raycast::GetSpriteScaleY^1, AGSPalRender::Ray_GetSpriteScaleY);
1605 SCRIPT_METHOD(Raycast::SetSpriteScaleY^2, AGSPalRender::Ray_SetSpriteScaleY);
1606 SCRIPT_METHOD(Raycast::GetSpriteBlendType^1, AGSPalRender::Ray_GetSpriteBlendType);
1607 SCRIPT_METHOD(Raycast::SetSpriteBlendType^2, AGSPalRender::Ray_SetSpriteBlendType);
1608
1609
1610 SCRIPT_METHOD(Raycast::SetFloorAt^3, AGSPalRender::Ray_SetFloorAt);
1611 SCRIPT_METHOD(Raycast::SetCeilingAt^3, AGSPalRender::Ray_SetCeilingAt);
1612 SCRIPT_METHOD(Raycast::GetCeilingAt^2, AGSPalRender::Ray_GetCeilingAt);
1613 SCRIPT_METHOD(Raycast::GetFloorAt^2, AGSPalRender::Ray_GetFloorAt);
1614 SCRIPT_METHOD(Raycast::GetLightingAt^2, AGSPalRender::Ray_GetLightingAt);
1615 SCRIPT_METHOD(Raycast::SetLightingAt^3, AGSPalRender::Ray_SetLightingAt);
1616 SCRIPT_METHOD(Raycast::GetWallHotspot^1, AGSPalRender::Ray_GetWallHotspot);
1617 SCRIPT_METHOD(Raycast::GetWallTexture^2, AGSPalRender::Ray_GetWallTexture);
1618 SCRIPT_METHOD(Raycast::GetWallSolid^2, AGSPalRender::Ray_GetWallSolid);
1619 SCRIPT_METHOD(Raycast::GetWallIgnoreLighting^2, AGSPalRender::Ray_GetWallIgnoreLighting);
1620 SCRIPT_METHOD(Raycast::GetWallAlpha^2, AGSPalRender::Ray_GetWallAlpha);
1621 SCRIPT_METHOD(Raycast::GetWallBlendType^2, AGSPalRender::Ray_GetWallBlendType);
1622 SCRIPT_METHOD(Raycast::SelectTile^3, AGSPalRender::Ray_SelectTile);
1623 SCRIPT_METHOD(Raycast::HasSeenTile^2, AGSPalRender::Ray_HasSeenTile);
1624
1625 SCRIPT_METHOD(LensDistort::SetPos^2, AGSPalRender::SetLensPos);
1626 SCRIPT_METHOD(LensDistort::GetX^0, AGSPalRender::GetLensX);
1627 SCRIPT_METHOD(LensDistort::GetY^0, AGSPalRender::GetLensY);
1628 SCRIPT_METHOD(LensDistort::Set^1, AGSPalRender::SetLensDrawn);
1629 SCRIPT_METHOD(LensDistort::IsDrawn^0, AGSPalRender::GetLensDrawn);
1630 SCRIPT_METHOD(LensDistort::SetOffsetClamp^1, AGSPalRender::SetLensOffsetClamp);
1631 SCRIPT_METHOD(LensDistort::GetOffsetClamp^0, AGSPalRender::GetLensOffsetClamp);
1632 SCRIPT_METHOD(LensDistort::GetLevel^0, AGSPalRender::GetLensLevel);
1633 SCRIPT_METHOD(LensDistort::SetLevel^1, AGSPalRender::SetLensLevel);
1634 SCRIPT_METHOD(LensDistort::Initialize^6, AGSPalRender::LensInitialize);
1635
1636 SCRIPT_METHOD(Translucence::CreateOverlay^8, AGSPalRender::CreateTranslucentOverlay);
1637 SCRIPT_METHOD(Translucence::DeleteOverlay^1, AGSPalRender::DeleteTranslucentOverlay);
1638 SCRIPT_METHOD(Translucence::Move^3, AGSPalRender::MoveTranslucentOverlay);
1639 SCRIPT_METHOD(Translucence::GetOverlayX^1, AGSPalRender::GetTranslucentOverlayX);
1640 SCRIPT_METHOD(Translucence::GetOverlayY^1, AGSPalRender::GetTranslucentOverlayY);
1641 SCRIPT_METHOD(Translucence::GetOverlaySprite^1, AGSPalRender::GetTranslucentOverlaySprite);
1642 SCRIPT_METHOD(Translucence::GetOverlayLevel^1, AGSPalRender::GetTranslucentOverlayLevel);
1643 SCRIPT_METHOD(Translucence::GetOverlayEnabled^1, AGSPalRender::GetTranslucentOverlayEnabled);
1644 SCRIPT_METHOD(Translucence::GetOverlayAlpha^1, AGSPalRender::GetTranslucentOverlayAlpha);
1645 SCRIPT_METHOD(Translucence::SetOverlayAlpha^2, AGSPalRender::SetTranslucentOverlayAlpha);
1646 SCRIPT_METHOD(Translucence::SetOverlayEnabled^2, AGSPalRender::SetTranslucentOverlayEnabled);
1647 SCRIPT_METHOD(Translucence::DrawTransSprite^6, AGSPalRender::DrawTransSprite);
1648
1649 SCRIPT_METHOD(Starfield::GetOverscan^0, AGSPalRender::GetStarfieldOverscan);
1650 SCRIPT_METHOD(Starfield::SetOverscan^1, AGSPalRender::SetStarfieldOverscan);
1651 SCRIPT_METHOD(Starfield::GetOriginX^0, AGSPalRender::GetStarfieldOriginX);
1652 SCRIPT_METHOD(Starfield::GetOriginY^0, AGSPalRender::GetStarfieldOriginY);
1653 SCRIPT_METHOD(Starfield::SetDepthMultiplier^1, AGSPalRender::SetStarfieldDepthMultiplier);
1654 SCRIPT_METHOD(Starfield::GetDepthMultiplier^0, AGSPalRender::GetStarfieldDepthMultiplier);
1655 SCRIPT_METHOD(Starfield::GetMaxStars^0, AGSPalRender::GetStarfieldMaxStars);
1656 SCRIPT_METHOD(Starfield::SetStarSpriteScaleBoost^1, AGSPalRender::SetStarSpriteScaleBoost);
1657 SCRIPT_METHOD(Starfield::GetStarSpriteScaleBoost^0, AGSPalRender::GetStarSpriteScaleBoost);
1658 SCRIPT_METHOD(Starfield::SetStarMaxRadius^2, AGSPalRender::SetStarMaxRadius);
1659 SCRIPT_METHOD(Starfield::GetStarMaxRadius^0, AGSPalRender::GetStarMaxRadius);
1660 SCRIPT_METHOD(Starfield::GetStarX^1, AGSPalRender::GetStarX);
1661 SCRIPT_METHOD(Starfield::GetStarY^1, AGSPalRender::GetStarY);
1662 SCRIPT_METHOD(Starfield::GetStarZ^1, AGSPalRender::GetStarZ);
1663 SCRIPT_METHOD(Starfield::SetStarPosition^4, AGSPalRender::SetStarPosition);
1664 SCRIPT_METHOD(Starfield::RotateStar^4, AGSPalRender::RotateStar);
1665 SCRIPT_METHOD(Starfield::SetStarColor^2, AGSPalRender::SetStarColor);
1666 SCRIPT_METHOD(Starfield::GetStarColor^1, AGSPalRender::GetStarColor);
1667 SCRIPT_METHOD(Starfield::SetStarSprite^2, AGSPalRender::SetStarSprite);
1668 SCRIPT_METHOD(Starfield::GetStarSprite^1, AGSPalRender::GetStarSprite);
1669 SCRIPT_METHOD(Starfield::SetStarSpriteRange^3, AGSPalRender::SetStarSpriteRange);
1670 SCRIPT_METHOD(Starfield::Initialize^2, AGSPalRender::InitializeStars);
1671 SCRIPT_METHOD(Starfield::Iterate^1, AGSPalRender::IterateStars);
1672 SCRIPT_METHOD(Starfield::Draw^2, AGSPalRender::DrawStars);
1673 SCRIPT_METHOD(Starfield::SetOriginPoint^2, AGSPalRender::SetStarsOriginPoint);
1674
1675 SCRIPT_METHOD(Plasma::DoFire^8, AGSPalRender::DoFire);
1676 SCRIPT_METHOD(Plasma::SetPlasmaType^5, AGSPalRender::SetPlasmaType);
1677 SCRIPT_METHOD(Plasma::ResetPlasmaSettings^0, AGSPalRender::ResetPlasmaSettings);
1678 SCRIPT_METHOD(Plasma::DrawPlasma^3, AGSPalRender::DrawPlasma);
1679 SCRIPT_METHOD(Plasma::SetRootType^1, AGSPalRender::SetPlasmaRootType);
1680 SCRIPT_METHOD(Plasma::GetRootType^0, AGSPalRender::GetPlasmaRootType);
1681
1682 SCRIPT_METHOD(Reflections::Set^1, AGSPalRender::SetReflections);
1683 SCRIPT_METHOD(Reflections::IsReflecting^0, AGSPalRender::IsReflectionsOn);
1684 SCRIPT_METHOD(Reflections::SetCharacterReflected^2, AGSPalRender::SetCharacterReflected);
1685 SCRIPT_METHOD(Reflections::GetCharacterReflected^1, AGSPalRender::GetCharacterReflected);
1686 SCRIPT_METHOD(Reflections::SetObjectReflected^2, AGSPalRender::SetObjectReflected);
1687 SCRIPT_METHOD(Reflections::GetObjectReflected^1, AGSPalRender::GetObjectReflected);
1688 SCRIPT_METHOD(Reflections::ReplaceCharacterReflectionView^2, AGSPalRender::ReplaceCharacterReflectionView);
1689 SCRIPT_METHOD(Reflections::SetObjectReflectionIgnoreScaling^2, AGSPalRender::SetObjectReflectionIgnoreScaling);
1690
1691 engine->RequestEventHook(AGSE_PRESCREENDRAW);
1692 engine->RequestEventHook(AGSE_PREGUIDRAW);
1693 engine->RequestEventHook(AGSE_POSTSCREENDRAW);
1694 engine->RequestEventHook(AGSE_SAVEGAME);
1695 engine->RequestEventHook(AGSE_RESTOREGAME);
1696 engine->RequestEventHook(AGSE_ENTERROOM);
1697 stars = new starstype [MAX_STARS];
1698 Starfield.maxstars = MAX_STARS;
1699 Starfield.depthmultiplier = 256;
1700 Starfield.speed = 0.5;
1701 Starfield.originx = 160;
1702 Starfield.originy = 100;
1703 Reflection.Characters = new charrefopt [engine->GetNumCharacters()]();
1704 lens = new LensDistort [LENS_WIDTH * LENS_WIDTH]();
1705 //PreMultiply_Alphas ();
1706 plasmaroottype = 0;
1707 Make_Sin_Lut();
1708 ScriptMethodParams params;
1709 Init_Raycaster(params);
1710 }
1711
AGS_EngineShutdown()1712 void AGSPalRender::AGS_EngineShutdown() {
1713 // no work to do here - but if we had created any dynamic sprites,
1714 // we should delete them here
1715 delete[] Reflection.Characters;
1716 delete[] Reflection.Objects;
1717 //QuitCleanup();
1718 }
1719
AGS_EngineOnEvent(int event,NumberPtr data)1720 int64 AGSPalRender::AGS_EngineOnEvent(int event, NumberPtr data) {
1721 if (event == AGSE_PRESCREENDRAW && clutslot > 0) {
1722 if (drawreflections) {
1723 int32 sh, sw = 0;
1724 engine->GetScreenDimensions(&sw, &sh, nullptr);
1725 reflectionmap = new long[sw * sh]();
1726 rcolormap = engine->CreateBlankBitmap(sw, sh, 8);
1727 ralphamap = engine->CreateBlankBitmap(sw, sh, 8);
1728 for (int i = 0; i < engine->GetNumCharacters(); i++) {
1729 if (Reflection.Characters[i].reflect == 0) continue;
1730 AGSCharacter *tempchar = engine->GetCharacter(i);
1731 if (tempchar->room != engine->GetCurrentRoom()) continue; //if character isn't even in the room, go to next iteration.
1732 int32 vx = tempchar->x;
1733 int32 vy = tempchar->y;
1734 engine->RoomToViewport(&vx, &vy);
1735 AGSViewFrame *vf = engine->GetViewFrame(tempchar->view + 1, tempchar->loop, tempchar->frame);
1736 int w = engine->GetSpriteWidth(vf->pic);
1737 int h = engine->GetSpriteHeight(vf->pic);
1738 vx = vx - (w / 2);
1739 int32 vxmax = vx + w;
1740 int32 vymax = vy + h;
1741 if (vxmax < 0 || vy > sh || vx > sw || vymax < 0) continue; //if all of the sprite is off screen in any direction, go to next iteration
1742 DrawReflections(i, 0);
1743 }
1744 for (int i = 0; i < engine->GetNumObjects(); i++) {
1745 if (Reflection.Objects[i].reflect == 0) continue;
1746 AGSObject *tempobj = engine->GetObject(i);
1747 if (!tempobj->on) continue;
1748 int32 vx = tempobj->x;
1749 int32 vy = tempobj->baseline - tempobj->y;
1750 engine->RoomToViewport(&vx, &vy);
1751 int32 w = engine->GetSpriteWidth(tempobj->num);
1752 int32 h = engine->GetSpriteHeight(tempobj->num);
1753 int32 vxmax = vx + w;
1754 int32 vymax = vy + h;
1755 if (vxmax < 0 || vy > sh || vx > sw || vymax < 0) continue; //if all of the sprite is off screen in any direction, go to next iteration
1756 DrawReflections(i, 1);
1757 }
1758 BITMAP *virtsc = engine->GetVirtualScreen();
1759 uint8 *screenbuffer = engine->GetRawBitmapSurface(virtsc);
1760 uint8 *colorbuffer = engine->GetRawBitmapSurface(rcolormap);
1761 uint8 *alphabuffer = engine->GetRawBitmapSurface(ralphamap);
1762 int screenPitch = engine->GetBitmapPitch(virtsc);
1763 int colorPitch = engine->GetBitmapPitch(rcolormap);
1764 int alphaPitch = engine->GetBitmapPitch(ralphamap);
1765 for (int y = 0, screeny = 0, colory = 0, alphay = 0; y < sh; y++, screeny += screenPitch, colory += colorPitch, alphay += alphaPitch)
1766 for (int x = 0; x < sw; x++)
1767 screenbuffer[screeny+x] = Mix::MixColorAlpha(colorbuffer[colory+x], screenbuffer[screeny+x], alphabuffer[alphay+x]);
1768 engine->ReleaseBitmapSurface(rcolormap);
1769 engine->ReleaseBitmapSurface(ralphamap);
1770 engine->ReleaseBitmapSurface(virtsc);
1771 engine->FreeBitmap(rcolormap);
1772 engine->FreeBitmap(ralphamap);
1773 delete[] reflectionmap;
1774 }
1775 int i = 0;
1776 if (LensOption.draw == 1 && LensOption.level == 0) DrawLens(LensOption.x, LensOption.y);
1777 while (i < MAX_OVERLAYS) {
1778 if (overlay[i].enabled && overlay[i].level == 0) {
1779 DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
1780 }
1781 i++;
1782 }
1783 if (LensOption.draw == 1 && LensOption.level == 1) DrawLens(LensOption.x, LensOption.y);
1784 }
1785 if (event == AGSE_PREGUIDRAW && clutslot > 0) {
1786 int i = 0;
1787 if (LensOption.draw == 1 && LensOption.level == 1) DrawLens(LensOption.x, LensOption.y);
1788 while (i < MAX_OVERLAYS) {
1789 if (overlay[i].enabled && overlay[i].level == 1) {
1790 DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
1791 }
1792 i++;
1793 }
1794 if (LensOption.draw == 1 && LensOption.level == 2) DrawLens(LensOption.x, LensOption.y);
1795 }
1796 if (event == AGSE_POSTSCREENDRAW && clutslot > 0) {
1797 int i = 0;
1798 if (LensOption.draw == 1 && LensOption.level == 3) DrawLens(LensOption.x, LensOption.y);
1799 while (i < MAX_OVERLAYS) {
1800 if (overlay[i].enabled && overlay[i].level == 2) {
1801 DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
1802 }
1803 i++;
1804 }
1805 if (LensOption.draw == 1 && LensOption.level == 4) DrawLens(LensOption.x, LensOption.y);
1806 }
1807 if (event == AGSE_SAVEGAME) {
1808 Serializer s(engine, data, false);
1809 syncGame(s);
1810 }
1811 if (event == AGSE_RESTOREGAME) {
1812 Serializer s(engine, data, true);
1813 syncGame(s);
1814 }
1815 if (event == AGSE_ENTERROOM) {
1816 ScriptMethodParams params;
1817 ResetRemapping(params);
1818 delete[] Reflection.Objects;
1819 Reflection.Objects = new objrefopt [engine->GetNumObjects()]();
1820 }
1821 return 0;
1822 }
1823
syncGame(Serializer & s)1824 void AGSPalRender::syncGame(Serializer &s) {
1825 for (int i = 0; i < MAX_OVERLAYS; ++i) {
1826 s.syncAsInt(overlay[i].sprite);
1827 s.syncAsInt(overlay[i].spritemask);
1828 s.syncAsInt(overlay[i].x);
1829 s.syncAsInt(overlay[i].y);
1830 s.syncAsInt(overlay[i].level);
1831 s.syncAsInt(overlay[i].trans);
1832 s.syncAsInt(overlay[i].blendtype);
1833 s.syncAsBool(overlay[i].enabled);
1834 }
1835 s.syncAsInt(clutslot);
1836 s.syncAsInt(drawreflections);
1837
1838 for (int j = 0; j < 256; ++j)
1839 s.syncAsByte(cycle_remap[j]);
1840
1841 for (int j = 0; j < 256; ++j) {
1842 s.syncAsByte(objectivepal[j].r);
1843 s.syncAsByte(objectivepal[j].b);
1844 s.syncAsByte(objectivepal[j].g);
1845 }
1846
1847 for (int j = 0; j < 256; ++j) {
1848 s.syncAsDouble(sprite[j].x);
1849 s.syncAsDouble(sprite[j].y);
1850 s.syncAsInt(sprite[j].texture);
1851 s.syncAsByte(sprite[j].alpha);
1852 s.syncAsDouble(sprite[j].uDivW);
1853 s.syncAsDouble(sprite[j].uDivH);
1854 s.syncAsDouble(sprite[j].vMove);
1855 s.syncAsDouble(sprite[j].hMove);
1856 s.syncAsInt8(sprite[j].objectinteract);
1857 s.syncAsInt(sprite[j].view);
1858 s.syncAsInt(sprite[j].frame);
1859 s.syncAsInt(sprite[j].angle);
1860 }
1861
1862 for (int j = 0; j < 256; ++j) {
1863 for (int k = 0; k < 4; ++k) {
1864 s.syncAsInt(wallData[j].texture[k]);
1865 s.syncAsInt(wallData[j].solid[k]);
1866 s.syncAsInt(wallData[j].ignorelighting[k]);
1867 s.syncAsInt(wallData[j].alpha[k]);
1868 s.syncAsInt(wallData[j].blendtype[k]);
1869 s.syncAsInt(wallData[j].mask[k]);
1870 }
1871
1872 s.syncAsByte(wallData[j].hotspotinteract);
1873 }
1874
1875 s.syncAsBool(raycastOn);
1876 s.syncAsBool(heightmapOn);
1877 s.syncAsDouble(posX);
1878 s.syncAsDouble(posY);
1879 s.syncAsDouble(dirX);
1880 s.syncAsDouble(dirY);
1881 s.syncAsDouble(planeX);
1882 s.syncAsDouble(planeY);
1883 s.syncAsDouble(moveSpeed);
1884 s.syncAsDouble(rotSpeed);
1885
1886 if (raycastOn) { //If the raycaster is active, we have additional data to save.
1887 for (int i = 0; i < MAP_WIDTH; ++i)
1888 for (int j = 0; j < MAP_HEIGHT; ++j) {
1889 s.syncAsByte(worldMap[i][j]);
1890 s.syncAsByte(lightMap[i][j]);
1891 s.syncAsInt(ceilingMap[i][j]);
1892 s.syncAsInt(floorMap[i][j]);
1893 s.syncAsInt(heightMap[i][j]);
1894 }
1895 }
1896
1897 s.syncAsInt(textureSlot);
1898 if (s.isLoading() && textureSlot) {
1899 ScriptMethodParams params;
1900 params.push_back(textureSlot);
1901 MakeTextures(params);
1902 }
1903
1904 s.syncAsInt(skybox);
1905 s.syncAsInt(ambientlight);
1906
1907 if (s.isLoading()) {
1908 ScriptMethodParams params;
1909 params.push_back(clutslot);
1910 LoadCLUT(params);
1911 }
1912 }
1913
1914 } // namespace AGSPalRender
1915 } // namespace Plugins
1916 } // namespace AGS3
1917