[Scummvm-git-logs] scummvm master -> bfe16d0ed420992d2c9d42bedb0edeb8f483260e

salty-horse ori at avtalion.name
Thu Feb 11 18:32:44 UTC 2021


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
31e33a1e08 AGS: Convert to Unix newlines
bfe16d0ed4 AGS: Silence clang warnings


Commit: 31e33a1e08e8fc1a71edd6099170cca6a5c1f1db
    https://github.com/scummvm/scummvm/commit/31e33a1e08e8fc1a71edd6099170cca6a5c1f1db
Author: Ori Avtalion (ori at avtalion.name)
Date: 2021-02-11T20:28:11+02:00

Commit Message:
AGS: Convert to Unix newlines

Changed paths:
    engines/ags/plugins/ags_pal_render/ags_pal_render.cpp
    engines/ags/plugins/ags_pal_render/pal_render.h
    engines/ags/plugins/ags_pal_render/raycast.cpp
    engines/ags/plugins/ags_pal_render/raycast.h


diff --git a/engines/ags/plugins/ags_pal_render/ags_pal_render.cpp b/engines/ags/plugins/ags_pal_render/ags_pal_render.cpp
index d21fe61da3..6680a187d9 100644
--- a/engines/ags/plugins/ags_pal_render/ags_pal_render.cpp
+++ b/engines/ags/plugins/ags_pal_render/ags_pal_render.cpp
@@ -1,1849 +1,1849 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "ags/lib/allegro.h"
-#include "ags/plugins/ags_pal_render/ags_pal_render.h"
-#include "ags/plugins/ags_pal_render/pal_render.h"
-#include "ags/plugins/ags_pal_render/raycast.h"
-#include "ags/ags.h"
-
-namespace AGS3 {
-namespace Plugins {
-namespace AGSPalRender {
-
-#define MAX_OVERLAYS 128
-#define MAX_STARS 1024
-#define MAX_DEPTH 64
-
-#define PI         (3.1415926535f)
-#define HALF_PI    (0.5f * PI)
-#define TWO_PI     (2.0f * PI)
-#define TWO_PI_INV (1.0f / TWO_PI)
-
-const float halfpi = (0.5f * PI);
-const float twopi  = (2.0f * PI);
-const float twopi_inv = (1.0f / TWO_PI);
-const float pisquared = PI * PI;
-const float picubed = PI * PI * PI;
-
-IAGSEngine *engine;
-
-//unsigned char clut[256][256];
-unsigned char clut[65536];
-
-struct transoverlaytype {
-	int sprite;
-	int spritemask;
-	int blendtype;
-	int x;
-	int y;
-	int trans;
-	int level;
-	bool enabled;
-} overlay[MAX_OVERLAYS];
-
-int clutslot;
-int drawreflections;
-unsigned char cycle_remap [256];
-
-struct starstype {
-	float x;
-	float y;
-	float z;
-	unsigned char color;
-	long sprite;
-	int maxrad;
-	int scaleboost;
-};
-starstype *stars;
-
-struct starsoptions {
-	float speed;
-	int maxstars;
-	int depthmultiplier;
-	int originx;
-	int originy;
-	int overscan;
-} Starfield;
-long *reflectionmap;
-BITMAP *rcolormap;
-BITMAP *ralphamap;
-
-struct charrefopt {
-	char reflect;
-	int replaceview;
-};
-
-struct objrefopt {
-	char reflect;
-	char ignorescaling;
-};
-
-struct reflectionopt {
-	charrefopt *Characters;
-	objrefopt *Objects;
-	int blendslot;
-	int blendamount;
-} Reflection;
-
-int dummy;
-
-#define LENS_WIDTH 150
-
-struct LensDistort {
-	int xoffset;
-	int yoffset;
-};
-
-LensDistort *lens;
-struct LensOpt {
-	bool draw;
-	int lenswidth;
-	int lenszoom;
-	int level;
-	int x;
-	int y;
-	int clampoffset;
-} LensOption;
-
-const int alphamultiply [4096] = {
-//#include "alphamultiply.txt"
-};
-float rot_sine_LUT[360];
-float rot_cos_LUT[360];
-
-BITMAP *backgroundimage;
-
-PALSTRUCT objectivepal[256];
-int bgimgspr;
-
-void WriteObjectivePalette(unsigned char index, unsigned char r, unsigned char b, unsigned char g) {
-	objectivepal[index].r = r;
-	objectivepal[index].b = b;
-	objectivepal[index].g = g;
-}
-
-int ReadObjectivePaletteR(unsigned char index) {
-	return objectivepal[index].r;
-}
-
-int ReadObjectivePaletteB(unsigned char index) {
-	return objectivepal[index].b;
-}
-int ReadObjectivePaletteG(unsigned char index) {
-	return objectivepal[index].g;
-}
-
-
-#define SQRT_MAGIC_F 0x5f3759df
-float  q3sqrt(const float x) {
-	const float xhalf = 0.5f * x;
-
-	union { // get bits for floating value
-		float x;
-		int i;
-	} u;
-	u.x = x;
-	u.i = SQRT_MAGIC_F - (u.i >> 1);  // gives initial guess y0
-	return x * u.x * (1.5f - xhalf * u.x * u.x); // Newton step, repeating increases accuracy
-}
-
-void Make_Sin_Lut() {
-	for (int angle = 0; angle < 360; angle++) {
-		double rad = (angle * PI) / 180.0;
-		rot_sine_LUT [angle] = static_cast<float>(sin(rad));
-		rot_cos_LUT [angle]  = static_cast<float>(cos(rad));
-	}
-}
-
-/*
-void PreMultiply_Alphas () //Ha ha, this isn't the kind of premultiplcation you're thinking of.
-{
-    for (int y=0;y<64;y++)
-        for (int x=0;x<64;x++)
-            alphamultiply [y*64+x] = y*x;
-}
-*/
-
-int GetModifiedBackgroundImage() {
-	return bgimgspr;
-}
-
-unsigned short root(unsigned short x) {
-	unsigned short a, b;
-	b = x;
-	a = x = 0x3f;
-	x = b / x;
-	a = x = (x + a) >> 1;
-	x = b / x;
-	a = x = (x + a) >> 1;
-	x = b / x;
-	x = (x + a) >> 1;
-	return (x);
-}
-
-
-float Hill(float x) {
-	const float a0 = 1.0f;
-	const float a2 = 2.0f / PI - 12.0f / (pisquared);
-	const float a3 = 16.0f / (picubed) - 4.0f / (pisquared);
-	const float xx = x * x;
-	const float xxx = xx * x;
-
-	return a0 + a2 * xx + a3 * xxx;
-}
-
-float FastSin(float x) {
-	// wrap x within [0, TWO_PI)
-	const float a = x * twopi_inv;
-	x -= static_cast<int>(a) * twopi;
-	if (x < 0.0f)
-		x += twopi;
-
-	// 4 pieces of hills
-	if (x < halfpi)
-		return Hill(halfpi - x);
-	else if (x < PI)
-		return Hill(x - halfpi);
-	else if (x < 3.0f * halfpi)
-		return -Hill(3.0f * halfpi - x);
-	else
-		return -Hill(x - 3.0f * halfpi);
-}
-
-float FastCos(float x) {
-	return FastSin(x + halfpi);
-}
-
-FLOAT_RETURN_TYPE AGSFastSin(SCRIPT_FLOAT(x)) {
-	INIT_SCRIPT_FLOAT(x);
-	x = FastSin(x);
-	RETURN_FLOAT(x);
-}
-
-FLOAT_RETURN_TYPE AGSFastCos(SCRIPT_FLOAT(x)) {
-	INIT_SCRIPT_FLOAT(x);
-	x = FastSin(x + halfpi);
-	RETURN_FLOAT(x);
-}
-
-
-void DrawLens(int ox, int oy) {
-	int32 sh, sw = 0;
-	engine->GetScreenDimensions(&sw, &sh, nullptr);
-	BITMAP *virtsc = engine->GetVirtualScreen();
-	if (!virtsc) engine->AbortGame("DrawLens: Cannot get virtual screen.");
-	BITMAP *lenswrite = engine->CreateBlankBitmap(LensOption.lenswidth, LensOption.lenswidth, 8);
-	unsigned char **vScreen = engine->GetRawBitmapSurface(virtsc);
-	unsigned char **lensarray = engine->GetRawBitmapSurface(lenswrite);
-	int radius = LensOption.lenswidth >> 1;
-	for (int y = 0; y < LensOption.lenswidth; y++) {
-		int ypos = y * LensOption.lenswidth;
-		for (int x = 0; x < LensOption.lenswidth; x++) {
-			int lenspos = ypos + x;
-			int coffx = lens[lenspos].xoffset;
-			int coffy = lens[lenspos].yoffset;
-			if (oy + coffy > 0 && oy + coffy < sh && ox + coffx > 0 && ox + coffx < sw) {
-				lensarray[y][x] = vScreen[oy + coffy][ox + coffx];
-				//vScreen[oy+coffy][ox+coffx] = ABS(coffy);
-			}
-		}
-	}
-	/*
-	for (int y=0;y<LensOption.lenswidth;y++)
-	{
-	    int ypos = y*LensOption.lenswidth;
-	    for (int x=0;x<LensOption.lenswidth;x++)
-	    {
-	        if (oy+y > 0 && oy+y < sh && ox+x > 0 && ox+x < sw)
-	        {
-	            vScreen[oy+y][ox+x] = lensarray[y][x];
-	        }
-	    }
-	}
-	*/
-	int radsq = radius * radius;
-	for (int cy = -radius; cy <= radius; cy++) { //Draw a circle around the point, for the mask.
-		int cysq = cy * cy;
-		for (int cx = -radius; cx <= radius; cx++) {
-			int cxsq = cx * cx;
-			int dx = cx + ox;
-			int dy = cy + oy;
-			if ((cxsq + cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0 && cy + radius < LensOption.lenswidth - 1 && cx + radius < LensOption.lenswidth - 1) {
-				//if (cy+radius < 0 || cx+radius < 0) engine->AbortGame ("I did something wrong");
-				vScreen[dy][dx] = lensarray[cy + radius][cx + radius];
-			}
-		}
-	}
-
-	engine->ReleaseBitmapSurface(lenswrite);
-	engine->ReleaseBitmapSurface(virtsc);
-	engine->FreeBitmap(lenswrite);
-}
-
-void SetLensPos(int x, int y) {
-	LensOption.x = x;
-	LensOption.y = y;
-}
-
-int GetLensX() {
-	return LensOption.x;
-}
-
-int GetLensY() {
-	return LensOption.y;
-}
-
-void SetLensDrawn(int toggle) {
-	if (toggle > 0) LensOption.draw = 1;
-	else LensOption.draw = 0;
-}
-
-int GetLensDrawn() {
-	return LensOption.draw;
-}
-
-void SetLensOffsetClamp(int clamp) {
-	if (clamp < 0) LensOption.clampoffset = LensOption.lenswidth;
-	else LensOption.clampoffset = clamp;
-}
-
-int GetLensOffsetClamp() {
-	return LensOption.clampoffset;
-}
-
-int GetLensLevel() {
-	return LensOption.level;
-}
-
-void SetLensLevel(int level) {
-	if (level < 0 || level > 4) engine->AbortGame("SetLensLevel: Invalid level.");
-	else LensOption.level = level;
-}
-
-void LensInitialize(int width, int zoom, int lensx, int lensy, int level, int clamp = -1) {
-	int32 sw, sh, radius;
-	if (width < 1) engine->AbortGame("Invalid lens dimension!");
-	radius = width >> 1;
-	lens = new LensDistort [width * width]();
-	engine->GetScreenDimensions(&sw, &sh, nullptr);
-	int radsq = radius * radius;
-	int zoomsq = zoom * zoom;
-	for (int y = 0; y < radius; y++) {
-		int ysq = y * y;
-		for (int x = 0; x < radius; x++) {
-			int lx, ly;
-			int xsq = x * x;
-			if ((xsq + ysq) < (radsq)) {
-				float shift = zoom / sqrt((float)(zoomsq - (xsq + ysq - radsq)));
-				lx = (int)(x * shift - x);
-				ly = (int)(y * shift - y);
-			} else {
-				lx = 0;
-				ly = 0;
-			}
-			lens[(radius - y)*width + (radius - x)].xoffset =  lx;
-			lens[(radius - y)*width + (radius - x)].yoffset =  ly;
-			lens[(radius + y)*width + (radius + x)].xoffset = -lx;
-			lens[(radius + y)*width + (radius + x)].yoffset = -ly;
-			lens[(radius + y)*width + (radius - x)].xoffset =  lx;
-			lens[(radius + y)*width + (radius - x)].yoffset = -ly;
-			lens[(radius - y)*width + (radius + x)].xoffset = -lx;
-			lens[(radius - y)*width + (radius + x)].yoffset =  ly;
-		}
-	}
-	LensOption.lenswidth = width;
-	LensOption.lenszoom = zoom;
-	if (clamp < 0) LensOption.clampoffset = width;
-	else LensOption.clampoffset = clamp;
-	LensOption.x = lensx;
-	LensOption.y = lensy;
-	if (level < 0 || level > 4) engine->AbortGame("SetLensLevel: Invalid level.");
-	else LensOption.level = level;
-}
-
-void ResetRemapping() {
-	for (int j = 0; j < 256; ++j) {
-		cycle_remap [j] = j;
-	}
-}
-
-#define MAX_PLASMA_COMPLEXITY 4
-int plasmatype[MAX_PLASMA_COMPLEXITY];
-int plasmadata [MAX_PLASMA_COMPLEXITY];
-int plasmadata2 [MAX_PLASMA_COMPLEXITY];
-int plasmadata3 [MAX_PLASMA_COMPLEXITY];
-int plasmaroottype;
-
-
-void SetPlasmaRootType(int real) {
-	if (real) plasmaroottype = 1;
-	else plasmaroottype = 0;
-}
-
-int GetPlasmaRootType() {
-	return plasmaroottype;
-}
-
-void SetPlasmaType(int component, int type, int data, int data2, int data3) {
-	if (component >= MAX_PLASMA_COMPLEXITY) engine->AbortGame("Plasma too complex!");
-	else {
-		plasmatype [component] = type;
-		plasmadata [component] = data;
-		plasmadata2[component] = data2;
-		plasmadata3[component] = data3;
-	}
-
-	//0 = None.
-	//1 = Horizontal Bars (data=width)
-	//2 = Vertical Bars (data=width)
-	//3 = Circle (data=x,data2=y,data3=width)
-	//4 = Diagonal Bars (data=width)
-}
-
-void ResetPlasmaSettings() {
-	int i = 0;
-	while (i < MAX_PLASMA_COMPLEXITY) {
-		plasmatype [i] = 0;
-		plasmadata [i] = 0;
-		plasmadata2[i] = 0;
-		plasmadata3[i] = 0;
-		i++;
-	}
-}
-
-void DrawPlasma(int slot, int palstart, int palend) {
-	BITMAP *plasmaspr = engine->GetSpriteGraphic(slot);
-	if (!plasmaspr) engine->AbortGame("Plasma: Not a sprite I can load.");
-	int32 w, h, basecol, range = 0;
-	if (palend > palstart) {
-		range = palend - palstart;
-		basecol = palstart;
-	} else {
-		range = palstart - palend;
-		basecol = palend;
-	}
-	engine->GetBitmapDimensions(plasmaspr, &w, &h, nullptr);
-	unsigned char **plasmarray = engine->GetRawBitmapSurface(plasmaspr);
-	double frange = range / 2.0;
-	int complex = 0;
-	int color = 0;
-	int i = 0;
-	while (i < MAX_PLASMA_COMPLEXITY) {
-		if (plasmatype[i] > 0) complex++;
-		i++;
-	}
-	for (int x = 0; x < w; x++) {
-		for (int y = 0; y < h; y++) {
-			color = 0;
-			for (int p = 0; p < MAX_PLASMA_COMPLEXITY; p++) {
-				if (plasmatype[p] == 1) { //1 = Horizontal Bars (data=width)
-					color += int(frange + (frange * FastSin(y / (float)plasmadata[p])));
-				} else if (plasmatype[p] == 2) { //2 = Vertical Bars (data=width)
-					color += int(frange + (frange * FastSin(x / (float)plasmadata[p])));
-				} else if (plasmatype[p] == 3) { //3 = Circle (data=x,data2=y,data3=width)
-					int cx, cy = 0;
-					cx = plasmadata [p];
-					cy = plasmadata2 [p];
-					if (plasmaroottype == 1) color += int(frange + (frange * FastSin(q3sqrt((float)((x - cx) * (x - cx) + (y - cy) * (y - cy)) / plasmadata3[p]))));
-					else color += int(frange + (frange * FastSin(root(((x - cx) * (x - cx) + (y - cy) * (y - cy)) / plasmadata3[p]))));
-				} else if (plasmatype[p] == 4) { //4 = Diagonal Bars (data=width)
-					color += int(frange + (frange * FastSin((x + y) / (float)plasmadata[p])));
-				}
-			}
-			if (color > 0 && complex > 0) color = color / complex;
-			plasmarray[y][x] = static_cast<unsigned char>(basecol + color);
-		}
-	}
-	engine->ReleaseBitmapSurface(plasmaspr);
-	engine->NotifySpriteUpdated(slot);
-}
-
-void DoFire(int spriteId, int masksprite, int palstart, int palend, int strength, int seed, int cutoff, int windspeed) {
-	BITMAP *firespr = engine->GetSpriteGraphic(masksprite);
-	BITMAP *firecolorspr = engine->GetSpriteGraphic(spriteId);
-	BITMAP *seedspr;
-	int32 w, h = 0;
-	int range, basecol, dir = 0;
-	if (palend > palstart) {
-		range = palend - palstart;
-		basecol = palstart;
-		dir = 1;
-	} else {
-		range = palstart - palend;
-		basecol = palend;
-		dir = -1;
-	}
-	int divider = 256 / range;
-	engine->GetBitmapDimensions(firespr, &w, &h, nullptr);
-	unsigned char **fire = engine->GetRawBitmapSurface(firespr);
-	unsigned char **color = engine->GetRawBitmapSurface(firecolorspr);
-	int sparky = 0;
-	//srand(time(NULL));
-	for (int y = 0; y < h - 1; y++) {
-		if ((int)::AGS::g_vm->getRandomNumber(9) > 7 - windspeed) { //Wind right
-			for (int x = w - 1; x > 1; x--) {
-				fire[y][x] = fire[y][x - 1];
-			}
-		} else if ((int)::AGS::g_vm->getRandomNumber(9) > 7 + windspeed) { // wind left
-			for (int x = 0; x < w - 1; x++) {
-				fire[y][x] = fire[y][x + 1];
-			}
-		}
-	}
-	for (int x = 0; x < w; x++) {
-		sparky = ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % (h - 2));
-		if (sparky < h && sparky > 0 && fire[h - sparky][x] > cutoff &&
-				ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % 10) > 7)
-			fire[h - sparky][x] = 255;
-		sparky = ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % (h - 2));
-		if (sparky < h && sparky > 0 && fire[h - sparky][x] > cutoff &&
-				ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % 10) > 7)
-			fire[h - sparky][x] = 0;
-	}
-	if (seed == 0) {
-		for (int x = 0; x < w; x++)
-			fire[h - 1][x] = 255;
-		for (int x = 0; x < w; x++)
-			fire[h - 2][x] = ::AGS::g_vm->getRandomNumber(255);
-	} else if (seed > 0) {
-		seedspr = engine->GetSpriteGraphic(seed);
-		BITMAP *virtsc = engine->GetVirtualScreen();
-		engine->SetVirtualScreen(firespr);
-		engine->BlitBitmap(0, 0, seedspr, 1);
-		engine->SetVirtualScreen(virtsc);
-		engine->ReleaseBitmapSurface(virtsc);
-		engine->ReleaseBitmapSurface(seedspr);
-		engine->NotifySpriteUpdated(spriteId);
-		engine->NotifySpriteUpdated(masksprite);
-	}
-
-	for (int y = 0; y < h - 1; y++) {
-		for (int x = 0; x < w; x++) {
-			fire[y][x] =
-			    ((fire[(y + 1) % h][(x - 1 + w) % w]
-			      + fire[(y + 1) % h][(x) % w]
-			      + fire[(y + 1) % h][(x + 1) % w]
-			      + fire[(y + 2) % h][(x) % w])
-			     * 100) / (400 + (100 - strength));
-			if (fire[y][x] < cutoff) fire[y][x] = 0;
-			//if (fire[y][x] ==255) color [y][x] = palend;
-			else color [y][x] = static_cast<unsigned char>(basecol + (fire[y][x] / divider) * dir);
-		}
-	}
-	engine->ReleaseBitmapSurface(firespr);
-	engine->ReleaseBitmapSurface(firecolorspr);
-	engine->NotifySpriteUpdated(spriteId);
-	engine->NotifySpriteUpdated(masksprite);
-}
-
-/*
-unsigned char MixColorAlpha (unsigned char fg,unsigned char bg,unsigned char alpha)
-{
-    //unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
-    //unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
-    //BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
-    //if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
-    //unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
-    AGSColor *palette = engine->GetPalette ();
-    int i=0;
-    int out_r = (palette[fg].r>>1) * alpha + (palette[bg].r>>1) * (255 - alpha);
-    int out_g = palette[fg].g * alpha + palette[bg].g * (255 - alpha);
-    int out_b = (palette[fg].b>>1) * alpha + (palette[bg].b>>1) * (255 - alpha);
-    //unsigned char ralpha = alpha>>2;
-    //unsigned char invralpha = 64-ralpha;
-    //if (ralpha > alpha) engine->AbortGame ("wtf");
-    //int out_r = alphamultiply[(palette[fg].r>>1)][ralpha] + alphamultiply[(palette[bg].r>>1)][(invralpha)];
-    //int out_g = alphamultiply[(palette[fg].g)][ralpha] + alphamultiply[(palette[bg].g)][(invralpha)];
-    //int out_b = alphamultiply[(palette[fg].b>>1)][ralpha] + alphamultiply[(palette[bg].b>>1)][(invralpha)];
-    out_r = (out_r + 1 + (out_r >> 8)) >> 8;
-    out_g = (out_g + 1 + (out_g >> 8)) >> 8;
-    out_b = (out_b + 1 + (out_b >> 8)) >> 8;
-    i = ((out_r << 11) | (out_g << 5) | out_b);
-    unsigned char (*clutp) = clut;
-    //unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
-    unsigned char result = cycle_remap [*(clutp+i)]; //Once again, to make sure that the palette slot used is the right one.
-    //engine->ReleaseBitmapSurface (clutspr);
-    return result;
-}
-
-unsigned char MixColorAdditive (unsigned char fg,unsigned char bg,unsigned char alpha)
-{
-    //unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
-    //unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
-    //BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
-    //if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
-    //unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
-    AGSColor *palette = engine->GetPalette ();
-    int i=0;
-    int add_r,add_b,add_g = 0;
-    char ralpha = alpha>>2;
-    //if (ralpha > alpha) engine->AbortGame ("wtf");
-    //add_r = (((palette[fg].r>>1) * (alpha))>>8);
-    //add_b = (((palette[fg].b>>1) * (alpha))>>8);
-    //add_g = (((palette[fg].g)    * (alpha))>>8);
-    add_r = ((alphamultiply[(palette[fg].r>>1)*64+ralpha])>>6);
-    add_b = ((alphamultiply[(palette[fg].b>>1)*64+ralpha])>>6);
-    add_g = ((alphamultiply[(palette[fg].g   )*64+ralpha])>>6);
-    int out_r = min(31,(palette[bg].r>>1) + add_r);
-    int out_g = min(63, palette[bg].g     + add_g);
-    int out_b = min(31,(palette[bg].b>>1) + add_b);
-    i = ((out_r << 11) | (out_g << 5) | out_b);
-    unsigned char (*clutp) = clut;
-    unsigned char result = cycle_remap [*(clutp+i)]; //Once again, to make sure that the palette slot used is the right one.
-    //unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
-    //engine->ReleaseBitmapSurface (clutspr);
-    return result;
-}
-*/
-unsigned char GetColor565(unsigned char r, unsigned char g, unsigned char b) {
-	//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
-	//if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
-	//unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
-	int i = ((r << 11) | (g << 5) | b);
-	unsigned char (*clutp) = clut;
-	unsigned char result = *(clutp + i);
-	result = cycle_remap [result]; //Once again, to make sure that the palette slot used is the right one.
-	//engine->ReleaseBitmapSurface (clutspr);
-	return result;
-}
-
-void CycleRemap(int start, int end) {
-	if (end > start) {
-		// Rotate left
-		int wraparound = cycle_remap [start];
-		for (; start < end; ++start) {
-			cycle_remap [start] = cycle_remap [start + 1];
-		}
-		cycle_remap [end] = wraparound;
-	} else if (end < start) {
-		// Rotate right
-		int wraparound = cycle_remap [start];
-		for (; start > end; --start) {
-			cycle_remap [start] = cycle_remap [start - 1];
-		}
-		cycle_remap [end] = wraparound;
-
-	}
-}
-
-unsigned char GetRemappedSlot(unsigned char slot) {
-	return cycle_remap [slot];
-}
-
-int LoadCLUT(int slot) {
-	if (engine->GetSpriteWidth(slot) != 256 || engine->GetSpriteHeight(slot) != 256) return 1;
-	BITMAP *clutimage = engine->GetSpriteGraphic(slot);
-	unsigned char **clutarray = engine->GetRawBitmapSurface(clutimage);
-	for (int y = 0; y < 256; y++) {
-		for (int x = 0; x < 256; x++) {
-			clut[y * 256 + x] = clutarray[y][x];
-		}
-	}
-	clutslot = slot;
-	engine->ReleaseBitmapSurface(clutimage);
-	return 0;
-}
-
-void SetReflections(int toggle) {
-	drawreflections = toggle;
-}
-
-int IsReflectionsOn() {
-	return drawreflections;
-}
-
-int GetLuminosityFromPalette(int slot) {
-	AGSColor *pal = engine->GetPalette();
-	int lum = (pal[slot].r +
-	           pal[slot].r +
-	           pal[slot].r +
-	           pal[slot].g +
-	           pal[slot].g +
-	           pal[slot].g +
-	           pal[slot].g +
-	           pal[slot].b) >> 3;
-	return lum;
-}
-
-
-
-void SetStarsOriginPoint(int x, int y) {
-	Starfield.originx = x;
-	Starfield.originy = y;
-}
-void InitializeStars(int slot, int maxstars) {
-	int32 sw, sh = 0;
-	BITMAP *canvas = engine->GetSpriteGraphic(slot);
-	engine->GetBitmapDimensions(canvas, &sw, &sh, nullptr);
-	Starfield.maxstars = maxstars;
-	Starfield.overscan = 20;
-	stars = new starstype [Starfield.maxstars];
-	for (int i = 0; i < Starfield.maxstars; i++) {
-		stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
-		if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
-		stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
-		if (stars[i].y < 1.0 && stars[i].y > -1.0) stars[i].y = (float)sh;
-		stars[i].z = (float)(MAX_DEPTH);
-		stars[i].color = (::AGS::g_vm->getRandomNumber(0x7fffffff) % 240);
-		stars[i].sprite = 0;
-		stars[i].maxrad = (::AGS::g_vm->getRandomNumber(0x7fffffff) % 5);
-	}
-}
-
-void IterateStars(int slot) {
-	long sw, sh = 0;
-	sw = engine->GetSpriteWidth(slot);
-	sh = engine->GetSpriteHeight(slot);
-	for (int i = 0; i < Starfield.maxstars; i++) {
-		stars[i].z -= Starfield.speed;
-		//if (stars[i].z < 1.0) stars[i].z = (double)MAX_DEPTH;
-		float k = Starfield.depthmultiplier / stars[i].z;
-		int px = static_cast<int>(stars[i].x * k + Starfield.originx);
-		int py = static_cast<int>(stars[i].y * k + Starfield.originy);
-		if (px >= sw + Starfield.overscan || px < 0 - Starfield.overscan || py >= sh + Starfield.overscan || py < 0 - Starfield.overscan) {
-			stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
-			if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
-			stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
-			if (stars[i].y < 1.0 && stars[i].y > 1.0) stars[i].y = (float)sh;
-			stars[i].z = (float)MAX_DEPTH;
-			//stars[i].color = (rand () %240);
-		}
-	}
-}
-int GetStarfieldOverscan() {
-	return Starfield.overscan;
-}
-void SetStarfieldOverscan(int overscan) {
-	Starfield.overscan = overscan;
-}
-
-int GetStarfieldOriginX() {
-	return Starfield.originx;
-}
-
-int GetStarfieldOriginY() {
-	return Starfield.originy;
-}
-
-void SetStarfieldDepthMultiplier(int multi) {
-	Starfield.depthmultiplier = multi;
-}
-
-int GetStarfieldDepthMultiplier() {
-	return Starfield.depthmultiplier;
-}
-
-int GetStarfieldMaxStars() {
-	return Starfield.maxstars;
-}
-
-void SetStarSpriteScaleBoost(int star, int boost) {
-	stars[star].scaleboost = boost;
-}
-
-int GetStarSpriteScaleBoost(int star) {
-	return stars[star].scaleboost;
-}
-
-void SetStarMaxRadius(int star, int radius) {
-	stars[star].maxrad = radius;
-}
-
-int GetStarMaxRadius(int star) {
-	return stars[star].maxrad;
-}
-
-void RotateStar(int star, int angle, int px, int py) {
-	float rsin = rot_sine_LUT[angle];
-	float rcos = rot_cos_LUT[angle];
-	float fPx = (float)px;
-	float fPy = (float)py;
-	float x1 = 0, y1 = 0, xRot = 0, yRot = 0;
-	int i = star;
-	x1 = stars[i].x;
-	y1 = stars[i].y;
-	xRot = fPx + rcos * (x1 - fPx) - rsin * (y1 - fPy);
-	yRot = fPy + rsin * (x1 - fPx) + rcos * (y1 - fPy);
-	stars[i].x = xRot;
-	stars[i].y = yRot;
-	i++;
-}
-
-FLOAT_RETURN_TYPE GetStarX(int i) {
-	float starx = (float)stars[i].x;
-	RETURN_FLOAT(starx);
-}
-
-FLOAT_RETURN_TYPE GetStarY(int i) {
-	float stary = (float)stars[i].y;
-	RETURN_FLOAT(stary);
-}
-
-FLOAT_RETURN_TYPE GetStarZ(int i) {
-	float starz = (float)stars[i].z;
-	RETURN_FLOAT(starz);
-}
-
-void SetStarPosition(int star, SCRIPT_FLOAT(x), SCRIPT_FLOAT(y), SCRIPT_FLOAT(z)) {
-	INIT_SCRIPT_FLOAT(x);
-	INIT_SCRIPT_FLOAT(y);
-	INIT_SCRIPT_FLOAT(z);
-	stars[star].x = x;
-	stars[star].y = y;
-	stars[star].z = z;
-}
-
-void SetStarColor(int star, unsigned char color) {
-	stars[star].color = color;
-}
-
-unsigned char GetStarColor(int star) {
-	return stars[star].color;
-}
-
-void SetStarSprite(int star, int slot) {
-	stars[star].sprite = slot;
-}
-
-int GetStarSprite(int star) {
-	return stars[star].sprite;
-}
-
-void SetStarSpriteRange(int start, int end, int slot) {
-	int sfix = start;
-	int efix = end;
-	if (start > Starfield.maxstars) sfix = Starfield.maxstars - 1;
-	if (end > Starfield.maxstars) efix = Starfield.maxstars;
-	for (int i = sfix; i < efix; i++)
-		stars[i].sprite = slot;
-}
-
-void DrawStars(int slot, int maskslot) {
-	int32 sw, sh = 0;
-	BITMAP *canvas = engine->GetSpriteGraphic(slot);
-	if (!canvas) engine->AbortGame("DrawStars: Can't load sprite slot.");
-	BITMAP *maskcanvas = engine->GetSpriteGraphic(maskslot);
-	if (!maskcanvas) engine->AbortGame("DrawStars: Can't load mask slot.");
-	engine->GetBitmapDimensions(canvas, &sw, &sh, nullptr);
-	unsigned char **screenarray = engine->GetRawBitmapSurface(canvas);
-	unsigned char **maskarray = engine->GetRawBitmapSurface(maskcanvas);
-	for (int i = 0; i < Starfield.maxstars; i++) {
-		//stars[i].z-= 0.5;
-		//if (stars[i].z < 1.0) stars[i].z = (double)MAX_DEPTH;
-		float k = (float)Starfield.depthmultiplier / stars[i].z;
-		int px = static_cast<int>(stars[i].x * k + Starfield.originx);
-		int py = static_cast<int>(stars[i].y * k + Starfield.originy);
-		if (px >= sw + Starfield.overscan || px < 0 - Starfield.overscan || py >= sh + Starfield.overscan || py < 0 - Starfield.overscan) {
-			stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
-			if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
-			stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
-			if (stars[i].y < 1.0 && stars[i].y > 1.0) stars[i].y = (float)sh;
-			stars[i].z = (float)MAX_DEPTH;
-			//stars[i].color = (rand () %240);
-		} else if (stars[i].z > 0) {
-			int ivalue = (63 - (int)stars[i].z);
-			if (ivalue > 63) ivalue = 63;
-			else if (ivalue < 0) ivalue = 0;
-			unsigned char value = (unsigned char)(ivalue);
-			unsigned char maskcolor = value << 2;
-			if (stars[i].sprite > 0) {
-				BITMAP *origspr = engine->GetSpriteGraphic(stars[i].sprite);
-				int scale = (ivalue + 1) * 100 >> 6;
-				//int scale = 50;
-				if (scale < 1) scale = 1;
-				/*
-				if (scale != 100)
-				{
-				unsigned char** orig = engine->GetRawBitmapSurface (origspr);
-				int32 h1,h2,w1,w2=0;
-				double fw2,fh2;
-				engine->GetBitmapDimensions (origspr,&w1,&h1,NULL);
-				fh2 = h1 * (scale / 100.0);
-				fw2 = w1 * (scale / 100.0);
-				h2 = static_cast<int>(fh2);
-				w2 = static_cast<int>(fw2);
-				if (w2 < 1) w2 = 1;
-				if (h2 < 1) h2 = 1;
-				resizspr = engine->CreateBlankBitmap (w2,h2,8);
-				unsigned char** resized = engine->GetRawBitmapSurface (resizspr);
-				int x_ratio = (int)((w1<<16)/w2) +1;
-				int y_ratio = (int)((h1<<16)/h2) +1;
-				int x2, y2 ;
-				for (int i=0;i<h2;i++)
-				{
-				    for (int j=0;j<w2;j++)
-				   {
-				       x2 = ((j*x_ratio)>>16) ;
-				       y2 = ((i*y_ratio)>>16) ;
-				       resized [i][j] = orig [y2][x2];
-				 }
-				}
-				engine->ReleaseBitmapSurface (resizspr);
-				}
-				//resizspr = origspr;
-				int32 w,h=0;
-				engine->GetBitmapDimensions (resizspr,&w,&h,NULL);
-				unsigned char **imagemap = engine->GetRawBitmapSurface (resizspr);
-				int ox = px - (w>>1);
-				int oy = py - (h>>1);
-				for (int dy=0;dy<h;dy++)
-				{
-				for (int dx=0;dx<w;dx++)
-				{
-				   int ex = ox+dx;
-				   int ey = oy+dy;
-				   if (ex < sw && ex >= 0 && ey < sh && ey >= 0)
-				   {
-				       if (maskcolor > maskarray [ey][ex] && imagemap[dy][dx] > 0)
-				       {
-				           maskarray [ey][ex] = maskcolor;
-				           screenarray [ey][ex] = imagemap[dy][dx];
-				       }
-				   }
-				}
-				}
-				*/
-
-				unsigned char **orig = engine->GetRawBitmapSurface(origspr);
-				int32 h1, h2, w1, w2 = 0;
-				double fw2, fh2;
-				engine->GetBitmapDimensions(origspr, &w1, &h1, nullptr);
-				fh2 = h1 * (scale / 100.0);
-				fw2 = w1 * (scale / 100.0);
-				h2 = static_cast<int>(fh2);
-				w2 = static_cast<int>(fw2);
-				if (w2 < 1) w2 = 1;
-				if (h2 < 1) h2 = 1;
-				int x_ratio = (int)((w1 << 16) / w2) + 1;
-				int y_ratio = (int)((h1 << 16) / h2) + 1;
-				int x2, y2 ;
-				int ox = px - (w2 >> 1);
-				int oy = py - (h2 >> 1);
-				for (int ii = 0; ii < h2; ii++) {
-					int temprzy = ii * y_ratio;
-					int ey = oy + ii;
-					for (int j = 0; j < w2; j++) {
-						x2 = ((j * x_ratio) >> 16);
-						y2 = ((temprzy) >> 16);
-						int ex = ox + j;
-						if (ex < sw && ex >= 0 && ey < sh && ey >= 0) {
-							if (maskcolor > maskarray [ey][ex] && orig[y2][x2] > 0) {
-								maskarray [ey][ex] = maskcolor;
-								screenarray [ey][ex] = orig[y2][x2];
-							}
-						}
-						//resized [ii][j] = orig [y2][x2];
-					}
-				}
-				engine->ReleaseBitmapSurface(origspr);
-			} else if (stars[i].sprite == 0) {
-				if (stars[i].maxrad == 1) {
-					if (px < sw && px >= 0 && py < sh && py >= 0) {
-						if (maskcolor > maskarray[py][px]) {
-							maskarray[py][px] = maskcolor;
-							screenarray[py][px] = stars[i].color;
-						}
-					}
-				} else {
-					int scale = ((((int)stars[i].z) * 100) / 63);
-					if (scale < 1) scale = 1;
-					int radius = (stars[i].maxrad * (100 - scale) / 100);
-					int radsq = radius * radius;
-					//unsigned char color = GetColor565 (value>>1,value,value>>1);
-					unsigned char color = stars[i].color;
-					for (int cy = -radius; cy <= radius; cy++) { //Draw a circle around the point, for the mask.
-						int cysq = cy * cy;
-						for (int cx = -radius; cx <= radius; cx++) {
-							int cxsq = cx * cx;
-							int dx = cx + px;
-							int dy = cy + py;
-							if ((cxsq + cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0) {
-								if (maskcolor > maskarray [dy][dx]) {
-									maskarray [dy][dx] = maskcolor;
-									screenarray [dy][dx] = color;
-								}
-							}
-						}
-					}
-					/*
-					for(int cy=-radius; cy<=radius; cy++) //Draw a circle around the point, for the color.
-					{
-					   int cysq = cy*cy;
-					for(int cx=-radius; cx<=radius; cx++)
-					   {
-					       int cxsq = cx*cx;
-					       int dx = cx+px;
-					       int dy = cy+py;
-					       if((cxsq+cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0)
-					       {
-					           if (maskarray [dy][dx] == maskcolor)screenarray [dy][dx] = color;
-					       }
-					   }
-					}
-					*/
-				}
-			}
-		}
-	}
-	engine->ReleaseBitmapSurface(canvas);
-	engine->ReleaseBitmapSurface(maskcanvas);
-	engine->NotifySpriteUpdated(slot);
-	engine->NotifySpriteUpdated(maskslot);
-}
-
-
-int CreateTranslucentOverlay(int id, int spriteId, int alpha, int level, int ox, int oy, int mask = 0, int blendmode = 0) {
-	BITMAP *testspr = engine->GetSpriteGraphic(spriteId);
-	if (testspr) overlay[id].sprite = spriteId;
-	else engine->AbortGame("CreateTranslucentOverlay: Invalid spriteId.");
-	engine->ReleaseBitmapSurface(testspr);
-	overlay[id].level = MAX(0, MIN(level, 4));
-	overlay[id].trans = MAX(0, MIN(alpha, 255));
-	overlay[id].spritemask = mask;
-	overlay[id].x = ox;
-	overlay[id].y = oy;
-	overlay[id].enabled = true;
-	overlay[id].blendtype = blendmode;
-	return 0;
-}
-
-int DeleteTranslucentOverlay(int id) {
-	overlay[id].enabled = false;
-	overlay[id].sprite = 0;
-	overlay[id].x = 0;
-	overlay[id].y = 0;
-	overlay[id].level = 0;
-	overlay[id].trans = 0;
-	return 0;
-}
-
-int MoveTranslucentOverlay(int id, int ox, int oy) {
-	overlay[id].x = ox;
-	overlay[id].y = oy;
-	return 0;
-}
-
-int GetTranslucentOverlayX(int id) {
-	return overlay[id].x;
-}
-
-int GetTranslucentOverlayY(int id) {
-	return overlay[id].y;
-}
-
-int GetTranslucentOverlaySprite(int id) {
-	return overlay[id].sprite;
-}
-
-int GetTranslucentOverlayLevel(int id) {
-	return overlay[id].level;
-}
-
-int GetTranslucentOverlayEnabled(int id) {
-	return overlay[id].enabled;
-}
-
-int GetTranslucentOverlayAlpha(int id) {
-	return overlay[id].trans;
-}
-
-int SetTranslucentOverlayAlpha(int id, int alpha) {
-	if (alpha >= 0 && alpha < 256)
-		overlay[id].trans = alpha;
-	else
-		engine->AbortGame("CreateTranslucentOverlay: Invalid alpha selected.");
-	return 0;
-}
-
-int SetTranslucentOverlayEnabled(int id, int toggle) {
-	if (toggle > 0)
-		overlay[id].enabled = true;
-	else
-		overlay[id].enabled = false;
-	return 0;
-}
-
-void SetCharacterReflected(int id, int refl) {
-	if (refl > 0) Reflection.Characters[id].reflect = 1;
-	else Reflection.Characters[id].reflect = 0;
-}
-
-void SetObjectReflected(int id, int refl) {
-	if (refl > 0)
-		Reflection.Objects[id].reflect = 1;
-	else
-		Reflection.Objects[id].reflect = 0;
-}
-
-int GetCharacterReflected(int id) {
-	return Reflection.Characters[id].reflect;
-}
-
-int GetObjectReflected(int id) {
-	return Reflection.Objects[id].reflect;
-}
-
-void ReplaceCharacterReflectionView(int id, int view) {
-	Reflection.Characters[id].replaceview = view - 1;
-}
-
-void SetObjectReflectionIgnoreScaling(int id, int wb) {
-	if (wb) Reflection.Objects[id].ignorescaling = 1;
-	else    Reflection.Objects[id].ignorescaling = 0;
-}
-
-int DrawReflections(int id, int charobj = 0) {
-	int32 screenw, screenh;
-	int32 bgw, bgh;
-	engine->GetScreenDimensions(&screenw, &screenh, nullptr);
-	BITMAP *bgmask = engine->GetBackgroundScene(1);
-	if (bgmask == nullptr) return 1;
-	//BITMAP *virtsc = engine->GetVirtualScreen();
-	BITMAP *walkbehind = engine->GetRoomMask(MASK_WALKBEHIND);
-	//if (!virtsc) engine->AbortGame ("Can't load virtual screen.");
-	if (!walkbehind) engine->AbortGame("DrawRelfections: Can't load Walkbehind into memory.");
-	engine->GetBitmapDimensions(walkbehind, &bgw, &bgh, nullptr);
-	if (!bgmask) engine->AbortGame("DrawReflections: Can't load reflection mask.");
-	//unsigned char **charbuffer = engine->GetRawBitmapSurface (virtsc);
-	unsigned char **wbarray = engine->GetRawBitmapSurface(walkbehind);
-	unsigned char **maskarray = engine->GetRawBitmapSurface(bgmask);
-	//Initialize stuff
-	BITMAP *charsprite = nullptr;
-	BITMAP *charsprite2 = nullptr;
-	AGSCharacter *currchar = nullptr;
-	AGSObject *currobj;
-	int cox = 0, coy = 0, coz = 0;
-	int scale = 0;
-	//Get character, and their sprite.
-	if (charobj == 0) {
-		currchar = engine->GetCharacter(id);
-		/*int view = 0;
-		if (Reflection.Characters[id].replaceview == 0) view = currchar->view + 1;
-		else view = Reflection.Characters[id].replaceview;
-		*/
-		AGSViewFrame *vf = engine->GetViewFrame(currchar->view + 1, currchar->loop, currchar->frame);
-		charsprite = engine->GetSpriteGraphic(vf->pic);
-		long scaling = currchar->flags & CHF_NOSCALING;
-		if (!scaling)scale = engine->GetAreaScaling(currchar->x, currchar->y);
-		else scale = 100;
-		cox = currchar->x;
-		coy = currchar->y;
-		coz = currchar->z;
-	} else if (charobj == 1) {
-		currobj = engine->GetObject(id);
-
-		charsprite = engine->GetSpriteGraphic(currobj->num);
-		if (Reflection.Objects[id].ignorescaling) scale = 100;
-		else scale = engine->GetAreaScaling(currobj->x, currobj->y);
-		cox = currobj->x;
-		if (currobj->baseline < 0) coy = currobj->y;
-		else coy = currobj->baseline;
-		coz = 0;
-	}
-	bool scaled = false;
-	int32 w, h;
-	engine->GetBitmapDimensions(charsprite, &w, &h, nullptr);
-	if (scale != 100) {
-		unsigned char **orig = engine->GetRawBitmapSurface(charsprite);
-		int h1, h2, w1, w2;
-		double fw2, fh2;
-		h1 = h;
-		w1 = w;
-		fh2 = h1 * ((double)scale / 100.0);
-		fw2 = w1 * ((double)scale / 100.0);
-		h2 = static_cast<int>(fh2);
-		w2 = static_cast<int>(fw2);
-		charsprite2 = engine->CreateBlankBitmap(w2, h2, 8);
-		unsigned char **resized = engine->GetRawBitmapSurface(charsprite2);
-		int x_ratio = (int)((w1 << 16) / w2) + 1;
-		int y_ratio = (int)((h1 << 16) / h2) + 1;
-		int x2, y2 ;
-		for (int i = 0; i < h2; i++) {
-			for (int j = 0; j < w2; j++) {
-				x2 = ((j * x_ratio) >> 16) ;
-				y2 = ((i * y_ratio) >> 16) ;
-				resized [i][j] = orig [y2][x2];
-			}
-		}
-		engine->ReleaseBitmapSurface(charsprite2);
-		scaled = true;
-		w = w2;
-		h = h2;
-	} else {
-		charsprite2 = charsprite;
-	}
-	int transamount = 0;
-	unsigned char **spritearray = engine->GetRawBitmapSurface(charsprite2);
-	unsigned char **charbuffer = engine->GetRawBitmapSurface(rcolormap);
-	unsigned char **alphaarray = engine->GetRawBitmapSurface(ralphamap);
-	int i = h - 1, j = 0;
-	int32 ox = cox;
-	if (charobj == 0) ox = ox - (w / 2);
-	int32 oy = coy + coz - 1;
-	engine->RoomToViewport(&ox, &oy);
-	int yoffset = 0;
-	int translevel = 7;
-	//bool dither = false;
-	//bool dodither = false;
-	int counter = 0;
-	int rowcount = 101 - (int)(50.0 * ((double)(scale) / 100.0));
-	int delay = screenh / rowcount;
-	int *obst;
-	int flipped = 0;
-	if (charobj == 0) {
-		int (*sfGetGameParameter)(int, int, int, int);
-		sfGetGameParameter = ((int(*)(int, int, int, int)) engine->GetScriptFunctionAddress("GetGameParameter"));
-		flipped = sfGetGameParameter(13, currchar->view + 1, currchar->loop, currchar->frame);
-	} else flipped = 0;
-	obst = new int [w];
-	for (int k = 0; k < w; k++) {
-		obst[k] = 0;
-	}
-	while (i > 0) {
-		//if ((counter == delay/2-1 || counter == delay-1) && yoffset < 36) dodither = (!dodither);
-		if (counter == delay) {
-			counter = 0;
-			if (translevel > 0) translevel--;
-		} else counter++;
-		yoffset++;
-		while (j < w) {
-			int xoffset;
-			if (flipped == 1) xoffset = w - j - 1;
-			else xoffset = j;
-			int32 rx = ox + xoffset, ry = oy + yoffset;
-			int wbb = 0;
-			engine->ViewportToRoom(&rx, &ry);
-			if (ry > 0 && ry < bgh && rx > 0 && rx < bgw) {
-				if (wbarray [ry][rx] > 0) {
-					wbb = engine->GetWalkbehindBaseline(wbarray[ry][rx]);
-				}
-				if (maskarray[ry][rx] == 21) obst[j] = 1;
-			}
-
-			//dither = (!dither);
-			transamount = 32 * translevel;
-			if (spritearray [i][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.
-				if (wbb < ry && obst[j] == 0 && (oy > reflectionmap[(ox + xoffset) + (screenw * (oy + yoffset))])) {
-					//charbuffer[oy+yoffset][ox+xoffset] = MixColorAlpha (spritearray [i][j],charbuffer[oy+yoffset][ox+xoffset],transamount);
-					charbuffer [oy + yoffset][ox + xoffset] = spritearray [i][j];
-					alphaarray [oy + yoffset][ox + xoffset] = transamount;
-					reflectionmap[(ox + xoffset) + (screenw * (oy + yoffset))] = oy;
-				}
-			}
-			j++;
-		}
-		//if (w % 2 == 0) dither = (!dither);
-		i--;
-		j = 0;
-	}
-
-	delete [] obst;
-	if (scaled == true)engine->FreeBitmap(charsprite2);
-	engine->ReleaseBitmapSurface(charsprite);
-	//engine->ReleaseBitmapSurface (virtsc);
-	//engine->ReleaseBitmapSurface (clutspr);
-	engine->ReleaseBitmapSurface(bgmask);
-	engine->ReleaseBitmapSurface(walkbehind);
-	engine->ReleaseBitmapSurface(rcolormap);
-	engine->ReleaseBitmapSurface(ralphamap);
-	engine->MarkRegionDirty(ox, oy, ox + w, oy + h);
-	return 0;
-}
-
-
-int DrawTransSprite(int spriteId, int bg, int translevel, int mask = 0, int blendmode = 0, int use_objpal = 0) {
-	BITMAP *maskspr = nullptr;
-	unsigned char **maskarray = nullptr;
-	if (mask > 0) maskspr = engine->GetSpriteGraphic(mask);
-	if (!maskspr && mask > 0) {
-		char maskerr [100];
-		snprintf(maskerr, 100, "DrawTransSprite: Can't load mask from slot %d.", mask);
-		engine->AbortGame(maskerr);
-	}
-	// Get a reference to the screen we'll draw onto
-	BITMAP *bgspr = engine->GetSpriteGraphic(bg);
-	//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
-	BITMAP *spritespr = engine->GetSpriteGraphic(spriteId);
-	if (!bgspr) engine->AbortGame("DrawTransSprite: Can't load background");
-	//if (!clutspr) engine->AbortGame ("Can't load CLUT spriteId into memory.");
-	if (!spritespr) engine->AbortGame("DrawTransSprite: Can't load overlay spriteId into memory.");
-	// Get its surface
-	int32 sprw, sprh, coldepth;
-	int32 bgw, bgh;
-	engine->GetBitmapDimensions(bgspr, &bgw, &bgh, &coldepth);
-	engine->GetBitmapDimensions(spritespr, &sprw, &sprh, &coldepth);
-
-	unsigned char **bgarray = engine->GetRawBitmapSurface(bgspr);
-	//unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
-	unsigned char **spritearray = engine->GetRawBitmapSurface(spritespr);
-	if (mask > 0) maskarray = engine->GetRawBitmapSurface(maskspr);
-	int tloffset = 255 - translevel;
-	int x = 0;
-	int y = 0;
-	//int transamount = 256 * translevel; //old
-	while (y < sprh) {
-		while (x < sprw) {
-			if (spritearray [y][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.
-				if (mask > 0) {
-					translevel = MAX(maskarray [y][x] - tloffset, 0);
-				}
-				//spritearray[y][x] = cycle_remap[clutarray [cycle_remap[bgarray[y][x]]+transamount][cycle_remap[spritearray [y][x]]]]; //old
-				if (blendmode == 0) spritearray[y][x] = Mix::MixColorAlpha(spritearray [y][x], bgarray[y][x], translevel, use_objpal);
-				else if (blendmode == 1) spritearray[y][x] = Mix::MixColorAdditive(spritearray [y][x], bgarray[y][x], translevel, use_objpal);
-			}
-			x++;
-		}
-		x = 0;
-		y++;
-	}
-
-	// Release the screen so that the engine can continue
-	engine->ReleaseBitmapSurface(bgspr);
-	//engine->ReleaseBitmapSurface (clutspr);
-	engine->ReleaseBitmapSurface(spritespr);
-	engine->NotifySpriteUpdated(spriteId);
-	return 0;
-}
-
-int DrawTranslucentOverlay(int spriteId, int translevel, int ox, int oy, int mask = 0, int blendmode = 0) {
-	if (translevel == 0) return 0;
-	BITMAP *maskspr = nullptr;
-	unsigned char **maskarray = nullptr;
-	// Get a reference to the screen we'll draw onto
-	BITMAP *virtsc = engine->GetVirtualScreen();
-	//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
-	BITMAP *spritespr = engine->GetSpriteGraphic(spriteId);
-	if (mask > 0) maskspr = engine->GetSpriteGraphic(mask);
-	if (!virtsc) engine->AbortGame("DrawTranslucentOverlay: Can't load virtual screen.");
-	//if (!clutspr) engine->AbortGame ("Can't load CLUT spriteId into memory.");
-	if (!spritespr) engine->AbortGame("DrawTranslucentOverlay: Can't load overlay spriteId into memory.");
-	// Get its surface
-	int32 sprw, sprh, coldepth;
-	int32 screenw, screenh;
-	engine->GetScreenDimensions(&screenw, &screenh, &coldepth);
-	engine->GetBitmapDimensions(spritespr, &sprw, &sprh, &coldepth);
-	unsigned char **charbuffer = engine->GetRawBitmapSurface(virtsc);
-	unsigned char **spritearray = engine->GetRawBitmapSurface(spritespr);
-	if (mask > 0) {
-		if (!maskspr && mask > 0) {
-			char maskerr [100];
-			snprintf(maskerr, 100, "DrawTransSprite: Can't load mask from slot %d.", mask);
-			engine->AbortGame(maskerr);
-		}
-		maskarray = engine->GetRawBitmapSurface(maskspr);
-	}
-	int tloffset = 255 - translevel;
-	int x = 0;
-	int y = 0;
-	//int transamount = 256 * translevel; //old
-	while (y < sprh) {
-		while (x < sprw) {
-			if (spritearray [y][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.
-				//charbuffer[y+oy][x+ox] = cycle_remap[clutarray [cycle_remap[charbuffer[y+oy][x+ox]]+transamount][cycle_remap[spritearray [y][x]]]]; //old
-				if (mask > 0) {
-					translevel = MAX(maskarray [y][x] - tloffset, 0);
-				}
-				if (blendmode == 0) {
-					if (translevel == 255) {
-						charbuffer[y + oy][x + ox] = spritearray [y][x];
-					} else charbuffer[y + oy][x + ox] = Mix::MixColorAlpha(spritearray [y][x], charbuffer[y + oy][x + ox], translevel);
-				} else if (blendmode == 1) charbuffer[y + oy][x + ox] = Mix::MixColorAdditive(spritearray [y][x], charbuffer[y + oy][x + ox], translevel);
-			}
-			x++;
-		}
-		x = 0;
-		y++;
-	}
-
-	// Release the screen so that the engine can continue
-	long dirtywidth = ox + sprw;
-	if (dirtywidth > screenw) dirtywidth = screenw - 1;
-	long dirtyheight = oy + sprh;
-	if (dirtyheight > screenh) dirtywidth = screenh - 1;
-	engine->ReleaseBitmapSurface(virtsc);
-	//engine->ReleaseBitmapSurface (clutspr);
-	engine->ReleaseBitmapSurface(spritespr);
-	if (mask > 0) engine->ReleaseBitmapSurface(maskspr);
-	engine->MarkRegionDirty(ox, oy, dirtywidth, dirtyheight);
-
-	return 0;
-}
-
-/*------------------------------------------------------------------*/
-
-AGSPalRender::AGSPalRender() : DLL() {
-	DLL_METHOD(AGS_GetPluginName);
-	DLL_METHOD(AGS_EngineStartup);
-	DLL_METHOD(AGS_EngineShutdown);
-	DLL_METHOD(AGS_EngineOnEvent);
-}
-
-const char *AGSPalRender::AGS_GetPluginName() {
-	return "PALgorithms Translucent Overlay Renderer";
-}
-
-void AGSPalRender::AGS_EngineStartup(IAGSEngine *lpEngine) {
-	engine = lpEngine;
-
-	// Make sure it's got the version with the features we need
-	if (engine->version < 3) {
-		engine->AbortGame("Engine interface is too old, need newer version of AGS.");
-	}
-	engine->RegisterScriptFunction("PALInternal::LoadCLUT^1", (void *)LoadCLUT);
-	engine->RegisterScriptFunction("PALInternal::CycleRemap^2", (void *)CycleRemap);
-	engine->RegisterScriptFunction("PALInternal::GetColor565^3", (void *)GetColor565);
-	engine->RegisterScriptFunction("PALInternal::GetLuminosityFromPalette^1", (void *)GetLuminosityFromPalette);
-	engine->RegisterScriptFunction("PALInternal::FastSin^1", (void *)AGSFastSin);
-	engine->RegisterScriptFunction("PALInternal::FastCos^1", (void *)AGSFastCos);
-	engine->RegisterScriptFunction("PALInternal::FastRoot^1", (void *)root);
-	engine->RegisterScriptFunction("PALInternal::GetRemappedSlot^1", (void *)GetRemappedSlot);
-	engine->RegisterScriptFunction("PALInternal::ResetRemapping^0", (void *)ResetRemapping);
-	engine->RegisterScriptFunction("PALInternal::GetModifiedBackgroundImage", (void *)GetModifiedBackgroundImage);
-	engine->RegisterScriptFunction("PALInternal::WriteObjectivePalette^4", (void *)WriteObjectivePalette);
-	engine->RegisterScriptFunction("PALInternal::ReadObjectivePaletteR^1", (void *)ReadObjectivePaletteR);
-	engine->RegisterScriptFunction("PALInternal::ReadObjectivePaletteB^1", (void *)ReadObjectivePaletteB);
-	engine->RegisterScriptFunction("PALInternal::ReadObjectivePaletteG^1", (void *)ReadObjectivePaletteG);
-
-	engine->RegisterScriptFunction("Raycast::Render^1", (void *)Raycast_Render);
-	engine->RegisterScriptFunction("Raycast::LoadMap^4", (void *)LoadMap);
-	engine->RegisterScriptFunction("Raycast::Initialize", (void *)Init_Raycaster);
-	engine->RegisterScriptFunction("Raycast::MakeTextures^1", (void *)MakeTextures);
-	engine->RegisterScriptFunction("Raycast::MoveForward^0", (void *)MoveForward);
-	engine->RegisterScriptFunction("Raycast::MoveBackward^0", (void *)MoveBackward);
-	engine->RegisterScriptFunction("Raycast::RotateLeft^0", (void *)RotateLeft);
-	engine->RegisterScriptFunction("Raycast::RotateRight^0", (void *)RotateRight);
-	engine->RegisterScriptFunction("Raycast::SetCameraPosition^2", (void *)Ray_SetPlayerPosition);
-	engine->RegisterScriptFunction("Raycast::GetCameraX^0", (void *)Ray_GetPlayerX);
-	engine->RegisterScriptFunction("Raycast::GetCameraY^0", (void *)Ray_GetPlayerY);
-	engine->RegisterScriptFunction("Raycast::GetCameraAngle^0", (void *)Ray_GetPlayerAngle);
-	engine->RegisterScriptFunction("Raycast::SetCameraAngle^1", (void *)Ray_SetPlayerAngle);
-	engine->RegisterScriptFunction("Raycast::InitSprite^9", (void *)Ray_InitSprite);
-	engine->RegisterScriptFunction("Raycast::UnloadEngine^0", (void *)QuitCleanup);
-	engine->RegisterScriptFunction("Raycast::GetHotspotAtXY^2", (void *)Ray_GetHotspotAt);
-	engine->RegisterScriptFunction("Raycast::GetObjectAtXY^2", (void *)Ray_GetObjectAt);
-	engine->RegisterScriptFunction("Raycast::SetSpriteInteractObj^2", (void *)Ray_SetSpriteInteractObj);
-	engine->RegisterScriptFunction("Raycast::GetSpriteInteractObj^1", (void *)Ray_GetSpriteInteractObj);
-	engine->RegisterScriptFunction("Raycast::SetSpritePosition^3", (void *)Ray_SetSpritePosition);
-	engine->RegisterScriptFunction("Raycast::SetSpriteVertOffset^2", (void *)Ray_SetSpriteVertOffset);
-	engine->RegisterScriptFunction("Raycast::GetSpriteVertOffset^1", (void *)Ray_GetSpriteVertOffset);
-	engine->RegisterScriptFunction("Raycast::GetSpriteX^1", (void *)Ray_GetSpriteX);
-	engine->RegisterScriptFunction("Raycast::GetSpriteY^1", (void *)Ray_GetSpriteY);
-	engine->RegisterScriptFunction("Raycast::SetWallHotspot^2", (void *)Ray_SetWallHotspot);
-	engine->RegisterScriptFunction("Raycast::SetWallTextures^5", (void *)Ray_SetWallTextures);
-	engine->RegisterScriptFunction("Raycast::SetWallSolid^5", (void *)Ray_SetWallSolid);
-	engine->RegisterScriptFunction("Raycast::SetWallIgnoreLighting^5", (void *)Ray_SetWallIgnoreLighting);
-	engine->RegisterScriptFunction("Raycast::SetWallAlpha^5", (void *)Ray_SetWallAlpha);
-	engine->RegisterScriptFunction("Raycast::SetWallBlendType^5", (void *)Ray_SetWallBlendType);
-	engine->RegisterScriptFunction("Raycast::GetMoveSpeed^0", (void *)Ray_GetMoveSpeed);
-	engine->RegisterScriptFunction("Raycast::SetMoveSpeed^1", (void *)Ray_SetMoveSpeed);
-	engine->RegisterScriptFunction("Raycast::GetRotSpeed^0", (void *)Ray_GetRotSpeed);
-	engine->RegisterScriptFunction("Raycast::SetRotSpeed^1", (void *)Ray_SetRotSpeed);
-	engine->RegisterScriptFunction("Raycast::GetWallAt^2", (void *)Ray_GetWallAt);
-	engine->RegisterScriptFunction("Raycast::GetLightAt^2", (void *)Ray_GetLightAt);
-	engine->RegisterScriptFunction("Raycast::SetLightAt^3", (void *)Ray_SetLightAt);
-	engine->RegisterScriptFunction("Raycast::SetWallAt^3", (void *)Ray_SetWallAt);
-	engine->RegisterScriptFunction("Raycast::SetPlaneY^1", (void *)Ray_SetPlaneY);
-	engine->RegisterScriptFunction("Raycast::GetDistanceAt^2", (void *)Ray_GetDistanceAt);
-	engine->RegisterScriptFunction("Raycast::GetSpriteAngle^1", (void *)Ray_GetSpriteAngle);
-	engine->RegisterScriptFunction("Raycast::SetSpriteAngle^2", (void *)Ray_SetSpriteAngle);
-	engine->RegisterScriptFunction("Raycast::SetSpriteView^2", (void *)Ray_SetSpriteView);
-	engine->RegisterScriptFunction("Raycast::GetSpriteView^1", (void *)Ray_GetSpriteView);
-	engine->RegisterScriptFunction("Raycast::SetSpriteFrame^2", (void *)Ray_SetSpriteFrame);
-	engine->RegisterScriptFunction("Raycast::GetSpriteFrame^1", (void *)Ray_GetSpriteFrame);
-	engine->RegisterScriptFunction("Raycast::SetSpritePic^2", (void *)Ray_SetSpritePic);
-	engine->RegisterScriptFunction("Raycast::GetSpritePic^1", (void *)Ray_GetSpritePic);
-	engine->RegisterScriptFunction("Raycast::SetSkyBox^1", (void *)Ray_SetSkyBox);
-	engine->RegisterScriptFunction("Raycast::SetSpriteAlpha^2", (void *)Ray_SetSpriteAlpha);
-	engine->RegisterScriptFunction("Raycast::GetSpriteAlpha^1", (void *)Ray_GetSpriteAlpha);
-	engine->RegisterScriptFunction("Raycast::GetSkyBox^1", (void *)Ray_GetSkyBox);
-	engine->RegisterScriptFunction("Raycast::SetAmbientLight^1", (void *)Ray_SetAmbientLight);
-	engine->RegisterScriptFunction("Raycast::SetAmbientColor^2", (void *)Ray_SetAmbientColor);
-	engine->RegisterScriptFunction("Raycast::GetAmbientLight^0", (void *)Ray_GetAmbientLight);
-	engine->RegisterScriptFunction("Raycast::GetAmbientWeight^0", (void *)Ray_GetAmbientWeight);
-	engine->RegisterScriptFunction("Raycast::GetTileX_At^2", (void *)Ray_GetTileX_At);
-	engine->RegisterScriptFunction("Raycast::GetTileY_At^2", (void *)Ray_GetTileY_At);
-	engine->RegisterScriptFunction("Raycast::DrawTile^2", (void *)Ray_DrawTile);
-	engine->RegisterScriptFunction("Raycast::DrawOntoTile^2", (void *)Ray_DrawOntoTile);
-	engine->RegisterScriptFunction("Raycast::SetNoClip^1", (void *)Ray_SetNoClip);
-	engine->RegisterScriptFunction("Raycast::GetNoClip^0", (void *)Ray_GetNoClip);
-	engine->RegisterScriptFunction("Raycast::GetSpriteScaleX^1", (void *)Ray_GetSpriteScaleX);
-	engine->RegisterScriptFunction("Raycast::SetSpriteScaleX^2", (void *)Ray_SetSpriteScaleX);
-	engine->RegisterScriptFunction("Raycast::GetSpriteScaleY^1", (void *)Ray_GetSpriteScaleY);
-	engine->RegisterScriptFunction("Raycast::SetSpriteScaleY^2", (void *)Ray_SetSpriteScaleY);
-	engine->RegisterScriptFunction("Raycast::GetSpriteBlendType^1", (void *)Ray_GetSpriteBlendType);
-	engine->RegisterScriptFunction("Raycast::SetSpriteBlendType^2", (void *)Ray_SetSpriteBlendType);
-
-
-	engine->RegisterScriptFunction("Raycast::SetFloorAt^3", (void *)Ray_SetFloorAt);
-	engine->RegisterScriptFunction("Raycast::SetCeilingAt^3", (void *)Ray_SetCeilingAt);
-	engine->RegisterScriptFunction("Raycast::GetCeilingAt^2", (void *)Ray_GetCeilingAt);
-	engine->RegisterScriptFunction("Raycast::GetFloorAt^2", (void *)Ray_GetFloorAt);
-	engine->RegisterScriptFunction("Raycast::GetLightingAt^2", (void *)Ray_GetLightingAt);
-	engine->RegisterScriptFunction("Raycast::SetLightingAt^3", (void *)Ray_SetLightingAt);
-	engine->RegisterScriptFunction("Raycast::GetWallHotspot^1", (void *)Ray_GetWallHotspot);
-	engine->RegisterScriptFunction("Raycast::GetWallTexture^2", (void *)Ray_GetWallTexture);
-	engine->RegisterScriptFunction("Raycast::GetWallSolid^2", (void *)Ray_GetWallSolid);
-	engine->RegisterScriptFunction("Raycast::GetWallIgnoreLighting^2", (void *)Ray_GetWallIgnoreLighting);
-	engine->RegisterScriptFunction("Raycast::GetWallAlpha^2", (void *)Ray_GetWallAlpha);
-	engine->RegisterScriptFunction("Raycast::GetWallBlendType^2", (void *)Ray_GetWallBlendType);
-	engine->RegisterScriptFunction("Raycast::SelectTile^3", (void *)Ray_SelectTile);
-	engine->RegisterScriptFunction("Raycast::HasSeenTile^2", (void *)Ray_HasSeenTile);
-
-	engine->RegisterScriptFunction("LensDistort::SetPos^2", (void *)SetLensPos);
-	engine->RegisterScriptFunction("LensDistort::GetX^0", (void *)GetLensX);
-	engine->RegisterScriptFunction("LensDistort::GetY^0", (void *)GetLensY);
-	engine->RegisterScriptFunction("LensDistort::Set^1", (void *)SetLensDrawn);
-	engine->RegisterScriptFunction("LensDistort::IsDrawn^0", (void *)GetLensDrawn);
-	engine->RegisterScriptFunction("LensDistort::SetOffsetClamp^1", (void *)SetLensOffsetClamp);
-	engine->RegisterScriptFunction("LensDistort::GetOffsetClamp^0", (void *)GetLensOffsetClamp);
-	engine->RegisterScriptFunction("LensDistort::GetLevel^0", (void *)GetLensLevel);
-	engine->RegisterScriptFunction("LensDistort::SetLevel^1", (void *)GetLensLevel);
-	engine->RegisterScriptFunction("LensDistort::Initialize^6", (void *)LensInitialize);
-
-	engine->RegisterScriptFunction("Translucence::CreateOverlay^8", (void *)CreateTranslucentOverlay);
-	engine->RegisterScriptFunction("Translucence::DeleteOverlay^1", (void *)DeleteTranslucentOverlay);
-	engine->RegisterScriptFunction("Translucence::Move^3", (void *)MoveTranslucentOverlay);
-	engine->RegisterScriptFunction("Translucence::GetOverlayX^1", (void *)GetTranslucentOverlayX);
-	engine->RegisterScriptFunction("Translucence::GetOverlayY^1", (void *)GetTranslucentOverlayY);
-	engine->RegisterScriptFunction("Translucence::GetOverlaySprite^1", (void *)GetTranslucentOverlaySprite);
-	engine->RegisterScriptFunction("Translucence::GetOverlayLevel^1", (void *)GetTranslucentOverlayLevel);
-	engine->RegisterScriptFunction("Translucence::GetOverlayEnabled^1", (void *)GetTranslucentOverlayEnabled);
-	engine->RegisterScriptFunction("Translucence::GetOverlayAlpha^1", (void *)GetTranslucentOverlayAlpha);
-	engine->RegisterScriptFunction("Translucence::SetOverlayAlpha^2", (void *)SetTranslucentOverlayAlpha);
-	engine->RegisterScriptFunction("Translucence::SetOverlayEnabled^2", (void *)SetTranslucentOverlayEnabled);
-	engine->RegisterScriptFunction("Translucence::DrawTransSprite^6", (void *)DrawTransSprite);
-
-	engine->RegisterScriptFunction("Starfield::GetOverscan^0", (void *)GetStarfieldOverscan);
-	engine->RegisterScriptFunction("Starfield::SetOverscan^1", (void *)SetStarfieldOverscan);
-	engine->RegisterScriptFunction("Starfield::GetOriginX^0", (void *)GetStarfieldOriginX);
-	engine->RegisterScriptFunction("Starfield::GetOriginY^0", (void *)GetStarfieldOriginY);
-	engine->RegisterScriptFunction("Starfield::SetDepthMultiplier^1", (void *)SetStarfieldDepthMultiplier);
-	engine->RegisterScriptFunction("Starfield::GetDepthMultiplier^0", (void *)GetStarfieldDepthMultiplier);
-	engine->RegisterScriptFunction("Starfield::GetMaxStars^0", (void *)GetStarfieldMaxStars);
-	engine->RegisterScriptFunction("Starfield::SetStarSpriteScaleBoost^1", (void *)SetStarSpriteScaleBoost);
-	engine->RegisterScriptFunction("Starfield::GetStarSpriteScaleBoost^0", (void *)GetStarSpriteScaleBoost);
-	engine->RegisterScriptFunction("Starfield::SetStarMaxRadius^2", (void *)SetStarMaxRadius);
-	engine->RegisterScriptFunction("Starfield::GetStarMaxRadius^0", (void *)GetStarMaxRadius);
-	engine->RegisterScriptFunction("Starfield::GetStarX^1", (void *)GetStarX);
-	engine->RegisterScriptFunction("Starfield::GetStarY^1", (void *)GetStarY);
-	engine->RegisterScriptFunction("Starfield::GetStarZ^1", (void *)GetStarZ);
-	engine->RegisterScriptFunction("Starfield::SetStarPosition^4", (void *)SetStarPosition);
-	engine->RegisterScriptFunction("Starfield::RotateStar^4", (void *)RotateStar);
-	engine->RegisterScriptFunction("Starfield::SetStarColor^2", (void *)SetStarColor);
-	engine->RegisterScriptFunction("Starfield::GetStarColor^1", (void *)GetStarColor);
-	engine->RegisterScriptFunction("Starfield::SetStarSprite^2", (void *)SetStarSprite);
-	engine->RegisterScriptFunction("Starfield::GetStarSprite^1", (void *)GetStarSprite);
-	engine->RegisterScriptFunction("Starfield::SetStarSpriteRange^3", (void *)SetStarSpriteRange);
-	engine->RegisterScriptFunction("Starfield::Initialize^2", (void *)InitializeStars);
-	engine->RegisterScriptFunction("Starfield::Iterate^1", (void *)IterateStars);
-	engine->RegisterScriptFunction("Starfield::Draw^2", (void *)DrawStars);
-	engine->RegisterScriptFunction("Starfield::SetOriginPoint^2", (void *)SetStarsOriginPoint);
-
-	engine->RegisterScriptFunction("Plasma::DoFire^8", (void *)DoFire);
-	engine->RegisterScriptFunction("Plasma::SetPlasmaType^5", (void *)SetPlasmaType);
-	engine->RegisterScriptFunction("Plasma::ResetPlasmaSettings^0", (void *)ResetPlasmaSettings);
-	engine->RegisterScriptFunction("Plasma::DrawPlasma^3", (void *)DrawPlasma);
-	engine->RegisterScriptFunction("Plasma::SetRootType^1", (void *)SetPlasmaRootType);
-	engine->RegisterScriptFunction("Plasma::GetRootType^0", (void *)GetPlasmaRootType);
-
-	engine->RegisterScriptFunction("Reflections::Set^1", (void *)SetReflections);
-	engine->RegisterScriptFunction("Reflections::IsReflecting^0", (void *)IsReflectionsOn);
-	engine->RegisterScriptFunction("Reflections::SetCharacterReflected^2", (void *)SetCharacterReflected);
-	engine->RegisterScriptFunction("Reflections::GetCharacterReflected^1", (void *)GetCharacterReflected);
-	engine->RegisterScriptFunction("Reflections::SetObjectReflected^2", (void *)SetObjectReflected);
-	engine->RegisterScriptFunction("Reflections::GetObjectReflected^1", (void *)GetObjectReflected);
-	engine->RegisterScriptFunction("Reflections::ReplaceCharacterReflectionView^2", (void *)ReplaceCharacterReflectionView);
-	engine->RegisterScriptFunction("Reflections::SetObjectReflectionIgnoreScaling^2", (void *)SetObjectReflectionIgnoreScaling);
-	engine->RequestEventHook(AGSE_PRESCREENDRAW);
-	engine->RequestEventHook(AGSE_PREGUIDRAW);
-	engine->RequestEventHook(AGSE_POSTSCREENDRAW);
-	engine->RequestEventHook(AGSE_SAVEGAME);
-	engine->RequestEventHook(AGSE_RESTOREGAME);
-	engine->RequestEventHook(AGSE_ENTERROOM);
-	stars = new starstype [MAX_STARS];
-	Starfield.maxstars = MAX_STARS;
-	Starfield.depthmultiplier = 256;
-	Starfield.speed = 0.5;
-	Starfield.originx = 160;
-	Starfield.originy = 100;
-	Reflection.Characters = new charrefopt [engine->GetNumCharacters()]();
-	lens = new LensDistort [LENS_WIDTH * LENS_WIDTH]();
-	//PreMultiply_Alphas ();
-	plasmaroottype = 0;
-	Make_Sin_Lut();
-	Init_Raycaster();
-}
-
-void AGSPalRender::AGS_EngineShutdown() {
-	// no work to do here - but if we had created any dynamic sprites,
-	// we should delete them here
-	delete[] Reflection.Characters;
-	delete[] Reflection.Objects;
-	//QuitCleanup();
-}
-
-NumberPtr AGSPalRender::AGS_EngineOnEvent(int event, NumberPtr data) {
-	if (event == AGSE_PRESCREENDRAW && clutslot > 0) {
-		if (drawreflections) {
-			int32 sh, sw = 0;
-			engine->GetScreenDimensions(&sw, &sh, nullptr);
-			reflectionmap = new long[sw * sh]();
-			rcolormap = engine->CreateBlankBitmap(sw, sh, 8);
-			ralphamap = engine->CreateBlankBitmap(sw, sh, 8);
-			for (int i = 0; i < engine->GetNumCharacters(); i++) {
-				if (Reflection.Characters[i].reflect == 0) continue;
-				AGSCharacter *tempchar = engine->GetCharacter(i);
-				if (tempchar->room != engine->GetCurrentRoom()) continue;  //if character isn't even in the room, go to next iteration.
-				int32 vx = tempchar->x;
-				int32 vy = tempchar->y;
-				engine->RoomToViewport(&vx, &vy);
-				AGSViewFrame *vf = engine->GetViewFrame(tempchar->view + 1, tempchar->loop, tempchar->frame);
-				int w = engine->GetSpriteWidth(vf->pic);
-				int h = engine->GetSpriteHeight(vf->pic);
-				vx = vx - (w / 2);
-				int32 vxmax = vx + w;
-				int32 vymax = vy + h;
-				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
-				DrawReflections(i, 0);
-			}
-			for (int i = 0; i < engine->GetNumObjects(); i++) {
-				if (Reflection.Objects[i].reflect == 0) continue;
-				AGSObject *tempobj = engine->GetObject(i);
-				if (!tempobj->on) continue;
-				int32 vx = tempobj->x;
-				int32 vy = tempobj->baseline - tempobj->y;
-				engine->RoomToViewport(&vx, &vy);
-				int32 w = engine->GetSpriteWidth(tempobj->num);
-				int32 h = engine->GetSpriteHeight(tempobj->num);
-				int32 vxmax = vx + w;
-				int32 vymax = vy + h;
-				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
-				DrawReflections(i, 1);
-			}
-			BITMAP *virtsc = engine->GetVirtualScreen();
-			unsigned char **screenbuffer = engine->GetRawBitmapSurface(virtsc);
-			unsigned char **colorbuffer = engine->GetRawBitmapSurface(rcolormap);
-			unsigned char **alphabuffer = engine->GetRawBitmapSurface(ralphamap);
-			for (int y = 0; y < sh; y++)
-				for (int x = 0; x < sw; x++)
-					screenbuffer[y][x] = Mix::MixColorAlpha(colorbuffer[y][x], screenbuffer[y][x], alphabuffer[y][x]);
-			engine->ReleaseBitmapSurface(rcolormap);
-			engine->ReleaseBitmapSurface(ralphamap);
-			engine->ReleaseBitmapSurface(virtsc);
-			engine->FreeBitmap(rcolormap);
-			engine->FreeBitmap(ralphamap);
-			delete [] reflectionmap;
-		}
-		int i = 0;
-		if (LensOption.draw == 1 && LensOption.level == 0) DrawLens(LensOption.x, LensOption.y);
-		while (i < MAX_OVERLAYS) {
-			if (overlay[i].enabled && overlay[i].level == 0) {
-				DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
-			}
-			i++;
-		}
-		if (LensOption.draw == 1 && LensOption.level == 1) DrawLens(LensOption.x, LensOption.y);
-	}
-	if (event == AGSE_PREGUIDRAW && clutslot > 0) {
-		int i = 0;
-		if (LensOption.draw == 1 && LensOption.level == 1) DrawLens(LensOption.x, LensOption.y);
-		while (i < MAX_OVERLAYS) {
-			if (overlay[i].enabled && overlay[i].level == 1) {
-				DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
-			}
-			i++;
-		}
-		if (LensOption.draw == 1 && LensOption.level == 2) DrawLens(LensOption.x, LensOption.y);
-	}
-	if (event == AGSE_POSTSCREENDRAW && clutslot > 0) {
-		int i = 0;
-		if (LensOption.draw == 1 && LensOption.level == 3) DrawLens(LensOption.x, LensOption.y);
-		while (i < MAX_OVERLAYS) {
-			if (overlay[i].enabled && overlay[i].level == 2) {
-				DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
-			}
-			i++;
-		}
-		if (LensOption.draw == 1 && LensOption.level == 4) DrawLens(LensOption.x, LensOption.y);
-	}
-	if (event == AGSE_SAVEGAME) {
-		for (int i = 0; i < MAX_OVERLAYS; ++i) {
-			engine->FWrite(&overlay[i].sprite, sizeof(int), data);
-			engine->FWrite(&overlay[i].spritemask, sizeof(int), data);
-			engine->FWrite(&overlay[i].x, sizeof(int), data);
-			engine->FWrite(&overlay[i].y, sizeof(int), data);
-			engine->FWrite(&overlay[i].level, sizeof(int), data);
-			engine->FWrite(&overlay[i].trans, sizeof(int), data);
-			engine->FWrite(&overlay[i].blendtype, sizeof(int), data);
-			engine->FWrite(&overlay[i].enabled, sizeof(bool), data);
-		}
-		engine->FWrite(&clutslot, sizeof(int), data);
-		engine->FWrite(&drawreflections, sizeof(int), data);
-		for (int j = 0; j < 256; ++j) {
-			engine->FWrite(&cycle_remap[j], sizeof(unsigned char), data);
-		}
-		for (int j = 0; j < 256; ++j) {
-			engine->FWrite(&objectivepal[j].r, sizeof(unsigned char), data);
-			engine->FWrite(&objectivepal[j].b, sizeof(unsigned char), data);
-			engine->FWrite(&objectivepal[j].g, sizeof(unsigned char), data);
-		}
-		for (int j = 0; j < 256; ++j) {
-			engine->FWrite(&sprite[j].x, sizeof(double), data);
-			engine->FWrite(&sprite[j].y, sizeof(double), data);
-			engine->FWrite(&sprite[j].texture, sizeof(int), data);
-			engine->FWrite(&sprite[j].alpha, sizeof(unsigned char), data);
-			engine->FWrite(&sprite[j].uDivW, sizeof(double), data);
-			engine->FWrite(&sprite[j].uDivH, sizeof(double), data);
-			engine->FWrite(&sprite[j].vMove, sizeof(double), data);
-			engine->FWrite(&sprite[j].hMove, sizeof(double), data);
-			engine->FWrite(&sprite[j].objectinteract, sizeof(char), data);
-			engine->FWrite(&sprite[j].view, sizeof(int), data);
-			engine->FWrite(&sprite[j].frame, sizeof(int), data);
-			engine->FWrite(&sprite[j].angle, sizeof(int), data);
-		}
-		for (int j = 0; j < 256; ++j) {
-			for (int k = 0; k < 4; ++k) {
-				engine->FWrite(&wallData[j].texture[k], sizeof(int), data);
-				engine->FWrite(&wallData[j].solid[k], sizeof(int), data);
-				engine->FWrite(&wallData[j].ignorelighting[k], sizeof(int), data);
-				engine->FWrite(&wallData[j].alpha[k], sizeof(int), data);
-				engine->FWrite(&wallData[j].blendtype[k], sizeof(int), data);
-				engine->FWrite(&wallData[j].mask[k], sizeof(int), data);
-			}
-			engine->FWrite(&wallData[j].hotspotinteract, sizeof(char), data);
-		}
-		engine->FWrite(&raycastOn, sizeof(bool), data);
-		engine->FWrite(&heightmapOn, sizeof(bool), data);
-		engine->FWrite(&posX, sizeof(double), data);
-		engine->FWrite(&posY, sizeof(double), data);
-		engine->FWrite(&dirX, sizeof(double), data);
-		engine->FWrite(&dirY, sizeof(double), data);
-		engine->FWrite(&planeX, sizeof(double), data);
-		engine->FWrite(&planeY, sizeof(double), data);
-		engine->FWrite(&moveSpeed, sizeof(double), data);
-		engine->FWrite(&rotSpeed, sizeof(double), data);
-		if (raycastOn) { //If the raycaster is active, we have additional data to save.
-			for (int i = 0; i < mapWidth; ++i)
-				for (int j = 0; j < mapHeight; ++j) {
-					engine->FWrite(&worldMap [i][j], sizeof(unsigned char), data);
-					engine->FWrite(&lightMap [i][j], sizeof(unsigned char), data);
-					engine->FWrite(&ceilingMap [i][j], sizeof(int), data);
-					engine->FWrite(&floorMap [i][j], sizeof(int), data);
-					engine->FWrite(&heightMap [i][j], sizeof(int), data);
-				}
-		}
-		engine->FWrite(&textureSlot, sizeof(int), data);
-		engine->FWrite(&skybox, sizeof(int), data);
-		engine->FWrite(&ambientlight, sizeof(int), data);
-	}
-	if (event == AGSE_RESTOREGAME) {
-
-
-		for (int i = 0; i < MAX_OVERLAYS; ++i) {
-			engine->FRead(&overlay[i].sprite, sizeof(int), data);
-			engine->FRead(&overlay[i].spritemask, sizeof(int), data);
-			engine->FRead(&overlay[i].x, sizeof(int), data);
-			engine->FRead(&overlay[i].y, sizeof(int), data);
-			engine->FRead(&overlay[i].level, sizeof(int), data);
-			engine->FRead(&overlay[i].trans, sizeof(int), data);
-			engine->FRead(&overlay[i].blendtype, sizeof(int), data);
-			engine->FRead(&overlay[i].enabled, sizeof(bool), data);
-		}
-		engine->FRead(&clutslot, sizeof(int), data);
-		engine->FRead(&drawreflections, sizeof(int), data);
-		for (int j = 0; j < 256; ++j) {
-			engine->FRead(&cycle_remap[j], sizeof(unsigned char), data);
-		}
-		for (int j = 0; j < 256; ++j) { //Save Objective Palette, for palette mixing.
-			engine->FRead(&objectivepal[j].r, sizeof(unsigned char), data);
-			engine->FRead(&objectivepal[j].b, sizeof(unsigned char), data);
-			engine->FRead(&objectivepal[j].g, sizeof(unsigned char), data);
-		}
-		for (int j = 0; j < 256; ++j) { //Save Raycaster Sprite struct, 256 instances.
-			engine->FRead(&sprite[j].x, sizeof(double), data);
-			engine->FRead(&sprite[j].y, sizeof(double), data);
-			engine->FRead(&sprite[j].texture, sizeof(int), data);
-			engine->FRead(&sprite[j].alpha, sizeof(unsigned char), data);
-			engine->FRead(&sprite[j].uDivW, sizeof(double), data);
-			engine->FRead(&sprite[j].uDivH, sizeof(double), data);
-			engine->FRead(&sprite[j].vMove, sizeof(double), data);
-			engine->FRead(&sprite[j].hMove, sizeof(double), data);
-			engine->FRead(&sprite[j].objectinteract, sizeof(char), data);
-			engine->FRead(&sprite[j].view, sizeof(int), data);
-			engine->FRead(&sprite[j].frame, sizeof(int), data);
-			engine->FRead(&sprite[j].angle, sizeof(int), data);
-		}
-		for (int j = 0; j < 256; ++j) { //Save Raycaster wall type data.
-			for (int k = 0; k < 4; ++k) {
-				engine->FRead(&wallData[j].texture[k], sizeof(int), data);
-				engine->FRead(&wallData[j].solid[k], sizeof(int), data);
-				engine->FRead(&wallData[j].ignorelighting[k], sizeof(int), data);
-				engine->FRead(&wallData[j].alpha[k], sizeof(int), data);
-				engine->FRead(&wallData[j].blendtype[k], sizeof(int), data);
-				engine->FRead(&wallData[j].mask[k], sizeof(int), data);
-			}
-			engine->FRead(&wallData[j].hotspotinteract, sizeof(char), data);
-		}
-		//Delete worldmap data if it exists.
-		engine->FRead(&raycastOn, sizeof(bool), data);
-		engine->FRead(&heightmapOn, sizeof(bool), data);
-		engine->FRead(&posX, sizeof(double), data);
-		engine->FRead(&posY, sizeof(double), data);
-		engine->FRead(&dirX, sizeof(double), data);
-		engine->FRead(&dirY, sizeof(double), data);
-		engine->FRead(&planeX, sizeof(double), data);
-		engine->FRead(&planeY, sizeof(double), data);
-		engine->FRead(&moveSpeed, sizeof(double), data);
-		engine->FRead(&rotSpeed, sizeof(double), data);
-		if (raycastOn) { //If the raycaster is currently running, we have additional data to load.
-			for (int i = 0; i < mapWidth; ++i) {
-				for (int j = 0; j < mapHeight; ++j) {
-					engine->FRead(&worldMap [i][j], sizeof(unsigned char), data);
-					engine->FRead(&lightMap [i][j], sizeof(unsigned char), data);
-					engine->FRead(&ceilingMap [i][j], sizeof(int), data);
-					engine->FRead(&floorMap [i][j], sizeof(int), data);
-					engine->FRead(&heightMap [i][j], sizeof(int), data);
-					seenMap [i][j] = 0;
-				}
-			}
-
-			//Reinitialize all the buffers and stuff.
-
-		}
-		engine->FRead(&textureSlot, sizeof(int), data);
-		if (textureSlot) MakeTextures(textureSlot);
-		engine->FRead(&skybox, sizeof(int), data);
-		engine->FRead(&ambientlight, sizeof(int), data);
-		LoadCLUT(clutslot);
-	}
-	if (event == AGSE_ENTERROOM) {
-		ResetRemapping();
-		delete[] Reflection.Objects;
-		Reflection.Objects = new objrefopt [engine->GetNumObjects()]();
-	}
-	return 0;
-}
-
-} // namespace AGSPalRender
-} // namespace Plugins
-} // namespace AGS3
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or(at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ags/lib/allegro.h"
+#include "ags/plugins/ags_pal_render/ags_pal_render.h"
+#include "ags/plugins/ags_pal_render/pal_render.h"
+#include "ags/plugins/ags_pal_render/raycast.h"
+#include "ags/ags.h"
+
+namespace AGS3 {
+namespace Plugins {
+namespace AGSPalRender {
+
+#define MAX_OVERLAYS 128
+#define MAX_STARS 1024
+#define MAX_DEPTH 64
+
+#define PI         (3.1415926535f)
+#define HALF_PI    (0.5f * PI)
+#define TWO_PI     (2.0f * PI)
+#define TWO_PI_INV (1.0f / TWO_PI)
+
+const float halfpi = (0.5f * PI);
+const float twopi  = (2.0f * PI);
+const float twopi_inv = (1.0f / TWO_PI);
+const float pisquared = PI * PI;
+const float picubed = PI * PI * PI;
+
+IAGSEngine *engine;
+
+//unsigned char clut[256][256];
+unsigned char clut[65536];
+
+struct transoverlaytype {
+	int sprite;
+	int spritemask;
+	int blendtype;
+	int x;
+	int y;
+	int trans;
+	int level;
+	bool enabled;
+} overlay[MAX_OVERLAYS];
+
+int clutslot;
+int drawreflections;
+unsigned char cycle_remap [256];
+
+struct starstype {
+	float x;
+	float y;
+	float z;
+	unsigned char color;
+	long sprite;
+	int maxrad;
+	int scaleboost;
+};
+starstype *stars;
+
+struct starsoptions {
+	float speed;
+	int maxstars;
+	int depthmultiplier;
+	int originx;
+	int originy;
+	int overscan;
+} Starfield;
+long *reflectionmap;
+BITMAP *rcolormap;
+BITMAP *ralphamap;
+
+struct charrefopt {
+	char reflect;
+	int replaceview;
+};
+
+struct objrefopt {
+	char reflect;
+	char ignorescaling;
+};
+
+struct reflectionopt {
+	charrefopt *Characters;
+	objrefopt *Objects;
+	int blendslot;
+	int blendamount;
+} Reflection;
+
+int dummy;
+
+#define LENS_WIDTH 150
+
+struct LensDistort {
+	int xoffset;
+	int yoffset;
+};
+
+LensDistort *lens;
+struct LensOpt {
+	bool draw;
+	int lenswidth;
+	int lenszoom;
+	int level;
+	int x;
+	int y;
+	int clampoffset;
+} LensOption;
+
+const int alphamultiply [4096] = {
+//#include "alphamultiply.txt"
+};
+float rot_sine_LUT[360];
+float rot_cos_LUT[360];
+
+BITMAP *backgroundimage;
+
+PALSTRUCT objectivepal[256];
+int bgimgspr;
+
+void WriteObjectivePalette(unsigned char index, unsigned char r, unsigned char b, unsigned char g) {
+	objectivepal[index].r = r;
+	objectivepal[index].b = b;
+	objectivepal[index].g = g;
+}
+
+int ReadObjectivePaletteR(unsigned char index) {
+	return objectivepal[index].r;
+}
+
+int ReadObjectivePaletteB(unsigned char index) {
+	return objectivepal[index].b;
+}
+int ReadObjectivePaletteG(unsigned char index) {
+	return objectivepal[index].g;
+}
+
+
+#define SQRT_MAGIC_F 0x5f3759df
+float  q3sqrt(const float x) {
+	const float xhalf = 0.5f * x;
+
+	union { // get bits for floating value
+		float x;
+		int i;
+	} u;
+	u.x = x;
+	u.i = SQRT_MAGIC_F - (u.i >> 1);  // gives initial guess y0
+	return x * u.x * (1.5f - xhalf * u.x * u.x); // Newton step, repeating increases accuracy
+}
+
+void Make_Sin_Lut() {
+	for (int angle = 0; angle < 360; angle++) {
+		double rad = (angle * PI) / 180.0;
+		rot_sine_LUT [angle] = static_cast<float>(sin(rad));
+		rot_cos_LUT [angle]  = static_cast<float>(cos(rad));
+	}
+}
+
+/*
+void PreMultiply_Alphas () //Ha ha, this isn't the kind of premultiplcation you're thinking of.
+{
+    for (int y=0;y<64;y++)
+        for (int x=0;x<64;x++)
+            alphamultiply [y*64+x] = y*x;
+}
+*/
+
+int GetModifiedBackgroundImage() {
+	return bgimgspr;
+}
+
+unsigned short root(unsigned short x) {
+	unsigned short a, b;
+	b = x;
+	a = x = 0x3f;
+	x = b / x;
+	a = x = (x + a) >> 1;
+	x = b / x;
+	a = x = (x + a) >> 1;
+	x = b / x;
+	x = (x + a) >> 1;
+	return (x);
+}
+
+
+float Hill(float x) {
+	const float a0 = 1.0f;
+	const float a2 = 2.0f / PI - 12.0f / (pisquared);
+	const float a3 = 16.0f / (picubed) - 4.0f / (pisquared);
+	const float xx = x * x;
+	const float xxx = xx * x;
+
+	return a0 + a2 * xx + a3 * xxx;
+}
+
+float FastSin(float x) {
+	// wrap x within [0, TWO_PI)
+	const float a = x * twopi_inv;
+	x -= static_cast<int>(a) * twopi;
+	if (x < 0.0f)
+		x += twopi;
+
+	// 4 pieces of hills
+	if (x < halfpi)
+		return Hill(halfpi - x);
+	else if (x < PI)
+		return Hill(x - halfpi);
+	else if (x < 3.0f * halfpi)
+		return -Hill(3.0f * halfpi - x);
+	else
+		return -Hill(x - 3.0f * halfpi);
+}
+
+float FastCos(float x) {
+	return FastSin(x + halfpi);
+}
+
+FLOAT_RETURN_TYPE AGSFastSin(SCRIPT_FLOAT(x)) {
+	INIT_SCRIPT_FLOAT(x);
+	x = FastSin(x);
+	RETURN_FLOAT(x);
+}
+
+FLOAT_RETURN_TYPE AGSFastCos(SCRIPT_FLOAT(x)) {
+	INIT_SCRIPT_FLOAT(x);
+	x = FastSin(x + halfpi);
+	RETURN_FLOAT(x);
+}
+
+
+void DrawLens(int ox, int oy) {
+	int32 sh, sw = 0;
+	engine->GetScreenDimensions(&sw, &sh, nullptr);
+	BITMAP *virtsc = engine->GetVirtualScreen();
+	if (!virtsc) engine->AbortGame("DrawLens: Cannot get virtual screen.");
+	BITMAP *lenswrite = engine->CreateBlankBitmap(LensOption.lenswidth, LensOption.lenswidth, 8);
+	unsigned char **vScreen = engine->GetRawBitmapSurface(virtsc);
+	unsigned char **lensarray = engine->GetRawBitmapSurface(lenswrite);
+	int radius = LensOption.lenswidth >> 1;
+	for (int y = 0; y < LensOption.lenswidth; y++) {
+		int ypos = y * LensOption.lenswidth;
+		for (int x = 0; x < LensOption.lenswidth; x++) {
+			int lenspos = ypos + x;
+			int coffx = lens[lenspos].xoffset;
+			int coffy = lens[lenspos].yoffset;
+			if (oy + coffy > 0 && oy + coffy < sh && ox + coffx > 0 && ox + coffx < sw) {
+				lensarray[y][x] = vScreen[oy + coffy][ox + coffx];
+				//vScreen[oy+coffy][ox+coffx] = ABS(coffy);
+			}
+		}
+	}
+	/*
+	for (int y=0;y<LensOption.lenswidth;y++)
+	{
+	    int ypos = y*LensOption.lenswidth;
+	    for (int x=0;x<LensOption.lenswidth;x++)
+	    {
+	        if (oy+y > 0 && oy+y < sh && ox+x > 0 && ox+x < sw)
+	        {
+	            vScreen[oy+y][ox+x] = lensarray[y][x];
+	        }
+	    }
+	}
+	*/
+	int radsq = radius * radius;
+	for (int cy = -radius; cy <= radius; cy++) { //Draw a circle around the point, for the mask.
+		int cysq = cy * cy;
+		for (int cx = -radius; cx <= radius; cx++) {
+			int cxsq = cx * cx;
+			int dx = cx + ox;
+			int dy = cy + oy;
+			if ((cxsq + cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0 && cy + radius < LensOption.lenswidth - 1 && cx + radius < LensOption.lenswidth - 1) {
+				//if (cy+radius < 0 || cx+radius < 0) engine->AbortGame ("I did something wrong");
+				vScreen[dy][dx] = lensarray[cy + radius][cx + radius];
+			}
+		}
+	}
+
+	engine->ReleaseBitmapSurface(lenswrite);
+	engine->ReleaseBitmapSurface(virtsc);
+	engine->FreeBitmap(lenswrite);
+}
+
+void SetLensPos(int x, int y) {
+	LensOption.x = x;
+	LensOption.y = y;
+}
+
+int GetLensX() {
+	return LensOption.x;
+}
+
+int GetLensY() {
+	return LensOption.y;
+}
+
+void SetLensDrawn(int toggle) {
+	if (toggle > 0) LensOption.draw = 1;
+	else LensOption.draw = 0;
+}
+
+int GetLensDrawn() {
+	return LensOption.draw;
+}
+
+void SetLensOffsetClamp(int clamp) {
+	if (clamp < 0) LensOption.clampoffset = LensOption.lenswidth;
+	else LensOption.clampoffset = clamp;
+}
+
+int GetLensOffsetClamp() {
+	return LensOption.clampoffset;
+}
+
+int GetLensLevel() {
+	return LensOption.level;
+}
+
+void SetLensLevel(int level) {
+	if (level < 0 || level > 4) engine->AbortGame("SetLensLevel: Invalid level.");
+	else LensOption.level = level;
+}
+
+void LensInitialize(int width, int zoom, int lensx, int lensy, int level, int clamp = -1) {
+	int32 sw, sh, radius;
+	if (width < 1) engine->AbortGame("Invalid lens dimension!");
+	radius = width >> 1;
+	lens = new LensDistort [width * width]();
+	engine->GetScreenDimensions(&sw, &sh, nullptr);
+	int radsq = radius * radius;
+	int zoomsq = zoom * zoom;
+	for (int y = 0; y < radius; y++) {
+		int ysq = y * y;
+		for (int x = 0; x < radius; x++) {
+			int lx, ly;
+			int xsq = x * x;
+			if ((xsq + ysq) < (radsq)) {
+				float shift = zoom / sqrt((float)(zoomsq - (xsq + ysq - radsq)));
+				lx = (int)(x * shift - x);
+				ly = (int)(y * shift - y);
+			} else {
+				lx = 0;
+				ly = 0;
+			}
+			lens[(radius - y)*width + (radius - x)].xoffset =  lx;
+			lens[(radius - y)*width + (radius - x)].yoffset =  ly;
+			lens[(radius + y)*width + (radius + x)].xoffset = -lx;
+			lens[(radius + y)*width + (radius + x)].yoffset = -ly;
+			lens[(radius + y)*width + (radius - x)].xoffset =  lx;
+			lens[(radius + y)*width + (radius - x)].yoffset = -ly;
+			lens[(radius - y)*width + (radius + x)].xoffset = -lx;
+			lens[(radius - y)*width + (radius + x)].yoffset =  ly;
+		}
+	}
+	LensOption.lenswidth = width;
+	LensOption.lenszoom = zoom;
+	if (clamp < 0) LensOption.clampoffset = width;
+	else LensOption.clampoffset = clamp;
+	LensOption.x = lensx;
+	LensOption.y = lensy;
+	if (level < 0 || level > 4) engine->AbortGame("SetLensLevel: Invalid level.");
+	else LensOption.level = level;
+}
+
+void ResetRemapping() {
+	for (int j = 0; j < 256; ++j) {
+		cycle_remap [j] = j;
+	}
+}
+
+#define MAX_PLASMA_COMPLEXITY 4
+int plasmatype[MAX_PLASMA_COMPLEXITY];
+int plasmadata [MAX_PLASMA_COMPLEXITY];
+int plasmadata2 [MAX_PLASMA_COMPLEXITY];
+int plasmadata3 [MAX_PLASMA_COMPLEXITY];
+int plasmaroottype;
+
+
+void SetPlasmaRootType(int real) {
+	if (real) plasmaroottype = 1;
+	else plasmaroottype = 0;
+}
+
+int GetPlasmaRootType() {
+	return plasmaroottype;
+}
+
+void SetPlasmaType(int component, int type, int data, int data2, int data3) {
+	if (component >= MAX_PLASMA_COMPLEXITY) engine->AbortGame("Plasma too complex!");
+	else {
+		plasmatype [component] = type;
+		plasmadata [component] = data;
+		plasmadata2[component] = data2;
+		plasmadata3[component] = data3;
+	}
+
+	//0 = None.
+	//1 = Horizontal Bars (data=width)
+	//2 = Vertical Bars (data=width)
+	//3 = Circle (data=x,data2=y,data3=width)
+	//4 = Diagonal Bars (data=width)
+}
+
+void ResetPlasmaSettings() {
+	int i = 0;
+	while (i < MAX_PLASMA_COMPLEXITY) {
+		plasmatype [i] = 0;
+		plasmadata [i] = 0;
+		plasmadata2[i] = 0;
+		plasmadata3[i] = 0;
+		i++;
+	}
+}
+
+void DrawPlasma(int slot, int palstart, int palend) {
+	BITMAP *plasmaspr = engine->GetSpriteGraphic(slot);
+	if (!plasmaspr) engine->AbortGame("Plasma: Not a sprite I can load.");
+	int32 w, h, basecol, range = 0;
+	if (palend > palstart) {
+		range = palend - palstart;
+		basecol = palstart;
+	} else {
+		range = palstart - palend;
+		basecol = palend;
+	}
+	engine->GetBitmapDimensions(plasmaspr, &w, &h, nullptr);
+	unsigned char **plasmarray = engine->GetRawBitmapSurface(plasmaspr);
+	double frange = range / 2.0;
+	int complex = 0;
+	int color = 0;
+	int i = 0;
+	while (i < MAX_PLASMA_COMPLEXITY) {
+		if (plasmatype[i] > 0) complex++;
+		i++;
+	}
+	for (int x = 0; x < w; x++) {
+		for (int y = 0; y < h; y++) {
+			color = 0;
+			for (int p = 0; p < MAX_PLASMA_COMPLEXITY; p++) {
+				if (plasmatype[p] == 1) { //1 = Horizontal Bars (data=width)
+					color += int(frange + (frange * FastSin(y / (float)plasmadata[p])));
+				} else if (plasmatype[p] == 2) { //2 = Vertical Bars (data=width)
+					color += int(frange + (frange * FastSin(x / (float)plasmadata[p])));
+				} else if (plasmatype[p] == 3) { //3 = Circle (data=x,data2=y,data3=width)
+					int cx, cy = 0;
+					cx = plasmadata [p];
+					cy = plasmadata2 [p];
+					if (plasmaroottype == 1) color += int(frange + (frange * FastSin(q3sqrt((float)((x - cx) * (x - cx) + (y - cy) * (y - cy)) / plasmadata3[p]))));
+					else color += int(frange + (frange * FastSin(root(((x - cx) * (x - cx) + (y - cy) * (y - cy)) / plasmadata3[p]))));
+				} else if (plasmatype[p] == 4) { //4 = Diagonal Bars (data=width)
+					color += int(frange + (frange * FastSin((x + y) / (float)plasmadata[p])));
+				}
+			}
+			if (color > 0 && complex > 0) color = color / complex;
+			plasmarray[y][x] = static_cast<unsigned char>(basecol + color);
+		}
+	}
+	engine->ReleaseBitmapSurface(plasmaspr);
+	engine->NotifySpriteUpdated(slot);
+}
+
+void DoFire(int spriteId, int masksprite, int palstart, int palend, int strength, int seed, int cutoff, int windspeed) {
+	BITMAP *firespr = engine->GetSpriteGraphic(masksprite);
+	BITMAP *firecolorspr = engine->GetSpriteGraphic(spriteId);
+	BITMAP *seedspr;
+	int32 w, h = 0;
+	int range, basecol, dir = 0;
+	if (palend > palstart) {
+		range = palend - palstart;
+		basecol = palstart;
+		dir = 1;
+	} else {
+		range = palstart - palend;
+		basecol = palend;
+		dir = -1;
+	}
+	int divider = 256 / range;
+	engine->GetBitmapDimensions(firespr, &w, &h, nullptr);
+	unsigned char **fire = engine->GetRawBitmapSurface(firespr);
+	unsigned char **color = engine->GetRawBitmapSurface(firecolorspr);
+	int sparky = 0;
+	//srand(time(NULL));
+	for (int y = 0; y < h - 1; y++) {
+		if ((int)::AGS::g_vm->getRandomNumber(9) > 7 - windspeed) { //Wind right
+			for (int x = w - 1; x > 1; x--) {
+				fire[y][x] = fire[y][x - 1];
+			}
+		} else if ((int)::AGS::g_vm->getRandomNumber(9) > 7 + windspeed) { // wind left
+			for (int x = 0; x < w - 1; x++) {
+				fire[y][x] = fire[y][x + 1];
+			}
+		}
+	}
+	for (int x = 0; x < w; x++) {
+		sparky = ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % (h - 2));
+		if (sparky < h && sparky > 0 && fire[h - sparky][x] > cutoff &&
+				ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % 10) > 7)
+			fire[h - sparky][x] = 255;
+		sparky = ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % (h - 2));
+		if (sparky < h && sparky > 0 && fire[h - sparky][x] > cutoff &&
+				ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % 10) > 7)
+			fire[h - sparky][x] = 0;
+	}
+	if (seed == 0) {
+		for (int x = 0; x < w; x++)
+			fire[h - 1][x] = 255;
+		for (int x = 0; x < w; x++)
+			fire[h - 2][x] = ::AGS::g_vm->getRandomNumber(255);
+	} else if (seed > 0) {
+		seedspr = engine->GetSpriteGraphic(seed);
+		BITMAP *virtsc = engine->GetVirtualScreen();
+		engine->SetVirtualScreen(firespr);
+		engine->BlitBitmap(0, 0, seedspr, 1);
+		engine->SetVirtualScreen(virtsc);
+		engine->ReleaseBitmapSurface(virtsc);
+		engine->ReleaseBitmapSurface(seedspr);
+		engine->NotifySpriteUpdated(spriteId);
+		engine->NotifySpriteUpdated(masksprite);
+	}
+
+	for (int y = 0; y < h - 1; y++) {
+		for (int x = 0; x < w; x++) {
+			fire[y][x] =
+			    ((fire[(y + 1) % h][(x - 1 + w) % w]
+			      + fire[(y + 1) % h][(x) % w]
+			      + fire[(y + 1) % h][(x + 1) % w]
+			      + fire[(y + 2) % h][(x) % w])
+			     * 100) / (400 + (100 - strength));
+			if (fire[y][x] < cutoff) fire[y][x] = 0;
+			//if (fire[y][x] ==255) color [y][x] = palend;
+			else color [y][x] = static_cast<unsigned char>(basecol + (fire[y][x] / divider) * dir);
+		}
+	}
+	engine->ReleaseBitmapSurface(firespr);
+	engine->ReleaseBitmapSurface(firecolorspr);
+	engine->NotifySpriteUpdated(spriteId);
+	engine->NotifySpriteUpdated(masksprite);
+}
+
+/*
+unsigned char MixColorAlpha (unsigned char fg,unsigned char bg,unsigned char alpha)
+{
+    //unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
+    //unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
+    //BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
+    //if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
+    //unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
+    AGSColor *palette = engine->GetPalette ();
+    int i=0;
+    int out_r = (palette[fg].r>>1) * alpha + (palette[bg].r>>1) * (255 - alpha);
+    int out_g = palette[fg].g * alpha + palette[bg].g * (255 - alpha);
+    int out_b = (palette[fg].b>>1) * alpha + (palette[bg].b>>1) * (255 - alpha);
+    //unsigned char ralpha = alpha>>2;
+    //unsigned char invralpha = 64-ralpha;
+    //if (ralpha > alpha) engine->AbortGame ("wtf");
+    //int out_r = alphamultiply[(palette[fg].r>>1)][ralpha] + alphamultiply[(palette[bg].r>>1)][(invralpha)];
+    //int out_g = alphamultiply[(palette[fg].g)][ralpha] + alphamultiply[(palette[bg].g)][(invralpha)];
+    //int out_b = alphamultiply[(palette[fg].b>>1)][ralpha] + alphamultiply[(palette[bg].b>>1)][(invralpha)];
+    out_r = (out_r + 1 + (out_r >> 8)) >> 8;
+    out_g = (out_g + 1 + (out_g >> 8)) >> 8;
+    out_b = (out_b + 1 + (out_b >> 8)) >> 8;
+    i = ((out_r << 11) | (out_g << 5) | out_b);
+    unsigned char (*clutp) = clut;
+    //unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
+    unsigned char result = cycle_remap [*(clutp+i)]; //Once again, to make sure that the palette slot used is the right one.
+    //engine->ReleaseBitmapSurface (clutspr);
+    return result;
+}
+
+unsigned char MixColorAdditive (unsigned char fg,unsigned char bg,unsigned char alpha)
+{
+    //unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
+    //unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
+    //BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
+    //if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
+    //unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
+    AGSColor *palette = engine->GetPalette ();
+    int i=0;
+    int add_r,add_b,add_g = 0;
+    char ralpha = alpha>>2;
+    //if (ralpha > alpha) engine->AbortGame ("wtf");
+    //add_r = (((palette[fg].r>>1) * (alpha))>>8);
+    //add_b = (((palette[fg].b>>1) * (alpha))>>8);
+    //add_g = (((palette[fg].g)    * (alpha))>>8);
+    add_r = ((alphamultiply[(palette[fg].r>>1)*64+ralpha])>>6);
+    add_b = ((alphamultiply[(palette[fg].b>>1)*64+ralpha])>>6);
+    add_g = ((alphamultiply[(palette[fg].g   )*64+ralpha])>>6);
+    int out_r = min(31,(palette[bg].r>>1) + add_r);
+    int out_g = min(63, palette[bg].g     + add_g);
+    int out_b = min(31,(palette[bg].b>>1) + add_b);
+    i = ((out_r << 11) | (out_g << 5) | out_b);
+    unsigned char (*clutp) = clut;
+    unsigned char result = cycle_remap [*(clutp+i)]; //Once again, to make sure that the palette slot used is the right one.
+    //unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
+    //engine->ReleaseBitmapSurface (clutspr);
+    return result;
+}
+*/
+unsigned char GetColor565(unsigned char r, unsigned char g, unsigned char b) {
+	//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
+	//if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
+	//unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
+	int i = ((r << 11) | (g << 5) | b);
+	unsigned char (*clutp) = clut;
+	unsigned char result = *(clutp + i);
+	result = cycle_remap [result]; //Once again, to make sure that the palette slot used is the right one.
+	//engine->ReleaseBitmapSurface (clutspr);
+	return result;
+}
+
+void CycleRemap(int start, int end) {
+	if (end > start) {
+		// Rotate left
+		int wraparound = cycle_remap [start];
+		for (; start < end; ++start) {
+			cycle_remap [start] = cycle_remap [start + 1];
+		}
+		cycle_remap [end] = wraparound;
+	} else if (end < start) {
+		// Rotate right
+		int wraparound = cycle_remap [start];
+		for (; start > end; --start) {
+			cycle_remap [start] = cycle_remap [start - 1];
+		}
+		cycle_remap [end] = wraparound;
+
+	}
+}
+
+unsigned char GetRemappedSlot(unsigned char slot) {
+	return cycle_remap [slot];
+}
+
+int LoadCLUT(int slot) {
+	if (engine->GetSpriteWidth(slot) != 256 || engine->GetSpriteHeight(slot) != 256) return 1;
+	BITMAP *clutimage = engine->GetSpriteGraphic(slot);
+	unsigned char **clutarray = engine->GetRawBitmapSurface(clutimage);
+	for (int y = 0; y < 256; y++) {
+		for (int x = 0; x < 256; x++) {
+			clut[y * 256 + x] = clutarray[y][x];
+		}
+	}
+	clutslot = slot;
+	engine->ReleaseBitmapSurface(clutimage);
+	return 0;
+}
+
+void SetReflections(int toggle) {
+	drawreflections = toggle;
+}
+
+int IsReflectionsOn() {
+	return drawreflections;
+}
+
+int GetLuminosityFromPalette(int slot) {
+	AGSColor *pal = engine->GetPalette();
+	int lum = (pal[slot].r +
+	           pal[slot].r +
+	           pal[slot].r +
+	           pal[slot].g +
+	           pal[slot].g +
+	           pal[slot].g +
+	           pal[slot].g +
+	           pal[slot].b) >> 3;
+	return lum;
+}
+
+
+
+void SetStarsOriginPoint(int x, int y) {
+	Starfield.originx = x;
+	Starfield.originy = y;
+}
+void InitializeStars(int slot, int maxstars) {
+	int32 sw, sh = 0;
+	BITMAP *canvas = engine->GetSpriteGraphic(slot);
+	engine->GetBitmapDimensions(canvas, &sw, &sh, nullptr);
+	Starfield.maxstars = maxstars;
+	Starfield.overscan = 20;
+	stars = new starstype [Starfield.maxstars];
+	for (int i = 0; i < Starfield.maxstars; i++) {
+		stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
+		if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
+		stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
+		if (stars[i].y < 1.0 && stars[i].y > -1.0) stars[i].y = (float)sh;
+		stars[i].z = (float)(MAX_DEPTH);
+		stars[i].color = (::AGS::g_vm->getRandomNumber(0x7fffffff) % 240);
+		stars[i].sprite = 0;
+		stars[i].maxrad = (::AGS::g_vm->getRandomNumber(0x7fffffff) % 5);
+	}
+}
+
+void IterateStars(int slot) {
+	long sw, sh = 0;
+	sw = engine->GetSpriteWidth(slot);
+	sh = engine->GetSpriteHeight(slot);
+	for (int i = 0; i < Starfield.maxstars; i++) {
+		stars[i].z -= Starfield.speed;
+		//if (stars[i].z < 1.0) stars[i].z = (double)MAX_DEPTH;
+		float k = Starfield.depthmultiplier / stars[i].z;
+		int px = static_cast<int>(stars[i].x * k + Starfield.originx);
+		int py = static_cast<int>(stars[i].y * k + Starfield.originy);
+		if (px >= sw + Starfield.overscan || px < 0 - Starfield.overscan || py >= sh + Starfield.overscan || py < 0 - Starfield.overscan) {
+			stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
+			if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
+			stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
+			if (stars[i].y < 1.0 && stars[i].y > 1.0) stars[i].y = (float)sh;
+			stars[i].z = (float)MAX_DEPTH;
+			//stars[i].color = (rand () %240);
+		}
+	}
+}
+int GetStarfieldOverscan() {
+	return Starfield.overscan;
+}
+void SetStarfieldOverscan(int overscan) {
+	Starfield.overscan = overscan;
+}
+
+int GetStarfieldOriginX() {
+	return Starfield.originx;
+}
+
+int GetStarfieldOriginY() {
+	return Starfield.originy;
+}
+
+void SetStarfieldDepthMultiplier(int multi) {
+	Starfield.depthmultiplier = multi;
+}
+
+int GetStarfieldDepthMultiplier() {
+	return Starfield.depthmultiplier;
+}
+
+int GetStarfieldMaxStars() {
+	return Starfield.maxstars;
+}
+
+void SetStarSpriteScaleBoost(int star, int boost) {
+	stars[star].scaleboost = boost;
+}
+
+int GetStarSpriteScaleBoost(int star) {
+	return stars[star].scaleboost;
+}
+
+void SetStarMaxRadius(int star, int radius) {
+	stars[star].maxrad = radius;
+}
+
+int GetStarMaxRadius(int star) {
+	return stars[star].maxrad;
+}
+
+void RotateStar(int star, int angle, int px, int py) {
+	float rsin = rot_sine_LUT[angle];
+	float rcos = rot_cos_LUT[angle];
+	float fPx = (float)px;
+	float fPy = (float)py;
+	float x1 = 0, y1 = 0, xRot = 0, yRot = 0;
+	int i = star;
+	x1 = stars[i].x;
+	y1 = stars[i].y;
+	xRot = fPx + rcos * (x1 - fPx) - rsin * (y1 - fPy);
+	yRot = fPy + rsin * (x1 - fPx) + rcos * (y1 - fPy);
+	stars[i].x = xRot;
+	stars[i].y = yRot;
+	i++;
+}
+
+FLOAT_RETURN_TYPE GetStarX(int i) {
+	float starx = (float)stars[i].x;
+	RETURN_FLOAT(starx);
+}
+
+FLOAT_RETURN_TYPE GetStarY(int i) {
+	float stary = (float)stars[i].y;
+	RETURN_FLOAT(stary);
+}
+
+FLOAT_RETURN_TYPE GetStarZ(int i) {
+	float starz = (float)stars[i].z;
+	RETURN_FLOAT(starz);
+}
+
+void SetStarPosition(int star, SCRIPT_FLOAT(x), SCRIPT_FLOAT(y), SCRIPT_FLOAT(z)) {
+	INIT_SCRIPT_FLOAT(x);
+	INIT_SCRIPT_FLOAT(y);
+	INIT_SCRIPT_FLOAT(z);
+	stars[star].x = x;
+	stars[star].y = y;
+	stars[star].z = z;
+}
+
+void SetStarColor(int star, unsigned char color) {
+	stars[star].color = color;
+}
+
+unsigned char GetStarColor(int star) {
+	return stars[star].color;
+}
+
+void SetStarSprite(int star, int slot) {
+	stars[star].sprite = slot;
+}
+
+int GetStarSprite(int star) {
+	return stars[star].sprite;
+}
+
+void SetStarSpriteRange(int start, int end, int slot) {
+	int sfix = start;
+	int efix = end;
+	if (start > Starfield.maxstars) sfix = Starfield.maxstars - 1;
+	if (end > Starfield.maxstars) efix = Starfield.maxstars;
+	for (int i = sfix; i < efix; i++)
+		stars[i].sprite = slot;
+}
+
+void DrawStars(int slot, int maskslot) {
+	int32 sw, sh = 0;
+	BITMAP *canvas = engine->GetSpriteGraphic(slot);
+	if (!canvas) engine->AbortGame("DrawStars: Can't load sprite slot.");
+	BITMAP *maskcanvas = engine->GetSpriteGraphic(maskslot);
+	if (!maskcanvas) engine->AbortGame("DrawStars: Can't load mask slot.");
+	engine->GetBitmapDimensions(canvas, &sw, &sh, nullptr);
+	unsigned char **screenarray = engine->GetRawBitmapSurface(canvas);
+	unsigned char **maskarray = engine->GetRawBitmapSurface(maskcanvas);
+	for (int i = 0; i < Starfield.maxstars; i++) {
+		//stars[i].z-= 0.5;
+		//if (stars[i].z < 1.0) stars[i].z = (double)MAX_DEPTH;
+		float k = (float)Starfield.depthmultiplier / stars[i].z;
+		int px = static_cast<int>(stars[i].x * k + Starfield.originx);
+		int py = static_cast<int>(stars[i].y * k + Starfield.originy);
+		if (px >= sw + Starfield.overscan || px < 0 - Starfield.overscan || py >= sh + Starfield.overscan || py < 0 - Starfield.overscan) {
+			stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
+			if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
+			stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
+			if (stars[i].y < 1.0 && stars[i].y > 1.0) stars[i].y = (float)sh;
+			stars[i].z = (float)MAX_DEPTH;
+			//stars[i].color = (rand () %240);
+		} else if (stars[i].z > 0) {
+			int ivalue = (63 - (int)stars[i].z);
+			if (ivalue > 63) ivalue = 63;
+			else if (ivalue < 0) ivalue = 0;
+			unsigned char value = (unsigned char)(ivalue);
+			unsigned char maskcolor = value << 2;
+			if (stars[i].sprite > 0) {
+				BITMAP *origspr = engine->GetSpriteGraphic(stars[i].sprite);
+				int scale = (ivalue + 1) * 100 >> 6;
+				//int scale = 50;
+				if (scale < 1) scale = 1;
+				/*
+				if (scale != 100)
+				{
+				unsigned char** orig = engine->GetRawBitmapSurface (origspr);
+				int32 h1,h2,w1,w2=0;
+				double fw2,fh2;
+				engine->GetBitmapDimensions (origspr,&w1,&h1,NULL);
+				fh2 = h1 * (scale / 100.0);
+				fw2 = w1 * (scale / 100.0);
+				h2 = static_cast<int>(fh2);
+				w2 = static_cast<int>(fw2);
+				if (w2 < 1) w2 = 1;
+				if (h2 < 1) h2 = 1;
+				resizspr = engine->CreateBlankBitmap (w2,h2,8);
+				unsigned char** resized = engine->GetRawBitmapSurface (resizspr);
+				int x_ratio = (int)((w1<<16)/w2) +1;
+				int y_ratio = (int)((h1<<16)/h2) +1;
+				int x2, y2 ;
+				for (int i=0;i<h2;i++)
+				{
+				    for (int j=0;j<w2;j++)
+				   {
+				       x2 = ((j*x_ratio)>>16) ;
+				       y2 = ((i*y_ratio)>>16) ;
+				       resized [i][j] = orig [y2][x2];
+				 }
+				}
+				engine->ReleaseBitmapSurface (resizspr);
+				}
+				//resizspr = origspr;
+				int32 w,h=0;
+				engine->GetBitmapDimensions (resizspr,&w,&h,NULL);
+				unsigned char **imagemap = engine->GetRawBitmapSurface (resizspr);
+				int ox = px - (w>>1);
+				int oy = py - (h>>1);
+				for (int dy=0;dy<h;dy++)
+				{
+				for (int dx=0;dx<w;dx++)
+				{
+				   int ex = ox+dx;
+				   int ey = oy+dy;
+				   if (ex < sw && ex >= 0 && ey < sh && ey >= 0)
+				   {
+				       if (maskcolor > maskarray [ey][ex] && imagemap[dy][dx] > 0)
+				       {
+				           maskarray [ey][ex] = maskcolor;
+				           screenarray [ey][ex] = imagemap[dy][dx];
+				       }
+				   }
+				}
+				}
+				*/
+
+				unsigned char **orig = engine->GetRawBitmapSurface(origspr);
+				int32 h1, h2, w1, w2 = 0;
+				double fw2, fh2;
+				engine->GetBitmapDimensions(origspr, &w1, &h1, nullptr);
+				fh2 = h1 * (scale / 100.0);
+				fw2 = w1 * (scale / 100.0);
+				h2 = static_cast<int>(fh2);
+				w2 = static_cast<int>(fw2);
+				if (w2 < 1) w2 = 1;
+				if (h2 < 1) h2 = 1;
+				int x_ratio = (int)((w1 << 16) / w2) + 1;
+				int y_ratio = (int)((h1 << 16) / h2) + 1;
+				int x2, y2 ;
+				int ox = px - (w2 >> 1);
+				int oy = py - (h2 >> 1);
+				for (int ii = 0; ii < h2; ii++) {
+					int temprzy = ii * y_ratio;
+					int ey = oy + ii;
+					for (int j = 0; j < w2; j++) {
+						x2 = ((j * x_ratio) >> 16);
+						y2 = ((temprzy) >> 16);
+						int ex = ox + j;
+						if (ex < sw && ex >= 0 && ey < sh && ey >= 0) {
+							if (maskcolor > maskarray [ey][ex] && orig[y2][x2] > 0) {
+								maskarray [ey][ex] = maskcolor;
+								screenarray [ey][ex] = orig[y2][x2];
+							}
+						}
+						//resized [ii][j] = orig [y2][x2];
+					}
+				}
+				engine->ReleaseBitmapSurface(origspr);
+			} else if (stars[i].sprite == 0) {
+				if (stars[i].maxrad == 1) {
+					if (px < sw && px >= 0 && py < sh && py >= 0) {
+						if (maskcolor > maskarray[py][px]) {
+							maskarray[py][px] = maskcolor;
+							screenarray[py][px] = stars[i].color;
+						}
+					}
+				} else {
+					int scale = ((((int)stars[i].z) * 100) / 63);
+					if (scale < 1) scale = 1;
+					int radius = (stars[i].maxrad * (100 - scale) / 100);
+					int radsq = radius * radius;
+					//unsigned char color = GetColor565 (value>>1,value,value>>1);
+					unsigned char color = stars[i].color;
+					for (int cy = -radius; cy <= radius; cy++) { //Draw a circle around the point, for the mask.
+						int cysq = cy * cy;
+						for (int cx = -radius; cx <= radius; cx++) {
+							int cxsq = cx * cx;
+							int dx = cx + px;
+							int dy = cy + py;
+							if ((cxsq + cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0) {
+								if (maskcolor > maskarray [dy][dx]) {
+									maskarray [dy][dx] = maskcolor;
+									screenarray [dy][dx] = color;
+								}
+							}
+						}
+					}
+					/*
+					for(int cy=-radius; cy<=radius; cy++) //Draw a circle around the point, for the color.
+					{
+					   int cysq = cy*cy;
+					for(int cx=-radius; cx<=radius; cx++)
+					   {
+					       int cxsq = cx*cx;
+					       int dx = cx+px;
+					       int dy = cy+py;
+					       if((cxsq+cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0)
+					       {
+					           if (maskarray [dy][dx] == maskcolor)screenarray [dy][dx] = color;
+					       }
+					   }
+					}
+					*/
+				}
+			}
+		}
+	}
+	engine->ReleaseBitmapSurface(canvas);
+	engine->ReleaseBitmapSurface(maskcanvas);
+	engine->NotifySpriteUpdated(slot);
+	engine->NotifySpriteUpdated(maskslot);
+}
+
+
+int CreateTranslucentOverlay(int id, int spriteId, int alpha, int level, int ox, int oy, int mask = 0, int blendmode = 0) {
+	BITMAP *testspr = engine->GetSpriteGraphic(spriteId);
+	if (testspr) overlay[id].sprite = spriteId;
+	else engine->AbortGame("CreateTranslucentOverlay: Invalid spriteId.");
+	engine->ReleaseBitmapSurface(testspr);
+	overlay[id].level = MAX(0, MIN(level, 4));
+	overlay[id].trans = MAX(0, MIN(alpha, 255));
+	overlay[id].spritemask = mask;
+	overlay[id].x = ox;
+	overlay[id].y = oy;
+	overlay[id].enabled = true;
+	overlay[id].blendtype = blendmode;
+	return 0;
+}
+
+int DeleteTranslucentOverlay(int id) {
+	overlay[id].enabled = false;
+	overlay[id].sprite = 0;
+	overlay[id].x = 0;
+	overlay[id].y = 0;
+	overlay[id].level = 0;
+	overlay[id].trans = 0;
+	return 0;
+}
+
+int MoveTranslucentOverlay(int id, int ox, int oy) {
+	overlay[id].x = ox;
+	overlay[id].y = oy;
+	return 0;
+}
+
+int GetTranslucentOverlayX(int id) {
+	return overlay[id].x;
+}
+
+int GetTranslucentOverlayY(int id) {
+	return overlay[id].y;
+}
+
+int GetTranslucentOverlaySprite(int id) {
+	return overlay[id].sprite;
+}
+
+int GetTranslucentOverlayLevel(int id) {
+	return overlay[id].level;
+}
+
+int GetTranslucentOverlayEnabled(int id) {
+	return overlay[id].enabled;
+}
+
+int GetTranslucentOverlayAlpha(int id) {
+	return overlay[id].trans;
+}
+
+int SetTranslucentOverlayAlpha(int id, int alpha) {
+	if (alpha >= 0 && alpha < 256)
+		overlay[id].trans = alpha;
+	else
+		engine->AbortGame("CreateTranslucentOverlay: Invalid alpha selected.");
+	return 0;
+}
+
+int SetTranslucentOverlayEnabled(int id, int toggle) {
+	if (toggle > 0)
+		overlay[id].enabled = true;
+	else
+		overlay[id].enabled = false;
+	return 0;
+}
+
+void SetCharacterReflected(int id, int refl) {
+	if (refl > 0) Reflection.Characters[id].reflect = 1;
+	else Reflection.Characters[id].reflect = 0;
+}
+
+void SetObjectReflected(int id, int refl) {
+	if (refl > 0)
+		Reflection.Objects[id].reflect = 1;
+	else
+		Reflection.Objects[id].reflect = 0;
+}
+
+int GetCharacterReflected(int id) {
+	return Reflection.Characters[id].reflect;
+}
+
+int GetObjectReflected(int id) {
+	return Reflection.Objects[id].reflect;
+}
+
+void ReplaceCharacterReflectionView(int id, int view) {
+	Reflection.Characters[id].replaceview = view - 1;
+}
+
+void SetObjectReflectionIgnoreScaling(int id, int wb) {
+	if (wb) Reflection.Objects[id].ignorescaling = 1;
+	else    Reflection.Objects[id].ignorescaling = 0;
+}
+
+int DrawReflections(int id, int charobj = 0) {
+	int32 screenw, screenh;
+	int32 bgw, bgh;
+	engine->GetScreenDimensions(&screenw, &screenh, nullptr);
+	BITMAP *bgmask = engine->GetBackgroundScene(1);
+	if (bgmask == nullptr) return 1;
+	//BITMAP *virtsc = engine->GetVirtualScreen();
+	BITMAP *walkbehind = engine->GetRoomMask(MASK_WALKBEHIND);
+	//if (!virtsc) engine->AbortGame ("Can't load virtual screen.");
+	if (!walkbehind) engine->AbortGame("DrawRelfections: Can't load Walkbehind into memory.");
+	engine->GetBitmapDimensions(walkbehind, &bgw, &bgh, nullptr);
+	if (!bgmask) engine->AbortGame("DrawReflections: Can't load reflection mask.");
+	//unsigned char **charbuffer = engine->GetRawBitmapSurface (virtsc);
+	unsigned char **wbarray = engine->GetRawBitmapSurface(walkbehind);
+	unsigned char **maskarray = engine->GetRawBitmapSurface(bgmask);
+	//Initialize stuff
+	BITMAP *charsprite = nullptr;
+	BITMAP *charsprite2 = nullptr;
+	AGSCharacter *currchar = nullptr;
+	AGSObject *currobj;
+	int cox = 0, coy = 0, coz = 0;
+	int scale = 0;
+	//Get character, and their sprite.
+	if (charobj == 0) {
+		currchar = engine->GetCharacter(id);
+		/*int view = 0;
+		if (Reflection.Characters[id].replaceview == 0) view = currchar->view + 1;
+		else view = Reflection.Characters[id].replaceview;
+		*/
+		AGSViewFrame *vf = engine->GetViewFrame(currchar->view + 1, currchar->loop, currchar->frame);
+		charsprite = engine->GetSpriteGraphic(vf->pic);
+		long scaling = currchar->flags & CHF_NOSCALING;
+		if (!scaling)scale = engine->GetAreaScaling(currchar->x, currchar->y);
+		else scale = 100;
+		cox = currchar->x;
+		coy = currchar->y;
+		coz = currchar->z;
+	} else if (charobj == 1) {
+		currobj = engine->GetObject(id);
+
+		charsprite = engine->GetSpriteGraphic(currobj->num);
+		if (Reflection.Objects[id].ignorescaling) scale = 100;
+		else scale = engine->GetAreaScaling(currobj->x, currobj->y);
+		cox = currobj->x;
+		if (currobj->baseline < 0) coy = currobj->y;
+		else coy = currobj->baseline;
+		coz = 0;
+	}
+	bool scaled = false;
+	int32 w, h;
+	engine->GetBitmapDimensions(charsprite, &w, &h, nullptr);
+	if (scale != 100) {
+		unsigned char **orig = engine->GetRawBitmapSurface(charsprite);
+		int h1, h2, w1, w2;
+		double fw2, fh2;
+		h1 = h;
+		w1 = w;
+		fh2 = h1 * ((double)scale / 100.0);
+		fw2 = w1 * ((double)scale / 100.0);
+		h2 = static_cast<int>(fh2);
+		w2 = static_cast<int>(fw2);
+		charsprite2 = engine->CreateBlankBitmap(w2, h2, 8);
+		unsigned char **resized = engine->GetRawBitmapSurface(charsprite2);
+		int x_ratio = (int)((w1 << 16) / w2) + 1;
+		int y_ratio = (int)((h1 << 16) / h2) + 1;
+		int x2, y2 ;
+		for (int i = 0; i < h2; i++) {
+			for (int j = 0; j < w2; j++) {
+				x2 = ((j * x_ratio) >> 16) ;
+				y2 = ((i * y_ratio) >> 16) ;
+				resized [i][j] = orig [y2][x2];
+			}
+		}
+		engine->ReleaseBitmapSurface(charsprite2);
+		scaled = true;
+		w = w2;
+		h = h2;
+	} else {
+		charsprite2 = charsprite;
+	}
+	int transamount = 0;
+	unsigned char **spritearray = engine->GetRawBitmapSurface(charsprite2);
+	unsigned char **charbuffer = engine->GetRawBitmapSurface(rcolormap);
+	unsigned char **alphaarray = engine->GetRawBitmapSurface(ralphamap);
+	int i = h - 1, j = 0;
+	int32 ox = cox;
+	if (charobj == 0) ox = ox - (w / 2);
+	int32 oy = coy + coz - 1;
+	engine->RoomToViewport(&ox, &oy);
+	int yoffset = 0;
+	int translevel = 7;
+	//bool dither = false;
+	//bool dodither = false;
+	int counter = 0;
+	int rowcount = 101 - (int)(50.0 * ((double)(scale) / 100.0));
+	int delay = screenh / rowcount;
+	int *obst;
+	int flipped = 0;
+	if (charobj == 0) {
+		int (*sfGetGameParameter)(int, int, int, int);
+		sfGetGameParameter = ((int(*)(int, int, int, int)) engine->GetScriptFunctionAddress("GetGameParameter"));
+		flipped = sfGetGameParameter(13, currchar->view + 1, currchar->loop, currchar->frame);
+	} else flipped = 0;
+	obst = new int [w];
+	for (int k = 0; k < w; k++) {
+		obst[k] = 0;
+	}
+	while (i > 0) {
+		//if ((counter == delay/2-1 || counter == delay-1) && yoffset < 36) dodither = (!dodither);
+		if (counter == delay) {
+			counter = 0;
+			if (translevel > 0) translevel--;
+		} else counter++;
+		yoffset++;
+		while (j < w) {
+			int xoffset;
+			if (flipped == 1) xoffset = w - j - 1;
+			else xoffset = j;
+			int32 rx = ox + xoffset, ry = oy + yoffset;
+			int wbb = 0;
+			engine->ViewportToRoom(&rx, &ry);
+			if (ry > 0 && ry < bgh && rx > 0 && rx < bgw) {
+				if (wbarray [ry][rx] > 0) {
+					wbb = engine->GetWalkbehindBaseline(wbarray[ry][rx]);
+				}
+				if (maskarray[ry][rx] == 21) obst[j] = 1;
+			}
+
+			//dither = (!dither);
+			transamount = 32 * translevel;
+			if (spritearray [i][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.
+				if (wbb < ry && obst[j] == 0 && (oy > reflectionmap[(ox + xoffset) + (screenw * (oy + yoffset))])) {
+					//charbuffer[oy+yoffset][ox+xoffset] = MixColorAlpha (spritearray [i][j],charbuffer[oy+yoffset][ox+xoffset],transamount);
+					charbuffer [oy + yoffset][ox + xoffset] = spritearray [i][j];
+					alphaarray [oy + yoffset][ox + xoffset] = transamount;
+					reflectionmap[(ox + xoffset) + (screenw * (oy + yoffset))] = oy;
+				}
+			}
+			j++;
+		}
+		//if (w % 2 == 0) dither = (!dither);
+		i--;
+		j = 0;
+	}
+
+	delete [] obst;
+	if (scaled == true)engine->FreeBitmap(charsprite2);
+	engine->ReleaseBitmapSurface(charsprite);
+	//engine->ReleaseBitmapSurface (virtsc);
+	//engine->ReleaseBitmapSurface (clutspr);
+	engine->ReleaseBitmapSurface(bgmask);
+	engine->ReleaseBitmapSurface(walkbehind);
+	engine->ReleaseBitmapSurface(rcolormap);
+	engine->ReleaseBitmapSurface(ralphamap);
+	engine->MarkRegionDirty(ox, oy, ox + w, oy + h);
+	return 0;
+}
+
+
+int DrawTransSprite(int spriteId, int bg, int translevel, int mask = 0, int blendmode = 0, int use_objpal = 0) {
+	BITMAP *maskspr = nullptr;
+	unsigned char **maskarray = nullptr;
+	if (mask > 0) maskspr = engine->GetSpriteGraphic(mask);
+	if (!maskspr && mask > 0) {
+		char maskerr [100];
+		snprintf(maskerr, 100, "DrawTransSprite: Can't load mask from slot %d.", mask);
+		engine->AbortGame(maskerr);
+	}
+	// Get a reference to the screen we'll draw onto
+	BITMAP *bgspr = engine->GetSpriteGraphic(bg);
+	//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
+	BITMAP *spritespr = engine->GetSpriteGraphic(spriteId);
+	if (!bgspr) engine->AbortGame("DrawTransSprite: Can't load background");
+	//if (!clutspr) engine->AbortGame ("Can't load CLUT spriteId into memory.");
+	if (!spritespr) engine->AbortGame("DrawTransSprite: Can't load overlay spriteId into memory.");
+	// Get its surface
+	int32 sprw, sprh, coldepth;
+	int32 bgw, bgh;
+	engine->GetBitmapDimensions(bgspr, &bgw, &bgh, &coldepth);
+	engine->GetBitmapDimensions(spritespr, &sprw, &sprh, &coldepth);
+
+	unsigned char **bgarray = engine->GetRawBitmapSurface(bgspr);
+	//unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
+	unsigned char **spritearray = engine->GetRawBitmapSurface(spritespr);
+	if (mask > 0) maskarray = engine->GetRawBitmapSurface(maskspr);
+	int tloffset = 255 - translevel;
+	int x = 0;
+	int y = 0;
+	//int transamount = 256 * translevel; //old
+	while (y < sprh) {
+		while (x < sprw) {
+			if (spritearray [y][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.
+				if (mask > 0) {
+					translevel = MAX(maskarray [y][x] - tloffset, 0);
+				}
+				//spritearray[y][x] = cycle_remap[clutarray [cycle_remap[bgarray[y][x]]+transamount][cycle_remap[spritearray [y][x]]]]; //old
+				if (blendmode == 0) spritearray[y][x] = Mix::MixColorAlpha(spritearray [y][x], bgarray[y][x], translevel, use_objpal);
+				else if (blendmode == 1) spritearray[y][x] = Mix::MixColorAdditive(spritearray [y][x], bgarray[y][x], translevel, use_objpal);
+			}
+			x++;
+		}
+		x = 0;
+		y++;
+	}
+
+	// Release the screen so that the engine can continue
+	engine->ReleaseBitmapSurface(bgspr);
+	//engine->ReleaseBitmapSurface (clutspr);
+	engine->ReleaseBitmapSurface(spritespr);
+	engine->NotifySpriteUpdated(spriteId);
+	return 0;
+}
+
+int DrawTranslucentOverlay(int spriteId, int translevel, int ox, int oy, int mask = 0, int blendmode = 0) {
+	if (translevel == 0) return 0;
+	BITMAP *maskspr = nullptr;
+	unsigned char **maskarray = nullptr;
+	// Get a reference to the screen we'll draw onto
+	BITMAP *virtsc = engine->GetVirtualScreen();
+	//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
+	BITMAP *spritespr = engine->GetSpriteGraphic(spriteId);
+	if (mask > 0) maskspr = engine->GetSpriteGraphic(mask);
+	if (!virtsc) engine->AbortGame("DrawTranslucentOverlay: Can't load virtual screen.");
+	//if (!clutspr) engine->AbortGame ("Can't load CLUT spriteId into memory.");
+	if (!spritespr) engine->AbortGame("DrawTranslucentOverlay: Can't load overlay spriteId into memory.");
+	// Get its surface
+	int32 sprw, sprh, coldepth;
+	int32 screenw, screenh;
+	engine->GetScreenDimensions(&screenw, &screenh, &coldepth);
+	engine->GetBitmapDimensions(spritespr, &sprw, &sprh, &coldepth);
+	unsigned char **charbuffer = engine->GetRawBitmapSurface(virtsc);
+	unsigned char **spritearray = engine->GetRawBitmapSurface(spritespr);
+	if (mask > 0) {
+		if (!maskspr && mask > 0) {
+			char maskerr [100];
+			snprintf(maskerr, 100, "DrawTransSprite: Can't load mask from slot %d.", mask);
+			engine->AbortGame(maskerr);
+		}
+		maskarray = engine->GetRawBitmapSurface(maskspr);
+	}
+	int tloffset = 255 - translevel;
+	int x = 0;
+	int y = 0;
+	//int transamount = 256 * translevel; //old
+	while (y < sprh) {
+		while (x < sprw) {
+			if (spritearray [y][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.
+				//charbuffer[y+oy][x+ox] = cycle_remap[clutarray [cycle_remap[charbuffer[y+oy][x+ox]]+transamount][cycle_remap[spritearray [y][x]]]]; //old
+				if (mask > 0) {
+					translevel = MAX(maskarray [y][x] - tloffset, 0);
+				}
+				if (blendmode == 0) {
+					if (translevel == 255) {
+						charbuffer[y + oy][x + ox] = spritearray [y][x];
+					} else charbuffer[y + oy][x + ox] = Mix::MixColorAlpha(spritearray [y][x], charbuffer[y + oy][x + ox], translevel);
+				} else if (blendmode == 1) charbuffer[y + oy][x + ox] = Mix::MixColorAdditive(spritearray [y][x], charbuffer[y + oy][x + ox], translevel);
+			}
+			x++;
+		}
+		x = 0;
+		y++;
+	}
+
+	// Release the screen so that the engine can continue
+	long dirtywidth = ox + sprw;
+	if (dirtywidth > screenw) dirtywidth = screenw - 1;
+	long dirtyheight = oy + sprh;
+	if (dirtyheight > screenh) dirtywidth = screenh - 1;
+	engine->ReleaseBitmapSurface(virtsc);
+	//engine->ReleaseBitmapSurface (clutspr);
+	engine->ReleaseBitmapSurface(spritespr);
+	if (mask > 0) engine->ReleaseBitmapSurface(maskspr);
+	engine->MarkRegionDirty(ox, oy, dirtywidth, dirtyheight);
+
+	return 0;
+}
+
+/*------------------------------------------------------------------*/
+
+AGSPalRender::AGSPalRender() : DLL() {
+	DLL_METHOD(AGS_GetPluginName);
+	DLL_METHOD(AGS_EngineStartup);
+	DLL_METHOD(AGS_EngineShutdown);
+	DLL_METHOD(AGS_EngineOnEvent);
+}
+
+const char *AGSPalRender::AGS_GetPluginName() {
+	return "PALgorithms Translucent Overlay Renderer";
+}
+
+void AGSPalRender::AGS_EngineStartup(IAGSEngine *lpEngine) {
+	engine = lpEngine;
+
+	// Make sure it's got the version with the features we need
+	if (engine->version < 3) {
+		engine->AbortGame("Engine interface is too old, need newer version of AGS.");
+	}
+	engine->RegisterScriptFunction("PALInternal::LoadCLUT^1", (void *)LoadCLUT);
+	engine->RegisterScriptFunction("PALInternal::CycleRemap^2", (void *)CycleRemap);
+	engine->RegisterScriptFunction("PALInternal::GetColor565^3", (void *)GetColor565);
+	engine->RegisterScriptFunction("PALInternal::GetLuminosityFromPalette^1", (void *)GetLuminosityFromPalette);
+	engine->RegisterScriptFunction("PALInternal::FastSin^1", (void *)AGSFastSin);
+	engine->RegisterScriptFunction("PALInternal::FastCos^1", (void *)AGSFastCos);
+	engine->RegisterScriptFunction("PALInternal::FastRoot^1", (void *)root);
+	engine->RegisterScriptFunction("PALInternal::GetRemappedSlot^1", (void *)GetRemappedSlot);
+	engine->RegisterScriptFunction("PALInternal::ResetRemapping^0", (void *)ResetRemapping);
+	engine->RegisterScriptFunction("PALInternal::GetModifiedBackgroundImage", (void *)GetModifiedBackgroundImage);
+	engine->RegisterScriptFunction("PALInternal::WriteObjectivePalette^4", (void *)WriteObjectivePalette);
+	engine->RegisterScriptFunction("PALInternal::ReadObjectivePaletteR^1", (void *)ReadObjectivePaletteR);
+	engine->RegisterScriptFunction("PALInternal::ReadObjectivePaletteB^1", (void *)ReadObjectivePaletteB);
+	engine->RegisterScriptFunction("PALInternal::ReadObjectivePaletteG^1", (void *)ReadObjectivePaletteG);
+
+	engine->RegisterScriptFunction("Raycast::Render^1", (void *)Raycast_Render);
+	engine->RegisterScriptFunction("Raycast::LoadMap^4", (void *)LoadMap);
+	engine->RegisterScriptFunction("Raycast::Initialize", (void *)Init_Raycaster);
+	engine->RegisterScriptFunction("Raycast::MakeTextures^1", (void *)MakeTextures);
+	engine->RegisterScriptFunction("Raycast::MoveForward^0", (void *)MoveForward);
+	engine->RegisterScriptFunction("Raycast::MoveBackward^0", (void *)MoveBackward);
+	engine->RegisterScriptFunction("Raycast::RotateLeft^0", (void *)RotateLeft);
+	engine->RegisterScriptFunction("Raycast::RotateRight^0", (void *)RotateRight);
+	engine->RegisterScriptFunction("Raycast::SetCameraPosition^2", (void *)Ray_SetPlayerPosition);
+	engine->RegisterScriptFunction("Raycast::GetCameraX^0", (void *)Ray_GetPlayerX);
+	engine->RegisterScriptFunction("Raycast::GetCameraY^0", (void *)Ray_GetPlayerY);
+	engine->RegisterScriptFunction("Raycast::GetCameraAngle^0", (void *)Ray_GetPlayerAngle);
+	engine->RegisterScriptFunction("Raycast::SetCameraAngle^1", (void *)Ray_SetPlayerAngle);
+	engine->RegisterScriptFunction("Raycast::InitSprite^9", (void *)Ray_InitSprite);
+	engine->RegisterScriptFunction("Raycast::UnloadEngine^0", (void *)QuitCleanup);
+	engine->RegisterScriptFunction("Raycast::GetHotspotAtXY^2", (void *)Ray_GetHotspotAt);
+	engine->RegisterScriptFunction("Raycast::GetObjectAtXY^2", (void *)Ray_GetObjectAt);
+	engine->RegisterScriptFunction("Raycast::SetSpriteInteractObj^2", (void *)Ray_SetSpriteInteractObj);
+	engine->RegisterScriptFunction("Raycast::GetSpriteInteractObj^1", (void *)Ray_GetSpriteInteractObj);
+	engine->RegisterScriptFunction("Raycast::SetSpritePosition^3", (void *)Ray_SetSpritePosition);
+	engine->RegisterScriptFunction("Raycast::SetSpriteVertOffset^2", (void *)Ray_SetSpriteVertOffset);
+	engine->RegisterScriptFunction("Raycast::GetSpriteVertOffset^1", (void *)Ray_GetSpriteVertOffset);
+	engine->RegisterScriptFunction("Raycast::GetSpriteX^1", (void *)Ray_GetSpriteX);
+	engine->RegisterScriptFunction("Raycast::GetSpriteY^1", (void *)Ray_GetSpriteY);
+	engine->RegisterScriptFunction("Raycast::SetWallHotspot^2", (void *)Ray_SetWallHotspot);
+	engine->RegisterScriptFunction("Raycast::SetWallTextures^5", (void *)Ray_SetWallTextures);
+	engine->RegisterScriptFunction("Raycast::SetWallSolid^5", (void *)Ray_SetWallSolid);
+	engine->RegisterScriptFunction("Raycast::SetWallIgnoreLighting^5", (void *)Ray_SetWallIgnoreLighting);
+	engine->RegisterScriptFunction("Raycast::SetWallAlpha^5", (void *)Ray_SetWallAlpha);
+	engine->RegisterScriptFunction("Raycast::SetWallBlendType^5", (void *)Ray_SetWallBlendType);
+	engine->RegisterScriptFunction("Raycast::GetMoveSpeed^0", (void *)Ray_GetMoveSpeed);
+	engine->RegisterScriptFunction("Raycast::SetMoveSpeed^1", (void *)Ray_SetMoveSpeed);
+	engine->RegisterScriptFunction("Raycast::GetRotSpeed^0", (void *)Ray_GetRotSpeed);
+	engine->RegisterScriptFunction("Raycast::SetRotSpeed^1", (void *)Ray_SetRotSpeed);
+	engine->RegisterScriptFunction("Raycast::GetWallAt^2", (void *)Ray_GetWallAt);
+	engine->RegisterScriptFunction("Raycast::GetLightAt^2", (void *)Ray_GetLightAt);
+	engine->RegisterScriptFunction("Raycast::SetLightAt^3", (void *)Ray_SetLightAt);
+	engine->RegisterScriptFunction("Raycast::SetWallAt^3", (void *)Ray_SetWallAt);
+	engine->RegisterScriptFunction("Raycast::SetPlaneY^1", (void *)Ray_SetPlaneY);
+	engine->RegisterScriptFunction("Raycast::GetDistanceAt^2", (void *)Ray_GetDistanceAt);
+	engine->RegisterScriptFunction("Raycast::GetSpriteAngle^1", (void *)Ray_GetSpriteAngle);
+	engine->RegisterScriptFunction("Raycast::SetSpriteAngle^2", (void *)Ray_SetSpriteAngle);
+	engine->RegisterScriptFunction("Raycast::SetSpriteView^2", (void *)Ray_SetSpriteView);
+	engine->RegisterScriptFunction("Raycast::GetSpriteView^1", (void *)Ray_GetSpriteView);
+	engine->RegisterScriptFunction("Raycast::SetSpriteFrame^2", (void *)Ray_SetSpriteFrame);
+	engine->RegisterScriptFunction("Raycast::GetSpriteFrame^1", (void *)Ray_GetSpriteFrame);
+	engine->RegisterScriptFunction("Raycast::SetSpritePic^2", (void *)Ray_SetSpritePic);
+	engine->RegisterScriptFunction("Raycast::GetSpritePic^1", (void *)Ray_GetSpritePic);
+	engine->RegisterScriptFunction("Raycast::SetSkyBox^1", (void *)Ray_SetSkyBox);
+	engine->RegisterScriptFunction("Raycast::SetSpriteAlpha^2", (void *)Ray_SetSpriteAlpha);
+	engine->RegisterScriptFunction("Raycast::GetSpriteAlpha^1", (void *)Ray_GetSpriteAlpha);
+	engine->RegisterScriptFunction("Raycast::GetSkyBox^1", (void *)Ray_GetSkyBox);
+	engine->RegisterScriptFunction("Raycast::SetAmbientLight^1", (void *)Ray_SetAmbientLight);
+	engine->RegisterScriptFunction("Raycast::SetAmbientColor^2", (void *)Ray_SetAmbientColor);
+	engine->RegisterScriptFunction("Raycast::GetAmbientLight^0", (void *)Ray_GetAmbientLight);
+	engine->RegisterScriptFunction("Raycast::GetAmbientWeight^0", (void *)Ray_GetAmbientWeight);
+	engine->RegisterScriptFunction("Raycast::GetTileX_At^2", (void *)Ray_GetTileX_At);
+	engine->RegisterScriptFunction("Raycast::GetTileY_At^2", (void *)Ray_GetTileY_At);
+	engine->RegisterScriptFunction("Raycast::DrawTile^2", (void *)Ray_DrawTile);
+	engine->RegisterScriptFunction("Raycast::DrawOntoTile^2", (void *)Ray_DrawOntoTile);
+	engine->RegisterScriptFunction("Raycast::SetNoClip^1", (void *)Ray_SetNoClip);
+	engine->RegisterScriptFunction("Raycast::GetNoClip^0", (void *)Ray_GetNoClip);
+	engine->RegisterScriptFunction("Raycast::GetSpriteScaleX^1", (void *)Ray_GetSpriteScaleX);
+	engine->RegisterScriptFunction("Raycast::SetSpriteScaleX^2", (void *)Ray_SetSpriteScaleX);
+	engine->RegisterScriptFunction("Raycast::GetSpriteScaleY^1", (void *)Ray_GetSpriteScaleY);
+	engine->RegisterScriptFunction("Raycast::SetSpriteScaleY^2", (void *)Ray_SetSpriteScaleY);
+	engine->RegisterScriptFunction("Raycast::GetSpriteBlendType^1", (void *)Ray_GetSpriteBlendType);
+	engine->RegisterScriptFunction("Raycast::SetSpriteBlendType^2", (void *)Ray_SetSpriteBlendType);
+
+
+	engine->RegisterScriptFunction("Raycast::SetFloorAt^3", (void *)Ray_SetFloorAt);
+	engine->RegisterScriptFunction("Raycast::SetCeilingAt^3", (void *)Ray_SetCeilingAt);
+	engine->RegisterScriptFunction("Raycast::GetCeilingAt^2", (void *)Ray_GetCeilingAt);
+	engine->RegisterScriptFunction("Raycast::GetFloorAt^2", (void *)Ray_GetFloorAt);
+	engine->RegisterScriptFunction("Raycast::GetLightingAt^2", (void *)Ray_GetLightingAt);
+	engine->RegisterScriptFunction("Raycast::SetLightingAt^3", (void *)Ray_SetLightingAt);
+	engine->RegisterScriptFunction("Raycast::GetWallHotspot^1", (void *)Ray_GetWallHotspot);
+	engine->RegisterScriptFunction("Raycast::GetWallTexture^2", (void *)Ray_GetWallTexture);
+	engine->RegisterScriptFunction("Raycast::GetWallSolid^2", (void *)Ray_GetWallSolid);
+	engine->RegisterScriptFunction("Raycast::GetWallIgnoreLighting^2", (void *)Ray_GetWallIgnoreLighting);
+	engine->RegisterScriptFunction("Raycast::GetWallAlpha^2", (void *)Ray_GetWallAlpha);
+	engine->RegisterScriptFunction("Raycast::GetWallBlendType^2", (void *)Ray_GetWallBlendType);
+	engine->RegisterScriptFunction("Raycast::SelectTile^3", (void *)Ray_SelectTile);
+	engine->RegisterScriptFunction("Raycast::HasSeenTile^2", (void *)Ray_HasSeenTile);
+
+	engine->RegisterScriptFunction("LensDistort::SetPos^2", (void *)SetLensPos);
+	engine->RegisterScriptFunction("LensDistort::GetX^0", (void *)GetLensX);
+	engine->RegisterScriptFunction("LensDistort::GetY^0", (void *)GetLensY);
+	engine->RegisterScriptFunction("LensDistort::Set^1", (void *)SetLensDrawn);
+	engine->RegisterScriptFunction("LensDistort::IsDrawn^0", (void *)GetLensDrawn);
+	engine->RegisterScriptFunction("LensDistort::SetOffsetClamp^1", (void *)SetLensOffsetClamp);
+	engine->RegisterScriptFunction("LensDistort::GetOffsetClamp^0", (void *)GetLensOffsetClamp);
+	engine->RegisterScriptFunction("LensDistort::GetLevel^0", (void *)GetLensLevel);
+	engine->RegisterScriptFunction("LensDistort::SetLevel^1", (void *)GetLensLevel);
+	engine->RegisterScriptFunction("LensDistort::Initialize^6", (void *)LensInitialize);
+
+	engine->RegisterScriptFunction("Translucence::CreateOverlay^8", (void *)CreateTranslucentOverlay);
+	engine->RegisterScriptFunction("Translucence::DeleteOverlay^1", (void *)DeleteTranslucentOverlay);
+	engine->RegisterScriptFunction("Translucence::Move^3", (void *)MoveTranslucentOverlay);
+	engine->RegisterScriptFunction("Translucence::GetOverlayX^1", (void *)GetTranslucentOverlayX);
+	engine->RegisterScriptFunction("Translucence::GetOverlayY^1", (void *)GetTranslucentOverlayY);
+	engine->RegisterScriptFunction("Translucence::GetOverlaySprite^1", (void *)GetTranslucentOverlaySprite);
+	engine->RegisterScriptFunction("Translucence::GetOverlayLevel^1", (void *)GetTranslucentOverlayLevel);
+	engine->RegisterScriptFunction("Translucence::GetOverlayEnabled^1", (void *)GetTranslucentOverlayEnabled);
+	engine->RegisterScriptFunction("Translucence::GetOverlayAlpha^1", (void *)GetTranslucentOverlayAlpha);
+	engine->RegisterScriptFunction("Translucence::SetOverlayAlpha^2", (void *)SetTranslucentOverlayAlpha);
+	engine->RegisterScriptFunction("Translucence::SetOverlayEnabled^2", (void *)SetTranslucentOverlayEnabled);
+	engine->RegisterScriptFunction("Translucence::DrawTransSprite^6", (void *)DrawTransSprite);
+
+	engine->RegisterScriptFunction("Starfield::GetOverscan^0", (void *)GetStarfieldOverscan);
+	engine->RegisterScriptFunction("Starfield::SetOverscan^1", (void *)SetStarfieldOverscan);
+	engine->RegisterScriptFunction("Starfield::GetOriginX^0", (void *)GetStarfieldOriginX);
+	engine->RegisterScriptFunction("Starfield::GetOriginY^0", (void *)GetStarfieldOriginY);
+	engine->RegisterScriptFunction("Starfield::SetDepthMultiplier^1", (void *)SetStarfieldDepthMultiplier);
+	engine->RegisterScriptFunction("Starfield::GetDepthMultiplier^0", (void *)GetStarfieldDepthMultiplier);
+	engine->RegisterScriptFunction("Starfield::GetMaxStars^0", (void *)GetStarfieldMaxStars);
+	engine->RegisterScriptFunction("Starfield::SetStarSpriteScaleBoost^1", (void *)SetStarSpriteScaleBoost);
+	engine->RegisterScriptFunction("Starfield::GetStarSpriteScaleBoost^0", (void *)GetStarSpriteScaleBoost);
+	engine->RegisterScriptFunction("Starfield::SetStarMaxRadius^2", (void *)SetStarMaxRadius);
+	engine->RegisterScriptFunction("Starfield::GetStarMaxRadius^0", (void *)GetStarMaxRadius);
+	engine->RegisterScriptFunction("Starfield::GetStarX^1", (void *)GetStarX);
+	engine->RegisterScriptFunction("Starfield::GetStarY^1", (void *)GetStarY);
+	engine->RegisterScriptFunction("Starfield::GetStarZ^1", (void *)GetStarZ);
+	engine->RegisterScriptFunction("Starfield::SetStarPosition^4", (void *)SetStarPosition);
+	engine->RegisterScriptFunction("Starfield::RotateStar^4", (void *)RotateStar);
+	engine->RegisterScriptFunction("Starfield::SetStarColor^2", (void *)SetStarColor);
+	engine->RegisterScriptFunction("Starfield::GetStarColor^1", (void *)GetStarColor);
+	engine->RegisterScriptFunction("Starfield::SetStarSprite^2", (void *)SetStarSprite);
+	engine->RegisterScriptFunction("Starfield::GetStarSprite^1", (void *)GetStarSprite);
+	engine->RegisterScriptFunction("Starfield::SetStarSpriteRange^3", (void *)SetStarSpriteRange);
+	engine->RegisterScriptFunction("Starfield::Initialize^2", (void *)InitializeStars);
+	engine->RegisterScriptFunction("Starfield::Iterate^1", (void *)IterateStars);
+	engine->RegisterScriptFunction("Starfield::Draw^2", (void *)DrawStars);
+	engine->RegisterScriptFunction("Starfield::SetOriginPoint^2", (void *)SetStarsOriginPoint);
+
+	engine->RegisterScriptFunction("Plasma::DoFire^8", (void *)DoFire);
+	engine->RegisterScriptFunction("Plasma::SetPlasmaType^5", (void *)SetPlasmaType);
+	engine->RegisterScriptFunction("Plasma::ResetPlasmaSettings^0", (void *)ResetPlasmaSettings);
+	engine->RegisterScriptFunction("Plasma::DrawPlasma^3", (void *)DrawPlasma);
+	engine->RegisterScriptFunction("Plasma::SetRootType^1", (void *)SetPlasmaRootType);
+	engine->RegisterScriptFunction("Plasma::GetRootType^0", (void *)GetPlasmaRootType);
+
+	engine->RegisterScriptFunction("Reflections::Set^1", (void *)SetReflections);
+	engine->RegisterScriptFunction("Reflections::IsReflecting^0", (void *)IsReflectionsOn);
+	engine->RegisterScriptFunction("Reflections::SetCharacterReflected^2", (void *)SetCharacterReflected);
+	engine->RegisterScriptFunction("Reflections::GetCharacterReflected^1", (void *)GetCharacterReflected);
+	engine->RegisterScriptFunction("Reflections::SetObjectReflected^2", (void *)SetObjectReflected);
+	engine->RegisterScriptFunction("Reflections::GetObjectReflected^1", (void *)GetObjectReflected);
+	engine->RegisterScriptFunction("Reflections::ReplaceCharacterReflectionView^2", (void *)ReplaceCharacterReflectionView);
+	engine->RegisterScriptFunction("Reflections::SetObjectReflectionIgnoreScaling^2", (void *)SetObjectReflectionIgnoreScaling);
+	engine->RequestEventHook(AGSE_PRESCREENDRAW);
+	engine->RequestEventHook(AGSE_PREGUIDRAW);
+	engine->RequestEventHook(AGSE_POSTSCREENDRAW);
+	engine->RequestEventHook(AGSE_SAVEGAME);
+	engine->RequestEventHook(AGSE_RESTOREGAME);
+	engine->RequestEventHook(AGSE_ENTERROOM);
+	stars = new starstype [MAX_STARS];
+	Starfield.maxstars = MAX_STARS;
+	Starfield.depthmultiplier = 256;
+	Starfield.speed = 0.5;
+	Starfield.originx = 160;
+	Starfield.originy = 100;
+	Reflection.Characters = new charrefopt [engine->GetNumCharacters()]();
+	lens = new LensDistort [LENS_WIDTH * LENS_WIDTH]();
+	//PreMultiply_Alphas ();
+	plasmaroottype = 0;
+	Make_Sin_Lut();
+	Init_Raycaster();
+}
+
+void AGSPalRender::AGS_EngineShutdown() {
+	// no work to do here - but if we had created any dynamic sprites,
+	// we should delete them here
+	delete[] Reflection.Characters;
+	delete[] Reflection.Objects;
+	//QuitCleanup();
+}
+
+NumberPtr AGSPalRender::AGS_EngineOnEvent(int event, NumberPtr data) {
+	if (event == AGSE_PRESCREENDRAW && clutslot > 0) {
+		if (drawreflections) {
+			int32 sh, sw = 0;
+			engine->GetScreenDimensions(&sw, &sh, nullptr);
+			reflectionmap = new long[sw * sh]();
+			rcolormap = engine->CreateBlankBitmap(sw, sh, 8);
+			ralphamap = engine->CreateBlankBitmap(sw, sh, 8);
+			for (int i = 0; i < engine->GetNumCharacters(); i++) {
+				if (Reflection.Characters[i].reflect == 0) continue;
+				AGSCharacter *tempchar = engine->GetCharacter(i);
+				if (tempchar->room != engine->GetCurrentRoom()) continue;  //if character isn't even in the room, go to next iteration.
+				int32 vx = tempchar->x;
+				int32 vy = tempchar->y;
+				engine->RoomToViewport(&vx, &vy);
+				AGSViewFrame *vf = engine->GetViewFrame(tempchar->view + 1, tempchar->loop, tempchar->frame);
+				int w = engine->GetSpriteWidth(vf->pic);
+				int h = engine->GetSpriteHeight(vf->pic);
+				vx = vx - (w / 2);
+				int32 vxmax = vx + w;
+				int32 vymax = vy + h;
+				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
+				DrawReflections(i, 0);
+			}
+			for (int i = 0; i < engine->GetNumObjects(); i++) {
+				if (Reflection.Objects[i].reflect == 0) continue;
+				AGSObject *tempobj = engine->GetObject(i);
+				if (!tempobj->on) continue;
+				int32 vx = tempobj->x;
+				int32 vy = tempobj->baseline - tempobj->y;
+				engine->RoomToViewport(&vx, &vy);
+				int32 w = engine->GetSpriteWidth(tempobj->num);
+				int32 h = engine->GetSpriteHeight(tempobj->num);
+				int32 vxmax = vx + w;
+				int32 vymax = vy + h;
+				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
+				DrawReflections(i, 1);
+			}
+			BITMAP *virtsc = engine->GetVirtualScreen();
+			unsigned char **screenbuffer = engine->GetRawBitmapSurface(virtsc);
+			unsigned char **colorbuffer = engine->GetRawBitmapSurface(rcolormap);
+			unsigned char **alphabuffer = engine->GetRawBitmapSurface(ralphamap);
+			for (int y = 0; y < sh; y++)
+				for (int x = 0; x < sw; x++)
+					screenbuffer[y][x] = Mix::MixColorAlpha(colorbuffer[y][x], screenbuffer[y][x], alphabuffer[y][x]);
+			engine->ReleaseBitmapSurface(rcolormap);
+			engine->ReleaseBitmapSurface(ralphamap);
+			engine->ReleaseBitmapSurface(virtsc);
+			engine->FreeBitmap(rcolormap);
+			engine->FreeBitmap(ralphamap);
+			delete [] reflectionmap;
+		}
+		int i = 0;
+		if (LensOption.draw == 1 && LensOption.level == 0) DrawLens(LensOption.x, LensOption.y);
+		while (i < MAX_OVERLAYS) {
+			if (overlay[i].enabled && overlay[i].level == 0) {
+				DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
+			}
+			i++;
+		}
+		if (LensOption.draw == 1 && LensOption.level == 1) DrawLens(LensOption.x, LensOption.y);
+	}
+	if (event == AGSE_PREGUIDRAW && clutslot > 0) {
+		int i = 0;
+		if (LensOption.draw == 1 && LensOption.level == 1) DrawLens(LensOption.x, LensOption.y);
+		while (i < MAX_OVERLAYS) {
+			if (overlay[i].enabled && overlay[i].level == 1) {
+				DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
+			}
+			i++;
+		}
+		if (LensOption.draw == 1 && LensOption.level == 2) DrawLens(LensOption.x, LensOption.y);
+	}
+	if (event == AGSE_POSTSCREENDRAW && clutslot > 0) {
+		int i = 0;
+		if (LensOption.draw == 1 && LensOption.level == 3) DrawLens(LensOption.x, LensOption.y);
+		while (i < MAX_OVERLAYS) {
+			if (overlay[i].enabled && overlay[i].level == 2) {
+				DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
+			}
+			i++;
+		}
+		if (LensOption.draw == 1 && LensOption.level == 4) DrawLens(LensOption.x, LensOption.y);
+	}
+	if (event == AGSE_SAVEGAME) {
+		for (int i = 0; i < MAX_OVERLAYS; ++i) {
+			engine->FWrite(&overlay[i].sprite, sizeof(int), data);
+			engine->FWrite(&overlay[i].spritemask, sizeof(int), data);
+			engine->FWrite(&overlay[i].x, sizeof(int), data);
+			engine->FWrite(&overlay[i].y, sizeof(int), data);
+			engine->FWrite(&overlay[i].level, sizeof(int), data);
+			engine->FWrite(&overlay[i].trans, sizeof(int), data);
+			engine->FWrite(&overlay[i].blendtype, sizeof(int), data);
+			engine->FWrite(&overlay[i].enabled, sizeof(bool), data);
+		}
+		engine->FWrite(&clutslot, sizeof(int), data);
+		engine->FWrite(&drawreflections, sizeof(int), data);
+		for (int j = 0; j < 256; ++j) {
+			engine->FWrite(&cycle_remap[j], sizeof(unsigned char), data);
+		}
+		for (int j = 0; j < 256; ++j) {
+			engine->FWrite(&objectivepal[j].r, sizeof(unsigned char), data);
+			engine->FWrite(&objectivepal[j].b, sizeof(unsigned char), data);
+			engine->FWrite(&objectivepal[j].g, sizeof(unsigned char), data);
+		}
+		for (int j = 0; j < 256; ++j) {
+			engine->FWrite(&sprite[j].x, sizeof(double), data);
+			engine->FWrite(&sprite[j].y, sizeof(double), data);
+			engine->FWrite(&sprite[j].texture, sizeof(int), data);
+			engine->FWrite(&sprite[j].alpha, sizeof(unsigned char), data);
+			engine->FWrite(&sprite[j].uDivW, sizeof(double), data);
+			engine->FWrite(&sprite[j].uDivH, sizeof(double), data);
+			engine->FWrite(&sprite[j].vMove, sizeof(double), data);
+			engine->FWrite(&sprite[j].hMove, sizeof(double), data);
+			engine->FWrite(&sprite[j].objectinteract, sizeof(char), data);
+			engine->FWrite(&sprite[j].view, sizeof(int), data);
+			engine->FWrite(&sprite[j].frame, sizeof(int), data);
+			engine->FWrite(&sprite[j].angle, sizeof(int), data);
+		}
+		for (int j = 0; j < 256; ++j) {
+			for (int k = 0; k < 4; ++k) {
+				engine->FWrite(&wallData[j].texture[k], sizeof(int), data);
+				engine->FWrite(&wallData[j].solid[k], sizeof(int), data);
+				engine->FWrite(&wallData[j].ignorelighting[k], sizeof(int), data);
+				engine->FWrite(&wallData[j].alpha[k], sizeof(int), data);
+				engine->FWrite(&wallData[j].blendtype[k], sizeof(int), data);
+				engine->FWrite(&wallData[j].mask[k], sizeof(int), data);
+			}
+			engine->FWrite(&wallData[j].hotspotinteract, sizeof(char), data);
+		}
+		engine->FWrite(&raycastOn, sizeof(bool), data);
+		engine->FWrite(&heightmapOn, sizeof(bool), data);
+		engine->FWrite(&posX, sizeof(double), data);
+		engine->FWrite(&posY, sizeof(double), data);
+		engine->FWrite(&dirX, sizeof(double), data);
+		engine->FWrite(&dirY, sizeof(double), data);
+		engine->FWrite(&planeX, sizeof(double), data);
+		engine->FWrite(&planeY, sizeof(double), data);
+		engine->FWrite(&moveSpeed, sizeof(double), data);
+		engine->FWrite(&rotSpeed, sizeof(double), data);
+		if (raycastOn) { //If the raycaster is active, we have additional data to save.
+			for (int i = 0; i < mapWidth; ++i)
+				for (int j = 0; j < mapHeight; ++j) {
+					engine->FWrite(&worldMap [i][j], sizeof(unsigned char), data);
+					engine->FWrite(&lightMap [i][j], sizeof(unsigned char), data);
+					engine->FWrite(&ceilingMap [i][j], sizeof(int), data);
+					engine->FWrite(&floorMap [i][j], sizeof(int), data);
+					engine->FWrite(&heightMap [i][j], sizeof(int), data);
+				}
+		}
+		engine->FWrite(&textureSlot, sizeof(int), data);
+		engine->FWrite(&skybox, sizeof(int), data);
+		engine->FWrite(&ambientlight, sizeof(int), data);
+	}
+	if (event == AGSE_RESTOREGAME) {
+
+
+		for (int i = 0; i < MAX_OVERLAYS; ++i) {
+			engine->FRead(&overlay[i].sprite, sizeof(int), data);
+			engine->FRead(&overlay[i].spritemask, sizeof(int), data);
+			engine->FRead(&overlay[i].x, sizeof(int), data);
+			engine->FRead(&overlay[i].y, sizeof(int), data);
+			engine->FRead(&overlay[i].level, sizeof(int), data);
+			engine->FRead(&overlay[i].trans, sizeof(int), data);
+			engine->FRead(&overlay[i].blendtype, sizeof(int), data);
+			engine->FRead(&overlay[i].enabled, sizeof(bool), data);
+		}
+		engine->FRead(&clutslot, sizeof(int), data);
+		engine->FRead(&drawreflections, sizeof(int), data);
+		for (int j = 0; j < 256; ++j) {
+			engine->FRead(&cycle_remap[j], sizeof(unsigned char), data);
+		}
+		for (int j = 0; j < 256; ++j) { //Save Objective Palette, for palette mixing.
+			engine->FRead(&objectivepal[j].r, sizeof(unsigned char), data);
+			engine->FRead(&objectivepal[j].b, sizeof(unsigned char), data);
+			engine->FRead(&objectivepal[j].g, sizeof(unsigned char), data);
+		}
+		for (int j = 0; j < 256; ++j) { //Save Raycaster Sprite struct, 256 instances.
+			engine->FRead(&sprite[j].x, sizeof(double), data);
+			engine->FRead(&sprite[j].y, sizeof(double), data);
+			engine->FRead(&sprite[j].texture, sizeof(int), data);
+			engine->FRead(&sprite[j].alpha, sizeof(unsigned char), data);
+			engine->FRead(&sprite[j].uDivW, sizeof(double), data);
+			engine->FRead(&sprite[j].uDivH, sizeof(double), data);
+			engine->FRead(&sprite[j].vMove, sizeof(double), data);
+			engine->FRead(&sprite[j].hMove, sizeof(double), data);
+			engine->FRead(&sprite[j].objectinteract, sizeof(char), data);
+			engine->FRead(&sprite[j].view, sizeof(int), data);
+			engine->FRead(&sprite[j].frame, sizeof(int), data);
+			engine->FRead(&sprite[j].angle, sizeof(int), data);
+		}
+		for (int j = 0; j < 256; ++j) { //Save Raycaster wall type data.
+			for (int k = 0; k < 4; ++k) {
+				engine->FRead(&wallData[j].texture[k], sizeof(int), data);
+				engine->FRead(&wallData[j].solid[k], sizeof(int), data);
+				engine->FRead(&wallData[j].ignorelighting[k], sizeof(int), data);
+				engine->FRead(&wallData[j].alpha[k], sizeof(int), data);
+				engine->FRead(&wallData[j].blendtype[k], sizeof(int), data);
+				engine->FRead(&wallData[j].mask[k], sizeof(int), data);
+			}
+			engine->FRead(&wallData[j].hotspotinteract, sizeof(char), data);
+		}
+		//Delete worldmap data if it exists.
+		engine->FRead(&raycastOn, sizeof(bool), data);
+		engine->FRead(&heightmapOn, sizeof(bool), data);
+		engine->FRead(&posX, sizeof(double), data);
+		engine->FRead(&posY, sizeof(double), data);
+		engine->FRead(&dirX, sizeof(double), data);
+		engine->FRead(&dirY, sizeof(double), data);
+		engine->FRead(&planeX, sizeof(double), data);
+		engine->FRead(&planeY, sizeof(double), data);
+		engine->FRead(&moveSpeed, sizeof(double), data);
+		engine->FRead(&rotSpeed, sizeof(double), data);
+		if (raycastOn) { //If the raycaster is currently running, we have additional data to load.
+			for (int i = 0; i < mapWidth; ++i) {
+				for (int j = 0; j < mapHeight; ++j) {
+					engine->FRead(&worldMap [i][j], sizeof(unsigned char), data);
+					engine->FRead(&lightMap [i][j], sizeof(unsigned char), data);
+					engine->FRead(&ceilingMap [i][j], sizeof(int), data);
+					engine->FRead(&floorMap [i][j], sizeof(int), data);
+					engine->FRead(&heightMap [i][j], sizeof(int), data);
+					seenMap [i][j] = 0;
+				}
+			}
+
+			//Reinitialize all the buffers and stuff.
+
+		}
+		engine->FRead(&textureSlot, sizeof(int), data);
+		if (textureSlot) MakeTextures(textureSlot);
+		engine->FRead(&skybox, sizeof(int), data);
+		engine->FRead(&ambientlight, sizeof(int), data);
+		LoadCLUT(clutslot);
+	}
+	if (event == AGSE_ENTERROOM) {
+		ResetRemapping();
+		delete[] Reflection.Objects;
+		Reflection.Objects = new objrefopt [engine->GetNumObjects()]();
+	}
+	return 0;
+}
+
+} // namespace AGSPalRender
+} // namespace Plugins
+} // namespace AGS3
diff --git a/engines/ags/plugins/ags_pal_render/pal_render.h b/engines/ags/plugins/ags_pal_render/pal_render.h
index 1d61dab866..1ea7951138 100644
--- a/engines/ags/plugins/ags_pal_render/pal_render.h
+++ b/engines/ags/plugins/ags_pal_render/pal_render.h
@@ -1,193 +1,193 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef AGS_PLUGINS_AGS_PAL_RENDER_PAL_RENDER_H
-#define AGS_PLUGINS_AGS_PAL_RENDER_PAL_RENDER_H
-
-#include "ags/lib/allegro.h"
-#include "ags/plugins/agsplugin.h"
-#include "common/algorithm.h"
-
-namespace AGS3 {
-namespace Plugins {
-namespace AGSPalRender {
-
-#define SCRIPT_FLOAT(x) int32 __script_float##x
-#define INIT_SCRIPT_FLOAT(x) float x; memcpy(&x, &__script_float##x, sizeof(float))
-#define FLOAT_RETURN_TYPE int32
-#define RETURN_FLOAT(x) int32 __ret##x; memcpy(&__ret##x, &x, sizeof(float)); return __ret##x
-
-struct PALSTRUCT {
-	int r;
-	int b;
-	int g;
-};
-
-extern IAGSEngine *engine;
-extern unsigned char clut[65536];
-extern unsigned char cycle_remap [256];
-extern const int alphamultiply [4096];
-extern PALSTRUCT objectivepal[256];
-
-// this class exists solely to take advantage of g++'s
-// -fvisibility-inlines-hidden option, so that these
-// methods can be inlined without any trace or complaint
-class Mix {
-public:
-//unsigned char MixColorAlpha (unsigned char fg,unsigned char bg,unsigned char alpha);
-//unsigned char MixColorAdditive (unsigned char fg,unsigned char bg,unsigned char alpha);
-	static unsigned char MixColorAlpha(unsigned char fg, unsigned char bg, unsigned char alpha, int use_objpal = 0) {
-		unsigned char rfg = cycle_remap[fg]; //Automatic remapping of palette slots.
-		//unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
-		AGSColor *palette = engine->GetPalette();
-		int i = 0;
-		//int out_r = (palette[fg].r>>1) * alpha + (palette[bg].r>>1) * (255 - alpha);
-		//int out_g = palette[fg].g * alpha + palette[bg].g * (255 - alpha);
-		//int out_b = (palette[fg].b>>1) * alpha + (palette[bg].b>>1) * (255 - alpha);
-		int out_r, out_g, out_b;
-		if (use_objpal == 0) {
-			out_r = (objectivepal[rfg].r >> 1) *alpha + (palette[bg].r >> 1) *(255 - alpha);
-			out_g = objectivepal[rfg].g * alpha + palette[bg].g * (255 - alpha);
-			out_b = (objectivepal[rfg].b >> 1) *alpha + (palette[bg].b >> 1) *(255 - alpha);
-		} else {
-			out_r = (objectivepal[rfg].r >> 1) *alpha + (objectivepal[bg].r >> 1) *(255 - alpha);
-			out_g = objectivepal[rfg].g * alpha + objectivepal[bg].g * (255 - alpha);
-			out_b = (objectivepal[rfg].b >> 1) *alpha + (objectivepal[bg].b >> 1) *(255 - alpha);
-		}
-		//char ralpha = MAX(0,MIN(63,alpha>>2));
-		//unsigned char invralpha = 64-ralpha;
-		//if (ralpha > alpha) engine->AbortGame ("wtf");
-		//int out_r = alphamultiply[((palette[fg].r>>1)<<6) +ralpha] + alphamultiply[((palette[bg].r>>1)<<6) +(invralpha)];
-		//int out_g = alphamultiply[((palette[fg].g)   <<6) +ralpha] + alphamultiply[((palette[bg].g)   <<6) +(invralpha)];
-		//int out_b = alphamultiply[((palette[fg].b>>1)<<6) +ralpha] + alphamultiply[((palette[bg].b>>1)<<6) +(invralpha)];
-		out_r = (out_r + 1 + (out_r >> 8)) >> 8;
-		out_g = (out_g + 1 + (out_g >> 8)) >> 8;
-		out_b = (out_b + 1 + (out_b >> 8)) >> 8;
-		//out_r = (out_r + 1 + (out_r >> 6)) >> 6;
-		//out_g = (out_g + 1 + (out_g >> 6)) >> 6;
-		//out_b = (out_b + 1 + (out_b >> 6)) >> 6;
-		i = ((out_r << 11) | (out_g << 5) | out_b);
-		unsigned char(*clutp) = clut;
-		//unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
-		return cycle_remap[*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
-		//engine->ReleaseBitmapSurface (clutspr);
-	}
-
-	static unsigned char MixColorLightLevel(unsigned char fg, unsigned char intensity) {
-		unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
-		int i = 0;
-		//int dark_r = (((palette[fg].r>>1) * (intensity))>>8);
-		//int dark_b = (((palette[fg].b>>1) * (intensity))>>8);
-		//int dark_g = (((palette[fg].g)    * (intensity))>>8);
-		int dark_r = (((objectivepal[rfg].r >> 1) * (intensity)) >> 8);
-		int dark_b = (((objectivepal[rfg].b >> 1) * (intensity)) >> 8);
-		int dark_g = (((objectivepal[rfg].g)    * (intensity)) >> 8);
-		i = ((dark_r << 11) | (dark_g << 5) | dark_b);
-		unsigned char (*clutp) = clut;
-		return cycle_remap [*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
-	}
-
-	static unsigned char MixColorAdditive(unsigned char fg, unsigned char bg, unsigned char alpha, int use_objpal = 0) {
-		unsigned char rfg = cycle_remap[fg]; //Automatic remapping of palette slots.
-		//unsigned char rbg = cycle_remap[bg]; //Saves on typing elsewhere.
-		//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
-		//if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
-		//unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
-		AGSColor *palette = engine->GetPalette();
-		int i = 0;
-		int add_r, add_b, add_g = 0;
-		//char ralpha = MAX(0,MIN(63,alpha>>2));
-		//add_r = (((palette[fg].r>>1) * (alpha))>>8);
-		//add_b = (((palette[fg].b>>1) * (alpha))>>8);
-		//add_g = (((palette[fg].g)    * (alpha))>>8);
-		add_r = (((objectivepal[rfg].r >> 1) * (alpha)) >> 8);
-		add_b = (((objectivepal[rfg].b >> 1) * (alpha)) >> 8);
-		add_g = (((objectivepal[rfg].g)    * (alpha)) >> 8);
-		//int a_g = MAX(0,MIN(63,alpha>>2));
-		//add_r = ((alphamultiply[(palette[fg].r>>1)<<6)+ralpha])>>6);
-		//add_b = ((alphamultiply[(palette[fg].b>>1)<<6)+ralpha])>>6);
-		//add_g = ((alphamultiply[(palette[fg].g)   <<6)+ralpha])>>6);
-		//int out_r = MIN(31,(palette[bg].r>>1) + add_r);
-		//int out_g = MIN(63, palette[bg].g     + add_g);
-		//int out_b = MIN(31,(palette[bg].b>>1) + add_b);
-		int out_r, out_g, out_b;
-		if (use_objpal == 0) {
-			out_r = MIN(31, (palette[bg].r >> 1) + add_r);
-			out_g = MIN(63, palette[bg].g     + add_g);
-			out_b = MIN(31, (palette[bg].b >> 1) + add_b);
-		} else {
-			out_r = MIN(31, (objectivepal [bg].r >> 1) + add_r);
-			out_g = MIN(63, objectivepal [bg].g     + add_g);
-			out_b = MIN(31, (objectivepal [bg].b >> 1) + add_b);
-		}
-		i = ((out_r << 11) | (out_g << 5) | out_b);
-		unsigned char (*clutp) = clut;
-		unsigned char result = cycle_remap [*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
-		//unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
-		//engine->ReleaseBitmapSurface (clutspr);
-		return result;
-	}
-
-	static unsigned char MixColorMultiply(unsigned char fg, unsigned char bg, unsigned char alpha, int use_objpal = 0) {
-		unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
-		unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
-		AGSColor *palette = engine->GetPalette();
-		int i = 0;
-		int mul_r, mul_b, mul_g = 0;
-		int out_r, out_g, out_b = 0;
-		if (use_objpal == 0) {
-			mul_r = ((objectivepal[rfg].r >> 1) * (palette[rbg].r >> 1)) / 64;
-			mul_b = ((objectivepal[rfg].b >> 1) * (palette[rbg].b >> 1)) / 64;
-			mul_g = ((objectivepal[rfg].g * palette[rbg].g) / 64);
-			out_r = ((palette[rbg].r >> 1) * (63 - (alpha / 4)) + (mul_r * (alpha / 4))) / 63;
-			out_g = (palette[rbg].g * (63 - (alpha / 4)) + (mul_g * (alpha / 4))) / 63;
-			out_b = ((palette[rbg].b >> 1) * (63 - (alpha / 4)) + (mul_b * (alpha / 4))) / 63;
-		} else {
-			mul_r = ((objectivepal[rfg].r >> 1) * (objectivepal[rbg].r >> 1)) / 64;
-			mul_b = ((objectivepal[rfg].b >> 1) * (objectivepal[rbg].b >> 1)) / 64;
-			mul_g = ((objectivepal[rfg].g * objectivepal[rbg].g) / 64);
-
-			out_r = ((objectivepal[rbg].r >> 1) * (63 - (alpha / 4)) + (mul_r * (alpha / 4))) / 63;
-			out_g = (objectivepal[rbg].g * (63 - (alpha / 4)) + (mul_g * (alpha / 4))) / 63;
-			out_b = ((objectivepal[rbg].b >> 1) * (63 - (alpha / 4)) + (mul_b * (alpha / 4))) / 63;
-		}
-		i = ((out_r << 11) | (out_g << 5) | out_b);
-		unsigned char (*clutp) = clut;
-		unsigned char result = cycle_remap [*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
-		//unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
-		//engine->ReleaseBitmapSurface (clutspr);
-		return result;
-	}
-
-};
-
-unsigned char GetColor565(unsigned char r, unsigned char g, unsigned char b);
-
-unsigned short root(unsigned short x);
-float FastSin(float x);
-float FastCos(float x);
-
-} // namespace AGSPalRender
-} // namespace Plugins
-} // namespace AGS3
-
-#endif
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or(at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef AGS_PLUGINS_AGS_PAL_RENDER_PAL_RENDER_H
+#define AGS_PLUGINS_AGS_PAL_RENDER_PAL_RENDER_H
+
+#include "ags/lib/allegro.h"
+#include "ags/plugins/agsplugin.h"
+#include "common/algorithm.h"
+
+namespace AGS3 {
+namespace Plugins {
+namespace AGSPalRender {
+
+#define SCRIPT_FLOAT(x) int32 __script_float##x
+#define INIT_SCRIPT_FLOAT(x) float x; memcpy(&x, &__script_float##x, sizeof(float))
+#define FLOAT_RETURN_TYPE int32
+#define RETURN_FLOAT(x) int32 __ret##x; memcpy(&__ret##x, &x, sizeof(float)); return __ret##x
+
+struct PALSTRUCT {
+	int r;
+	int b;
+	int g;
+};
+
+extern IAGSEngine *engine;
+extern unsigned char clut[65536];
+extern unsigned char cycle_remap [256];
+extern const int alphamultiply [4096];
+extern PALSTRUCT objectivepal[256];
+
+// this class exists solely to take advantage of g++'s
+// -fvisibility-inlines-hidden option, so that these
+// methods can be inlined without any trace or complaint
+class Mix {
+public:
+//unsigned char MixColorAlpha (unsigned char fg,unsigned char bg,unsigned char alpha);
+//unsigned char MixColorAdditive (unsigned char fg,unsigned char bg,unsigned char alpha);
+	static unsigned char MixColorAlpha(unsigned char fg, unsigned char bg, unsigned char alpha, int use_objpal = 0) {
+		unsigned char rfg = cycle_remap[fg]; //Automatic remapping of palette slots.
+		//unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
+		AGSColor *palette = engine->GetPalette();
+		int i = 0;
+		//int out_r = (palette[fg].r>>1) * alpha + (palette[bg].r>>1) * (255 - alpha);
+		//int out_g = palette[fg].g * alpha + palette[bg].g * (255 - alpha);
+		//int out_b = (palette[fg].b>>1) * alpha + (palette[bg].b>>1) * (255 - alpha);
+		int out_r, out_g, out_b;
+		if (use_objpal == 0) {
+			out_r = (objectivepal[rfg].r >> 1) *alpha + (palette[bg].r >> 1) *(255 - alpha);
+			out_g = objectivepal[rfg].g * alpha + palette[bg].g * (255 - alpha);
+			out_b = (objectivepal[rfg].b >> 1) *alpha + (palette[bg].b >> 1) *(255 - alpha);
+		} else {
+			out_r = (objectivepal[rfg].r >> 1) *alpha + (objectivepal[bg].r >> 1) *(255 - alpha);
+			out_g = objectivepal[rfg].g * alpha + objectivepal[bg].g * (255 - alpha);
+			out_b = (objectivepal[rfg].b >> 1) *alpha + (objectivepal[bg].b >> 1) *(255 - alpha);
+		}
+		//char ralpha = MAX(0,MIN(63,alpha>>2));
+		//unsigned char invralpha = 64-ralpha;
+		//if (ralpha > alpha) engine->AbortGame ("wtf");
+		//int out_r = alphamultiply[((palette[fg].r>>1)<<6) +ralpha] + alphamultiply[((palette[bg].r>>1)<<6) +(invralpha)];
+		//int out_g = alphamultiply[((palette[fg].g)   <<6) +ralpha] + alphamultiply[((palette[bg].g)   <<6) +(invralpha)];
+		//int out_b = alphamultiply[((palette[fg].b>>1)<<6) +ralpha] + alphamultiply[((palette[bg].b>>1)<<6) +(invralpha)];
+		out_r = (out_r + 1 + (out_r >> 8)) >> 8;
+		out_g = (out_g + 1 + (out_g >> 8)) >> 8;
+		out_b = (out_b + 1 + (out_b >> 8)) >> 8;
+		//out_r = (out_r + 1 + (out_r >> 6)) >> 6;
+		//out_g = (out_g + 1 + (out_g >> 6)) >> 6;
+		//out_b = (out_b + 1 + (out_b >> 6)) >> 6;
+		i = ((out_r << 11) | (out_g << 5) | out_b);
+		unsigned char(*clutp) = clut;
+		//unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
+		return cycle_remap[*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
+		//engine->ReleaseBitmapSurface (clutspr);
+	}
+
+	static unsigned char MixColorLightLevel(unsigned char fg, unsigned char intensity) {
+		unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
+		int i = 0;
+		//int dark_r = (((palette[fg].r>>1) * (intensity))>>8);
+		//int dark_b = (((palette[fg].b>>1) * (intensity))>>8);
+		//int dark_g = (((palette[fg].g)    * (intensity))>>8);
+		int dark_r = (((objectivepal[rfg].r >> 1) * (intensity)) >> 8);
+		int dark_b = (((objectivepal[rfg].b >> 1) * (intensity)) >> 8);
+		int dark_g = (((objectivepal[rfg].g)    * (intensity)) >> 8);
+		i = ((dark_r << 11) | (dark_g << 5) | dark_b);
+		unsigned char (*clutp) = clut;
+		return cycle_remap [*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
+	}
+
+	static unsigned char MixColorAdditive(unsigned char fg, unsigned char bg, unsigned char alpha, int use_objpal = 0) {
+		unsigned char rfg = cycle_remap[fg]; //Automatic remapping of palette slots.
+		//unsigned char rbg = cycle_remap[bg]; //Saves on typing elsewhere.
+		//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
+		//if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
+		//unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
+		AGSColor *palette = engine->GetPalette();
+		int i = 0;
+		int add_r, add_b, add_g = 0;
+		//char ralpha = MAX(0,MIN(63,alpha>>2));
+		//add_r = (((palette[fg].r>>1) * (alpha))>>8);
+		//add_b = (((palette[fg].b>>1) * (alpha))>>8);
+		//add_g = (((palette[fg].g)    * (alpha))>>8);
+		add_r = (((objectivepal[rfg].r >> 1) * (alpha)) >> 8);
+		add_b = (((objectivepal[rfg].b >> 1) * (alpha)) >> 8);
+		add_g = (((objectivepal[rfg].g)    * (alpha)) >> 8);
+		//int a_g = MAX(0,MIN(63,alpha>>2));
+		//add_r = ((alphamultiply[(palette[fg].r>>1)<<6)+ralpha])>>6);
+		//add_b = ((alphamultiply[(palette[fg].b>>1)<<6)+ralpha])>>6);
+		//add_g = ((alphamultiply[(palette[fg].g)   <<6)+ralpha])>>6);
+		//int out_r = MIN(31,(palette[bg].r>>1) + add_r);
+		//int out_g = MIN(63, palette[bg].g     + add_g);
+		//int out_b = MIN(31,(palette[bg].b>>1) + add_b);
+		int out_r, out_g, out_b;
+		if (use_objpal == 0) {
+			out_r = MIN(31, (palette[bg].r >> 1) + add_r);
+			out_g = MIN(63, palette[bg].g     + add_g);
+			out_b = MIN(31, (palette[bg].b >> 1) + add_b);
+		} else {
+			out_r = MIN(31, (objectivepal [bg].r >> 1) + add_r);
+			out_g = MIN(63, objectivepal [bg].g     + add_g);
+			out_b = MIN(31, (objectivepal [bg].b >> 1) + add_b);
+		}
+		i = ((out_r << 11) | (out_g << 5) | out_b);
+		unsigned char (*clutp) = clut;
+		unsigned char result = cycle_remap [*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
+		//unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
+		//engine->ReleaseBitmapSurface (clutspr);
+		return result;
+	}
+
+	static unsigned char MixColorMultiply(unsigned char fg, unsigned char bg, unsigned char alpha, int use_objpal = 0) {
+		unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
+		unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
+		AGSColor *palette = engine->GetPalette();
+		int i = 0;
+		int mul_r, mul_b, mul_g = 0;
+		int out_r, out_g, out_b = 0;
+		if (use_objpal == 0) {
+			mul_r = ((objectivepal[rfg].r >> 1) * (palette[rbg].r >> 1)) / 64;
+			mul_b = ((objectivepal[rfg].b >> 1) * (palette[rbg].b >> 1)) / 64;
+			mul_g = ((objectivepal[rfg].g * palette[rbg].g) / 64);
+			out_r = ((palette[rbg].r >> 1) * (63 - (alpha / 4)) + (mul_r * (alpha / 4))) / 63;
+			out_g = (palette[rbg].g * (63 - (alpha / 4)) + (mul_g * (alpha / 4))) / 63;
+			out_b = ((palette[rbg].b >> 1) * (63 - (alpha / 4)) + (mul_b * (alpha / 4))) / 63;
+		} else {
+			mul_r = ((objectivepal[rfg].r >> 1) * (objectivepal[rbg].r >> 1)) / 64;
+			mul_b = ((objectivepal[rfg].b >> 1) * (objectivepal[rbg].b >> 1)) / 64;
+			mul_g = ((objectivepal[rfg].g * objectivepal[rbg].g) / 64);
+
+			out_r = ((objectivepal[rbg].r >> 1) * (63 - (alpha / 4)) + (mul_r * (alpha / 4))) / 63;
+			out_g = (objectivepal[rbg].g * (63 - (alpha / 4)) + (mul_g * (alpha / 4))) / 63;
+			out_b = ((objectivepal[rbg].b >> 1) * (63 - (alpha / 4)) + (mul_b * (alpha / 4))) / 63;
+		}
+		i = ((out_r << 11) | (out_g << 5) | out_b);
+		unsigned char (*clutp) = clut;
+		unsigned char result = cycle_remap [*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
+		//unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
+		//engine->ReleaseBitmapSurface (clutspr);
+		return result;
+	}
+
+};
+
+unsigned char GetColor565(unsigned char r, unsigned char g, unsigned char b);
+
+unsigned short root(unsigned short x);
+float FastSin(float x);
+float FastCos(float x);
+
+} // namespace AGSPalRender
+} // namespace Plugins
+} // namespace AGS3
+
+#endif
diff --git a/engines/ags/plugins/ags_pal_render/raycast.cpp b/engines/ags/plugins/ags_pal_render/raycast.cpp
index 405c7550c7..2095c00916 100644
--- a/engines/ags/plugins/ags_pal_render/raycast.cpp
+++ b/engines/ags/plugins/ags_pal_render/raycast.cpp
@@ -1,1497 +1,1497 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "ags/lib/allegro.h"
-#include "ags/plugins/ags_pal_render/raycast.h"
-
-namespace AGS3 {
-namespace Plugins {
-namespace AGSPalRender {
-
-#define PI         (3.1415926535f)
-
-//Variable Declaration
-bool raycastOn;
-double posX = 22.0, posY = 11.5; //x and y start position
-double dirX = -1.0, dirY = 0.0; //initial direction vector
-double planeX = 0.0, planeY = 0.77; //the 2d raycaster version of camera plane
-double moveSpeed = (1.0 / 60.0) * 3.0; //the constant value is in squares/second
-double rotSpeed = (1.0 / 60.0) * 2.0; //the constant value is in radians/second
-unsigned char worldMap[64][64];
-unsigned char lightMap[64][64];
-int ceilingMap[64][64];
-int floorMap[64][64];
-int heightMap[64][64];
-unsigned char seenMap[64][64];
-//int mapWidth;
-//int mapHeight;
-#define mapWidth 64
-#define mapHeight 64
-int textureSlot;
-int ambientlight;
-int ambientweight = 0;
-int ambientcolor = 0;
-int ambientcolorAmount = 0;
-
-Sprite sprite[numSprites] = {};
-
-
-#define sWidth 320
-#define sHeight 160
-
-int editorMap [sWidth][sHeight] = {};
-
-unsigned char texture[MAX_TEXTURES][texWidth * texHeight];
-
-wallType wallData[256] = {};
-
-//arrays used to sort the sprites
-int spriteOrder[numSprites];
-double spriteTransformX[numSprites];
-double spriteTransformY[numSprites];
-
-unsigned char **transcolorbuffer;
-unsigned char **transalphabuffer;
-double **transzbuffer;
-bool *transslicedrawn;
-int *transwallblendmode;
-double **ZBuffer;
-double *distTable;
-short *interactionmap;
-int skybox = 0;
-bool heightmapOn;
-
-int noclip = 0;
-
-int selectedX;
-int selectedY;
-unsigned char selectedColor;
-
-void Ray_SelectTile(int x, int y, unsigned char color) {
-	if (x < 0 || x > mapWidth) selectedX = -1;
-	else if (y < 0 || y > mapWidth) selectedY = -1;
-	else {
-		selectedX = x;
-		selectedY = y;
-		selectedColor = color;
-	}
-}
-
-int Ray_HasSeenTile(int x, int y) {
-	if (x < 0 || x > mapWidth) return -1;
-	else if (y < 0 || y > mapWidth) return -1;
-	return seenMap [x][y];
-}
-
-void Ray_SetNoClip(int value) {
-	noclip = value;
-}
-
-int Ray_GetNoClip() {
-	return noclip;
-}
-
-void Ray_DrawTile(int spr, int tile) {
-	BITMAP *img = engine->GetSpriteGraphic(spr);
-	unsigned char **sprarray = engine->GetRawBitmapSurface(img);
-	for (int y = 0; y < 64; ++y)
-		for (int x = 0; x < 64; ++x)
-			sprarray [y][x] = texture [tile][(texWidth * y) + x];
-	engine->ReleaseBitmapSurface(img);
-}
-
-void Ray_DrawOntoTile(int spr, int tile) {
-	BITMAP *img = engine->GetSpriteGraphic(spr);
-	unsigned char **sprarray = engine->GetRawBitmapSurface(img);
-	for (int y = 0; y < 64; ++y)
-		for (int x = 0; x < 64; ++x)
-			texture [tile][(texWidth * y) + x] = sprarray [y][x];
-	engine->ReleaseBitmapSurface(img);
-}
-
-int Ray_GetTileX_At(int x, int y) {
-	if (x < 0 || x > 319  || y < 0 || y > 159) return -1;
-	else return editorMap [x][y] >> 16;
-}
-
-int Ray_GetTileY_At(int x, int y) {
-	if (x < 0 || x > 319  || y < 0 || y > 159) return -1;
-	else return editorMap [x][y] & 0x0000FFFF;
-}
-
-void Ray_SetWallAt(int x, int y, int id) {
-	if (x < 0 || x >= mapWidth) return;
-	if (y < 0 || y >= mapHeight) return;
-	worldMap [x][y] = id;
-}
-
-int Ray_GetWallAt(int x, int y) {
-	if (x < 0 || x >= mapWidth) return -1;
-	if (y < 0 || y >= mapHeight) return -1;
-	return worldMap [x][y];
-}
-
-int Ray_GetAmbientWeight() {
-	return ambientweight;
-}
-
-void Ray_SetAmbientLight(int value) {
-	ambientlight = MIN(255, MAX(0, value));
-}
-
-void Ray_SetAmbientColor(int color, int amount) {
-	ambientcolor = color;
-	ambientcolorAmount = amount;
-}
-
-int Ray_GetAmbientLight() {
-	return ambientlight;
-}
-double fsqrt(double y) {
-	double x, z, tempf;
-	unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
-
-	tempf = y;
-	*tfptr = (0xbfcdd90a - *tfptr) >> 1; /* estimate of 1/sqrt(y) */
-	x =  tempf;
-	z =  y * 0.5;                      /* hoist out the �/2�    */
-	x = (1.5 * x) - (x * x) * (x * z); /* iteration formula     */
-	x = (1.5 * x) - (x * x) * (x * z);
-	x = (1.5 * x) - (x * x) * (x * z);
-	x = (1.5 * x) - (x * x) * (x * z);
-	x = (1.5 * x) - (x * x) * (x * z);
-	return x * y;
-}
-
-void Ray_SetWallHotspot(int id, char hotsp) {
-	wallData[id].hotspotinteract = hotsp;
-}
-
-void Ray_SetWallTextures(int id, int n, int s, int w, int e) {
-	wallData[id].texture[0] = n;
-	wallData[id].texture[1] = s;
-	wallData[id].texture[2] = w;
-	wallData[id].texture[3] = e;
-}
-
-void Ray_SetWallSolid(int id, int n, int s, int w, int e) {
-	wallData[id].solid [0] = MAX(0, MIN(n, 1));
-	wallData[id].solid [1] = MAX(0, MIN(s, 1));
-	wallData[id].solid [2] = MAX(0, MIN(w, 1));
-	wallData[id].solid [3] = MAX(0, MIN(e, 1));
-}
-
-void Ray_SetWallIgnoreLighting(int id, int n, int s, int w, int e) {
-	wallData[id].ignorelighting [0] = MAX(0, MIN(n, 1));
-	wallData[id].ignorelighting [1] = MAX(0, MIN(s, 1));
-	wallData[id].ignorelighting [2] = MAX(0, MIN(w, 1));
-	wallData[id].ignorelighting [3] = MAX(0, MIN(e, 1));
-}
-
-void Ray_SetWallAlpha(int id, int n, int s, int w, int e) {
-	wallData[id].alpha [0] = MAX(0, MIN(n, 255));
-	wallData[id].alpha [1] = MAX(0, MIN(s, 255));
-	wallData[id].alpha [2] = MAX(0, MIN(w, 255));
-	wallData[id].alpha [3] = MAX(0, MIN(e, 255));
-}
-
-void Ray_SetWallBlendType(int id, int n, int s, int w, int e) {
-	wallData[id].blendtype [0] = MAX(0, MIN(n, 10));
-	wallData[id].blendtype [1] = MAX(0, MIN(s, 10));
-	wallData[id].blendtype [2] = MAX(0, MIN(w, 10));
-	wallData[id].blendtype [3] = MAX(0, MIN(e, 10));
-}
-
-
-
-
-int Ray_GetWallHotspot(int id) {
-	return wallData[id].hotspotinteract;
-}
-
-int Ray_GetWallTexture(int id, int dir) {
-	return wallData[id].texture[dir];
-}
-
-int Ray_GetWallSolid(int id, int dir) {
-	return wallData[id].solid [dir];
-}
-
-int Ray_GetWallIgnoreLighting(int id, int dir) {
-	return wallData[id].ignorelighting [dir];
-}
-
-int Ray_GetWallAlpha(int id, int dir) {
-	return wallData[id].alpha [dir];
-}
-
-int Ray_GetWallBlendType(int id, int dir) {
-	return wallData[id].blendtype [dir];
-}
-
-
-
-
-
-FLOAT_RETURN_TYPE Ray_GetMoveSpeed() {
-	float mSpeed = (float)moveSpeed;
-	RETURN_FLOAT(mSpeed);
-}
-
-
-void Ray_SetMoveSpeed(SCRIPT_FLOAT(speed)) {
-	INIT_SCRIPT_FLOAT(speed);
-	moveSpeed = (double)speed;
-}
-
-FLOAT_RETURN_TYPE Ray_GetRotSpeed() {
-	float rSpeed = (float)rotSpeed;
-	RETURN_FLOAT(rSpeed);
-}
-
-void Ray_SetRotSpeed(SCRIPT_FLOAT(speed)) {
-	INIT_SCRIPT_FLOAT(speed);
-	rotSpeed = (double)speed;
-}
-
-
-int Ray_GetLightAt(int x, int y) {
-	return lightMap [x][y];
-}
-
-void Ray_SetLightAt(int x, int y, int light) {
-	lightMap [x][y] = light;
-}
-
-void Ray_SetPlaneY(SCRIPT_FLOAT(y)) {
-	INIT_SCRIPT_FLOAT(y);
-	planeY = (double)y;
-}
-
-FLOAT_RETURN_TYPE Ray_GetPlaneY() {
-	float pY = (float)planeY;
-	RETURN_FLOAT(pY);
-}
-
-void Ray_SetPlayerPosition(SCRIPT_FLOAT(x), SCRIPT_FLOAT(y)) {
-	INIT_SCRIPT_FLOAT(x);
-	INIT_SCRIPT_FLOAT(y);
-	posX = (double)x;
-	posY = (double)y;
-}
-
-FLOAT_RETURN_TYPE Ray_GetPlayerX() {
-
-	float x = (float)posX;
-	RETURN_FLOAT(x);
-}
-
-FLOAT_RETURN_TYPE Ray_GetPlayerY() {
-	float y = (float)posY;
-	RETURN_FLOAT(y);
-}
-
-int Ray_GetPlayerAngle() {
-	double bgrad = atan2(dirY, dirX);
-	int bgdeg = (int)(bgrad / PI * 180.0) + 180;
-	return bgdeg % 360;
-}
-
-void Ray_SetPlayerAngle(int angle) {
-	int realangle = angle % 360;
-	if (realangle < 0) realangle += 360;
-
-	int anglediff = realangle - Ray_GetPlayerAngle();
-	double radians = 0.0174533 * anglediff;
-	double oldDirX = dirX;
-	dirX = dirX * cos(radians) - dirY * sin(radians);
-	dirY = oldDirX * sin(radians) + dirY * cos(radians);
-	double oldPlaneX = planeX;
-	planeX = planeX * cos(radians) - planeY * sin(radians);
-	planeY = oldPlaneX * sin(radians) + planeY * cos(radians);
-}
-
-
-void LoadHeightMap(int heightmapSlot) {
-	int tempw = engine->GetSpriteWidth(heightmapSlot);
-	int temph = engine->GetSpriteHeight(heightmapSlot);
-	if (tempw != mapWidth || temph != mapHeight) engine->AbortGame("LoadHeightMap: Map sizes are mismatched!");
-	BITMAP *heightmapBm = engine->GetSpriteGraphic(heightmapSlot);
-	if (!heightmapBm) engine->AbortGame("LoadHeightMap: Cannot load sprite into memory.");
-	unsigned char **hmArray = engine->GetRawBitmapSurface(heightmapBm);
-
-	for (int i = 0; i < tempw; i++) {
-		for (int j = 0; j < temph; j++) {
-			heightMap[i][j] = hmArray[i][j];
-		}
-	}
-	engine->ReleaseBitmapSurface(heightmapBm);
-	heightmapOn = true;
-}
-
-void LoadMap(int worldmapSlot, int lightmapSlot, int ceilingmapSlot, int floormapSlot) {
-	int tempw = engine->GetSpriteWidth(worldmapSlot);
-	int temph = engine->GetSpriteHeight(worldmapSlot);
-	BITMAP *worldmapBm = nullptr;
-	BITMAP *lightmapBm = nullptr;
-	BITMAP *floormapBm = nullptr;
-	BITMAP *ceilingmapBm = nullptr;
-	unsigned char **wmArray = nullptr;
-	unsigned char **lmArray = nullptr;
-	unsigned char **fmArray = nullptr;
-	unsigned char **cmArray = nullptr;
-	worldmapBm = engine->GetSpriteGraphic(worldmapSlot);
-	if (!worldmapBm) engine->AbortGame("LoadMap: Couldn't load worldmap sprite into memory.");
-	wmArray = engine->GetRawBitmapSurface(worldmapBm);
-	if (engine->GetSpriteWidth(lightmapSlot) != tempw || engine->GetSpriteHeight(lightmapSlot) != temph) engine->AbortGame("LoadMap: Lightmap has different dimensions to worldmap.");
-	else {
-		lightmapBm = engine->GetSpriteGraphic(lightmapSlot);
-		if (!lightmapBm) engine->AbortGame("LoadMap: Couldn't load lightmap sprite into memory.");
-		lmArray = engine->GetRawBitmapSurface(lightmapBm);
-	}
-	if (engine->GetSpriteWidth(ceilingmapSlot) != tempw || engine->GetSpriteHeight(ceilingmapSlot) != temph) engine->AbortGame("LoadMap: Ceilingmap has different dimensions to worldmap.");
-	else {
-		ceilingmapBm = engine->GetSpriteGraphic(ceilingmapSlot);
-		if (!ceilingmapBm) engine->AbortGame("LoadMap: Couldn't load ceilingmap sprite into memory.");
-		cmArray = engine->GetRawBitmapSurface(ceilingmapBm);
-	}
-	if (engine->GetSpriteWidth(floormapSlot) != tempw || engine->GetSpriteHeight(floormapSlot) != temph) engine->AbortGame("LoadMap: Floormap has different dimensions to worldmap.");
-	else {
-		floormapBm = engine->GetSpriteGraphic(floormapSlot);
-		if (!floormapBm) engine->AbortGame("LoadMap: Couldn't load floormap sprite into memory.");
-		fmArray = engine->GetRawBitmapSurface(floormapBm);
-	}
-	for (int i = 0; i < tempw; i++) {
-		for (int j = 0; j < temph; j++) {
-			worldMap[i][j] = wmArray[i][j];
-			lightMap[i][j] = lmArray[i][j];
-			floorMap[i][j] = fmArray[i][j];
-			ceilingMap[i][j] = cmArray[i][j];
-			heightMap[i][j] = 0;
-			seenMap[i][j] = 0;
-		}
-	}
-	engine->ReleaseBitmapSurface(worldmapBm);
-	engine->ReleaseBitmapSurface(lightmapBm);
-	engine->ReleaseBitmapSurface(ceilingmapBm);
-	engine->ReleaseBitmapSurface(floormapBm);
-	//LoadHeightMap (31); //debug only
-}
-
-FLOAT_RETURN_TYPE Ray_GetSpriteScaleX(int id) {
-	float scale = (float)sprite[id].uDivW;
-	RETURN_FLOAT(scale);
-}
-
-void Ray_SetSpriteScaleX(int id, SCRIPT_FLOAT(scale)) {
-	INIT_SCRIPT_FLOAT(scale);
-	sprite[id].uDivW = scale;
-}
-
-FLOAT_RETURN_TYPE Ray_GetSpriteScaleY(int id) {
-	float scale = (float)sprite[id].uDivH;
-	RETURN_FLOAT(scale);
-}
-
-void Ray_SetSpriteScaleY(int id, SCRIPT_FLOAT(scale)) {
-	INIT_SCRIPT_FLOAT(scale);
-	sprite[id].uDivH = scale;
-}
-
-int Ray_GetSpriteAlpha(int id) {
-	return sprite[id].alpha;
-}
-
-void Ray_SetSpriteAlpha(int id, int alpha) {
-	sprite[id].alpha = alpha;
-}
-
-int Ray_GetSpritePic(int id) {
-	return sprite[id].texture;
-}
-
-void Ray_SetSpritePic(int id, int slot) {
-	sprite[id].texture = slot;
-}
-
-
-
-int Ray_GetSpriteAngle(int id) {
-	return sprite[id].angle;
-}
-
-void Ray_SetSpriteAngle(int id, int angle) {
-	sprite[id].angle = angle % 360;
-}
-
-int Ray_GetSpriteInteractObj(int id) {
-	return sprite[id].objectinteract;
-}
-
-void Ray_SetSpriteView(int id, int view) {
-	sprite[id].view = view;
-}
-
-void Ray_SetSpriteBlendType(int id, int type) {
-	sprite[id].blendmode = type;
-}
-
-int Ray_GetSpriteBlendType(int id) {
-	return sprite[id].blendmode;
-}
-
-
-int Ray_GetSpriteView(int id) {
-	return sprite[id].view;
-}
-
-void Ray_SetSpriteFrame(int id, int frame) {
-	sprite[id].frame = frame;
-}
-
-int Ray_GetSpriteFrame(int id) {
-	return sprite[id].frame;
-}
-
-void Ray_SetSpriteInteractObj(int id, int obj) {
-	sprite[id].objectinteract = obj;
-}
-
-void Ray_SetSpritePosition(int id, SCRIPT_FLOAT(x), SCRIPT_FLOAT(y)) {
-	INIT_SCRIPT_FLOAT(x);
-	INIT_SCRIPT_FLOAT(y);
-	sprite[id].x = x;
-	sprite[id].y = y;
-}
-
-void Ray_SetSpriteVertOffset(int id, SCRIPT_FLOAT(vMove)) {
-	INIT_SCRIPT_FLOAT(vMove);
-	sprite[id].vMove = vMove;
-}
-
-
-FLOAT_RETURN_TYPE Ray_GetSpriteVertOffset(int id) {
-	float x = (float)sprite[id].vMove;
-	RETURN_FLOAT(x);
-}
-
-FLOAT_RETURN_TYPE Ray_GetSpriteX(int id) {
-	float x = (float)sprite[id].x;
-	RETURN_FLOAT(x);
-}
-
-FLOAT_RETURN_TYPE Ray_GetSpriteY(int id) {
-	float y = (float)sprite[id].y;
-	RETURN_FLOAT(y);
-}
-
-void Ray_InitSprite(int id, SCRIPT_FLOAT(x), SCRIPT_FLOAT(y), int slot, unsigned char alpha, int blendmode, SCRIPT_FLOAT(scale_x), SCRIPT_FLOAT(scale_y), SCRIPT_FLOAT(vMove)) {
-	INIT_SCRIPT_FLOAT(x);
-	INIT_SCRIPT_FLOAT(y);
-	INIT_SCRIPT_FLOAT(scale_x);
-	INIT_SCRIPT_FLOAT(scale_y);
-	INIT_SCRIPT_FLOAT(vMove);
-	sprite[id].x = x;
-	sprite[id].y = y;
-	sprite[id].texture = slot;
-	sprite[id].alpha = alpha;
-	sprite[id].blendmode = blendmode;
-	sprite[id].uDivW = scale_x;
-	sprite[id].uDivH = scale_y;
-	sprite[id].vMove = vMove;
-}
-
-//function used to sort the sprites
-void combSort(int *order, double *dist, int amount);
-
-void MakeTextures(int slot) {
-	textureSlot = slot;
-	int sourceWidth = engine->GetSpriteWidth(slot);
-	int sourceHeight = engine->GetSpriteHeight(slot);
-	int max = (sourceWidth / texWidth) * (sourceHeight / texHeight);
-	if (max > MAX_TEXTURES) engine->AbortGame("MakeTextures: Source file has too many tiles to load.");
-	BITMAP *texspr = engine->GetSpriteGraphic(slot);
-	unsigned char **texbuffer = engine->GetRawBitmapSurface(texspr);
-	int numTilesX = sourceWidth / texWidth;
-	int numTilesY = sourceHeight / texHeight;
-	//int totaltiles = numTilesX * numTilesY;
-	for (int numX = 0; numX < numTilesX; ++numX) {
-		for (int numY = 0; numY < numTilesY; ++numY) {
-			for (int x = 0; x < texWidth; ++x)
-				for (int y = 0; y < texHeight; ++y) {
-					texture[(numY * numTilesX) + numX][(texWidth * y) + x] = texbuffer [y + (texHeight * numY)][x + (texWidth * numX)];
-				}
-		}
-	}
-	engine->ReleaseBitmapSurface(texspr);
-
-	for (int i = 0; i < 11; i++) {
-		for (int j = 0; j < 4; j++) {
-			wallData[i].texture[j] = i;
-			if (i == 10) wallData[i].texture[j] = 11;
-			if (i > 0) wallData[i].solid[j] = 1;
-			else wallData[i].solid[j] = 0;
-			if (i != 10) wallData[i].alpha[j] = 255;
-			else {
-				wallData[i].alpha[j] = 128;
-				wallData[i].blendtype[j] = 0;
-				wallData[i].solid[j] = 0;
-			}
-		}
-	}
-	wallData[1].texture[0] = 1;
-	wallData[1].texture[1] = 2;
-	wallData[1].texture[2] = 3;
-	wallData[1].texture[3] = 4;
-	wallData[1].solid[0] = 0;
-
-
-
-}
-
-//double ZBuffer[screenWidth][screenHeight];
-
-void Ray_SetFloorAt(int x, int y, int tex) {
-	if (x < 0 || x > mapWidth || y < 0 || y > mapHeight || tex > 511) return;
-	else floorMap[x][y] = tex;
-}
-
-void Ray_SetCeilingAt(int x, int y, int tex) {
-	if (x < 0 || x > mapWidth || y < 0 || y > mapHeight || tex > 511) return;
-	else ceilingMap[x][y] = tex;
-}
-
-int Ray_GetCeilingAt(int x, int y) {
-	if (x < 0 || x > mapWidth || y < 0 || y > mapHeight) return -1;
-	else return ceilingMap [x][y];
-}
-
-
-int Ray_GetFloorAt(int x, int y) {
-	if (x < 0 || x > mapWidth || y < 0 || y > mapHeight) return -1;
-	else return floorMap [x][y];
-}
-
-
-int Ray_GetLightingAt(int x, int y) {
-	if (x < 0 || x > mapWidth || y < 0 || y > mapHeight) return -1;
-	else {
-		int lighting = 0;
-		if (ceilingMap[x][y] == 0) {
-			lighting = ambientlight;
-			if (ambientlight < lightMap [x][y]) lighting = lightMap[x][y];
-		}
-		return lighting;
-	}
-}
-
-void Ray_SetLightingAt(int x, int y, unsigned char lighting) {
-	if (x < 0 || x > mapWidth || y < 0 || y > mapHeight) return;
-	else {
-		lightMap [x][y] = lighting;
-	}
-}
-
-void Ray_SetSkyBox(int slot) {
-	BITMAP *test = engine->GetSpriteGraphic(slot);
-	if (test) {
-		skybox = slot;
-	} else engine->AbortGame("Ray_SetSkybox: No such sprite!");
-}
-
-int Ray_GetSkyBox(int slot) {
-	return skybox;
-}
-
-int Ray_GetHotspotAt(int x, int y) {
-	if (!interactionmap) return -1;
-	else if (x > sWidth || x < 0 || y > sHeight || y < 0) return -1;
-	else return interactionmap [x * sWidth + y] & 0x00FF;
-}
-
-int Ray_GetObjectAt(int x, int y) {
-	if (!interactionmap) return -1;
-	else if (x > sWidth || x < 0 || y > sHeight || y < 0) return -1;
-	else return interactionmap [x * sWidth + y] >> 8;
-}
-
-FLOAT_RETURN_TYPE Ray_GetDistanceAt(int x, int y) {
-	float falsereturn = -1.0f;
-	if (!ZBuffer) {
-		RETURN_FLOAT(falsereturn);
-	} else if (x > sWidth || x < 0 || y > sHeight || y < 0) {
-		RETURN_FLOAT(falsereturn);
-	} else {
-
-		float zbuf = (float)ZBuffer[x][y];
-		RETURN_FLOAT(zbuf);
-	}
-}
-
-void Init_Raycaster() {
-	if (ZBuffer)
-		return;
-	//if (!worldMap) return;
-	transcolorbuffer = new unsigned char *[sWidth];
-	transalphabuffer = new unsigned char *[sWidth];
-	transslicedrawn = new bool[sWidth]();
-	transzbuffer = new double*[sWidth];
-	transwallblendmode = new int [mapWidth]();
-	ZBuffer = new double*[sWidth];
-	distTable = new double[sHeight + (sHeight >> 1)];
-	interactionmap = new short[sWidth * sHeight]();
-	for (int y = 0; y < sHeight + (sHeight >> 1); y++) {
-		distTable [y] = sHeight / (2.0 * y - sHeight);
-	}
-	for (int x = 0; x < sWidth; x++) {
-		transcolorbuffer[x] = new unsigned char [sHeight * (mapWidth)]();
-		transalphabuffer[x] = new unsigned char [sHeight * (mapWidth)]();
-		transzbuffer[x] = new double [sHeight * (mapWidth)]();
-		ZBuffer[x] = new double [sHeight]();
-		transslicedrawn [x] = false;
-	}
-}
-
-bool rendering;
-void Raycast_Render(int slot) {
-	ambientweight = 0;
-	raycastOn = true;
-	double playerrad = atan2(dirY, dirX) + (2.0 * PI);
-	rendering = true;
-	int32 w = sWidth, h = sHeight;
-	BITMAP *screen = engine->GetSpriteGraphic(slot);
-	if (!screen) engine->AbortGame("Raycast_Render: No valid sprite to draw on.");
-	engine->GetBitmapDimensions(screen, &w, &h, nullptr);
-	BITMAP *sbBm = engine->GetSpriteGraphic(skybox);
-	if (!sbBm) engine->AbortGame("Raycast_Render: No valid skybox sprite.");
-	if (skybox > 0) {
-		//int bgdeg = (int)((playerrad / PI) * 180.0) + 180;
-		int xoffset = (int)(playerrad * 320.0);
-		BITMAP *virtsc = engine->GetVirtualScreen();
-		engine->SetVirtualScreen(screen);
-		xoffset = abs(xoffset % w);
-		if (xoffset > 0) {
-			engine->BlitBitmap(xoffset - 320, 1, sbBm, false);
-		}
-		engine->BlitBitmap(xoffset, 1, sbBm, false);
-		engine->SetVirtualScreen(virtsc);
-	}
-	int transwallcount = 0;
-	unsigned char **buffer = engine->GetRawBitmapSurface(screen);
-	for (int x = 0; x < w; x++) {
-		transslicedrawn [x] = false;
-		for (int y = 0; y < h; y++) {
-			ZBuffer[x][y] = 0;
-		}
-	}
-	//int multiplier = mapWidth;
-	memset(interactionmap, 0, sizeof(short) * (sHeight * sWidth));
-	//start the main loop
-	for (int x = 0; x < w; x++) {
-		transwallcount = 0;
-		//calculate ray position and direction
-		double cameraX = 2 * x / double(w) - 1; //x-coordinate in camera space
-		double rayPosX = posX;
-		double rayPosY = posY;
-		double rayDirX = dirX + planeX * cameraX;
-		double rayDirY = dirY + planeY * cameraX;
-
-		//which box of the map we're in
-		int mapX = int(rayPosX);
-		int mapY = int(rayPosY);
-
-		//length of ray from current position to next x or y-side
-		double sideDistX;
-		double sideDistY;
-
-		//length of ray from one x or y-side to next x or y-side
-		double deltaDistX = fsqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
-		double deltaDistY = fsqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));
-		double perpWallDist = 0.0;
-
-		//what direction to step in x or y-direction (either +1 or -1)
-		int stepX;
-		int stepY;
-		int prevmapX = 0;
-		int prevmapY = 0;
-		int hit = 0; //was there a wall hit?
-		int side = 0; //was a NS or a EW wall hit?
-
-		//calculate step and initial sideDist
-		if (rayDirX < 0) {
-			stepX = -1;
-			sideDistX = (rayPosX - mapX) * deltaDistX;
-		} else {
-			stepX = 1;
-			sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX;
-		}
-		if (rayDirY < 0) {
-			stepY = -1;
-			sideDistY = (rayPosY - mapY) * deltaDistY;
-		} else {
-			stepY = 1;
-			sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY;
-		}
-		// Perform DDA
-		bool deeper = true;
-		bool opposite = true;
-		bool oppositedrawn = false;
-		double wallX = 0; // Where exactly the wall was hit
-		int drawStart;
-		int drawEnd = 0;
-		while (hit == 0 && deeper == true) {
-			if (opposite) {
-				rayDirX = -rayDirX;
-				rayDirY = -rayDirY;
-				stepX = -stepX;
-				stepY = -stepY;
-				if (sideDistX < sideDistY) side = 0;
-				else side = 1;
-			} else if (sideDistX < sideDistY) { // jump to next map square, OR in x-direction, OR in y-direction
-				sideDistX += deltaDistX;
-				mapX += stepX;
-				mapX = abs(mapX) % mapHeight;
-				side = 0;
-				if (oppositedrawn && worldMap[mapX][mapY] > 8) {
-					opposite = true;
-					oppositedrawn = false;
-					rayDirX = -rayDirX;
-					rayDirY = -rayDirY;
-					stepX = -stepX;
-					stepY = -stepY;
-					if (sideDistX < sideDistY) side = 0;
-					else side = 1;
-				} else {
-					oppositedrawn = false;
-					opposite = false;
-				}
-			} else {
-				sideDistY += deltaDistY;
-				mapY += stepY;
-				mapY = abs(mapY) % mapHeight;
-				side = 1;
-				if (oppositedrawn && worldMap[mapX][mapY] > 8) {
-					opposite = true;
-					oppositedrawn = false;
-					rayDirX = -rayDirX;
-					rayDirY = -rayDirY;
-					stepX = -stepX;
-					stepY = -stepY;
-					if (sideDistX < sideDistY) side = 0;
-					else side = 1;
-				} else {
-					oppositedrawn = false;
-					opposite = false;
-				}
-			}
-			int texside = 0;
-			if (rayDirX > 0 && side == 0) texside = 0;
-			if (rayDirX < 0 && side == 0) texside = 1;
-			if (rayDirY > 0 && side == 1) texside = 2;
-			if (rayDirY < 0 && side == 1) texside = 3;
-
-			//set this tile as seen.
-			seenMap[mapX][mapY] = 1;
-			//Check if ray has hit a wall
-			if (wallData[worldMap[mapX][mapY]].texture[texside]) {
-				bool ambientpixels = false;
-				hit = 1; //Set this to true so that by default, it's impossible to hang the engine.
-				deeper = false; //Set this to false so that we don't go deeper than we need to.
-
-				//Calculate distance of perpendicular ray (oblique distance will give fisheye effect!)
-				if (side == 0) perpWallDist = fabs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX);
-				else       perpWallDist = fabs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);
-				//Calculate height of line to draw on screen
-				int lineHeight = abs(int(h / perpWallDist));
-
-				//calculate lowest and highest pixel to fill in current stripe
-				drawStart = -lineHeight / 2 + h / 2;
-				if (drawStart < 0) drawStart = 0;
-				drawEnd = lineHeight / 2 + h / 2;
-				if (drawEnd >= h) drawEnd = h;
-				//texturing calculations
-				int texNum = wallData[worldMap[mapX][mapY]].texture[texside] - 1; //1 subtracted from it so that texture 0 can be used!
-				if (!opposite) {
-					//calculate value of wallX
-					if (side == 1) wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) / 2) / rayDirY) * rayDirX;
-					else       wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) / 2) / rayDirX) * rayDirY;
-				} else {
-					if (side == 1) wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) / 2) / -rayDirY) * -rayDirX;
-					else       wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) / 2) / -rayDirX) * -rayDirY;
-				}
-				wallX -= floor((wallX));
-
-				//x coordinate on the texture
-				int wall_light = 255;
-				int texX = int(wallX * double(texWidth));
-				if (side == 0 && rayDirX > 0) texX = texWidth - texX - 1;
-				if (side == 1 && rayDirY < 0) texX = texWidth - texX - 1;
-				bool do_ambient = false;
-				if (!opposite) {
-					if (rayDirX > 0 && side == 0) {
-						wall_light = lightMap [(int)mapX - 1 % mapWidth][(int)mapY] << 5;
-						if (ceilingMap [(int)mapX - 1 % mapWidth][(int)mapY] <= 1) do_ambient = true;
-						else if (texture[ceilingMap [(int)mapX - 1 % mapWidth][(int)mapY] - 1][(texWidth * (63 - texX)) + 63] == 0) do_ambient = true;
-					}
-					if (rayDirX < 0 && side == 0) {
-						wall_light = lightMap [(int)mapX + 1 % mapWidth][(int)mapY] << 5;
-						if (ceilingMap [(int)mapX + 1 % mapWidth][(int)mapY] <= 1) do_ambient = true;
-						else if (texture[ceilingMap [(int)mapX + 1 % mapWidth][(int)mapY] - 1][(texWidth * texX) + 0] == 0) do_ambient = true;
-
-					}
-					if (rayDirY > 0 && side == 1) {
-						wall_light = lightMap [(int)mapX][(int)mapY - 1 % mapHeight] << 5;
-						if (ceilingMap [(int)mapX][(int)mapY - 1 % mapHeight] <= 1) do_ambient = true;
-						else if (texture[ceilingMap [(int)mapX][(int)mapY - 1 % mapHeight] - 1][(texWidth * 63) + texX] == 0) do_ambient = true;
-					}
-					if (rayDirY < 0 && side == 1) {
-						wall_light = lightMap [(int)mapX][(int)mapY + 1 % mapHeight] << 5;
-						if (ceilingMap [(int)mapX][(int)mapY + 1 % mapHeight] <= 1) do_ambient = true;
-						else if (texture[ceilingMap [(int)mapX][(int)mapY + 1 % mapHeight] - 1][(texWidth * 0) + 63 - texX] == 0) do_ambient = true;
-					}
-				} else if (opposite) {
-					wall_light = lightMap [(int)mapX][(int)mapY] << 5;
-					if (ceilingMap [(int)mapX][(int)mapY] <= 1) do_ambient = true;
-					if (rayDirX > 0 && side == 0) {
-						if (texture[ceilingMap [(int)mapX][(int)mapY] - 1][(texWidth * (63 - texX)) + 63] == 0) do_ambient = true;
-					}
-					if (rayDirX < 0 && side == 0) {
-						if (texture[ceilingMap [(int)mapX][(int)mapY] - 1][(texWidth * texX) + 63] == 0) do_ambient = true;
-					}
-					if (rayDirY > 0 && side == 1) {
-						if (texture[ceilingMap [(int)mapX][(int)mapY] - 1][(texWidth * 0) + (63 - texX)] == 0) do_ambient = true;
-					}
-					if (rayDirY < 0 && side == 1) {
-						if (texture[ceilingMap [(int)mapX][(int)mapY] - 1][(texWidth * 63) + texX] == 0) do_ambient = true;
-					}
-				}
-				if (do_ambient) {
-					ambientpixels = true;
-					wall_light = MAX(wall_light, ambientlight);
-				}
-				wall_light = MIN(255, MAX(0, wall_light));
-				bool alphastripe = false;
-				for (int y = drawStart; y < drawEnd; y++) {
-					if (ZBuffer[x][y] > perpWallDist || ZBuffer[x][y] == 0) { //We can draw.
-						int d = y * 256 - h * 128 + lineHeight * 128; //256 and 128 factors to avoid floats
-						int texY = ((d * texHeight) / lineHeight) / 256;
-						int color = texture[texNum][texWidth * texY + texX];
-						if (color > 0) {
-							if (ambientpixels && ambientcolor) color = Mix::MixColorMultiply(ambientcolor, color, ambientcolorAmount, 1);
-							if (!wallData[worldMap[mapX][mapY]].ignorelighting[texside] && wall_light < 255) color = Mix::MixColorLightLevel(color, wall_light);
-							if (wallData[worldMap[mapX][mapY]].alpha[texside] == 255 && wallData[worldMap[mapX][mapY]].mask[texside] == 0) {
-								buffer[y][x] = color;
-								if (ambientpixels) ambientweight++;
-								//SET THE ZBUFFER FOR THE SPRITE CASTING
-								ZBuffer[x][y] = perpWallDist; //perpendicular distance is used
-								interactionmap [x * sWidth + y] = wallData[worldMap[mapX][mapY]].hotspotinteract;
-								editorMap [x][y] = ((short)mapX) << 16 | ((short)mapY);
-							} else {
-								if (transslicedrawn[x] == false) {
-									memset(transcolorbuffer[x], 0, sizeof(unsigned char) * (sHeight * mapWidth));
-									memset(transalphabuffer[x], 0, sizeof(unsigned char) * (sHeight * mapWidth));
-									//memset (transzbuffer[x],0,sizeof(double)*(sHeight*mapWidth));
-									transslicedrawn[x] = true;
-								}
-								transwallblendmode[transwallcount] = wallData[worldMap[mapX][mapY]].blendtype[texside];
-								int transwalloffset = transwallcount * h;
-								transcolorbuffer[x][transwalloffset + y] = color;
-								if (ambientpixels) ambientweight++;
-								if (wallData[worldMap[mapX][mapY]].mask[texside] == 0) transalphabuffer[x][transwalloffset + y] = wallData[worldMap[mapX][mapY]].alpha[texside];
-								else {
-									transalphabuffer[x][transwalloffset + y] = (wallData[worldMap[mapX][mapY]].alpha[texside] + texture[wallData[worldMap[mapX][mapY]].mask[texside]][texWidth * texY + texX]) >> 1;
-								}
-								transzbuffer[x][transwalloffset + y] = perpWallDist;
-								hit = 0;
-								deeper = true;
-								alphastripe = true;
-							}
-						} else {
-							//We found transparency, we have to draw deeper.
-							deeper = true;
-							hit = 0;
-						}
-						if ((int)mapX == selectedX && (int)mapY == selectedY) {
-							if (texX == 0 || texX == 63 || texY == 0 || texY == 63) {
-								buffer[y][x] = selectedColor;
-								ZBuffer [x][y] = perpWallDist;
-							}
-						}
-
-					}
-				}
-				if (alphastripe) {
-					if (transwallcount < mapWidth) {
-						transwallcount++;
-					}
-					alphastripe = false;
-				}
-				if (opposite) {
-					if (mapX == 0 || mapX == mapWidth || mapY == 0 || mapY == mapHeight) {
-						deeper = false;
-						hit = 0;
-					}
-					oppositedrawn = true;
-					if (deeper) opposite = false;
-					rayDirX = -rayDirX;
-					rayDirY = -rayDirY;
-					stepX = -stepX;
-					stepY = -stepY;
-				} else if (!opposite && deeper) {
-					opposite = true;
-					prevmapX = mapX;
-					prevmapY = mapY;
-				}
-				//End of wall drawing functions.
-			} else if (opposite) {
-				opposite = false;
-				//oppositedrawn = false;
-				rayDirX = -rayDirX;
-				rayDirY = -rayDirY;
-				stepX = -stepX;
-				stepY = -stepY;
-			} else if (!opposite && deeper) {
-				opposite = true;
-				prevmapX = mapX;
-				prevmapY = mapY;
-			}
-			//End of loop.
-		}
-
-		// Unused variables
-		(void)prevmapX;
-		(void)prevmapY;
-
-		//FLOOR CASTING
-
-		double floorXWall, floorYWall; //x, y position of the floor texel at the bottom of the wall
-		//4 different wall directions possible
-		if (side == 0 && rayDirX > 0) {
-			floorXWall = mapX;
-			floorYWall = mapY + wallX;
-			if (opposite) floorXWall = floorXWall + 1.0;
-		} else if (side == 0 && rayDirX < 0) {
-			floorXWall = mapX + 1.0;
-			floorYWall = mapY + wallX;
-			if (opposite) floorXWall = floorXWall - 1.0;
-		} else if (side == 1 && rayDirY > 0) {
-			floorXWall = mapX + wallX;
-			floorYWall = mapY;
-			if (opposite) floorYWall = floorYWall + 1.0;
-		} else {
-			floorXWall = mapX + wallX;
-			floorYWall = mapY + 1.0;
-			if (opposite) floorYWall = floorYWall - 1.0;
-		}
-
-		double distWall, distPlayer, currentDist;
-
-		distWall = perpWallDist;
-		distPlayer = 0.0;
-		if (drawEnd < 0)
-			drawEnd = h - 1; //becomes < 0 when the integer overflows
-		//draw the floor from drawEnd to the bottom of the screen
-		int drawdist = h;
-		int expandeddraw = h >> 1;
-		for (int y = drawEnd; y < drawdist + expandeddraw; y++) {
-			//currentDist = h / (2.0 * y - h); //you could make a small lookup table for this instead
-			currentDist = distTable[y];
-			if (y > h - 1) {
-				//if (!heightMap) break;
-				double weight = (currentDist - distPlayer) / (distWall - distPlayer);
-
-				double currentFloorX = weight * floorXWall + (1.0 - weight) * posX;
-				double currentFloorY = weight * floorYWall + (1.0 - weight) * posY;
-
-				int floorTexX, floorTexY;
-				int cmapX = (int)currentFloorX;
-				if (cmapX > mapWidth - 1) cmapX = mapWidth - 1;
-				if (cmapX < 0) cmapX = 0;
-				int cmapY = (int)currentFloorY;
-				if (cmapY > mapHeight - 1) cmapY = mapHeight - 1;
-				if (cmapY < 0) cmapY = 0;
-				if (heightMap[cmapX][cmapY] - 1 < 1) continue;
-				int lighting = lightMap [cmapX][cmapY] << 5;
-				lighting = MIN(255, MAX(0, lighting));
-				floorTexX = int(currentFloorX * texWidth) % texWidth;
-				floorTexY = int(currentFloorY * texHeight) % texHeight;
-				int floorcolor = 0;
-				int ceilingcolor = 0;
-				int texpos = texWidth * floorTexY + floorTexX;
-				if (ceilingMap[cmapX][cmapY] - 1 > 0) {
-					ceilingcolor = texture[ceilingMap[cmapX][cmapY] - 1][texWidth * floorTexY + floorTexX];
-				}
-				if (floorMap[cmapX][cmapY] - 1 > 0) {
-					floorcolor = texture[floorMap[cmapX][cmapY] - 1][texpos];
-				} else continue;
-				if (ceilingcolor == 0) {
-					lighting = MAX(lighting, ambientlight);
-					ambientweight ++;
-				}
-				if (lighting < 255) {
-					if (floorcolor) floorcolor = Mix::MixColorLightLevel(floorcolor, lighting);
-				}
-
-				if (/*heightMap &&*/ floorcolor > 0) {
-					if (heightMap[cmapX][cmapY] - 1 > 0) {
-						int raisedfloorstart = y - (int)(texture[heightMap[cmapX][cmapY] - 1][texpos] / currentDist);
-						if (raisedfloorstart > h - 1) continue;
-						if (raisedfloorstart < 0) raisedfloorstart = 0;
-						for (int ny = raisedfloorstart; ny < y; ny++) {
-							if (ny < h && (ZBuffer[x][ny] > currentDist || ZBuffer[x][ny] == 0)) {
-								ZBuffer[x][ny] = currentDist; //perpendicular distance is used
-								buffer[ny][x] = floorcolor;
-								interactionmap [x * sWidth + ny] = 0;
-								editorMap [x][ny] = ((short)mapX) << 16 | ((short)mapY);
-							}
-						}
-						if (raisedfloorstart < y && y == h - 1 && y == h + expandeddraw) expandeddraw ++;
-					}
-				}
-			} else {
-				double weight = (currentDist - distPlayer) / (distWall - distPlayer);
-
-				double currentFloorX = weight * floorXWall + (1.0 - weight) * posX;
-				double currentFloorY = weight * floorYWall + (1.0 - weight) * posY;
-
-				int floorTexX, floorTexY;
-				int cmapX = (int)currentFloorX % mapWidth;
-				if (cmapX < 0) cmapX = 0;
-				int cmapY = (int)currentFloorY % mapHeight;
-				if (cmapY < 0) cmapY = 0;
-				int lighting = lightMap [cmapX][cmapY] << 5;
-				lighting = MIN(255, MAX(0, lighting));
-				floorTexX = int(currentFloorX * texWidth) % texWidth;
-				floorTexY = int(currentFloorY * texHeight) % texHeight;
-				int floorcolor = 0;
-				int ceilingcolor = 0;
-				if (floorMap[cmapX][cmapY] - 1 > 0) {
-					floorcolor = texture[floorMap[cmapX][cmapY] - 1][texWidth * floorTexY + floorTexX];
-				}
-				if (ceilingMap[cmapX][cmapY] - 1 > 0) {
-					ceilingcolor = texture[ceilingMap[cmapX][cmapY] - 1][texWidth * floorTexY + floorTexX];
-				}
-				if (ceilingcolor == 0) {
-					lighting = MAX(lighting, ambientlight);
-					ambientweight++;
-				}
-				if (lighting < 255) {
-					if (floorcolor) floorcolor = Mix::MixColorLightLevel(floorcolor, lighting);
-					if (ceilingcolor) ceilingcolor = Mix::MixColorLightLevel(ceilingcolor, lighting);
-				}
-
-				if (/*heightMap &&*/ floorcolor > 0 && (currentDist < ZBuffer[x][y] || ZBuffer[x][y] == 0)) {
-					if (heightMap[cmapX][cmapY] - 1 > 0) {
-						int raisedfloorstart = y - (int)(texture[heightMap[cmapX][cmapY] - 1][texWidth * floorTexY + floorTexX] / currentDist);
-						if (raisedfloorstart > h - 1) continue;
-						if (raisedfloorstart < 0) raisedfloorstart = 0;
-						for (int ny = raisedfloorstart; ny < y; ny++) {
-							if (ZBuffer[x][ny] > currentDist || ZBuffer[x][ny] == 0) {
-								ZBuffer[x][ny] = currentDist; //perpendicular distance is used
-								buffer[ny][x] = floorcolor;
-								interactionmap [x * sWidth + ny] = 0;
-								editorMap [x][ny] = ((short)cmapX) << 16 | ((short)cmapY);
-							}
-						}
-						if (raisedfloorstart < y && y == h - 1 && y == h + expandeddraw) expandeddraw ++;
-					}
-				}
-				//floor
-				//ceiling (symmetrical!)
-				//SET THE ZBUFFER FOR THE SPRITE CASTING
-				if (floorcolor > 0 && (currentDist < ZBuffer[x][y] || ZBuffer[x][y] == 0)) {
-					ZBuffer[x][y] = currentDist; //perpendicular distance is used
-					buffer[y][x] = floorcolor;
-					editorMap [x][y] = ((short)cmapX) << 16 | ((short)cmapY);
-				} else ZBuffer[x][y] = 9999999999999.0;
-				if (currentDist < ZBuffer[x][h - y] || ZBuffer[x][h - y] == 0) {
-					if (ceilingcolor > 0) {
-						ZBuffer[x][h - y] = currentDist; //perpendicular distance is used
-						buffer[h - y][x] = ceilingcolor;
-					} else ZBuffer[x][h - y] = 999999999999.0;
-					editorMap [x][h - y] = ((short)cmapX) << 16 | ((short)cmapY);
-				}
-				interactionmap [x * sWidth + y] = 0;
-				interactionmap [x * sWidth + (h - y)] = 0;
-				if ((int)cmapX == selectedX && (int)cmapY == selectedY) {
-					if (floorTexX == 0 || floorTexX == 63 || floorTexY == 0 || floorTexY == 63) {
-						buffer[y][x] = selectedColor;
-						ZBuffer [x][y] = perpWallDist;
-						buffer[h - y][x] = selectedColor;
-						ZBuffer [x][h - y] = perpWallDist;
-					}
-				}
-
-
-			}
-		}
-		//TRANSLUCENT WALL RENDERING
-		if (transslicedrawn[x] == true) {
-			for (int y = 0; y < h; y++) {
-				for (int transwalldrawn = 0; transwalldrawn < transwallcount; transwalldrawn++) {
-					int transwalloffset = transwalldrawn * h;
-					int color = transcolorbuffer[x][transwalloffset + y];
-					if (color != 0) {
-						if (transwallblendmode[transwalldrawn] == 0) buffer[y][x] = Mix::MixColorAlpha(color, buffer[y][x], transalphabuffer[x][transwalloffset + y]); //paint pixel if it isn't black, black is the invisible color
-						else if (transwallblendmode[transwalldrawn] == 1) buffer[y][x] = Mix::MixColorAdditive(color, buffer[y][x], transalphabuffer[x][transwalloffset + y]);
-						//if (ZBuffer[x][y] > transzbuffer[transwalldrawn*h+y]) ZBuffer[x][y] = transzbuffer[transwalldrawn*h+y]; //put the sprite on the zbuffer so we can draw around it.
-					}
-				}
-			}
-		}
-		//End of wall loop.
-	}
-
-
-	//SPRITE CASTING
-	//sort sprites from far to close
-
-	//Initialize Sprites for casting.
-	double invDet = 1.0 / (planeX * dirY - dirX * planeY);
-	for (int i = 0; i < numSprites; i++) {
-		spriteOrder[i] = i;
-		spriteTransformY[i] = ((posX - sprite[i].x) * (posX - sprite[i].x) + (posY - sprite[i].y) * (posY - sprite[i].y));
-	}
-	combSort(spriteOrder, spriteTransformY, numSprites);
-	for (int i = 0; i < numSprites; i++) {
-		double spriteX = sprite[spriteOrder[i]].x - posX;
-		double spriteY = sprite[spriteOrder[i]].y - posY;
-		spriteTransformX[i] = invDet * (dirY * spriteX - dirX * spriteY);
-		spriteTransformY[i] = invDet * (-planeY * spriteX + planeX * spriteY);
-	}
-
-	int transwalldraw = 0;
-	//after sorting the sprites, do the projection and draw them
-	for (int i = 0; i < numSprites; i++) {
-		int flipped = 0;
-		if (sprite[spriteOrder[i]].view != 0) {
-
-			double sprrad = atan2(sprite[spriteOrder[i]].y - posY, sprite[spriteOrder[i]].x - posX);
-			int sprdeg = (int)(sprrad / 3.1415 * 180.0);
-			sprdeg = ((sprdeg + 180) + sprite[spriteOrder[i]].angle) % 360;
-			int loop = 0;
-			if (sprdeg > 336 || sprdeg < 23) loop = 0;
-			else if (sprdeg > 22 && sprdeg < 68) loop = 6;
-			else if (sprdeg > 67 && sprdeg < 113) loop = 1;
-			else if (sprdeg > 112 && sprdeg < 158) loop = 7;
-			else if (sprdeg > 157 && sprdeg < 203) loop = 3;
-			else if (sprdeg > 202 && sprdeg < 248) loop = 5;
-			else if (sprdeg > 247 && sprdeg < 293) loop = 2;
-			else if (sprdeg > 292 && sprdeg < 337) loop = 4;
-			AGSViewFrame *vf = engine->GetViewFrame(sprite[spriteOrder[i]].view, loop, sprite[spriteOrder[i]].frame);
-			if (vf == nullptr) engine->AbortGame("Raycast_Render: Unable to load viewframe of sprite.");
-			else {
-				sprite[spriteOrder[i]].texture = vf->pic;
-				int (*sfGetGameParameter)(int, int, int, int);
-				sfGetGameParameter = ((int(*)(int, int, int, int)) engine->GetScriptFunctionAddress("GetGameParameter"));
-				flipped = sfGetGameParameter(13, sprite[spriteOrder[i]].view, loop, sprite[spriteOrder[i]].frame);
-			}
-		}
-		//translate sprite position to relative to camera
-		//double spriteX = sprite[spriteOrder[i]].x - posX;
-		//double spriteY = sprite[spriteOrder[i]].y - posY;
-
-		//transform sprite with the inverse camera matrix
-		// [ planeX   dirX ] -1                                       [ dirY      -dirX ]
-		// [               ]       =  1/(planeX*dirY-dirX*planeY) *   [                 ]
-		// [ planeY   dirY ]                                          [ -planeY  planeX ]
-
-		//double invDet = 1.0 / (planeX * dirY - dirX * planeY); //required for correct matrix multiplication
-		//double spriteX = sprite[spriteOrder[i]].x - posX;
-		//double spriteY = sprite[spriteOrder[i]].y - posY;
-		//double transformX = invDet * (dirY * spriteX - dirX * spriteY);
-		//double transformY = invDet * (-planeY * spriteX + planeX * spriteY); //this is actually the depth inside the screen, that what Z is in 3D
-
-		int spriteScreenX = int((w / 2) * (1 + spriteTransformX[i] / spriteTransformY[i]));
-
-		//parameters for scaling and moving the sprites
-		BITMAP *spritetexbm = engine->GetSpriteGraphic(sprite[spriteOrder[i]].texture);
-		unsigned char **spritetex = engine->GetRawBitmapSurface(spritetexbm);
-		int sprw = engine->GetSpriteWidth(sprite[spriteOrder[i]].texture);
-		int sprh = engine->GetSpriteHeight(sprite[spriteOrder[i]].texture);
-
-		double uDiv = ((double)sprw / (double)texWidth) + sprite[spriteOrder[i]].uDivW;
-		double vDiv = ((double)sprh / (double)texHeight) + sprite[spriteOrder[i]].uDivH;
-		double vMove = sprite[spriteOrder[i]].vMove + ((double)texHeight - (double)sprh) * 1.6;
-		double hMove = sprite[spriteOrder[i]].hMove;
-		int vMoveScreen = int(vMove / spriteTransformY[i]);
-		int hMoveScreen = int(hMove / spriteTransformY[i]);
-		//calculate height of the sprite on screen
-		int spriteHeight = abs(int(h / (spriteTransformY[i]) * vDiv)) ; //using "transformY" instead of the real distance prevents fisheye
-		//calculate lowest and highest pixel to fill in current stripe
-		int drawStartY = -spriteHeight / 2 + h / 2 + vMoveScreen;
-		if (drawStartY < 0) drawStartY = 0;
-		int drawEndY = spriteHeight / 2 + h / 2 + vMoveScreen;
-		if (drawEndY >= h) drawEndY = h - 1;
-
-		//calculate width of the sprite
-		int spriteWidth = abs(int (h / (spriteTransformY[i]) * uDiv)) ;
-		int drawStartX = -spriteWidth / 2 + spriteScreenX + hMoveScreen;
-		if (drawStartX < 0) drawStartX = 0;
-		int drawEndX = spriteWidth / 2 + spriteScreenX + hMoveScreen;
-		if (drawEndX >= w) drawEndX = w - 1;
-		int spr_light = lightMap [(int)sprite[spriteOrder[i]].x][(int)sprite[spriteOrder[i]].y] << 5;
-		spr_light = MIN(255, MAX(0, spr_light));
-		int floorTexX = int(sprite[spriteOrder[i]].x * texWidth) % texWidth;
-		int floorTexY = int(sprite[spriteOrder[i]].y * texHeight) % texHeight;
-		if (ceilingMap [(int)sprite[spriteOrder[i]].x][(int)sprite[spriteOrder[i]].y] == 0) {
-			spr_light = MAX(spr_light, ambientlight);
-		} else if (texture[ceilingMap [(int)sprite[spriteOrder[i]].x][(int)sprite[spriteOrder[i]].y] - 1][texWidth * floorTexY + floorTexX] == 0) spr_light = MAX(spr_light, ambientlight);
-		//loop through every vertical stripe of the sprite on screen
-
-
-		for (int stripe = drawStartX; stripe < drawEndX; stripe++) {
-			transwalldraw = 0;
-			//int texX = int(256 * (stripe - (-spriteWidth / 2 + spriteScreenX)) * texWidth / spriteWidth) / 256;
-			int texX = int(256 * (stripe - (-spriteWidth / 2 + spriteScreenX)) *  sprw / spriteWidth) / 256;
-			if (texX >= sprw || texX < 0) continue;
-			if (flipped) texX = sprw - texX;
-			//the conditions in the if are:
-			//1) it's in front of camera plane so you don't see things behind you
-			//2) it's on the screen (left)
-			//3) it's on the screen (right)
-			//4) ZBuffer, with perpendicular distance
-			if (spriteTransformY[i] > 0 && stripe > 0 && stripe < w)
-				for (int y = drawStartY; y < drawEndY; y++) { //for every pixel of the current stripe
-					if (spriteTransformY[i] < ZBuffer[stripe][y]) {
-						if (transslicedrawn[stripe]) while ((transzbuffer[stripe][transwalldraw * h + y] > spriteTransformY[i] && transzbuffer[stripe][transwalldraw * h + y] != 0) && (transwalldraw < transwallcount)) transwalldraw++;
-						int d = (y - vMoveScreen) * 256 - h * 128 + spriteHeight * 128; //256 and 128 factors to avoid floats
-						//int texY = ((d * texHeight) / spriteHeight) / 256;
-						int texY = ((d * sprh) / spriteHeight) / 256;
-						if (texY >= sprh || texY < 0) continue;
-						//unsigned char color = texture[sprite[spriteOrder[i]].texture][texWidth * texY + texX]; //get current color from the texture
-						unsigned char color = spritetex[texY][texX]; //get current color from the texture
-						if (color != 0) {
-							if (sprite[spriteOrder[i]].alpha < 255) {
-								if (sprite[spriteOrder[i]].blendmode == 0) color = Mix::MixColorAlpha(color, buffer[y][stripe], sprite[spriteOrder[i]].alpha);
-								if (sprite[spriteOrder[i]].blendmode == 1) color = Mix::MixColorAdditive(color, buffer[y][stripe], sprite[spriteOrder[i]].alpha);
-							}
-							color = Mix::MixColorLightLevel(color, spr_light);
-							if (transzbuffer[stripe][transwalldraw * h + y] < spriteTransformY[i] && transzbuffer[stripe][transwalldraw * h + y] != 0 && transslicedrawn[stripe] && transcolorbuffer[stripe][transwalldraw * h + y] > 0 && transalphabuffer[stripe][transwalldraw * h + y] > 0) {
-								if (transwallblendmode[transwalldraw] == 0) color = Mix::MixColorAlpha(color, transcolorbuffer[stripe][transwalldraw * h + y], transalphabuffer[stripe][transwalldraw * h + y]);
-								else if (transwallblendmode[transwalldraw] == 1) color = Mix::MixColorAdditive(color, transcolorbuffer[stripe][transwalldraw * h + y], transalphabuffer[stripe][transwalldraw * h + y]);
-								buffer[y][stripe] = color;
-								ZBuffer[stripe][y] = transzbuffer[stripe][transwalldraw * h + y];
-							} else {
-								buffer[y][stripe] = color; //paint pixel if it isn't black, black is the invisible color
-								ZBuffer[stripe][y] = spriteTransformY[i]; //put the sprite on the zbuffer so we can draw around it.
-							}
-							interactionmap [stripe * sWidth + y] = sprite[spriteOrder[i]].objectinteract << 8;
-						}
-					}
-				}
-		}
-		engine->ReleaseBitmapSurface(spritetexbm);
-	}
-	engine->ReleaseBitmapSurface(screen);
-	engine->NotifySpriteUpdated(slot);
-	rendering = false;
-
-}
-
-void QuitCleanup() {
-	if (!rendering) {
-		for (int i = 0; i < sWidth; ++i) {
-			if (transcolorbuffer[i])delete [] transcolorbuffer[i];
-			if (transalphabuffer[i])delete [] transalphabuffer[i];
-			if (transzbuffer[i])delete [] transzbuffer[i];
-			if (ZBuffer[i]) delete [] ZBuffer[i];
-		}
-		if (transcolorbuffer) delete [] transcolorbuffer;
-		if (transalphabuffer) delete [] transalphabuffer;
-		if (transzbuffer) delete [] transzbuffer;
-		if (ZBuffer) delete [] ZBuffer;
-		if (transwallblendmode) delete [] transwallblendmode;
-		if (interactionmap) delete [] interactionmap;
-	}
-}
-
-void MoveForward() {
-	double newposx = 0;
-	if (dirX > 0) newposx = 0.1 + posX + dirX * moveSpeed;
-	else newposx = -0.1 + posX + dirX * moveSpeed;
-	int texsidex = 0;
-	int inside_texsidex = 0;
-	double newposy = 0;
-	if (dirY > 0) newposy = 0.1 + posY + dirY * moveSpeed;
-	else newposy = -0.1 + posY + dirY * moveSpeed;
-	int texsidey = 0;
-	int inside_texsidey = 0;
-	bool inside = false;
-	if ((int)newposx == (int)posX && (int)newposy == (int)posY) inside = true;
-	if (dirX > 0 && !inside) {
-		texsidex = 0;
-		inside_texsidex = 1;
-	} else if (dirX > 0) {
-		texsidex = 1;
-		inside_texsidex = 0;
-	}
-	if (dirX < 0 && !inside) {
-		texsidex = 1;
-		inside_texsidex = 0;
-	} else if (dirX < 0) {
-		texsidex = 0;
-		inside_texsidex = 1;
-	}
-
-	if (dirY > 0 && !inside) {
-		texsidey = 2;
-		inside_texsidey = 3;
-	} else if (dirY > 0) {
-		texsidey = 3;
-		inside_texsidey = 2;
-	}
-	if (dirY < 0 && !inside) {
-		texsidey = 3;
-		inside_texsidey = 2;
-	} else if (dirY < 0) {
-		texsidey = 2;
-		inside_texsidey = 3;
-	}
-
-	if (!noclip && !inside) {
-		if (wallData[worldMap[int(newposx)][int(posY)]].solid[texsidex] == false && wallData[worldMap[int(posX)][int(posY)]].solid[inside_texsidex] == false && int(newposx) > -1 && int(newposx) < mapWidth) posX += dirX * moveSpeed;
-		if (wallData[worldMap[int(posX)][int(newposy)]].solid[texsidey] == false && wallData[worldMap[int(posX)][int(posY)]].solid[inside_texsidey] == false && int(newposy) > -1 && int(newposy) < mapHeight) posY += dirY * moveSpeed;
-	} else if (!noclip && inside) {
-		posX += dirX * moveSpeed;
-		posY += dirY * moveSpeed;
-	} else {
-		if (int(newposx) > -1 && int(newposx) < mapWidth) posX += dirX * moveSpeed;
-		if (int(newposy) > -1 && int(newposy) < mapHeight) posY += dirY * moveSpeed;
-	}
-}
-
-void MoveBackward() {
-	double newposx = 0;
-	if (dirX > 0) newposx = -0.1 + posX - dirX * moveSpeed;
-	else newposx = 0.1 + posX - dirX * moveSpeed;
-	int texsidex = 0;
-	int inside_texsidex = 0;
-	double newposy = 0;
-	if (dirY > 0) newposy = -0.1 + posY - dirY * moveSpeed;
-	else newposy = 0.1 + posY - dirY * moveSpeed;
-	int texsidey = 0;
-	int inside_texsidey = 0;
-	bool inside = false;
-	if ((int)newposx == (int)posX && (int)newposy == (int)posY) inside = true;
-	if (dirX > 0 && !inside) {
-		texsidex = 1;
-		inside_texsidex = 0;
-	} else if (dirX > 0) {
-		texsidex = 0;
-		inside_texsidex = 1;
-	}
-	if (dirX < 0 && !inside) {
-		texsidex = 0;
-		inside_texsidex = 1;
-	} else if (dirX < 0) {
-		texsidex = 1;
-		inside_texsidex = 0;
-	}
-
-	if (dirY > 0 && !inside) {
-		texsidey = 3;
-		inside_texsidey = 2;
-	} else if (dirY > 0) {
-		texsidey = 2;
-		inside_texsidey = 3;
-	}
-	if (dirY < 0 && !inside) {
-		texsidey = 2;
-		inside_texsidey = 3;
-	} else if (dirY < 0) {
-		texsidey = 3;
-		inside_texsidey = 2;
-	}
-
-	if ((int)posX == (int)newposy && (int)posY == (int)newposy) inside = true;
-	if (!noclip && !inside) {
-		if (wallData[worldMap[int(newposx)][int(posY)]].solid[texsidex] == false && wallData[worldMap[int(posX)][int(posY)]].solid[inside_texsidex] == false && int(newposx) > -1 && int(newposx) < mapWidth) posX -= dirX * moveSpeed;
-		if (wallData[worldMap[int(posX)][int(newposy)]].solid[texsidey] == false && wallData[worldMap[int(posX)][int(posY)]].solid[inside_texsidey] == false && int(newposy) > -1 && int(newposy) < mapHeight) posY -= dirY * moveSpeed;
-	} else if (!noclip && inside) {
-		posX -= dirX * moveSpeed;
-		posY -= dirY * moveSpeed;
-	} else {
-		if (int(newposx) > -1 && int(newposx) < mapWidth) posX -= dirX * moveSpeed;
-		if (int(newposy) > -1 && int(newposy) < mapHeight) posY -= dirY * moveSpeed;
-	}
-}
-
-
-
-/*
-void MoveBackward ()
-{
-      double newposx;
-      if (dirX > 0) newposx = -0.2 + posX - dirX * moveSpeed;
-      else newposx = 0.2 + posX - dirX * moveSpeed;
-      double newposy;
-      if (dirY > 0) newposy = -0.2 + posY - dirY * moveSpeed;
-      else newposy = 0.2 + posY - dirY * moveSpeed;
-      if(worldMap[int(newposx)][int(posY)] == false || worldMap[int(newposx)][int(posY)] > 8) posX -= dirX * moveSpeed;
-      if(worldMap[int(posX)][int(newposy)] == false || worldMap[int(posX)][int(newposy)] > 8) posY -= dirY * moveSpeed;
-}
-*/
-
-void RotateLeft() {
-	double oldDirX = dirX;
-	dirX = dirX * cos(rotSpeed) - dirY * sin(rotSpeed);
-	dirY = oldDirX * sin(rotSpeed) + dirY * cos(rotSpeed);
-	double oldPlaneX = planeX;
-	planeX = planeX * cos(rotSpeed) - planeY * sin(rotSpeed);
-	planeY = oldPlaneX * sin(rotSpeed) + planeY * cos(rotSpeed);
-}
-
-void RotateRight() {
-	double oldDirX = dirX;
-	dirX = dirX * cos(-rotSpeed) - dirY * sin(-rotSpeed);
-	dirY = oldDirX * sin(-rotSpeed) + dirY * cos(-rotSpeed);
-	double oldPlaneX = planeX;
-	planeX = planeX * cos(-rotSpeed) - planeY * sin(-rotSpeed);
-	planeY = oldPlaneX * sin(-rotSpeed) + planeY * cos(-rotSpeed);
-}
-
-//sort algorithm
-void combSort(int *order, double *dist, int amount) {
-	int gap = amount;
-	bool swapped = false;
-	while (gap > 1 || swapped) {
-		//shrink factor 1.3
-		gap = (gap * 10) / 13;
-		if (gap == 9 || gap == 10) gap = 11;
-		if (gap < 1) gap = 1;
-		swapped = false;
-		for (int i = 0; i < amount - gap; i++) {
-			int j = i + gap;
-			if (dist[i] < dist[j]) {
-				SWAP(dist[i], dist[j]);
-				SWAP(order[i], order[j]);
-				swapped = true;
-			}
-		}
-	}
-}
-
-} // namespace AGSPalRender
-} // namespace Plugins
-} // namespace AGS3
-
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or(at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ags/lib/allegro.h"
+#include "ags/plugins/ags_pal_render/raycast.h"
+
+namespace AGS3 {
+namespace Plugins {
+namespace AGSPalRender {
+
+#define PI         (3.1415926535f)
+
+//Variable Declaration
+bool raycastOn;
+double posX = 22.0, posY = 11.5; //x and y start position
+double dirX = -1.0, dirY = 0.0; //initial direction vector
+double planeX = 0.0, planeY = 0.77; //the 2d raycaster version of camera plane
+double moveSpeed = (1.0 / 60.0) * 3.0; //the constant value is in squares/second
+double rotSpeed = (1.0 / 60.0) * 2.0; //the constant value is in radians/second
+unsigned char worldMap[64][64];
+unsigned char lightMap[64][64];
+int ceilingMap[64][64];
+int floorMap[64][64];
+int heightMap[64][64];
+unsigned char seenMap[64][64];
+//int mapWidth;
+//int mapHeight;
+#define mapWidth 64
+#define mapHeight 64
+int textureSlot;
+int ambientlight;
+int ambientweight = 0;
+int ambientcolor = 0;
+int ambientcolorAmount = 0;
+
+Sprite sprite[numSprites] = {};
+
+
+#define sWidth 320
+#define sHeight 160
+
+int editorMap [sWidth][sHeight] = {};
+
+unsigned char texture[MAX_TEXTURES][texWidth * texHeight];
+
+wallType wallData[256] = {};
+
+//arrays used to sort the sprites
+int spriteOrder[numSprites];
+double spriteTransformX[numSprites];
+double spriteTransformY[numSprites];
+
+unsigned char **transcolorbuffer;
+unsigned char **transalphabuffer;
+double **transzbuffer;
+bool *transslicedrawn;
+int *transwallblendmode;
+double **ZBuffer;
+double *distTable;
+short *interactionmap;
+int skybox = 0;
+bool heightmapOn;
+
+int noclip = 0;
+
+int selectedX;
+int selectedY;
+unsigned char selectedColor;
+
+void Ray_SelectTile(int x, int y, unsigned char color) {
+	if (x < 0 || x > mapWidth) selectedX = -1;
+	else if (y < 0 || y > mapWidth) selectedY = -1;
+	else {
+		selectedX = x;
+		selectedY = y;
+		selectedColor = color;
+	}
+}
+
+int Ray_HasSeenTile(int x, int y) {
+	if (x < 0 || x > mapWidth) return -1;
+	else if (y < 0 || y > mapWidth) return -1;
+	return seenMap [x][y];
+}
+
+void Ray_SetNoClip(int value) {
+	noclip = value;
+}
+
+int Ray_GetNoClip() {
+	return noclip;
+}
+
+void Ray_DrawTile(int spr, int tile) {
+	BITMAP *img = engine->GetSpriteGraphic(spr);
+	unsigned char **sprarray = engine->GetRawBitmapSurface(img);
+	for (int y = 0; y < 64; ++y)
+		for (int x = 0; x < 64; ++x)
+			sprarray [y][x] = texture [tile][(texWidth * y) + x];
+	engine->ReleaseBitmapSurface(img);
+}
+
+void Ray_DrawOntoTile(int spr, int tile) {
+	BITMAP *img = engine->GetSpriteGraphic(spr);
+	unsigned char **sprarray = engine->GetRawBitmapSurface(img);
+	for (int y = 0; y < 64; ++y)
+		for (int x = 0; x < 64; ++x)
+			texture [tile][(texWidth * y) + x] = sprarray [y][x];
+	engine->ReleaseBitmapSurface(img);
+}
+
+int Ray_GetTileX_At(int x, int y) {
+	if (x < 0 || x > 319  || y < 0 || y > 159) return -1;
+	else return editorMap [x][y] >> 16;
+}
+
+int Ray_GetTileY_At(int x, int y) {
+	if (x < 0 || x > 319  || y < 0 || y > 159) return -1;
+	else return editorMap [x][y] & 0x0000FFFF;
+}
+
+void Ray_SetWallAt(int x, int y, int id) {
+	if (x < 0 || x >= mapWidth) return;
+	if (y < 0 || y >= mapHeight) return;
+	worldMap [x][y] = id;
+}
+
+int Ray_GetWallAt(int x, int y) {
+	if (x < 0 || x >= mapWidth) return -1;
+	if (y < 0 || y >= mapHeight) return -1;
+	return worldMap [x][y];
+}
+
+int Ray_GetAmbientWeight() {
+	return ambientweight;
+}
+
+void Ray_SetAmbientLight(int value) {
+	ambientlight = MIN(255, MAX(0, value));
+}
+
+void Ray_SetAmbientColor(int color, int amount) {
+	ambientcolor = color;
+	ambientcolorAmount = amount;
+}
+
+int Ray_GetAmbientLight() {
+	return ambientlight;
+}
+double fsqrt(double y) {
+	double x, z, tempf;
+	unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
+
+	tempf = y;
+	*tfptr = (0xbfcdd90a - *tfptr) >> 1; /* estimate of 1/sqrt(y) */
+	x =  tempf;
+	z =  y * 0.5;                      /* hoist out the �/2�    */
+	x = (1.5 * x) - (x * x) * (x * z); /* iteration formula     */
+	x = (1.5 * x) - (x * x) * (x * z);
+	x = (1.5 * x) - (x * x) * (x * z);
+	x = (1.5 * x) - (x * x) * (x * z);
+	x = (1.5 * x) - (x * x) * (x * z);
+	return x * y;
+}
+
+void Ray_SetWallHotspot(int id, char hotsp) {
+	wallData[id].hotspotinteract = hotsp;
+}
+
+void Ray_SetWallTextures(int id, int n, int s, int w, int e) {
+	wallData[id].texture[0] = n;
+	wallData[id].texture[1] = s;
+	wallData[id].texture[2] = w;
+	wallData[id].texture[3] = e;
+}
+
+void Ray_SetWallSolid(int id, int n, int s, int w, int e) {
+	wallData[id].solid [0] = MAX(0, MIN(n, 1));
+	wallData[id].solid [1] = MAX(0, MIN(s, 1));
+	wallData[id].solid [2] = MAX(0, MIN(w, 1));
+	wallData[id].solid [3] = MAX(0, MIN(e, 1));
+}
+
+void Ray_SetWallIgnoreLighting(int id, int n, int s, int w, int e) {
+	wallData[id].ignorelighting [0] = MAX(0, MIN(n, 1));
+	wallData[id].ignorelighting [1] = MAX(0, MIN(s, 1));
+	wallData[id].ignorelighting [2] = MAX(0, MIN(w, 1));
+	wallData[id].ignorelighting [3] = MAX(0, MIN(e, 1));
+}
+
+void Ray_SetWallAlpha(int id, int n, int s, int w, int e) {
+	wallData[id].alpha [0] = MAX(0, MIN(n, 255));
+	wallData[id].alpha [1] = MAX(0, MIN(s, 255));
+	wallData[id].alpha [2] = MAX(0, MIN(w, 255));
+	wallData[id].alpha [3] = MAX(0, MIN(e, 255));
+}
+
+void Ray_SetWallBlendType(int id, int n, int s, int w, int e) {
+	wallData[id].blendtype [0] = MAX(0, MIN(n, 10));
+	wallData[id].blendtype [1] = MAX(0, MIN(s, 10));
+	wallData[id].blendtype [2] = MAX(0, MIN(w, 10));
+	wallData[id].blendtype [3] = MAX(0, MIN(e, 10));
+}
+
+
+
+
+int Ray_GetWallHotspot(int id) {
+	return wallData[id].hotspotinteract;
+}
+
+int Ray_GetWallTexture(int id, int dir) {
+	return wallData[id].texture[dir];
+}
+
+int Ray_GetWallSolid(int id, int dir) {
+	return wallData[id].solid [dir];
+}
+
+int Ray_GetWallIgnoreLighting(int id, int dir) {
+	return wallData[id].ignorelighting [dir];
+}
+
+int Ray_GetWallAlpha(int id, int dir) {
+	return wallData[id].alpha [dir];
+}
+
+int Ray_GetWallBlendType(int id, int dir) {
+	return wallData[id].blendtype [dir];
+}
+
+
+
+
+
+FLOAT_RETURN_TYPE Ray_GetMoveSpeed() {
+	float mSpeed = (float)moveSpeed;
+	RETURN_FLOAT(mSpeed);
+}
+
+
+void Ray_SetMoveSpeed(SCRIPT_FLOAT(speed)) {
+	INIT_SCRIPT_FLOAT(speed);
+	moveSpeed = (double)speed;
+}
+
+FLOAT_RETURN_TYPE Ray_GetRotSpeed() {
+	float rSpeed = (float)rotSpeed;
+	RETURN_FLOAT(rSpeed);
+}
+
+void Ray_SetRotSpeed(SCRIPT_FLOAT(speed)) {
+	INIT_SCRIPT_FLOAT(speed);
+	rotSpeed = (double)speed;
+}
+
+
+int Ray_GetLightAt(int x, int y) {
+	return lightMap [x][y];
+}
+
+void Ray_SetLightAt(int x, int y, int light) {
+	lightMap [x][y] = light;
+}
+
+void Ray_SetPlaneY(SCRIPT_FLOAT(y)) {
+	INIT_SCRIPT_FLOAT(y);
+	planeY = (double)y;
+}
+
+FLOAT_RETURN_TYPE Ray_GetPlaneY() {
+	float pY = (float)planeY;
+	RETURN_FLOAT(pY);
+}
+
+void Ray_SetPlayerPosition(SCRIPT_FLOAT(x), SCRIPT_FLOAT(y)) {
+	INIT_SCRIPT_FLOAT(x);
+	INIT_SCRIPT_FLOAT(y);
+	posX = (double)x;
+	posY = (double)y;
+}
+
+FLOAT_RETURN_TYPE Ray_GetPlayerX() {
+
+	float x = (float)posX;
+	RETURN_FLOAT(x);
+}
+
+FLOAT_RETURN_TYPE Ray_GetPlayerY() {
+	float y = (float)posY;
+	RETURN_FLOAT(y);
+}
+
+int Ray_GetPlayerAngle() {
+	double bgrad = atan2(dirY, dirX);
+	int bgdeg = (int)(bgrad / PI * 180.0) + 180;
+	return bgdeg % 360;
+}
+
+void Ray_SetPlayerAngle(int angle) {
+	int realangle = angle % 360;
+	if (realangle < 0) realangle += 360;
+
+	int anglediff = realangle - Ray_GetPlayerAngle();
+	double radians = 0.0174533 * anglediff;
+	double oldDirX = dirX;
+	dirX = dirX * cos(radians) - dirY * sin(radians);
+	dirY = oldDirX * sin(radians) + dirY * cos(radians);
+	double oldPlaneX = planeX;
+	planeX = planeX * cos(radians) - planeY * sin(radians);
+	planeY = oldPlaneX * sin(radians) + planeY * cos(radians);
+}
+
+
+void LoadHeightMap(int heightmapSlot) {
+	int tempw = engine->GetSpriteWidth(heightmapSlot);
+	int temph = engine->GetSpriteHeight(heightmapSlot);
+	if (tempw != mapWidth || temph != mapHeight) engine->AbortGame("LoadHeightMap: Map sizes are mismatched!");
+	BITMAP *heightmapBm = engine->GetSpriteGraphic(heightmapSlot);
+	if (!heightmapBm) engine->AbortGame("LoadHeightMap: Cannot load sprite into memory.");
+	unsigned char **hmArray = engine->GetRawBitmapSurface(heightmapBm);
+
+	for (int i = 0; i < tempw; i++) {
+		for (int j = 0; j < temph; j++) {
+			heightMap[i][j] = hmArray[i][j];
+		}
+	}
+	engine->ReleaseBitmapSurface(heightmapBm);
+	heightmapOn = true;
+}
+
+void LoadMap(int worldmapSlot, int lightmapSlot, int ceilingmapSlot, int floormapSlot) {
+	int tempw = engine->GetSpriteWidth(worldmapSlot);
+	int temph = engine->GetSpriteHeight(worldmapSlot);
+	BITMAP *worldmapBm = nullptr;
+	BITMAP *lightmapBm = nullptr;
+	BITMAP *floormapBm = nullptr;
+	BITMAP *ceilingmapBm = nullptr;
+	unsigned char **wmArray = nullptr;
+	unsigned char **lmArray = nullptr;
+	unsigned char **fmArray = nullptr;
+	unsigned char **cmArray = nullptr;
+	worldmapBm = engine->GetSpriteGraphic(worldmapSlot);
+	if (!worldmapBm) engine->AbortGame("LoadMap: Couldn't load worldmap sprite into memory.");
+	wmArray = engine->GetRawBitmapSurface(worldmapBm);
+	if (engine->GetSpriteWidth(lightmapSlot) != tempw || engine->GetSpriteHeight(lightmapSlot) != temph) engine->AbortGame("LoadMap: Lightmap has different dimensions to worldmap.");
+	else {
+		lightmapBm = engine->GetSpriteGraphic(lightmapSlot);
+		if (!lightmapBm) engine->AbortGame("LoadMap: Couldn't load lightmap sprite into memory.");
+		lmArray = engine->GetRawBitmapSurface(lightmapBm);
+	}
+	if (engine->GetSpriteWidth(ceilingmapSlot) != tempw || engine->GetSpriteHeight(ceilingmapSlot) != temph) engine->AbortGame("LoadMap: Ceilingmap has different dimensions to worldmap.");
+	else {
+		ceilingmapBm = engine->GetSpriteGraphic(ceilingmapSlot);
+		if (!ceilingmapBm) engine->AbortGame("LoadMap: Couldn't load ceilingmap sprite into memory.");
+		cmArray = engine->GetRawBitmapSurface(ceilingmapBm);
+	}
+	if (engine->GetSpriteWidth(floormapSlot) != tempw || engine->GetSpriteHeight(floormapSlot) != temph) engine->AbortGame("LoadMap: Floormap has different dimensions to worldmap.");
+	else {
+		floormapBm = engine->GetSpriteGraphic(floormapSlot);
+		if (!floormapBm) engine->AbortGame("LoadMap: Couldn't load floormap sprite into memory.");
+		fmArray = engine->GetRawBitmapSurface(floormapBm);
+	}
+	for (int i = 0; i < tempw; i++) {
+		for (int j = 0; j < temph; j++) {
+			worldMap[i][j] = wmArray[i][j];
+			lightMap[i][j] = lmArray[i][j];
+			floorMap[i][j] = fmArray[i][j];
+			ceilingMap[i][j] = cmArray[i][j];
+			heightMap[i][j] = 0;
+			seenMap[i][j] = 0;
+		}
+	}
+	engine->ReleaseBitmapSurface(worldmapBm);
+	engine->ReleaseBitmapSurface(lightmapBm);
+	engine->ReleaseBitmapSurface(ceilingmapBm);
+	engine->ReleaseBitmapSurface(floormapBm);
+	//LoadHeightMap (31); //debug only
+}
+
+FLOAT_RETURN_TYPE Ray_GetSpriteScaleX(int id) {
+	float scale = (float)sprite[id].uDivW;
+	RETURN_FLOAT(scale);
+}
+
+void Ray_SetSpriteScaleX(int id, SCRIPT_FLOAT(scale)) {
+	INIT_SCRIPT_FLOAT(scale);
+	sprite[id].uDivW = scale;
+}
+
+FLOAT_RETURN_TYPE Ray_GetSpriteScaleY(int id) {
+	float scale = (float)sprite[id].uDivH;
+	RETURN_FLOAT(scale);
+}
+
+void Ray_SetSpriteScaleY(int id, SCRIPT_FLOAT(scale)) {
+	INIT_SCRIPT_FLOAT(scale);
+	sprite[id].uDivH = scale;
+}
+
+int Ray_GetSpriteAlpha(int id) {
+	return sprite[id].alpha;
+}
+
+void Ray_SetSpriteAlpha(int id, int alpha) {
+	sprite[id].alpha = alpha;
+}
+
+int Ray_GetSpritePic(int id) {
+	return sprite[id].texture;
+}
+
+void Ray_SetSpritePic(int id, int slot) {
+	sprite[id].texture = slot;
+}
+
+
+
+int Ray_GetSpriteAngle(int id) {
+	return sprite[id].angle;
+}
+
+void Ray_SetSpriteAngle(int id, int angle) {
+	sprite[id].angle = angle % 360;
+}
+
+int Ray_GetSpriteInteractObj(int id) {
+	return sprite[id].objectinteract;
+}
+
+void Ray_SetSpriteView(int id, int view) {
+	sprite[id].view = view;
+}
+
+void Ray_SetSpriteBlendType(int id, int type) {
+	sprite[id].blendmode = type;
+}
+
+int Ray_GetSpriteBlendType(int id) {
+	return sprite[id].blendmode;
+}
+
+
+int Ray_GetSpriteView(int id) {
+	return sprite[id].view;
+}
+
+void Ray_SetSpriteFrame(int id, int frame) {
+	sprite[id].frame = frame;
+}
+
+int Ray_GetSpriteFrame(int id) {
+	return sprite[id].frame;
+}
+
+void Ray_SetSpriteInteractObj(int id, int obj) {
+	sprite[id].objectinteract = obj;
+}
+
+void Ray_SetSpritePosition(int id, SCRIPT_FLOAT(x), SCRIPT_FLOAT(y)) {
+	INIT_SCRIPT_FLOAT(x);
+	INIT_SCRIPT_FLOAT(y);
+	sprite[id].x = x;
+	sprite[id].y = y;
+}
+
+void Ray_SetSpriteVertOffset(int id, SCRIPT_FLOAT(vMove)) {
+	INIT_SCRIPT_FLOAT(vMove);
+	sprite[id].vMove = vMove;
+}
+
+
+FLOAT_RETURN_TYPE Ray_GetSpriteVertOffset(int id) {
+	float x = (float)sprite[id].vMove;
+	RETURN_FLOAT(x);
+}
+
+FLOAT_RETURN_TYPE Ray_GetSpriteX(int id) {
+	float x = (float)sprite[id].x;
+	RETURN_FLOAT(x);
+}
+
+FLOAT_RETURN_TYPE Ray_GetSpriteY(int id) {
+	float y = (float)sprite[id].y;
+	RETURN_FLOAT(y);
+}
+
+void Ray_InitSprite(int id, SCRIPT_FLOAT(x), SCRIPT_FLOAT(y), int slot, unsigned char alpha, int blendmode, SCRIPT_FLOAT(scale_x), SCRIPT_FLOAT(scale_y), SCRIPT_FLOAT(vMove)) {
+	INIT_SCRIPT_FLOAT(x);
+	INIT_SCRIPT_FLOAT(y);
+	INIT_SCRIPT_FLOAT(scale_x);
+	INIT_SCRIPT_FLOAT(scale_y);
+	INIT_SCRIPT_FLOAT(vMove);
+	sprite[id].x = x;
+	sprite[id].y = y;
+	sprite[id].texture = slot;
+	sprite[id].alpha = alpha;
+	sprite[id].blendmode = blendmode;
+	sprite[id].uDivW = scale_x;
+	sprite[id].uDivH = scale_y;
+	sprite[id].vMove = vMove;
+}
+
+//function used to sort the sprites
+void combSort(int *order, double *dist, int amount);
+
+void MakeTextures(int slot) {
+	textureSlot = slot;
+	int sourceWidth = engine->GetSpriteWidth(slot);
+	int sourceHeight = engine->GetSpriteHeight(slot);
+	int max = (sourceWidth / texWidth) * (sourceHeight / texHeight);
+	if (max > MAX_TEXTURES) engine->AbortGame("MakeTextures: Source file has too many tiles to load.");
+	BITMAP *texspr = engine->GetSpriteGraphic(slot);
+	unsigned char **texbuffer = engine->GetRawBitmapSurface(texspr);
+	int numTilesX = sourceWidth / texWidth;
+	int numTilesY = sourceHeight / texHeight;
+	//int totaltiles = numTilesX * numTilesY;
+	for (int numX = 0; numX < numTilesX; ++numX) {
+		for (int numY = 0; numY < numTilesY; ++numY) {
+			for (int x = 0; x < texWidth; ++x)
+				for (int y = 0; y < texHeight; ++y) {
+					texture[(numY * numTilesX) + numX][(texWidth * y) + x] = texbuffer [y + (texHeight * numY)][x + (texWidth * numX)];
+				}
+		}
+	}
+	engine->ReleaseBitmapSurface(texspr);
+
+	for (int i = 0; i < 11; i++) {
+		for (int j = 0; j < 4; j++) {
+			wallData[i].texture[j] = i;
+			if (i == 10) wallData[i].texture[j] = 11;
+			if (i > 0) wallData[i].solid[j] = 1;
+			else wallData[i].solid[j] = 0;
+			if (i != 10) wallData[i].alpha[j] = 255;
+			else {
+				wallData[i].alpha[j] = 128;
+				wallData[i].blendtype[j] = 0;
+				wallData[i].solid[j] = 0;
+			}
+		}
+	}
+	wallData[1].texture[0] = 1;
+	wallData[1].texture[1] = 2;
+	wallData[1].texture[2] = 3;
+	wallData[1].texture[3] = 4;
+	wallData[1].solid[0] = 0;
+
+
+
+}
+
+//double ZBuffer[screenWidth][screenHeight];
+
+void Ray_SetFloorAt(int x, int y, int tex) {
+	if (x < 0 || x > mapWidth || y < 0 || y > mapHeight || tex > 511) return;
+	else floorMap[x][y] = tex;
+}
+
+void Ray_SetCeilingAt(int x, int y, int tex) {
+	if (x < 0 || x > mapWidth || y < 0 || y > mapHeight || tex > 511) return;
+	else ceilingMap[x][y] = tex;
+}
+
+int Ray_GetCeilingAt(int x, int y) {
+	if (x < 0 || x > mapWidth || y < 0 || y > mapHeight) return -1;
+	else return ceilingMap [x][y];
+}
+
+
+int Ray_GetFloorAt(int x, int y) {
+	if (x < 0 || x > mapWidth || y < 0 || y > mapHeight) return -1;
+	else return floorMap [x][y];
+}
+
+
+int Ray_GetLightingAt(int x, int y) {
+	if (x < 0 || x > mapWidth || y < 0 || y > mapHeight) return -1;
+	else {
+		int lighting = 0;
+		if (ceilingMap[x][y] == 0) {
+			lighting = ambientlight;
+			if (ambientlight < lightMap [x][y]) lighting = lightMap[x][y];
+		}
+		return lighting;
+	}
+}
+
+void Ray_SetLightingAt(int x, int y, unsigned char lighting) {
+	if (x < 0 || x > mapWidth || y < 0 || y > mapHeight) return;
+	else {
+		lightMap [x][y] = lighting;
+	}
+}
+
+void Ray_SetSkyBox(int slot) {
+	BITMAP *test = engine->GetSpriteGraphic(slot);
+	if (test) {
+		skybox = slot;
+	} else engine->AbortGame("Ray_SetSkybox: No such sprite!");
+}
+
+int Ray_GetSkyBox(int slot) {
+	return skybox;
+}
+
+int Ray_GetHotspotAt(int x, int y) {
+	if (!interactionmap) return -1;
+	else if (x > sWidth || x < 0 || y > sHeight || y < 0) return -1;
+	else return interactionmap [x * sWidth + y] & 0x00FF;
+}
+
+int Ray_GetObjectAt(int x, int y) {
+	if (!interactionmap) return -1;
+	else if (x > sWidth || x < 0 || y > sHeight || y < 0) return -1;
+	else return interactionmap [x * sWidth + y] >> 8;
+}
+
+FLOAT_RETURN_TYPE Ray_GetDistanceAt(int x, int y) {
+	float falsereturn = -1.0f;
+	if (!ZBuffer) {
+		RETURN_FLOAT(falsereturn);
+	} else if (x > sWidth || x < 0 || y > sHeight || y < 0) {
+		RETURN_FLOAT(falsereturn);
+	} else {
+
+		float zbuf = (float)ZBuffer[x][y];
+		RETURN_FLOAT(zbuf);
+	}
+}
+
+void Init_Raycaster() {
+	if (ZBuffer)
+		return;
+	//if (!worldMap) return;
+	transcolorbuffer = new unsigned char *[sWidth];
+	transalphabuffer = new unsigned char *[sWidth];
+	transslicedrawn = new bool[sWidth]();
+	transzbuffer = new double*[sWidth];
+	transwallblendmode = new int [mapWidth]();
+	ZBuffer = new double*[sWidth];
+	distTable = new double[sHeight + (sHeight >> 1)];
+	interactionmap = new short[sWidth * sHeight]();
+	for (int y = 0; y < sHeight + (sHeight >> 1); y++) {
+		distTable [y] = sHeight / (2.0 * y - sHeight);
+	}
+	for (int x = 0; x < sWidth; x++) {
+		transcolorbuffer[x] = new unsigned char [sHeight * (mapWidth)]();
+		transalphabuffer[x] = new unsigned char [sHeight * (mapWidth)]();
+		transzbuffer[x] = new double [sHeight * (mapWidth)]();
+		ZBuffer[x] = new double [sHeight]();
+		transslicedrawn [x] = false;
+	}
+}
+
+bool rendering;
+void Raycast_Render(int slot) {
+	ambientweight = 0;
+	raycastOn = true;
+	double playerrad = atan2(dirY, dirX) + (2.0 * PI);
+	rendering = true;
+	int32 w = sWidth, h = sHeight;
+	BITMAP *screen = engine->GetSpriteGraphic(slot);
+	if (!screen) engine->AbortGame("Raycast_Render: No valid sprite to draw on.");
+	engine->GetBitmapDimensions(screen, &w, &h, nullptr);
+	BITMAP *sbBm = engine->GetSpriteGraphic(skybox);
+	if (!sbBm) engine->AbortGame("Raycast_Render: No valid skybox sprite.");
+	if (skybox > 0) {
+		//int bgdeg = (int)((playerrad / PI) * 180.0) + 180;
+		int xoffset = (int)(playerrad * 320.0);
+		BITMAP *virtsc = engine->GetVirtualScreen();
+		engine->SetVirtualScreen(screen);
+		xoffset = abs(xoffset % w);
+		if (xoffset > 0) {
+			engine->BlitBitmap(xoffset - 320, 1, sbBm, false);
+		}
+		engine->BlitBitmap(xoffset, 1, sbBm, false);
+		engine->SetVirtualScreen(virtsc);
+	}
+	int transwallcount = 0;
+	unsigned char **buffer = engine->GetRawBitmapSurface(screen);
+	for (int x = 0; x < w; x++) {
+		transslicedrawn [x] = false;
+		for (int y = 0; y < h; y++) {
+			ZBuffer[x][y] = 0;
+		}
+	}
+	//int multiplier = mapWidth;
+	memset(interactionmap, 0, sizeof(short) * (sHeight * sWidth));
+	//start the main loop
+	for (int x = 0; x < w; x++) {
+		transwallcount = 0;
+		//calculate ray position and direction
+		double cameraX = 2 * x / double(w) - 1; //x-coordinate in camera space
+		double rayPosX = posX;
+		double rayPosY = posY;
+		double rayDirX = dirX + planeX * cameraX;
+		double rayDirY = dirY + planeY * cameraX;
+
+		//which box of the map we're in
+		int mapX = int(rayPosX);
+		int mapY = int(rayPosY);
+
+		//length of ray from current position to next x or y-side
+		double sideDistX;
+		double sideDistY;
+
+		//length of ray from one x or y-side to next x or y-side
+		double deltaDistX = fsqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
+		double deltaDistY = fsqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));
+		double perpWallDist = 0.0;
+
+		//what direction to step in x or y-direction (either +1 or -1)
+		int stepX;
+		int stepY;
+		int prevmapX = 0;
+		int prevmapY = 0;
+		int hit = 0; //was there a wall hit?
+		int side = 0; //was a NS or a EW wall hit?
+
+		//calculate step and initial sideDist
+		if (rayDirX < 0) {
+			stepX = -1;
+			sideDistX = (rayPosX - mapX) * deltaDistX;
+		} else {
+			stepX = 1;
+			sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX;
+		}
+		if (rayDirY < 0) {
+			stepY = -1;
+			sideDistY = (rayPosY - mapY) * deltaDistY;
+		} else {
+			stepY = 1;
+			sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY;
+		}
+		// Perform DDA
+		bool deeper = true;
+		bool opposite = true;
+		bool oppositedrawn = false;
+		double wallX = 0; // Where exactly the wall was hit
+		int drawStart;
+		int drawEnd = 0;
+		while (hit == 0 && deeper == true) {
+			if (opposite) {
+				rayDirX = -rayDirX;
+				rayDirY = -rayDirY;
+				stepX = -stepX;
+				stepY = -stepY;
+				if (sideDistX < sideDistY) side = 0;
+				else side = 1;
+			} else if (sideDistX < sideDistY) { // jump to next map square, OR in x-direction, OR in y-direction
+				sideDistX += deltaDistX;
+				mapX += stepX;
+				mapX = abs(mapX) % mapHeight;
+				side = 0;
+				if (oppositedrawn && worldMap[mapX][mapY] > 8) {
+					opposite = true;
+					oppositedrawn = false;
+					rayDirX = -rayDirX;
+					rayDirY = -rayDirY;
+					stepX = -stepX;
+					stepY = -stepY;
+					if (sideDistX < sideDistY) side = 0;
+					else side = 1;
+				} else {
+					oppositedrawn = false;
+					opposite = false;
+				}
+			} else {
+				sideDistY += deltaDistY;
+				mapY += stepY;
+				mapY = abs(mapY) % mapHeight;
+				side = 1;
+				if (oppositedrawn && worldMap[mapX][mapY] > 8) {
+					opposite = true;
+					oppositedrawn = false;
+					rayDirX = -rayDirX;
+					rayDirY = -rayDirY;
+					stepX = -stepX;
+					stepY = -stepY;
+					if (sideDistX < sideDistY) side = 0;
+					else side = 1;
+				} else {
+					oppositedrawn = false;
+					opposite = false;
+				}
+			}
+			int texside = 0;
+			if (rayDirX > 0 && side == 0) texside = 0;
+			if (rayDirX < 0 && side == 0) texside = 1;
+			if (rayDirY > 0 && side == 1) texside = 2;
+			if (rayDirY < 0 && side == 1) texside = 3;
+
+			//set this tile as seen.
+			seenMap[mapX][mapY] = 1;
+			//Check if ray has hit a wall
+			if (wallData[worldMap[mapX][mapY]].texture[texside]) {
+				bool ambientpixels = false;
+				hit = 1; //Set this to true so that by default, it's impossible to hang the engine.
+				deeper = false; //Set this to false so that we don't go deeper than we need to.
+
+				//Calculate distance of perpendicular ray (oblique distance will give fisheye effect!)
+				if (side == 0) perpWallDist = fabs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX);
+				else       perpWallDist = fabs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);
+				//Calculate height of line to draw on screen
+				int lineHeight = abs(int(h / perpWallDist));
+
+				//calculate lowest and highest pixel to fill in current stripe
+				drawStart = -lineHeight / 2 + h / 2;
+				if (drawStart < 0) drawStart = 0;
+				drawEnd = lineHeight / 2 + h / 2;
+				if (drawEnd >= h) drawEnd = h;
+				//texturing calculations
+				int texNum = wallData[worldMap[mapX][mapY]].texture[texside] - 1; //1 subtracted from it so that texture 0 can be used!
+				if (!opposite) {
+					//calculate value of wallX
+					if (side == 1) wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) / 2) / rayDirY) * rayDirX;
+					else       wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) / 2) / rayDirX) * rayDirY;
+				} else {
+					if (side == 1) wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) / 2) / -rayDirY) * -rayDirX;
+					else       wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) / 2) / -rayDirX) * -rayDirY;
+				}
+				wallX -= floor((wallX));
+
+				//x coordinate on the texture
+				int wall_light = 255;
+				int texX = int(wallX * double(texWidth));
+				if (side == 0 && rayDirX > 0) texX = texWidth - texX - 1;
+				if (side == 1 && rayDirY < 0) texX = texWidth - texX - 1;
+				bool do_ambient = false;
+				if (!opposite) {
+					if (rayDirX > 0 && side == 0) {
+						wall_light = lightMap [(int)mapX - 1 % mapWidth][(int)mapY] << 5;
+						if (ceilingMap [(int)mapX - 1 % mapWidth][(int)mapY] <= 1) do_ambient = true;
+						else if (texture[ceilingMap [(int)mapX - 1 % mapWidth][(int)mapY] - 1][(texWidth * (63 - texX)) + 63] == 0) do_ambient = true;
+					}
+					if (rayDirX < 0 && side == 0) {
+						wall_light = lightMap [(int)mapX + 1 % mapWidth][(int)mapY] << 5;
+						if (ceilingMap [(int)mapX + 1 % mapWidth][(int)mapY] <= 1) do_ambient = true;
+						else if (texture[ceilingMap [(int)mapX + 1 % mapWidth][(int)mapY] - 1][(texWidth * texX) + 0] == 0) do_ambient = true;
+
+					}
+					if (rayDirY > 0 && side == 1) {
+						wall_light = lightMap [(int)mapX][(int)mapY - 1 % mapHeight] << 5;
+						if (ceilingMap [(int)mapX][(int)mapY - 1 % mapHeight] <= 1) do_ambient = true;
+						else if (texture[ceilingMap [(int)mapX][(int)mapY - 1 % mapHeight] - 1][(texWidth * 63) + texX] == 0) do_ambient = true;
+					}
+					if (rayDirY < 0 && side == 1) {
+						wall_light = lightMap [(int)mapX][(int)mapY + 1 % mapHeight] << 5;
+						if (ceilingMap [(int)mapX][(int)mapY + 1 % mapHeight] <= 1) do_ambient = true;
+						else if (texture[ceilingMap [(int)mapX][(int)mapY + 1 % mapHeight] - 1][(texWidth * 0) + 63 - texX] == 0) do_ambient = true;
+					}
+				} else if (opposite) {
+					wall_light = lightMap [(int)mapX][(int)mapY] << 5;
+					if (ceilingMap [(int)mapX][(int)mapY] <= 1) do_ambient = true;
+					if (rayDirX > 0 && side == 0) {
+						if (texture[ceilingMap [(int)mapX][(int)mapY] - 1][(texWidth * (63 - texX)) + 63] == 0) do_ambient = true;
+					}
+					if (rayDirX < 0 && side == 0) {
+						if (texture[ceilingMap [(int)mapX][(int)mapY] - 1][(texWidth * texX) + 63] == 0) do_ambient = true;
+					}
+					if (rayDirY > 0 && side == 1) {
+						if (texture[ceilingMap [(int)mapX][(int)mapY] - 1][(texWidth * 0) + (63 - texX)] == 0) do_ambient = true;
+					}
+					if (rayDirY < 0 && side == 1) {
+						if (texture[ceilingMap [(int)mapX][(int)mapY] - 1][(texWidth * 63) + texX] == 0) do_ambient = true;
+					}
+				}
+				if (do_ambient) {
+					ambientpixels = true;
+					wall_light = MAX(wall_light, ambientlight);
+				}
+				wall_light = MIN(255, MAX(0, wall_light));
+				bool alphastripe = false;
+				for (int y = drawStart; y < drawEnd; y++) {
+					if (ZBuffer[x][y] > perpWallDist || ZBuffer[x][y] == 0) { //We can draw.
+						int d = y * 256 - h * 128 + lineHeight * 128; //256 and 128 factors to avoid floats
+						int texY = ((d * texHeight) / lineHeight) / 256;
+						int color = texture[texNum][texWidth * texY + texX];
+						if (color > 0) {
+							if (ambientpixels && ambientcolor) color = Mix::MixColorMultiply(ambientcolor, color, ambientcolorAmount, 1);
+							if (!wallData[worldMap[mapX][mapY]].ignorelighting[texside] && wall_light < 255) color = Mix::MixColorLightLevel(color, wall_light);
+							if (wallData[worldMap[mapX][mapY]].alpha[texside] == 255 && wallData[worldMap[mapX][mapY]].mask[texside] == 0) {
+								buffer[y][x] = color;
+								if (ambientpixels) ambientweight++;
+								//SET THE ZBUFFER FOR THE SPRITE CASTING
+								ZBuffer[x][y] = perpWallDist; //perpendicular distance is used
+								interactionmap [x * sWidth + y] = wallData[worldMap[mapX][mapY]].hotspotinteract;
+								editorMap [x][y] = ((short)mapX) << 16 | ((short)mapY);
+							} else {
+								if (transslicedrawn[x] == false) {
+									memset(transcolorbuffer[x], 0, sizeof(unsigned char) * (sHeight * mapWidth));
+									memset(transalphabuffer[x], 0, sizeof(unsigned char) * (sHeight * mapWidth));
+									//memset (transzbuffer[x],0,sizeof(double)*(sHeight*mapWidth));
+									transslicedrawn[x] = true;
+								}
+								transwallblendmode[transwallcount] = wallData[worldMap[mapX][mapY]].blendtype[texside];
+								int transwalloffset = transwallcount * h;
+								transcolorbuffer[x][transwalloffset + y] = color;
+								if (ambientpixels) ambientweight++;
+								if (wallData[worldMap[mapX][mapY]].mask[texside] == 0) transalphabuffer[x][transwalloffset + y] = wallData[worldMap[mapX][mapY]].alpha[texside];
+								else {
+									transalphabuffer[x][transwalloffset + y] = (wallData[worldMap[mapX][mapY]].alpha[texside] + texture[wallData[worldMap[mapX][mapY]].mask[texside]][texWidth * texY + texX]) >> 1;
+								}
+								transzbuffer[x][transwalloffset + y] = perpWallDist;
+								hit = 0;
+								deeper = true;
+								alphastripe = true;
+							}
+						} else {
+							//We found transparency, we have to draw deeper.
+							deeper = true;
+							hit = 0;
+						}
+						if ((int)mapX == selectedX && (int)mapY == selectedY) {
+							if (texX == 0 || texX == 63 || texY == 0 || texY == 63) {
+								buffer[y][x] = selectedColor;
+								ZBuffer [x][y] = perpWallDist;
+							}
+						}
+
+					}
+				}
+				if (alphastripe) {
+					if (transwallcount < mapWidth) {
+						transwallcount++;
+					}
+					alphastripe = false;
+				}
+				if (opposite) {
+					if (mapX == 0 || mapX == mapWidth || mapY == 0 || mapY == mapHeight) {
+						deeper = false;
+						hit = 0;
+					}
+					oppositedrawn = true;
+					if (deeper) opposite = false;
+					rayDirX = -rayDirX;
+					rayDirY = -rayDirY;
+					stepX = -stepX;
+					stepY = -stepY;
+				} else if (!opposite && deeper) {
+					opposite = true;
+					prevmapX = mapX;
+					prevmapY = mapY;
+				}
+				//End of wall drawing functions.
+			} else if (opposite) {
+				opposite = false;
+				//oppositedrawn = false;
+				rayDirX = -rayDirX;
+				rayDirY = -rayDirY;
+				stepX = -stepX;
+				stepY = -stepY;
+			} else if (!opposite && deeper) {
+				opposite = true;
+				prevmapX = mapX;
+				prevmapY = mapY;
+			}
+			//End of loop.
+		}
+
+		// Unused variables
+		(void)prevmapX;
+		(void)prevmapY;
+
+		//FLOOR CASTING
+
+		double floorXWall, floorYWall; //x, y position of the floor texel at the bottom of the wall
+		//4 different wall directions possible
+		if (side == 0 && rayDirX > 0) {
+			floorXWall = mapX;
+			floorYWall = mapY + wallX;
+			if (opposite) floorXWall = floorXWall + 1.0;
+		} else if (side == 0 && rayDirX < 0) {
+			floorXWall = mapX + 1.0;
+			floorYWall = mapY + wallX;
+			if (opposite) floorXWall = floorXWall - 1.0;
+		} else if (side == 1 && rayDirY > 0) {
+			floorXWall = mapX + wallX;
+			floorYWall = mapY;
+			if (opposite) floorYWall = floorYWall + 1.0;
+		} else {
+			floorXWall = mapX + wallX;
+			floorYWall = mapY + 1.0;
+			if (opposite) floorYWall = floorYWall - 1.0;
+		}
+
+		double distWall, distPlayer, currentDist;
+
+		distWall = perpWallDist;
+		distPlayer = 0.0;
+		if (drawEnd < 0)
+			drawEnd = h - 1; //becomes < 0 when the integer overflows
+		//draw the floor from drawEnd to the bottom of the screen
+		int drawdist = h;
+		int expandeddraw = h >> 1;
+		for (int y = drawEnd; y < drawdist + expandeddraw; y++) {
+			//currentDist = h / (2.0 * y - h); //you could make a small lookup table for this instead
+			currentDist = distTable[y];
+			if (y > h - 1) {
+				//if (!heightMap) break;
+				double weight = (currentDist - distPlayer) / (distWall - distPlayer);
+
+				double currentFloorX = weight * floorXWall + (1.0 - weight) * posX;
+				double currentFloorY = weight * floorYWall + (1.0 - weight) * posY;
+
+				int floorTexX, floorTexY;
+				int cmapX = (int)currentFloorX;
+				if (cmapX > mapWidth - 1) cmapX = mapWidth - 1;
+				if (cmapX < 0) cmapX = 0;
+				int cmapY = (int)currentFloorY;
+				if (cmapY > mapHeight - 1) cmapY = mapHeight - 1;
+				if (cmapY < 0) cmapY = 0;
+				if (heightMap[cmapX][cmapY] - 1 < 1) continue;
+				int lighting = lightMap [cmapX][cmapY] << 5;
+				lighting = MIN(255, MAX(0, lighting));
+				floorTexX = int(currentFloorX * texWidth) % texWidth;
+				floorTexY = int(currentFloorY * texHeight) % texHeight;
+				int floorcolor = 0;
+				int ceilingcolor = 0;
+				int texpos = texWidth * floorTexY + floorTexX;
+				if (ceilingMap[cmapX][cmapY] - 1 > 0) {
+					ceilingcolor = texture[ceilingMap[cmapX][cmapY] - 1][texWidth * floorTexY + floorTexX];
+				}
+				if (floorMap[cmapX][cmapY] - 1 > 0) {
+					floorcolor = texture[floorMap[cmapX][cmapY] - 1][texpos];
+				} else continue;
+				if (ceilingcolor == 0) {
+					lighting = MAX(lighting, ambientlight);
+					ambientweight ++;
+				}
+				if (lighting < 255) {
+					if (floorcolor) floorcolor = Mix::MixColorLightLevel(floorcolor, lighting);
+				}
+
+				if (/*heightMap &&*/ floorcolor > 0) {
+					if (heightMap[cmapX][cmapY] - 1 > 0) {
+						int raisedfloorstart = y - (int)(texture[heightMap[cmapX][cmapY] - 1][texpos] / currentDist);
+						if (raisedfloorstart > h - 1) continue;
+						if (raisedfloorstart < 0) raisedfloorstart = 0;
+						for (int ny = raisedfloorstart; ny < y; ny++) {
+							if (ny < h && (ZBuffer[x][ny] > currentDist || ZBuffer[x][ny] == 0)) {
+								ZBuffer[x][ny] = currentDist; //perpendicular distance is used
+								buffer[ny][x] = floorcolor;
+								interactionmap [x * sWidth + ny] = 0;
+								editorMap [x][ny] = ((short)mapX) << 16 | ((short)mapY);
+							}
+						}
+						if (raisedfloorstart < y && y == h - 1 && y == h + expandeddraw) expandeddraw ++;
+					}
+				}
+			} else {
+				double weight = (currentDist - distPlayer) / (distWall - distPlayer);
+
+				double currentFloorX = weight * floorXWall + (1.0 - weight) * posX;
+				double currentFloorY = weight * floorYWall + (1.0 - weight) * posY;
+
+				int floorTexX, floorTexY;
+				int cmapX = (int)currentFloorX % mapWidth;
+				if (cmapX < 0) cmapX = 0;
+				int cmapY = (int)currentFloorY % mapHeight;
+				if (cmapY < 0) cmapY = 0;
+				int lighting = lightMap [cmapX][cmapY] << 5;
+				lighting = MIN(255, MAX(0, lighting));
+				floorTexX = int(currentFloorX * texWidth) % texWidth;
+				floorTexY = int(currentFloorY * texHeight) % texHeight;
+				int floorcolor = 0;
+				int ceilingcolor = 0;
+				if (floorMap[cmapX][cmapY] - 1 > 0) {
+					floorcolor = texture[floorMap[cmapX][cmapY] - 1][texWidth * floorTexY + floorTexX];
+				}
+				if (ceilingMap[cmapX][cmapY] - 1 > 0) {
+					ceilingcolor = texture[ceilingMap[cmapX][cmapY] - 1][texWidth * floorTexY + floorTexX];
+				}
+				if (ceilingcolor == 0) {
+					lighting = MAX(lighting, ambientlight);
+					ambientweight++;
+				}
+				if (lighting < 255) {
+					if (floorcolor) floorcolor = Mix::MixColorLightLevel(floorcolor, lighting);
+					if (ceilingcolor) ceilingcolor = Mix::MixColorLightLevel(ceilingcolor, lighting);
+				}
+
+				if (/*heightMap &&*/ floorcolor > 0 && (currentDist < ZBuffer[x][y] || ZBuffer[x][y] == 0)) {
+					if (heightMap[cmapX][cmapY] - 1 > 0) {
+						int raisedfloorstart = y - (int)(texture[heightMap[cmapX][cmapY] - 1][texWidth * floorTexY + floorTexX] / currentDist);
+						if (raisedfloorstart > h - 1) continue;
+						if (raisedfloorstart < 0) raisedfloorstart = 0;
+						for (int ny = raisedfloorstart; ny < y; ny++) {
+							if (ZBuffer[x][ny] > currentDist || ZBuffer[x][ny] == 0) {
+								ZBuffer[x][ny] = currentDist; //perpendicular distance is used
+								buffer[ny][x] = floorcolor;
+								interactionmap [x * sWidth + ny] = 0;
+								editorMap [x][ny] = ((short)cmapX) << 16 | ((short)cmapY);
+							}
+						}
+						if (raisedfloorstart < y && y == h - 1 && y == h + expandeddraw) expandeddraw ++;
+					}
+				}
+				//floor
+				//ceiling (symmetrical!)
+				//SET THE ZBUFFER FOR THE SPRITE CASTING
+				if (floorcolor > 0 && (currentDist < ZBuffer[x][y] || ZBuffer[x][y] == 0)) {
+					ZBuffer[x][y] = currentDist; //perpendicular distance is used
+					buffer[y][x] = floorcolor;
+					editorMap [x][y] = ((short)cmapX) << 16 | ((short)cmapY);
+				} else ZBuffer[x][y] = 9999999999999.0;
+				if (currentDist < ZBuffer[x][h - y] || ZBuffer[x][h - y] == 0) {
+					if (ceilingcolor > 0) {
+						ZBuffer[x][h - y] = currentDist; //perpendicular distance is used
+						buffer[h - y][x] = ceilingcolor;
+					} else ZBuffer[x][h - y] = 999999999999.0;
+					editorMap [x][h - y] = ((short)cmapX) << 16 | ((short)cmapY);
+				}
+				interactionmap [x * sWidth + y] = 0;
+				interactionmap [x * sWidth + (h - y)] = 0;
+				if ((int)cmapX == selectedX && (int)cmapY == selectedY) {
+					if (floorTexX == 0 || floorTexX == 63 || floorTexY == 0 || floorTexY == 63) {
+						buffer[y][x] = selectedColor;
+						ZBuffer [x][y] = perpWallDist;
+						buffer[h - y][x] = selectedColor;
+						ZBuffer [x][h - y] = perpWallDist;
+					}
+				}
+
+
+			}
+		}
+		//TRANSLUCENT WALL RENDERING
+		if (transslicedrawn[x] == true) {
+			for (int y = 0; y < h; y++) {
+				for (int transwalldrawn = 0; transwalldrawn < transwallcount; transwalldrawn++) {
+					int transwalloffset = transwalldrawn * h;
+					int color = transcolorbuffer[x][transwalloffset + y];
+					if (color != 0) {
+						if (transwallblendmode[transwalldrawn] == 0) buffer[y][x] = Mix::MixColorAlpha(color, buffer[y][x], transalphabuffer[x][transwalloffset + y]); //paint pixel if it isn't black, black is the invisible color
+						else if (transwallblendmode[transwalldrawn] == 1) buffer[y][x] = Mix::MixColorAdditive(color, buffer[y][x], transalphabuffer[x][transwalloffset + y]);
+						//if (ZBuffer[x][y] > transzbuffer[transwalldrawn*h+y]) ZBuffer[x][y] = transzbuffer[transwalldrawn*h+y]; //put the sprite on the zbuffer so we can draw around it.
+					}
+				}
+			}
+		}
+		//End of wall loop.
+	}
+
+
+	//SPRITE CASTING
+	//sort sprites from far to close
+
+	//Initialize Sprites for casting.
+	double invDet = 1.0 / (planeX * dirY - dirX * planeY);
+	for (int i = 0; i < numSprites; i++) {
+		spriteOrder[i] = i;
+		spriteTransformY[i] = ((posX - sprite[i].x) * (posX - sprite[i].x) + (posY - sprite[i].y) * (posY - sprite[i].y));
+	}
+	combSort(spriteOrder, spriteTransformY, numSprites);
+	for (int i = 0; i < numSprites; i++) {
+		double spriteX = sprite[spriteOrder[i]].x - posX;
+		double spriteY = sprite[spriteOrder[i]].y - posY;
+		spriteTransformX[i] = invDet * (dirY * spriteX - dirX * spriteY);
+		spriteTransformY[i] = invDet * (-planeY * spriteX + planeX * spriteY);
+	}
+
+	int transwalldraw = 0;
+	//after sorting the sprites, do the projection and draw them
+	for (int i = 0; i < numSprites; i++) {
+		int flipped = 0;
+		if (sprite[spriteOrder[i]].view != 0) {
+
+			double sprrad = atan2(sprite[spriteOrder[i]].y - posY, sprite[spriteOrder[i]].x - posX);
+			int sprdeg = (int)(sprrad / 3.1415 * 180.0);
+			sprdeg = ((sprdeg + 180) + sprite[spriteOrder[i]].angle) % 360;
+			int loop = 0;
+			if (sprdeg > 336 || sprdeg < 23) loop = 0;
+			else if (sprdeg > 22 && sprdeg < 68) loop = 6;
+			else if (sprdeg > 67 && sprdeg < 113) loop = 1;
+			else if (sprdeg > 112 && sprdeg < 158) loop = 7;
+			else if (sprdeg > 157 && sprdeg < 203) loop = 3;
+			else if (sprdeg > 202 && sprdeg < 248) loop = 5;
+			else if (sprdeg > 247 && sprdeg < 293) loop = 2;
+			else if (sprdeg > 292 && sprdeg < 337) loop = 4;
+			AGSViewFrame *vf = engine->GetViewFrame(sprite[spriteOrder[i]].view, loop, sprite[spriteOrder[i]].frame);
+			if (vf == nullptr) engine->AbortGame("Raycast_Render: Unable to load viewframe of sprite.");
+			else {
+				sprite[spriteOrder[i]].texture = vf->pic;
+				int (*sfGetGameParameter)(int, int, int, int);
+				sfGetGameParameter = ((int(*)(int, int, int, int)) engine->GetScriptFunctionAddress("GetGameParameter"));
+				flipped = sfGetGameParameter(13, sprite[spriteOrder[i]].view, loop, sprite[spriteOrder[i]].frame);
+			}
+		}
+		//translate sprite position to relative to camera
+		//double spriteX = sprite[spriteOrder[i]].x - posX;
+		//double spriteY = sprite[spriteOrder[i]].y - posY;
+
+		//transform sprite with the inverse camera matrix
+		// [ planeX   dirX ] -1                                       [ dirY      -dirX ]
+		// [               ]       =  1/(planeX*dirY-dirX*planeY) *   [                 ]
+		// [ planeY   dirY ]                                          [ -planeY  planeX ]
+
+		//double invDet = 1.0 / (planeX * dirY - dirX * planeY); //required for correct matrix multiplication
+		//double spriteX = sprite[spriteOrder[i]].x - posX;
+		//double spriteY = sprite[spriteOrder[i]].y - posY;
+		//double transformX = invDet * (dirY * spriteX - dirX * spriteY);
+		//double transformY = invDet * (-planeY * spriteX + planeX * spriteY); //this is actually the depth inside the screen, that what Z is in 3D
+
+		int spriteScreenX = int((w / 2) * (1 + spriteTransformX[i] / spriteTransformY[i]));
+
+		//parameters for scaling and moving the sprites
+		BITMAP *spritetexbm = engine->GetSpriteGraphic(sprite[spriteOrder[i]].texture);
+		unsigned char **spritetex = engine->GetRawBitmapSurface(spritetexbm);
+		int sprw = engine->GetSpriteWidth(sprite[spriteOrder[i]].texture);
+		int sprh = engine->GetSpriteHeight(sprite[spriteOrder[i]].texture);
+
+		double uDiv = ((double)sprw / (double)texWidth) + sprite[spriteOrder[i]].uDivW;
+		double vDiv = ((double)sprh / (double)texHeight) + sprite[spriteOrder[i]].uDivH;
+		double vMove = sprite[spriteOrder[i]].vMove + ((double)texHeight - (double)sprh) * 1.6;
+		double hMove = sprite[spriteOrder[i]].hMove;
+		int vMoveScreen = int(vMove / spriteTransformY[i]);
+		int hMoveScreen = int(hMove / spriteTransformY[i]);
+		//calculate height of the sprite on screen
+		int spriteHeight = abs(int(h / (spriteTransformY[i]) * vDiv)) ; //using "transformY" instead of the real distance prevents fisheye
+		//calculate lowest and highest pixel to fill in current stripe
+		int drawStartY = -spriteHeight / 2 + h / 2 + vMoveScreen;
+		if (drawStartY < 0) drawStartY = 0;
+		int drawEndY = spriteHeight / 2 + h / 2 + vMoveScreen;
+		if (drawEndY >= h) drawEndY = h - 1;
+
+		//calculate width of the sprite
+		int spriteWidth = abs(int (h / (spriteTransformY[i]) * uDiv)) ;
+		int drawStartX = -spriteWidth / 2 + spriteScreenX + hMoveScreen;
+		if (drawStartX < 0) drawStartX = 0;
+		int drawEndX = spriteWidth / 2 + spriteScreenX + hMoveScreen;
+		if (drawEndX >= w) drawEndX = w - 1;
+		int spr_light = lightMap [(int)sprite[spriteOrder[i]].x][(int)sprite[spriteOrder[i]].y] << 5;
+		spr_light = MIN(255, MAX(0, spr_light));
+		int floorTexX = int(sprite[spriteOrder[i]].x * texWidth) % texWidth;
+		int floorTexY = int(sprite[spriteOrder[i]].y * texHeight) % texHeight;
+		if (ceilingMap [(int)sprite[spriteOrder[i]].x][(int)sprite[spriteOrder[i]].y] == 0) {
+			spr_light = MAX(spr_light, ambientlight);
+		} else if (texture[ceilingMap [(int)sprite[spriteOrder[i]].x][(int)sprite[spriteOrder[i]].y] - 1][texWidth * floorTexY + floorTexX] == 0) spr_light = MAX(spr_light, ambientlight);
+		//loop through every vertical stripe of the sprite on screen
+
+
+		for (int stripe = drawStartX; stripe < drawEndX; stripe++) {
+			transwalldraw = 0;
+			//int texX = int(256 * (stripe - (-spriteWidth / 2 + spriteScreenX)) * texWidth / spriteWidth) / 256;
+			int texX = int(256 * (stripe - (-spriteWidth / 2 + spriteScreenX)) *  sprw / spriteWidth) / 256;
+			if (texX >= sprw || texX < 0) continue;
+			if (flipped) texX = sprw - texX;
+			//the conditions in the if are:
+			//1) it's in front of camera plane so you don't see things behind you
+			//2) it's on the screen (left)
+			//3) it's on the screen (right)
+			//4) ZBuffer, with perpendicular distance
+			if (spriteTransformY[i] > 0 && stripe > 0 && stripe < w)
+				for (int y = drawStartY; y < drawEndY; y++) { //for every pixel of the current stripe
+					if (spriteTransformY[i] < ZBuffer[stripe][y]) {
+						if (transslicedrawn[stripe]) while ((transzbuffer[stripe][transwalldraw * h + y] > spriteTransformY[i] && transzbuffer[stripe][transwalldraw * h + y] != 0) && (transwalldraw < transwallcount)) transwalldraw++;
+						int d = (y - vMoveScreen) * 256 - h * 128 + spriteHeight * 128; //256 and 128 factors to avoid floats
+						//int texY = ((d * texHeight) / spriteHeight) / 256;
+						int texY = ((d * sprh) / spriteHeight) / 256;
+						if (texY >= sprh || texY < 0) continue;
+						//unsigned char color = texture[sprite[spriteOrder[i]].texture][texWidth * texY + texX]; //get current color from the texture
+						unsigned char color = spritetex[texY][texX]; //get current color from the texture
+						if (color != 0) {
+							if (sprite[spriteOrder[i]].alpha < 255) {
+								if (sprite[spriteOrder[i]].blendmode == 0) color = Mix::MixColorAlpha(color, buffer[y][stripe], sprite[spriteOrder[i]].alpha);
+								if (sprite[spriteOrder[i]].blendmode == 1) color = Mix::MixColorAdditive(color, buffer[y][stripe], sprite[spriteOrder[i]].alpha);
+							}
+							color = Mix::MixColorLightLevel(color, spr_light);
+							if (transzbuffer[stripe][transwalldraw * h + y] < spriteTransformY[i] && transzbuffer[stripe][transwalldraw * h + y] != 0 && transslicedrawn[stripe] && transcolorbuffer[stripe][transwalldraw * h + y] > 0 && transalphabuffer[stripe][transwalldraw * h + y] > 0) {
+								if (transwallblendmode[transwalldraw] == 0) color = Mix::MixColorAlpha(color, transcolorbuffer[stripe][transwalldraw * h + y], transalphabuffer[stripe][transwalldraw * h + y]);
+								else if (transwallblendmode[transwalldraw] == 1) color = Mix::MixColorAdditive(color, transcolorbuffer[stripe][transwalldraw * h + y], transalphabuffer[stripe][transwalldraw * h + y]);
+								buffer[y][stripe] = color;
+								ZBuffer[stripe][y] = transzbuffer[stripe][transwalldraw * h + y];
+							} else {
+								buffer[y][stripe] = color; //paint pixel if it isn't black, black is the invisible color
+								ZBuffer[stripe][y] = spriteTransformY[i]; //put the sprite on the zbuffer so we can draw around it.
+							}
+							interactionmap [stripe * sWidth + y] = sprite[spriteOrder[i]].objectinteract << 8;
+						}
+					}
+				}
+		}
+		engine->ReleaseBitmapSurface(spritetexbm);
+	}
+	engine->ReleaseBitmapSurface(screen);
+	engine->NotifySpriteUpdated(slot);
+	rendering = false;
+
+}
+
+void QuitCleanup() {
+	if (!rendering) {
+		for (int i = 0; i < sWidth; ++i) {
+			if (transcolorbuffer[i])delete [] transcolorbuffer[i];
+			if (transalphabuffer[i])delete [] transalphabuffer[i];
+			if (transzbuffer[i])delete [] transzbuffer[i];
+			if (ZBuffer[i]) delete [] ZBuffer[i];
+		}
+		if (transcolorbuffer) delete [] transcolorbuffer;
+		if (transalphabuffer) delete [] transalphabuffer;
+		if (transzbuffer) delete [] transzbuffer;
+		if (ZBuffer) delete [] ZBuffer;
+		if (transwallblendmode) delete [] transwallblendmode;
+		if (interactionmap) delete [] interactionmap;
+	}
+}
+
+void MoveForward() {
+	double newposx = 0;
+	if (dirX > 0) newposx = 0.1 + posX + dirX * moveSpeed;
+	else newposx = -0.1 + posX + dirX * moveSpeed;
+	int texsidex = 0;
+	int inside_texsidex = 0;
+	double newposy = 0;
+	if (dirY > 0) newposy = 0.1 + posY + dirY * moveSpeed;
+	else newposy = -0.1 + posY + dirY * moveSpeed;
+	int texsidey = 0;
+	int inside_texsidey = 0;
+	bool inside = false;
+	if ((int)newposx == (int)posX && (int)newposy == (int)posY) inside = true;
+	if (dirX > 0 && !inside) {
+		texsidex = 0;
+		inside_texsidex = 1;
+	} else if (dirX > 0) {
+		texsidex = 1;
+		inside_texsidex = 0;
+	}
+	if (dirX < 0 && !inside) {
+		texsidex = 1;
+		inside_texsidex = 0;
+	} else if (dirX < 0) {
+		texsidex = 0;
+		inside_texsidex = 1;
+	}
+
+	if (dirY > 0 && !inside) {
+		texsidey = 2;
+		inside_texsidey = 3;
+	} else if (dirY > 0) {
+		texsidey = 3;
+		inside_texsidey = 2;
+	}
+	if (dirY < 0 && !inside) {
+		texsidey = 3;
+		inside_texsidey = 2;
+	} else if (dirY < 0) {
+		texsidey = 2;
+		inside_texsidey = 3;
+	}
+
+	if (!noclip && !inside) {
+		if (wallData[worldMap[int(newposx)][int(posY)]].solid[texsidex] == false && wallData[worldMap[int(posX)][int(posY)]].solid[inside_texsidex] == false && int(newposx) > -1 && int(newposx) < mapWidth) posX += dirX * moveSpeed;
+		if (wallData[worldMap[int(posX)][int(newposy)]].solid[texsidey] == false && wallData[worldMap[int(posX)][int(posY)]].solid[inside_texsidey] == false && int(newposy) > -1 && int(newposy) < mapHeight) posY += dirY * moveSpeed;
+	} else if (!noclip && inside) {
+		posX += dirX * moveSpeed;
+		posY += dirY * moveSpeed;
+	} else {
+		if (int(newposx) > -1 && int(newposx) < mapWidth) posX += dirX * moveSpeed;
+		if (int(newposy) > -1 && int(newposy) < mapHeight) posY += dirY * moveSpeed;
+	}
+}
+
+void MoveBackward() {
+	double newposx = 0;
+	if (dirX > 0) newposx = -0.1 + posX - dirX * moveSpeed;
+	else newposx = 0.1 + posX - dirX * moveSpeed;
+	int texsidex = 0;
+	int inside_texsidex = 0;
+	double newposy = 0;
+	if (dirY > 0) newposy = -0.1 + posY - dirY * moveSpeed;
+	else newposy = 0.1 + posY - dirY * moveSpeed;
+	int texsidey = 0;
+	int inside_texsidey = 0;
+	bool inside = false;
+	if ((int)newposx == (int)posX && (int)newposy == (int)posY) inside = true;
+	if (dirX > 0 && !inside) {
+		texsidex = 1;
+		inside_texsidex = 0;
+	} else if (dirX > 0) {
+		texsidex = 0;
+		inside_texsidex = 1;
+	}
+	if (dirX < 0 && !inside) {
+		texsidex = 0;
+		inside_texsidex = 1;
+	} else if (dirX < 0) {
+		texsidex = 1;
+		inside_texsidex = 0;
+	}
+
+	if (dirY > 0 && !inside) {
+		texsidey = 3;
+		inside_texsidey = 2;
+	} else if (dirY > 0) {
+		texsidey = 2;
+		inside_texsidey = 3;
+	}
+	if (dirY < 0 && !inside) {
+		texsidey = 2;
+		inside_texsidey = 3;
+	} else if (dirY < 0) {
+		texsidey = 3;
+		inside_texsidey = 2;
+	}
+
+	if ((int)posX == (int)newposy && (int)posY == (int)newposy) inside = true;
+	if (!noclip && !inside) {
+		if (wallData[worldMap[int(newposx)][int(posY)]].solid[texsidex] == false && wallData[worldMap[int(posX)][int(posY)]].solid[inside_texsidex] == false && int(newposx) > -1 && int(newposx) < mapWidth) posX -= dirX * moveSpeed;
+		if (wallData[worldMap[int(posX)][int(newposy)]].solid[texsidey] == false && wallData[worldMap[int(posX)][int(posY)]].solid[inside_texsidey] == false && int(newposy) > -1 && int(newposy) < mapHeight) posY -= dirY * moveSpeed;
+	} else if (!noclip && inside) {
+		posX -= dirX * moveSpeed;
+		posY -= dirY * moveSpeed;
+	} else {
+		if (int(newposx) > -1 && int(newposx) < mapWidth) posX -= dirX * moveSpeed;
+		if (int(newposy) > -1 && int(newposy) < mapHeight) posY -= dirY * moveSpeed;
+	}
+}
+
+
+
+/*
+void MoveBackward ()
+{
+      double newposx;
+      if (dirX > 0) newposx = -0.2 + posX - dirX * moveSpeed;
+      else newposx = 0.2 + posX - dirX * moveSpeed;
+      double newposy;
+      if (dirY > 0) newposy = -0.2 + posY - dirY * moveSpeed;
+      else newposy = 0.2 + posY - dirY * moveSpeed;
+      if(worldMap[int(newposx)][int(posY)] == false || worldMap[int(newposx)][int(posY)] > 8) posX -= dirX * moveSpeed;
+      if(worldMap[int(posX)][int(newposy)] == false || worldMap[int(posX)][int(newposy)] > 8) posY -= dirY * moveSpeed;
+}
+*/
+
+void RotateLeft() {
+	double oldDirX = dirX;
+	dirX = dirX * cos(rotSpeed) - dirY * sin(rotSpeed);
+	dirY = oldDirX * sin(rotSpeed) + dirY * cos(rotSpeed);
+	double oldPlaneX = planeX;
+	planeX = planeX * cos(rotSpeed) - planeY * sin(rotSpeed);
+	planeY = oldPlaneX * sin(rotSpeed) + planeY * cos(rotSpeed);
+}
+
+void RotateRight() {
+	double oldDirX = dirX;
+	dirX = dirX * cos(-rotSpeed) - dirY * sin(-rotSpeed);
+	dirY = oldDirX * sin(-rotSpeed) + dirY * cos(-rotSpeed);
+	double oldPlaneX = planeX;
+	planeX = planeX * cos(-rotSpeed) - planeY * sin(-rotSpeed);
+	planeY = oldPlaneX * sin(-rotSpeed) + planeY * cos(-rotSpeed);
+}
+
+//sort algorithm
+void combSort(int *order, double *dist, int amount) {
+	int gap = amount;
+	bool swapped = false;
+	while (gap > 1 || swapped) {
+		//shrink factor 1.3
+		gap = (gap * 10) / 13;
+		if (gap == 9 || gap == 10) gap = 11;
+		if (gap < 1) gap = 1;
+		swapped = false;
+		for (int i = 0; i < amount - gap; i++) {
+			int j = i + gap;
+			if (dist[i] < dist[j]) {
+				SWAP(dist[i], dist[j]);
+				SWAP(order[i], order[j]);
+				swapped = true;
+			}
+		}
+	}
+}
+
+} // namespace AGSPalRender
+} // namespace Plugins
+} // namespace AGS3
+
diff --git a/engines/ags/plugins/ags_pal_render/raycast.h b/engines/ags/plugins/ags_pal_render/raycast.h
index 3e797a37e3..f12947968f 100644
--- a/engines/ags/plugins/ags_pal_render/raycast.h
+++ b/engines/ags/plugins/ags_pal_render/raycast.h
@@ -1,211 +1,211 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef AGS_PLUGINS_AGS_PAL_RENDER_RAYCAST_H
-#define AGS_PLUGINS_AGS_PAL_RENDER_RAYCAST_H
-
-#include "ags/plugins/ags_pal_render/pal_render.h"
-
-namespace AGS3 {
-namespace Plugins {
-namespace AGSPalRender {
-
-#define mapWidth 64
-#define mapHeight 64
-
-struct Sprite {
-	double x;
-	double y;
-	int texture;
-	unsigned char alpha;
-	int blendmode;
-	double uDivW;
-	double uDivH;
-	double vMove;
-	double hMove;
-	char objectinteract;
-	int view;
-	int frame;
-	int angle;
-};
-
-struct wallType {
-	int texture[4];
-	int solid[4];
-	int ignorelighting[4];
-	int alpha[4];
-	int blendtype[4];
-	int mask[4];
-	unsigned char hotspotinteract;
-};
-
-
-extern bool raycastOn;
-extern double posX;
-extern double posY; //x and y start position
-extern double dirX;
-extern double dirY; //initial direction vector
-extern double planeX;
-extern double planeY; //the 2d raycaster version of camera plane
-extern double moveSpeed; //the constant value is in squares/second
-extern double rotSpeed; //the constant value is in radians/second
-extern unsigned char worldMap[64][64];
-extern unsigned char lightMap[64][64];
-extern int ceilingMap[64][64];
-extern int floorMap[64][64];
-extern int heightMap[64][64];
-extern unsigned char seenMap[64][64];
-//extern int mapWidth;
-//extern int mapHeight;
-extern int textureSlot;
-extern int ambientlight;
-
-#define numSprites 256
-extern Sprite sprite[numSprites];
-
-
-#define texWidth 64
-#define texHeight 64
-#define MAX_TEXTURES 512
-extern unsigned char texture[][texWidth * texHeight];
-
-extern bool heightmapOn;
-
-
-extern wallType wallData[256];
-
-//arrays used to sort the sprites
-extern unsigned char **transcolorbuffer;
-extern unsigned char **transalphabuffer;
-extern double **transzbuffer;
-extern bool *transslicedrawn;
-extern int *transwallblendmode;
-extern double **ZBuffer;
-extern double *distTable;
-extern short *interactionmap;
-extern int skybox;
-
-
-
-void MakeTextures(int slot);
-void Raycast_Render(int slot);
-void MoveForward();
-void MoveBackward();
-void RotateLeft();
-void RotateRight();
-void Init_Raycaster();
-void QuitCleanup();
-void LoadMap(int worldmapSlot, int lightmapSlot, int ceilingmapSlot, int floormapSlot);
-void Ray_InitSprite(int id, SCRIPT_FLOAT(x), SCRIPT_FLOAT(y), int slot, unsigned char alpha, int blendmode, SCRIPT_FLOAT(scale_x), SCRIPT_FLOAT(scale_y), SCRIPT_FLOAT(vMove));
-void Ray_SetPlayerPosition(SCRIPT_FLOAT(x), SCRIPT_FLOAT(y));
-FLOAT_RETURN_TYPE Ray_GetPlayerX();
-FLOAT_RETURN_TYPE Ray_GetPlayerY();
-int Ray_GetPlayerAngle();
-void Ray_SetPlayerAngle(int angle);
-
-int Ray_GetWallHotspot(int id);
-int Ray_GetWallTexture(int id, int dir);
-int Ray_GetWallSolid(int id, int dir);
-int Ray_GetWallIgnoreLighting(int id, int dir);
-int Ray_GetWallAlpha(int id, int dir);
-int Ray_GetWallBlendType(int id, int dir);
-
-void Ray_SelectTile(int x, int y, unsigned char color);
-
-int Ray_GetHotspotAt(int x, int y);
-int Ray_GetObjectAt(int x, int y);
-
-void Ray_DrawTile(int spr, int tile);
-void Ray_DrawOntoTile(int spr, int tile);
-void Ray_SetNoClip(int value);
-int Ray_GetNoClip();
-void Ray_SetSpriteInteractObj(int id, int obj);
-int  Ray_GetSpriteInteractObj(int id);
-void Ray_SetSpritePosition(int id, SCRIPT_FLOAT(x), SCRIPT_FLOAT(y));
-void Ray_SetSpriteVertOffset(int id, SCRIPT_FLOAT(vMove));
-FLOAT_RETURN_TYPE Ray_GetSpriteVertOffset(int id);
-FLOAT_RETURN_TYPE Ray_GetSpriteX(int id);
-FLOAT_RETURN_TYPE Ray_GetSpriteY(int id);
-
-void Ray_SetWallHotspot(int id, char hotsp);
-void Ray_SetWallTextures(int id, int n, int s, int w, int e);
-void Ray_SetWallSolid(int id, int n, int s, int w, int e);
-void Ray_SetWallIgnoreLighting(int id, int n, int s, int w, int e);
-void Ray_SetWallAlpha(int id, int n, int s, int w, int e);
-void Ray_SetWallBlendType(int id, int n, int s, int w, int e);
-
-FLOAT_RETURN_TYPE Ray_GetMoveSpeed();
-void Ray_SetMoveSpeed(SCRIPT_FLOAT(speed));
-FLOAT_RETURN_TYPE Ray_GetRotSpeed();
-void Ray_SetRotSpeed(SCRIPT_FLOAT(speed));
-int Ray_GetWallAt(int x, int y);
-int Ray_GetLightAt(int x, int y);
-void Ray_SetLightAt(int x, int y, int light);
-void Ray_SetWallAt(int x, int y, int id);
-void Ray_SetPlaneY(SCRIPT_FLOAT(y));
-FLOAT_RETURN_TYPE Ray_GetDistanceAt(int x, int y);
-int Ray_GetSpriteAngle(int id);
-void Ray_SetSpriteAngle(int id, int angle);
-void Ray_SetSpriteView(int id, int view);
-int Ray_GetSpriteView(int id);
-void Ray_SetSpriteFrame(int id, int frame);
-int Ray_GetSpriteFrame(int id);
-
-int Ray_GetTileX_At(int x, int y);
-int Ray_GetTileY_At(int x, int y);
-
-void Ray_SetSkyBox(int slot);
-int Ray_GetSkyBox(int slot);
-
-void Ray_SetAmbientLight(int value);
-int Ray_GetAmbientLight();
-void Ray_SetAmbientColor(int color, int amount);
-
-
-int Ray_GetSpriteAlpha(int id);
-void Ray_SetSpriteAlpha(int id, int alpha);
-int Ray_GetSpritePic(int id);
-void Ray_SetSpritePic(int id, int slot);
-
-FLOAT_RETURN_TYPE Ray_GetSpriteScaleX(int id);
-void Ray_SetSpriteScaleX(int id, SCRIPT_FLOAT(scale));
-FLOAT_RETURN_TYPE Ray_GetSpriteScaleY(int id);
-void Ray_SetSpriteScaleY(int id, SCRIPT_FLOAT(scale));
-
-void Ray_SetSpriteBlendType(int id, int type);
-int Ray_GetSpriteBlendType(int id);
-
-void Ray_SetFloorAt(int x, int y, int tex);
-void Ray_SetCeilingAt(int x, int y, int tex);
-int Ray_GetCeilingAt(int x, int y);
-int Ray_GetFloorAt(int x, int y);
-int Ray_GetLightingAt(int x, int y);
-void Ray_SetLightingAt(int x, int y, unsigned char lighting);
-int Ray_GetAmbientWeight();
-
-int Ray_HasSeenTile(int x, int y);
-
-} // namespace AGSPalRender
-} // namespace Plugins
-} // namespace AGS3
-
-#endif
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or(at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef AGS_PLUGINS_AGS_PAL_RENDER_RAYCAST_H
+#define AGS_PLUGINS_AGS_PAL_RENDER_RAYCAST_H
+
+#include "ags/plugins/ags_pal_render/pal_render.h"
+
+namespace AGS3 {
+namespace Plugins {
+namespace AGSPalRender {
+
+#define mapWidth 64
+#define mapHeight 64
+
+struct Sprite {
+	double x;
+	double y;
+	int texture;
+	unsigned char alpha;
+	int blendmode;
+	double uDivW;
+	double uDivH;
+	double vMove;
+	double hMove;
+	char objectinteract;
+	int view;
+	int frame;
+	int angle;
+};
+
+struct wallType {
+	int texture[4];
+	int solid[4];
+	int ignorelighting[4];
+	int alpha[4];
+	int blendtype[4];
+	int mask[4];
+	unsigned char hotspotinteract;
+};
+
+
+extern bool raycastOn;
+extern double posX;
+extern double posY; //x and y start position
+extern double dirX;
+extern double dirY; //initial direction vector
+extern double planeX;
+extern double planeY; //the 2d raycaster version of camera plane
+extern double moveSpeed; //the constant value is in squares/second
+extern double rotSpeed; //the constant value is in radians/second
+extern unsigned char worldMap[64][64];
+extern unsigned char lightMap[64][64];
+extern int ceilingMap[64][64];
+extern int floorMap[64][64];
+extern int heightMap[64][64];
+extern unsigned char seenMap[64][64];
+//extern int mapWidth;
+//extern int mapHeight;
+extern int textureSlot;
+extern int ambientlight;
+
+#define numSprites 256
+extern Sprite sprite[numSprites];
+
+
+#define texWidth 64
+#define texHeight 64
+#define MAX_TEXTURES 512
+extern unsigned char texture[][texWidth * texHeight];
+
+extern bool heightmapOn;
+
+
+extern wallType wallData[256];
+
+//arrays used to sort the sprites
+extern unsigned char **transcolorbuffer;
+extern unsigned char **transalphabuffer;
+extern double **transzbuffer;
+extern bool *transslicedrawn;
+extern int *transwallblendmode;
+extern double **ZBuffer;
+extern double *distTable;
+extern short *interactionmap;
+extern int skybox;
+
+
+
+void MakeTextures(int slot);
+void Raycast_Render(int slot);
+void MoveForward();
+void MoveBackward();
+void RotateLeft();
+void RotateRight();
+void Init_Raycaster();
+void QuitCleanup();
+void LoadMap(int worldmapSlot, int lightmapSlot, int ceilingmapSlot, int floormapSlot);
+void Ray_InitSprite(int id, SCRIPT_FLOAT(x), SCRIPT_FLOAT(y), int slot, unsigned char alpha, int blendmode, SCRIPT_FLOAT(scale_x), SCRIPT_FLOAT(scale_y), SCRIPT_FLOAT(vMove));
+void Ray_SetPlayerPosition(SCRIPT_FLOAT(x), SCRIPT_FLOAT(y));
+FLOAT_RETURN_TYPE Ray_GetPlayerX();
+FLOAT_RETURN_TYPE Ray_GetPlayerY();
+int Ray_GetPlayerAngle();
+void Ray_SetPlayerAngle(int angle);
+
+int Ray_GetWallHotspot(int id);
+int Ray_GetWallTexture(int id, int dir);
+int Ray_GetWallSolid(int id, int dir);
+int Ray_GetWallIgnoreLighting(int id, int dir);
+int Ray_GetWallAlpha(int id, int dir);
+int Ray_GetWallBlendType(int id, int dir);
+
+void Ray_SelectTile(int x, int y, unsigned char color);
+
+int Ray_GetHotspotAt(int x, int y);
+int Ray_GetObjectAt(int x, int y);
+
+void Ray_DrawTile(int spr, int tile);
+void Ray_DrawOntoTile(int spr, int tile);
+void Ray_SetNoClip(int value);
+int Ray_GetNoClip();
+void Ray_SetSpriteInteractObj(int id, int obj);
+int  Ray_GetSpriteInteractObj(int id);
+void Ray_SetSpritePosition(int id, SCRIPT_FLOAT(x), SCRIPT_FLOAT(y));
+void Ray_SetSpriteVertOffset(int id, SCRIPT_FLOAT(vMove));
+FLOAT_RETURN_TYPE Ray_GetSpriteVertOffset(int id);
+FLOAT_RETURN_TYPE Ray_GetSpriteX(int id);
+FLOAT_RETURN_TYPE Ray_GetSpriteY(int id);
+
+void Ray_SetWallHotspot(int id, char hotsp);
+void Ray_SetWallTextures(int id, int n, int s, int w, int e);
+void Ray_SetWallSolid(int id, int n, int s, int w, int e);
+void Ray_SetWallIgnoreLighting(int id, int n, int s, int w, int e);
+void Ray_SetWallAlpha(int id, int n, int s, int w, int e);
+void Ray_SetWallBlendType(int id, int n, int s, int w, int e);
+
+FLOAT_RETURN_TYPE Ray_GetMoveSpeed();
+void Ray_SetMoveSpeed(SCRIPT_FLOAT(speed));
+FLOAT_RETURN_TYPE Ray_GetRotSpeed();
+void Ray_SetRotSpeed(SCRIPT_FLOAT(speed));
+int Ray_GetWallAt(int x, int y);
+int Ray_GetLightAt(int x, int y);
+void Ray_SetLightAt(int x, int y, int light);
+void Ray_SetWallAt(int x, int y, int id);
+void Ray_SetPlaneY(SCRIPT_FLOAT(y));
+FLOAT_RETURN_TYPE Ray_GetDistanceAt(int x, int y);
+int Ray_GetSpriteAngle(int id);
+void Ray_SetSpriteAngle(int id, int angle);
+void Ray_SetSpriteView(int id, int view);
+int Ray_GetSpriteView(int id);
+void Ray_SetSpriteFrame(int id, int frame);
+int Ray_GetSpriteFrame(int id);
+
+int Ray_GetTileX_At(int x, int y);
+int Ray_GetTileY_At(int x, int y);
+
+void Ray_SetSkyBox(int slot);
+int Ray_GetSkyBox(int slot);
+
+void Ray_SetAmbientLight(int value);
+int Ray_GetAmbientLight();
+void Ray_SetAmbientColor(int color, int amount);
+
+
+int Ray_GetSpriteAlpha(int id);
+void Ray_SetSpriteAlpha(int id, int alpha);
+int Ray_GetSpritePic(int id);
+void Ray_SetSpritePic(int id, int slot);
+
+FLOAT_RETURN_TYPE Ray_GetSpriteScaleX(int id);
+void Ray_SetSpriteScaleX(int id, SCRIPT_FLOAT(scale));
+FLOAT_RETURN_TYPE Ray_GetSpriteScaleY(int id);
+void Ray_SetSpriteScaleY(int id, SCRIPT_FLOAT(scale));
+
+void Ray_SetSpriteBlendType(int id, int type);
+int Ray_GetSpriteBlendType(int id);
+
+void Ray_SetFloorAt(int x, int y, int tex);
+void Ray_SetCeilingAt(int x, int y, int tex);
+int Ray_GetCeilingAt(int x, int y);
+int Ray_GetFloorAt(int x, int y);
+int Ray_GetLightingAt(int x, int y);
+void Ray_SetLightingAt(int x, int y, unsigned char lighting);
+int Ray_GetAmbientWeight();
+
+int Ray_HasSeenTile(int x, int y);
+
+} // namespace AGSPalRender
+} // namespace Plugins
+} // namespace AGS3
+
+#endif


Commit: bfe16d0ed420992d2c9d42bedb0edeb8f483260e
    https://github.com/scummvm/scummvm/commit/bfe16d0ed420992d2c9d42bedb0edeb8f483260e
Author: Ori Avtalion (ori at avtalion.name)
Date: 2021-02-11T20:31:17+02:00

Commit Message:
AGS: Silence clang warnings

Changed paths:
    engines/ags/engine/script/cc_instance.cpp
    engines/ags/game_scanner.cpp
    engines/ags/plugins/ags_pal_render/ags_pal_render.cpp
    engines/ags/plugins/ags_pal_render/pal_render.h


diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index cab7c8f729..6a2a70a7cd 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -252,15 +252,13 @@ ccInstance *ccInstance::Fork() {
 }
 
 void ccInstance::Abort() {
-	if ((this != nullptr) && (pc != 0))
+	if (pc != 0)
 		flags |= INSTF_ABORTED;
 }
 
 void ccInstance::AbortAndDestroy() {
-	if (this != nullptr) {
-		Abort();
-		flags |= INSTF_FREE;
-	}
+	Abort();
+	flags |= INSTF_FREE;
 }
 
 #define ASSERT_STACK_SPACE_AVAILABLE(N) \
diff --git a/engines/ags/game_scanner.cpp b/engines/ags/game_scanner.cpp
index 0d4ccc69d5..ef19dcbba5 100644
--- a/engines/ags/game_scanner.cpp
+++ b/engines/ags/game_scanner.cpp
@@ -51,10 +51,10 @@ void GameScanner::scan(const Common::String &startFolder) {
 	if (!_oldGames.empty()) {
 		debug("// Pre 2.5 games that aren't supported");
 		for (EntryArray::iterator it = _oldGames.begin(); it != _oldGames.end(); ++it) {
-			debug("UNSUPPORTED_ENTRY(\"\", \"%s\", \"%s\", %u),",
+			debug("UNSUPPORTED_ENTRY(\"\", \"%s\", \"%s\", %lu),",
 				it->_filename.c_str(), it->_md5.c_str(), it->_filesize);
 		}
-		debug("");
+		debugN("\n");
 	}
 
 	debug("// 2.5+ games that should be supported");
@@ -64,14 +64,14 @@ void GameScanner::scan(const Common::String &startFolder) {
 			debug("{ \"%s\", \"%s\" },", it->_id.c_str(), it->_gameName.c_str());
 		gameDescs[it->_id] = true;
 	}
-	debug("");
+	debugN("\n");
 
 	for (EntryArray::iterator it = _games.begin(); it != _games.end(); ++it) {
-		debug("ENGLISH_ENTRY(\"%s\", \"%s\", \"%s\", %u),",
+		debug("ENGLISH_ENTRY(\"%s\", \"%s\", \"%s\", %lu),",
 			it->_id.c_str(), it->_filename.c_str(),
 			it->_md5.c_str(), it->_filesize);
 	}
-	debug("");
+	debugN("\n");
 }
 
 void GameScanner::scanFolder(const Common::FSNode &folder) {
diff --git a/engines/ags/plugins/ags_pal_render/ags_pal_render.cpp b/engines/ags/plugins/ags_pal_render/ags_pal_render.cpp
index 6680a187d9..99316a3bd0 100644
--- a/engines/ags/plugins/ags_pal_render/ags_pal_render.cpp
+++ b/engines/ags/plugins/ags_pal_render/ags_pal_render.cpp
@@ -1,1849 +1,1849 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "ags/lib/allegro.h"
-#include "ags/plugins/ags_pal_render/ags_pal_render.h"
-#include "ags/plugins/ags_pal_render/pal_render.h"
-#include "ags/plugins/ags_pal_render/raycast.h"
-#include "ags/ags.h"
-
-namespace AGS3 {
-namespace Plugins {
-namespace AGSPalRender {
-
-#define MAX_OVERLAYS 128
-#define MAX_STARS 1024
-#define MAX_DEPTH 64
-
-#define PI         (3.1415926535f)
-#define HALF_PI    (0.5f * PI)
-#define TWO_PI     (2.0f * PI)
-#define TWO_PI_INV (1.0f / TWO_PI)
-
-const float halfpi = (0.5f * PI);
-const float twopi  = (2.0f * PI);
-const float twopi_inv = (1.0f / TWO_PI);
-const float pisquared = PI * PI;
-const float picubed = PI * PI * PI;
-
-IAGSEngine *engine;
-
-//unsigned char clut[256][256];
-unsigned char clut[65536];
-
-struct transoverlaytype {
-	int sprite;
-	int spritemask;
-	int blendtype;
-	int x;
-	int y;
-	int trans;
-	int level;
-	bool enabled;
-} overlay[MAX_OVERLAYS];
-
-int clutslot;
-int drawreflections;
-unsigned char cycle_remap [256];
-
-struct starstype {
-	float x;
-	float y;
-	float z;
-	unsigned char color;
-	long sprite;
-	int maxrad;
-	int scaleboost;
-};
-starstype *stars;
-
-struct starsoptions {
-	float speed;
-	int maxstars;
-	int depthmultiplier;
-	int originx;
-	int originy;
-	int overscan;
-} Starfield;
-long *reflectionmap;
-BITMAP *rcolormap;
-BITMAP *ralphamap;
-
-struct charrefopt {
-	char reflect;
-	int replaceview;
-};
-
-struct objrefopt {
-	char reflect;
-	char ignorescaling;
-};
-
-struct reflectionopt {
-	charrefopt *Characters;
-	objrefopt *Objects;
-	int blendslot;
-	int blendamount;
-} Reflection;
-
-int dummy;
-
-#define LENS_WIDTH 150
-
-struct LensDistort {
-	int xoffset;
-	int yoffset;
-};
-
-LensDistort *lens;
-struct LensOpt {
-	bool draw;
-	int lenswidth;
-	int lenszoom;
-	int level;
-	int x;
-	int y;
-	int clampoffset;
-} LensOption;
-
-const int alphamultiply [4096] = {
-//#include "alphamultiply.txt"
-};
-float rot_sine_LUT[360];
-float rot_cos_LUT[360];
-
-BITMAP *backgroundimage;
-
-PALSTRUCT objectivepal[256];
-int bgimgspr;
-
-void WriteObjectivePalette(unsigned char index, unsigned char r, unsigned char b, unsigned char g) {
-	objectivepal[index].r = r;
-	objectivepal[index].b = b;
-	objectivepal[index].g = g;
-}
-
-int ReadObjectivePaletteR(unsigned char index) {
-	return objectivepal[index].r;
-}
-
-int ReadObjectivePaletteB(unsigned char index) {
-	return objectivepal[index].b;
-}
-int ReadObjectivePaletteG(unsigned char index) {
-	return objectivepal[index].g;
-}
-
-
-#define SQRT_MAGIC_F 0x5f3759df
-float  q3sqrt(const float x) {
-	const float xhalf = 0.5f * x;
-
-	union { // get bits for floating value
-		float x;
-		int i;
-	} u;
-	u.x = x;
-	u.i = SQRT_MAGIC_F - (u.i >> 1);  // gives initial guess y0
-	return x * u.x * (1.5f - xhalf * u.x * u.x); // Newton step, repeating increases accuracy
-}
-
-void Make_Sin_Lut() {
-	for (int angle = 0; angle < 360; angle++) {
-		double rad = (angle * PI) / 180.0;
-		rot_sine_LUT [angle] = static_cast<float>(sin(rad));
-		rot_cos_LUT [angle]  = static_cast<float>(cos(rad));
-	}
-}
-
-/*
-void PreMultiply_Alphas () //Ha ha, this isn't the kind of premultiplcation you're thinking of.
-{
-    for (int y=0;y<64;y++)
-        for (int x=0;x<64;x++)
-            alphamultiply [y*64+x] = y*x;
-}
-*/
-
-int GetModifiedBackgroundImage() {
-	return bgimgspr;
-}
-
-unsigned short root(unsigned short x) {
-	unsigned short a, b;
-	b = x;
-	a = x = 0x3f;
-	x = b / x;
-	a = x = (x + a) >> 1;
-	x = b / x;
-	a = x = (x + a) >> 1;
-	x = b / x;
-	x = (x + a) >> 1;
-	return (x);
-}
-
-
-float Hill(float x) {
-	const float a0 = 1.0f;
-	const float a2 = 2.0f / PI - 12.0f / (pisquared);
-	const float a3 = 16.0f / (picubed) - 4.0f / (pisquared);
-	const float xx = x * x;
-	const float xxx = xx * x;
-
-	return a0 + a2 * xx + a3 * xxx;
-}
-
-float FastSin(float x) {
-	// wrap x within [0, TWO_PI)
-	const float a = x * twopi_inv;
-	x -= static_cast<int>(a) * twopi;
-	if (x < 0.0f)
-		x += twopi;
-
-	// 4 pieces of hills
-	if (x < halfpi)
-		return Hill(halfpi - x);
-	else if (x < PI)
-		return Hill(x - halfpi);
-	else if (x < 3.0f * halfpi)
-		return -Hill(3.0f * halfpi - x);
-	else
-		return -Hill(x - 3.0f * halfpi);
-}
-
-float FastCos(float x) {
-	return FastSin(x + halfpi);
-}
-
-FLOAT_RETURN_TYPE AGSFastSin(SCRIPT_FLOAT(x)) {
-	INIT_SCRIPT_FLOAT(x);
-	x = FastSin(x);
-	RETURN_FLOAT(x);
-}
-
-FLOAT_RETURN_TYPE AGSFastCos(SCRIPT_FLOAT(x)) {
-	INIT_SCRIPT_FLOAT(x);
-	x = FastSin(x + halfpi);
-	RETURN_FLOAT(x);
-}
-
-
-void DrawLens(int ox, int oy) {
-	int32 sh, sw = 0;
-	engine->GetScreenDimensions(&sw, &sh, nullptr);
-	BITMAP *virtsc = engine->GetVirtualScreen();
-	if (!virtsc) engine->AbortGame("DrawLens: Cannot get virtual screen.");
-	BITMAP *lenswrite = engine->CreateBlankBitmap(LensOption.lenswidth, LensOption.lenswidth, 8);
-	unsigned char **vScreen = engine->GetRawBitmapSurface(virtsc);
-	unsigned char **lensarray = engine->GetRawBitmapSurface(lenswrite);
-	int radius = LensOption.lenswidth >> 1;
-	for (int y = 0; y < LensOption.lenswidth; y++) {
-		int ypos = y * LensOption.lenswidth;
-		for (int x = 0; x < LensOption.lenswidth; x++) {
-			int lenspos = ypos + x;
-			int coffx = lens[lenspos].xoffset;
-			int coffy = lens[lenspos].yoffset;
-			if (oy + coffy > 0 && oy + coffy < sh && ox + coffx > 0 && ox + coffx < sw) {
-				lensarray[y][x] = vScreen[oy + coffy][ox + coffx];
-				//vScreen[oy+coffy][ox+coffx] = ABS(coffy);
-			}
-		}
-	}
-	/*
-	for (int y=0;y<LensOption.lenswidth;y++)
-	{
-	    int ypos = y*LensOption.lenswidth;
-	    for (int x=0;x<LensOption.lenswidth;x++)
-	    {
-	        if (oy+y > 0 && oy+y < sh && ox+x > 0 && ox+x < sw)
-	        {
-	            vScreen[oy+y][ox+x] = lensarray[y][x];
-	        }
-	    }
-	}
-	*/
-	int radsq = radius * radius;
-	for (int cy = -radius; cy <= radius; cy++) { //Draw a circle around the point, for the mask.
-		int cysq = cy * cy;
-		for (int cx = -radius; cx <= radius; cx++) {
-			int cxsq = cx * cx;
-			int dx = cx + ox;
-			int dy = cy + oy;
-			if ((cxsq + cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0 && cy + radius < LensOption.lenswidth - 1 && cx + radius < LensOption.lenswidth - 1) {
-				//if (cy+radius < 0 || cx+radius < 0) engine->AbortGame ("I did something wrong");
-				vScreen[dy][dx] = lensarray[cy + radius][cx + radius];
-			}
-		}
-	}
-
-	engine->ReleaseBitmapSurface(lenswrite);
-	engine->ReleaseBitmapSurface(virtsc);
-	engine->FreeBitmap(lenswrite);
-}
-
-void SetLensPos(int x, int y) {
-	LensOption.x = x;
-	LensOption.y = y;
-}
-
-int GetLensX() {
-	return LensOption.x;
-}
-
-int GetLensY() {
-	return LensOption.y;
-}
-
-void SetLensDrawn(int toggle) {
-	if (toggle > 0) LensOption.draw = 1;
-	else LensOption.draw = 0;
-}
-
-int GetLensDrawn() {
-	return LensOption.draw;
-}
-
-void SetLensOffsetClamp(int clamp) {
-	if (clamp < 0) LensOption.clampoffset = LensOption.lenswidth;
-	else LensOption.clampoffset = clamp;
-}
-
-int GetLensOffsetClamp() {
-	return LensOption.clampoffset;
-}
-
-int GetLensLevel() {
-	return LensOption.level;
-}
-
-void SetLensLevel(int level) {
-	if (level < 0 || level > 4) engine->AbortGame("SetLensLevel: Invalid level.");
-	else LensOption.level = level;
-}
-
-void LensInitialize(int width, int zoom, int lensx, int lensy, int level, int clamp = -1) {
-	int32 sw, sh, radius;
-	if (width < 1) engine->AbortGame("Invalid lens dimension!");
-	radius = width >> 1;
-	lens = new LensDistort [width * width]();
-	engine->GetScreenDimensions(&sw, &sh, nullptr);
-	int radsq = radius * radius;
-	int zoomsq = zoom * zoom;
-	for (int y = 0; y < radius; y++) {
-		int ysq = y * y;
-		for (int x = 0; x < radius; x++) {
-			int lx, ly;
-			int xsq = x * x;
-			if ((xsq + ysq) < (radsq)) {
-				float shift = zoom / sqrt((float)(zoomsq - (xsq + ysq - radsq)));
-				lx = (int)(x * shift - x);
-				ly = (int)(y * shift - y);
-			} else {
-				lx = 0;
-				ly = 0;
-			}
-			lens[(radius - y)*width + (radius - x)].xoffset =  lx;
-			lens[(radius - y)*width + (radius - x)].yoffset =  ly;
-			lens[(radius + y)*width + (radius + x)].xoffset = -lx;
-			lens[(radius + y)*width + (radius + x)].yoffset = -ly;
-			lens[(radius + y)*width + (radius - x)].xoffset =  lx;
-			lens[(radius + y)*width + (radius - x)].yoffset = -ly;
-			lens[(radius - y)*width + (radius + x)].xoffset = -lx;
-			lens[(radius - y)*width + (radius + x)].yoffset =  ly;
-		}
-	}
-	LensOption.lenswidth = width;
-	LensOption.lenszoom = zoom;
-	if (clamp < 0) LensOption.clampoffset = width;
-	else LensOption.clampoffset = clamp;
-	LensOption.x = lensx;
-	LensOption.y = lensy;
-	if (level < 0 || level > 4) engine->AbortGame("SetLensLevel: Invalid level.");
-	else LensOption.level = level;
-}
-
-void ResetRemapping() {
-	for (int j = 0; j < 256; ++j) {
-		cycle_remap [j] = j;
-	}
-}
-
-#define MAX_PLASMA_COMPLEXITY 4
-int plasmatype[MAX_PLASMA_COMPLEXITY];
-int plasmadata [MAX_PLASMA_COMPLEXITY];
-int plasmadata2 [MAX_PLASMA_COMPLEXITY];
-int plasmadata3 [MAX_PLASMA_COMPLEXITY];
-int plasmaroottype;
-
-
-void SetPlasmaRootType(int real) {
-	if (real) plasmaroottype = 1;
-	else plasmaroottype = 0;
-}
-
-int GetPlasmaRootType() {
-	return plasmaroottype;
-}
-
-void SetPlasmaType(int component, int type, int data, int data2, int data3) {
-	if (component >= MAX_PLASMA_COMPLEXITY) engine->AbortGame("Plasma too complex!");
-	else {
-		plasmatype [component] = type;
-		plasmadata [component] = data;
-		plasmadata2[component] = data2;
-		plasmadata3[component] = data3;
-	}
-
-	//0 = None.
-	//1 = Horizontal Bars (data=width)
-	//2 = Vertical Bars (data=width)
-	//3 = Circle (data=x,data2=y,data3=width)
-	//4 = Diagonal Bars (data=width)
-}
-
-void ResetPlasmaSettings() {
-	int i = 0;
-	while (i < MAX_PLASMA_COMPLEXITY) {
-		plasmatype [i] = 0;
-		plasmadata [i] = 0;
-		plasmadata2[i] = 0;
-		plasmadata3[i] = 0;
-		i++;
-	}
-}
-
-void DrawPlasma(int slot, int palstart, int palend) {
-	BITMAP *plasmaspr = engine->GetSpriteGraphic(slot);
-	if (!plasmaspr) engine->AbortGame("Plasma: Not a sprite I can load.");
-	int32 w, h, basecol, range = 0;
-	if (palend > palstart) {
-		range = palend - palstart;
-		basecol = palstart;
-	} else {
-		range = palstart - palend;
-		basecol = palend;
-	}
-	engine->GetBitmapDimensions(plasmaspr, &w, &h, nullptr);
-	unsigned char **plasmarray = engine->GetRawBitmapSurface(plasmaspr);
-	double frange = range / 2.0;
-	int complex = 0;
-	int color = 0;
-	int i = 0;
-	while (i < MAX_PLASMA_COMPLEXITY) {
-		if (plasmatype[i] > 0) complex++;
-		i++;
-	}
-	for (int x = 0; x < w; x++) {
-		for (int y = 0; y < h; y++) {
-			color = 0;
-			for (int p = 0; p < MAX_PLASMA_COMPLEXITY; p++) {
-				if (plasmatype[p] == 1) { //1 = Horizontal Bars (data=width)
-					color += int(frange + (frange * FastSin(y / (float)plasmadata[p])));
-				} else if (plasmatype[p] == 2) { //2 = Vertical Bars (data=width)
-					color += int(frange + (frange * FastSin(x / (float)plasmadata[p])));
-				} else if (plasmatype[p] == 3) { //3 = Circle (data=x,data2=y,data3=width)
-					int cx, cy = 0;
-					cx = plasmadata [p];
-					cy = plasmadata2 [p];
-					if (plasmaroottype == 1) color += int(frange + (frange * FastSin(q3sqrt((float)((x - cx) * (x - cx) + (y - cy) * (y - cy)) / plasmadata3[p]))));
-					else color += int(frange + (frange * FastSin(root(((x - cx) * (x - cx) + (y - cy) * (y - cy)) / plasmadata3[p]))));
-				} else if (plasmatype[p] == 4) { //4 = Diagonal Bars (data=width)
-					color += int(frange + (frange * FastSin((x + y) / (float)plasmadata[p])));
-				}
-			}
-			if (color > 0 && complex > 0) color = color / complex;
-			plasmarray[y][x] = static_cast<unsigned char>(basecol + color);
-		}
-	}
-	engine->ReleaseBitmapSurface(plasmaspr);
-	engine->NotifySpriteUpdated(slot);
-}
-
-void DoFire(int spriteId, int masksprite, int palstart, int palend, int strength, int seed, int cutoff, int windspeed) {
-	BITMAP *firespr = engine->GetSpriteGraphic(masksprite);
-	BITMAP *firecolorspr = engine->GetSpriteGraphic(spriteId);
-	BITMAP *seedspr;
-	int32 w, h = 0;
-	int range, basecol, dir = 0;
-	if (palend > palstart) {
-		range = palend - palstart;
-		basecol = palstart;
-		dir = 1;
-	} else {
-		range = palstart - palend;
-		basecol = palend;
-		dir = -1;
-	}
-	int divider = 256 / range;
-	engine->GetBitmapDimensions(firespr, &w, &h, nullptr);
-	unsigned char **fire = engine->GetRawBitmapSurface(firespr);
-	unsigned char **color = engine->GetRawBitmapSurface(firecolorspr);
-	int sparky = 0;
-	//srand(time(NULL));
-	for (int y = 0; y < h - 1; y++) {
-		if ((int)::AGS::g_vm->getRandomNumber(9) > 7 - windspeed) { //Wind right
-			for (int x = w - 1; x > 1; x--) {
-				fire[y][x] = fire[y][x - 1];
-			}
-		} else if ((int)::AGS::g_vm->getRandomNumber(9) > 7 + windspeed) { // wind left
-			for (int x = 0; x < w - 1; x++) {
-				fire[y][x] = fire[y][x + 1];
-			}
-		}
-	}
-	for (int x = 0; x < w; x++) {
-		sparky = ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % (h - 2));
-		if (sparky < h && sparky > 0 && fire[h - sparky][x] > cutoff &&
-				ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % 10) > 7)
-			fire[h - sparky][x] = 255;
-		sparky = ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % (h - 2));
-		if (sparky < h && sparky > 0 && fire[h - sparky][x] > cutoff &&
-				ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % 10) > 7)
-			fire[h - sparky][x] = 0;
-	}
-	if (seed == 0) {
-		for (int x = 0; x < w; x++)
-			fire[h - 1][x] = 255;
-		for (int x = 0; x < w; x++)
-			fire[h - 2][x] = ::AGS::g_vm->getRandomNumber(255);
-	} else if (seed > 0) {
-		seedspr = engine->GetSpriteGraphic(seed);
-		BITMAP *virtsc = engine->GetVirtualScreen();
-		engine->SetVirtualScreen(firespr);
-		engine->BlitBitmap(0, 0, seedspr, 1);
-		engine->SetVirtualScreen(virtsc);
-		engine->ReleaseBitmapSurface(virtsc);
-		engine->ReleaseBitmapSurface(seedspr);
-		engine->NotifySpriteUpdated(spriteId);
-		engine->NotifySpriteUpdated(masksprite);
-	}
-
-	for (int y = 0; y < h - 1; y++) {
-		for (int x = 0; x < w; x++) {
-			fire[y][x] =
-			    ((fire[(y + 1) % h][(x - 1 + w) % w]
-			      + fire[(y + 1) % h][(x) % w]
-			      + fire[(y + 1) % h][(x + 1) % w]
-			      + fire[(y + 2) % h][(x) % w])
-			     * 100) / (400 + (100 - strength));
-			if (fire[y][x] < cutoff) fire[y][x] = 0;
-			//if (fire[y][x] ==255) color [y][x] = palend;
-			else color [y][x] = static_cast<unsigned char>(basecol + (fire[y][x] / divider) * dir);
-		}
-	}
-	engine->ReleaseBitmapSurface(firespr);
-	engine->ReleaseBitmapSurface(firecolorspr);
-	engine->NotifySpriteUpdated(spriteId);
-	engine->NotifySpriteUpdated(masksprite);
-}
-
-/*
-unsigned char MixColorAlpha (unsigned char fg,unsigned char bg,unsigned char alpha)
-{
-    //unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
-    //unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
-    //BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
-    //if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
-    //unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
-    AGSColor *palette = engine->GetPalette ();
-    int i=0;
-    int out_r = (palette[fg].r>>1) * alpha + (palette[bg].r>>1) * (255 - alpha);
-    int out_g = palette[fg].g * alpha + palette[bg].g * (255 - alpha);
-    int out_b = (palette[fg].b>>1) * alpha + (palette[bg].b>>1) * (255 - alpha);
-    //unsigned char ralpha = alpha>>2;
-    //unsigned char invralpha = 64-ralpha;
-    //if (ralpha > alpha) engine->AbortGame ("wtf");
-    //int out_r = alphamultiply[(palette[fg].r>>1)][ralpha] + alphamultiply[(palette[bg].r>>1)][(invralpha)];
-    //int out_g = alphamultiply[(palette[fg].g)][ralpha] + alphamultiply[(palette[bg].g)][(invralpha)];
-    //int out_b = alphamultiply[(palette[fg].b>>1)][ralpha] + alphamultiply[(palette[bg].b>>1)][(invralpha)];
-    out_r = (out_r + 1 + (out_r >> 8)) >> 8;
-    out_g = (out_g + 1 + (out_g >> 8)) >> 8;
-    out_b = (out_b + 1 + (out_b >> 8)) >> 8;
-    i = ((out_r << 11) | (out_g << 5) | out_b);
-    unsigned char (*clutp) = clut;
-    //unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
-    unsigned char result = cycle_remap [*(clutp+i)]; //Once again, to make sure that the palette slot used is the right one.
-    //engine->ReleaseBitmapSurface (clutspr);
-    return result;
-}
-
-unsigned char MixColorAdditive (unsigned char fg,unsigned char bg,unsigned char alpha)
-{
-    //unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
-    //unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
-    //BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
-    //if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
-    //unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
-    AGSColor *palette = engine->GetPalette ();
-    int i=0;
-    int add_r,add_b,add_g = 0;
-    char ralpha = alpha>>2;
-    //if (ralpha > alpha) engine->AbortGame ("wtf");
-    //add_r = (((palette[fg].r>>1) * (alpha))>>8);
-    //add_b = (((palette[fg].b>>1) * (alpha))>>8);
-    //add_g = (((palette[fg].g)    * (alpha))>>8);
-    add_r = ((alphamultiply[(palette[fg].r>>1)*64+ralpha])>>6);
-    add_b = ((alphamultiply[(palette[fg].b>>1)*64+ralpha])>>6);
-    add_g = ((alphamultiply[(palette[fg].g   )*64+ralpha])>>6);
-    int out_r = min(31,(palette[bg].r>>1) + add_r);
-    int out_g = min(63, palette[bg].g     + add_g);
-    int out_b = min(31,(palette[bg].b>>1) + add_b);
-    i = ((out_r << 11) | (out_g << 5) | out_b);
-    unsigned char (*clutp) = clut;
-    unsigned char result = cycle_remap [*(clutp+i)]; //Once again, to make sure that the palette slot used is the right one.
-    //unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
-    //engine->ReleaseBitmapSurface (clutspr);
-    return result;
-}
-*/
-unsigned char GetColor565(unsigned char r, unsigned char g, unsigned char b) {
-	//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
-	//if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
-	//unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
-	int i = ((r << 11) | (g << 5) | b);
-	unsigned char (*clutp) = clut;
-	unsigned char result = *(clutp + i);
-	result = cycle_remap [result]; //Once again, to make sure that the palette slot used is the right one.
-	//engine->ReleaseBitmapSurface (clutspr);
-	return result;
-}
-
-void CycleRemap(int start, int end) {
-	if (end > start) {
-		// Rotate left
-		int wraparound = cycle_remap [start];
-		for (; start < end; ++start) {
-			cycle_remap [start] = cycle_remap [start + 1];
-		}
-		cycle_remap [end] = wraparound;
-	} else if (end < start) {
-		// Rotate right
-		int wraparound = cycle_remap [start];
-		for (; start > end; --start) {
-			cycle_remap [start] = cycle_remap [start - 1];
-		}
-		cycle_remap [end] = wraparound;
-
-	}
-}
-
-unsigned char GetRemappedSlot(unsigned char slot) {
-	return cycle_remap [slot];
-}
-
-int LoadCLUT(int slot) {
-	if (engine->GetSpriteWidth(slot) != 256 || engine->GetSpriteHeight(slot) != 256) return 1;
-	BITMAP *clutimage = engine->GetSpriteGraphic(slot);
-	unsigned char **clutarray = engine->GetRawBitmapSurface(clutimage);
-	for (int y = 0; y < 256; y++) {
-		for (int x = 0; x < 256; x++) {
-			clut[y * 256 + x] = clutarray[y][x];
-		}
-	}
-	clutslot = slot;
-	engine->ReleaseBitmapSurface(clutimage);
-	return 0;
-}
-
-void SetReflections(int toggle) {
-	drawreflections = toggle;
-}
-
-int IsReflectionsOn() {
-	return drawreflections;
-}
-
-int GetLuminosityFromPalette(int slot) {
-	AGSColor *pal = engine->GetPalette();
-	int lum = (pal[slot].r +
-	           pal[slot].r +
-	           pal[slot].r +
-	           pal[slot].g +
-	           pal[slot].g +
-	           pal[slot].g +
-	           pal[slot].g +
-	           pal[slot].b) >> 3;
-	return lum;
-}
-
-
-
-void SetStarsOriginPoint(int x, int y) {
-	Starfield.originx = x;
-	Starfield.originy = y;
-}
-void InitializeStars(int slot, int maxstars) {
-	int32 sw, sh = 0;
-	BITMAP *canvas = engine->GetSpriteGraphic(slot);
-	engine->GetBitmapDimensions(canvas, &sw, &sh, nullptr);
-	Starfield.maxstars = maxstars;
-	Starfield.overscan = 20;
-	stars = new starstype [Starfield.maxstars];
-	for (int i = 0; i < Starfield.maxstars; i++) {
-		stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
-		if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
-		stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
-		if (stars[i].y < 1.0 && stars[i].y > -1.0) stars[i].y = (float)sh;
-		stars[i].z = (float)(MAX_DEPTH);
-		stars[i].color = (::AGS::g_vm->getRandomNumber(0x7fffffff) % 240);
-		stars[i].sprite = 0;
-		stars[i].maxrad = (::AGS::g_vm->getRandomNumber(0x7fffffff) % 5);
-	}
-}
-
-void IterateStars(int slot) {
-	long sw, sh = 0;
-	sw = engine->GetSpriteWidth(slot);
-	sh = engine->GetSpriteHeight(slot);
-	for (int i = 0; i < Starfield.maxstars; i++) {
-		stars[i].z -= Starfield.speed;
-		//if (stars[i].z < 1.0) stars[i].z = (double)MAX_DEPTH;
-		float k = Starfield.depthmultiplier / stars[i].z;
-		int px = static_cast<int>(stars[i].x * k + Starfield.originx);
-		int py = static_cast<int>(stars[i].y * k + Starfield.originy);
-		if (px >= sw + Starfield.overscan || px < 0 - Starfield.overscan || py >= sh + Starfield.overscan || py < 0 - Starfield.overscan) {
-			stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
-			if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
-			stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
-			if (stars[i].y < 1.0 && stars[i].y > 1.0) stars[i].y = (float)sh;
-			stars[i].z = (float)MAX_DEPTH;
-			//stars[i].color = (rand () %240);
-		}
-	}
-}
-int GetStarfieldOverscan() {
-	return Starfield.overscan;
-}
-void SetStarfieldOverscan(int overscan) {
-	Starfield.overscan = overscan;
-}
-
-int GetStarfieldOriginX() {
-	return Starfield.originx;
-}
-
-int GetStarfieldOriginY() {
-	return Starfield.originy;
-}
-
-void SetStarfieldDepthMultiplier(int multi) {
-	Starfield.depthmultiplier = multi;
-}
-
-int GetStarfieldDepthMultiplier() {
-	return Starfield.depthmultiplier;
-}
-
-int GetStarfieldMaxStars() {
-	return Starfield.maxstars;
-}
-
-void SetStarSpriteScaleBoost(int star, int boost) {
-	stars[star].scaleboost = boost;
-}
-
-int GetStarSpriteScaleBoost(int star) {
-	return stars[star].scaleboost;
-}
-
-void SetStarMaxRadius(int star, int radius) {
-	stars[star].maxrad = radius;
-}
-
-int GetStarMaxRadius(int star) {
-	return stars[star].maxrad;
-}
-
-void RotateStar(int star, int angle, int px, int py) {
-	float rsin = rot_sine_LUT[angle];
-	float rcos = rot_cos_LUT[angle];
-	float fPx = (float)px;
-	float fPy = (float)py;
-	float x1 = 0, y1 = 0, xRot = 0, yRot = 0;
-	int i = star;
-	x1 = stars[i].x;
-	y1 = stars[i].y;
-	xRot = fPx + rcos * (x1 - fPx) - rsin * (y1 - fPy);
-	yRot = fPy + rsin * (x1 - fPx) + rcos * (y1 - fPy);
-	stars[i].x = xRot;
-	stars[i].y = yRot;
-	i++;
-}
-
-FLOAT_RETURN_TYPE GetStarX(int i) {
-	float starx = (float)stars[i].x;
-	RETURN_FLOAT(starx);
-}
-
-FLOAT_RETURN_TYPE GetStarY(int i) {
-	float stary = (float)stars[i].y;
-	RETURN_FLOAT(stary);
-}
-
-FLOAT_RETURN_TYPE GetStarZ(int i) {
-	float starz = (float)stars[i].z;
-	RETURN_FLOAT(starz);
-}
-
-void SetStarPosition(int star, SCRIPT_FLOAT(x), SCRIPT_FLOAT(y), SCRIPT_FLOAT(z)) {
-	INIT_SCRIPT_FLOAT(x);
-	INIT_SCRIPT_FLOAT(y);
-	INIT_SCRIPT_FLOAT(z);
-	stars[star].x = x;
-	stars[star].y = y;
-	stars[star].z = z;
-}
-
-void SetStarColor(int star, unsigned char color) {
-	stars[star].color = color;
-}
-
-unsigned char GetStarColor(int star) {
-	return stars[star].color;
-}
-
-void SetStarSprite(int star, int slot) {
-	stars[star].sprite = slot;
-}
-
-int GetStarSprite(int star) {
-	return stars[star].sprite;
-}
-
-void SetStarSpriteRange(int start, int end, int slot) {
-	int sfix = start;
-	int efix = end;
-	if (start > Starfield.maxstars) sfix = Starfield.maxstars - 1;
-	if (end > Starfield.maxstars) efix = Starfield.maxstars;
-	for (int i = sfix; i < efix; i++)
-		stars[i].sprite = slot;
-}
-
-void DrawStars(int slot, int maskslot) {
-	int32 sw, sh = 0;
-	BITMAP *canvas = engine->GetSpriteGraphic(slot);
-	if (!canvas) engine->AbortGame("DrawStars: Can't load sprite slot.");
-	BITMAP *maskcanvas = engine->GetSpriteGraphic(maskslot);
-	if (!maskcanvas) engine->AbortGame("DrawStars: Can't load mask slot.");
-	engine->GetBitmapDimensions(canvas, &sw, &sh, nullptr);
-	unsigned char **screenarray = engine->GetRawBitmapSurface(canvas);
-	unsigned char **maskarray = engine->GetRawBitmapSurface(maskcanvas);
-	for (int i = 0; i < Starfield.maxstars; i++) {
-		//stars[i].z-= 0.5;
-		//if (stars[i].z < 1.0) stars[i].z = (double)MAX_DEPTH;
-		float k = (float)Starfield.depthmultiplier / stars[i].z;
-		int px = static_cast<int>(stars[i].x * k + Starfield.originx);
-		int py = static_cast<int>(stars[i].y * k + Starfield.originy);
-		if (px >= sw + Starfield.overscan || px < 0 - Starfield.overscan || py >= sh + Starfield.overscan || py < 0 - Starfield.overscan) {
-			stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
-			if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
-			stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
-			if (stars[i].y < 1.0 && stars[i].y > 1.0) stars[i].y = (float)sh;
-			stars[i].z = (float)MAX_DEPTH;
-			//stars[i].color = (rand () %240);
-		} else if (stars[i].z > 0) {
-			int ivalue = (63 - (int)stars[i].z);
-			if (ivalue > 63) ivalue = 63;
-			else if (ivalue < 0) ivalue = 0;
-			unsigned char value = (unsigned char)(ivalue);
-			unsigned char maskcolor = value << 2;
-			if (stars[i].sprite > 0) {
-				BITMAP *origspr = engine->GetSpriteGraphic(stars[i].sprite);
-				int scale = (ivalue + 1) * 100 >> 6;
-				//int scale = 50;
-				if (scale < 1) scale = 1;
-				/*
-				if (scale != 100)
-				{
-				unsigned char** orig = engine->GetRawBitmapSurface (origspr);
-				int32 h1,h2,w1,w2=0;
-				double fw2,fh2;
-				engine->GetBitmapDimensions (origspr,&w1,&h1,NULL);
-				fh2 = h1 * (scale / 100.0);
-				fw2 = w1 * (scale / 100.0);
-				h2 = static_cast<int>(fh2);
-				w2 = static_cast<int>(fw2);
-				if (w2 < 1) w2 = 1;
-				if (h2 < 1) h2 = 1;
-				resizspr = engine->CreateBlankBitmap (w2,h2,8);
-				unsigned char** resized = engine->GetRawBitmapSurface (resizspr);
-				int x_ratio = (int)((w1<<16)/w2) +1;
-				int y_ratio = (int)((h1<<16)/h2) +1;
-				int x2, y2 ;
-				for (int i=0;i<h2;i++)
-				{
-				    for (int j=0;j<w2;j++)
-				   {
-				       x2 = ((j*x_ratio)>>16) ;
-				       y2 = ((i*y_ratio)>>16) ;
-				       resized [i][j] = orig [y2][x2];
-				 }
-				}
-				engine->ReleaseBitmapSurface (resizspr);
-				}
-				//resizspr = origspr;
-				int32 w,h=0;
-				engine->GetBitmapDimensions (resizspr,&w,&h,NULL);
-				unsigned char **imagemap = engine->GetRawBitmapSurface (resizspr);
-				int ox = px - (w>>1);
-				int oy = py - (h>>1);
-				for (int dy=0;dy<h;dy++)
-				{
-				for (int dx=0;dx<w;dx++)
-				{
-				   int ex = ox+dx;
-				   int ey = oy+dy;
-				   if (ex < sw && ex >= 0 && ey < sh && ey >= 0)
-				   {
-				       if (maskcolor > maskarray [ey][ex] && imagemap[dy][dx] > 0)
-				       {
-				           maskarray [ey][ex] = maskcolor;
-				           screenarray [ey][ex] = imagemap[dy][dx];
-				       }
-				   }
-				}
-				}
-				*/
-
-				unsigned char **orig = engine->GetRawBitmapSurface(origspr);
-				int32 h1, h2, w1, w2 = 0;
-				double fw2, fh2;
-				engine->GetBitmapDimensions(origspr, &w1, &h1, nullptr);
-				fh2 = h1 * (scale / 100.0);
-				fw2 = w1 * (scale / 100.0);
-				h2 = static_cast<int>(fh2);
-				w2 = static_cast<int>(fw2);
-				if (w2 < 1) w2 = 1;
-				if (h2 < 1) h2 = 1;
-				int x_ratio = (int)((w1 << 16) / w2) + 1;
-				int y_ratio = (int)((h1 << 16) / h2) + 1;
-				int x2, y2 ;
-				int ox = px - (w2 >> 1);
-				int oy = py - (h2 >> 1);
-				for (int ii = 0; ii < h2; ii++) {
-					int temprzy = ii * y_ratio;
-					int ey = oy + ii;
-					for (int j = 0; j < w2; j++) {
-						x2 = ((j * x_ratio) >> 16);
-						y2 = ((temprzy) >> 16);
-						int ex = ox + j;
-						if (ex < sw && ex >= 0 && ey < sh && ey >= 0) {
-							if (maskcolor > maskarray [ey][ex] && orig[y2][x2] > 0) {
-								maskarray [ey][ex] = maskcolor;
-								screenarray [ey][ex] = orig[y2][x2];
-							}
-						}
-						//resized [ii][j] = orig [y2][x2];
-					}
-				}
-				engine->ReleaseBitmapSurface(origspr);
-			} else if (stars[i].sprite == 0) {
-				if (stars[i].maxrad == 1) {
-					if (px < sw && px >= 0 && py < sh && py >= 0) {
-						if (maskcolor > maskarray[py][px]) {
-							maskarray[py][px] = maskcolor;
-							screenarray[py][px] = stars[i].color;
-						}
-					}
-				} else {
-					int scale = ((((int)stars[i].z) * 100) / 63);
-					if (scale < 1) scale = 1;
-					int radius = (stars[i].maxrad * (100 - scale) / 100);
-					int radsq = radius * radius;
-					//unsigned char color = GetColor565 (value>>1,value,value>>1);
-					unsigned char color = stars[i].color;
-					for (int cy = -radius; cy <= radius; cy++) { //Draw a circle around the point, for the mask.
-						int cysq = cy * cy;
-						for (int cx = -radius; cx <= radius; cx++) {
-							int cxsq = cx * cx;
-							int dx = cx + px;
-							int dy = cy + py;
-							if ((cxsq + cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0) {
-								if (maskcolor > maskarray [dy][dx]) {
-									maskarray [dy][dx] = maskcolor;
-									screenarray [dy][dx] = color;
-								}
-							}
-						}
-					}
-					/*
-					for(int cy=-radius; cy<=radius; cy++) //Draw a circle around the point, for the color.
-					{
-					   int cysq = cy*cy;
-					for(int cx=-radius; cx<=radius; cx++)
-					   {
-					       int cxsq = cx*cx;
-					       int dx = cx+px;
-					       int dy = cy+py;
-					       if((cxsq+cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0)
-					       {
-					           if (maskarray [dy][dx] == maskcolor)screenarray [dy][dx] = color;
-					       }
-					   }
-					}
-					*/
-				}
-			}
-		}
-	}
-	engine->ReleaseBitmapSurface(canvas);
-	engine->ReleaseBitmapSurface(maskcanvas);
-	engine->NotifySpriteUpdated(slot);
-	engine->NotifySpriteUpdated(maskslot);
-}
-
-
-int CreateTranslucentOverlay(int id, int spriteId, int alpha, int level, int ox, int oy, int mask = 0, int blendmode = 0) {
-	BITMAP *testspr = engine->GetSpriteGraphic(spriteId);
-	if (testspr) overlay[id].sprite = spriteId;
-	else engine->AbortGame("CreateTranslucentOverlay: Invalid spriteId.");
-	engine->ReleaseBitmapSurface(testspr);
-	overlay[id].level = MAX(0, MIN(level, 4));
-	overlay[id].trans = MAX(0, MIN(alpha, 255));
-	overlay[id].spritemask = mask;
-	overlay[id].x = ox;
-	overlay[id].y = oy;
-	overlay[id].enabled = true;
-	overlay[id].blendtype = blendmode;
-	return 0;
-}
-
-int DeleteTranslucentOverlay(int id) {
-	overlay[id].enabled = false;
-	overlay[id].sprite = 0;
-	overlay[id].x = 0;
-	overlay[id].y = 0;
-	overlay[id].level = 0;
-	overlay[id].trans = 0;
-	return 0;
-}
-
-int MoveTranslucentOverlay(int id, int ox, int oy) {
-	overlay[id].x = ox;
-	overlay[id].y = oy;
-	return 0;
-}
-
-int GetTranslucentOverlayX(int id) {
-	return overlay[id].x;
-}
-
-int GetTranslucentOverlayY(int id) {
-	return overlay[id].y;
-}
-
-int GetTranslucentOverlaySprite(int id) {
-	return overlay[id].sprite;
-}
-
-int GetTranslucentOverlayLevel(int id) {
-	return overlay[id].level;
-}
-
-int GetTranslucentOverlayEnabled(int id) {
-	return overlay[id].enabled;
-}
-
-int GetTranslucentOverlayAlpha(int id) {
-	return overlay[id].trans;
-}
-
-int SetTranslucentOverlayAlpha(int id, int alpha) {
-	if (alpha >= 0 && alpha < 256)
-		overlay[id].trans = alpha;
-	else
-		engine->AbortGame("CreateTranslucentOverlay: Invalid alpha selected.");
-	return 0;
-}
-
-int SetTranslucentOverlayEnabled(int id, int toggle) {
-	if (toggle > 0)
-		overlay[id].enabled = true;
-	else
-		overlay[id].enabled = false;
-	return 0;
-}
-
-void SetCharacterReflected(int id, int refl) {
-	if (refl > 0) Reflection.Characters[id].reflect = 1;
-	else Reflection.Characters[id].reflect = 0;
-}
-
-void SetObjectReflected(int id, int refl) {
-	if (refl > 0)
-		Reflection.Objects[id].reflect = 1;
-	else
-		Reflection.Objects[id].reflect = 0;
-}
-
-int GetCharacterReflected(int id) {
-	return Reflection.Characters[id].reflect;
-}
-
-int GetObjectReflected(int id) {
-	return Reflection.Objects[id].reflect;
-}
-
-void ReplaceCharacterReflectionView(int id, int view) {
-	Reflection.Characters[id].replaceview = view - 1;
-}
-
-void SetObjectReflectionIgnoreScaling(int id, int wb) {
-	if (wb) Reflection.Objects[id].ignorescaling = 1;
-	else    Reflection.Objects[id].ignorescaling = 0;
-}
-
-int DrawReflections(int id, int charobj = 0) {
-	int32 screenw, screenh;
-	int32 bgw, bgh;
-	engine->GetScreenDimensions(&screenw, &screenh, nullptr);
-	BITMAP *bgmask = engine->GetBackgroundScene(1);
-	if (bgmask == nullptr) return 1;
-	//BITMAP *virtsc = engine->GetVirtualScreen();
-	BITMAP *walkbehind = engine->GetRoomMask(MASK_WALKBEHIND);
-	//if (!virtsc) engine->AbortGame ("Can't load virtual screen.");
-	if (!walkbehind) engine->AbortGame("DrawRelfections: Can't load Walkbehind into memory.");
-	engine->GetBitmapDimensions(walkbehind, &bgw, &bgh, nullptr);
-	if (!bgmask) engine->AbortGame("DrawReflections: Can't load reflection mask.");
-	//unsigned char **charbuffer = engine->GetRawBitmapSurface (virtsc);
-	unsigned char **wbarray = engine->GetRawBitmapSurface(walkbehind);
-	unsigned char **maskarray = engine->GetRawBitmapSurface(bgmask);
-	//Initialize stuff
-	BITMAP *charsprite = nullptr;
-	BITMAP *charsprite2 = nullptr;
-	AGSCharacter *currchar = nullptr;
-	AGSObject *currobj;
-	int cox = 0, coy = 0, coz = 0;
-	int scale = 0;
-	//Get character, and their sprite.
-	if (charobj == 0) {
-		currchar = engine->GetCharacter(id);
-		/*int view = 0;
-		if (Reflection.Characters[id].replaceview == 0) view = currchar->view + 1;
-		else view = Reflection.Characters[id].replaceview;
-		*/
-		AGSViewFrame *vf = engine->GetViewFrame(currchar->view + 1, currchar->loop, currchar->frame);
-		charsprite = engine->GetSpriteGraphic(vf->pic);
-		long scaling = currchar->flags & CHF_NOSCALING;
-		if (!scaling)scale = engine->GetAreaScaling(currchar->x, currchar->y);
-		else scale = 100;
-		cox = currchar->x;
-		coy = currchar->y;
-		coz = currchar->z;
-	} else if (charobj == 1) {
-		currobj = engine->GetObject(id);
-
-		charsprite = engine->GetSpriteGraphic(currobj->num);
-		if (Reflection.Objects[id].ignorescaling) scale = 100;
-		else scale = engine->GetAreaScaling(currobj->x, currobj->y);
-		cox = currobj->x;
-		if (currobj->baseline < 0) coy = currobj->y;
-		else coy = currobj->baseline;
-		coz = 0;
-	}
-	bool scaled = false;
-	int32 w, h;
-	engine->GetBitmapDimensions(charsprite, &w, &h, nullptr);
-	if (scale != 100) {
-		unsigned char **orig = engine->GetRawBitmapSurface(charsprite);
-		int h1, h2, w1, w2;
-		double fw2, fh2;
-		h1 = h;
-		w1 = w;
-		fh2 = h1 * ((double)scale / 100.0);
-		fw2 = w1 * ((double)scale / 100.0);
-		h2 = static_cast<int>(fh2);
-		w2 = static_cast<int>(fw2);
-		charsprite2 = engine->CreateBlankBitmap(w2, h2, 8);
-		unsigned char **resized = engine->GetRawBitmapSurface(charsprite2);
-		int x_ratio = (int)((w1 << 16) / w2) + 1;
-		int y_ratio = (int)((h1 << 16) / h2) + 1;
-		int x2, y2 ;
-		for (int i = 0; i < h2; i++) {
-			for (int j = 0; j < w2; j++) {
-				x2 = ((j * x_ratio) >> 16) ;
-				y2 = ((i * y_ratio) >> 16) ;
-				resized [i][j] = orig [y2][x2];
-			}
-		}
-		engine->ReleaseBitmapSurface(charsprite2);
-		scaled = true;
-		w = w2;
-		h = h2;
-	} else {
-		charsprite2 = charsprite;
-	}
-	int transamount = 0;
-	unsigned char **spritearray = engine->GetRawBitmapSurface(charsprite2);
-	unsigned char **charbuffer = engine->GetRawBitmapSurface(rcolormap);
-	unsigned char **alphaarray = engine->GetRawBitmapSurface(ralphamap);
-	int i = h - 1, j = 0;
-	int32 ox = cox;
-	if (charobj == 0) ox = ox - (w / 2);
-	int32 oy = coy + coz - 1;
-	engine->RoomToViewport(&ox, &oy);
-	int yoffset = 0;
-	int translevel = 7;
-	//bool dither = false;
-	//bool dodither = false;
-	int counter = 0;
-	int rowcount = 101 - (int)(50.0 * ((double)(scale) / 100.0));
-	int delay = screenh / rowcount;
-	int *obst;
-	int flipped = 0;
-	if (charobj == 0) {
-		int (*sfGetGameParameter)(int, int, int, int);
-		sfGetGameParameter = ((int(*)(int, int, int, int)) engine->GetScriptFunctionAddress("GetGameParameter"));
-		flipped = sfGetGameParameter(13, currchar->view + 1, currchar->loop, currchar->frame);
-	} else flipped = 0;
-	obst = new int [w];
-	for (int k = 0; k < w; k++) {
-		obst[k] = 0;
-	}
-	while (i > 0) {
-		//if ((counter == delay/2-1 || counter == delay-1) && yoffset < 36) dodither = (!dodither);
-		if (counter == delay) {
-			counter = 0;
-			if (translevel > 0) translevel--;
-		} else counter++;
-		yoffset++;
-		while (j < w) {
-			int xoffset;
-			if (flipped == 1) xoffset = w - j - 1;
-			else xoffset = j;
-			int32 rx = ox + xoffset, ry = oy + yoffset;
-			int wbb = 0;
-			engine->ViewportToRoom(&rx, &ry);
-			if (ry > 0 && ry < bgh && rx > 0 && rx < bgw) {
-				if (wbarray [ry][rx] > 0) {
-					wbb = engine->GetWalkbehindBaseline(wbarray[ry][rx]);
-				}
-				if (maskarray[ry][rx] == 21) obst[j] = 1;
-			}
-
-			//dither = (!dither);
-			transamount = 32 * translevel;
-			if (spritearray [i][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.
-				if (wbb < ry && obst[j] == 0 && (oy > reflectionmap[(ox + xoffset) + (screenw * (oy + yoffset))])) {
-					//charbuffer[oy+yoffset][ox+xoffset] = MixColorAlpha (spritearray [i][j],charbuffer[oy+yoffset][ox+xoffset],transamount);
-					charbuffer [oy + yoffset][ox + xoffset] = spritearray [i][j];
-					alphaarray [oy + yoffset][ox + xoffset] = transamount;
-					reflectionmap[(ox + xoffset) + (screenw * (oy + yoffset))] = oy;
-				}
-			}
-			j++;
-		}
-		//if (w % 2 == 0) dither = (!dither);
-		i--;
-		j = 0;
-	}
-
-	delete [] obst;
-	if (scaled == true)engine->FreeBitmap(charsprite2);
-	engine->ReleaseBitmapSurface(charsprite);
-	//engine->ReleaseBitmapSurface (virtsc);
-	//engine->ReleaseBitmapSurface (clutspr);
-	engine->ReleaseBitmapSurface(bgmask);
-	engine->ReleaseBitmapSurface(walkbehind);
-	engine->ReleaseBitmapSurface(rcolormap);
-	engine->ReleaseBitmapSurface(ralphamap);
-	engine->MarkRegionDirty(ox, oy, ox + w, oy + h);
-	return 0;
-}
-
-
-int DrawTransSprite(int spriteId, int bg, int translevel, int mask = 0, int blendmode = 0, int use_objpal = 0) {
-	BITMAP *maskspr = nullptr;
-	unsigned char **maskarray = nullptr;
-	if (mask > 0) maskspr = engine->GetSpriteGraphic(mask);
-	if (!maskspr && mask > 0) {
-		char maskerr [100];
-		snprintf(maskerr, 100, "DrawTransSprite: Can't load mask from slot %d.", mask);
-		engine->AbortGame(maskerr);
-	}
-	// Get a reference to the screen we'll draw onto
-	BITMAP *bgspr = engine->GetSpriteGraphic(bg);
-	//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
-	BITMAP *spritespr = engine->GetSpriteGraphic(spriteId);
-	if (!bgspr) engine->AbortGame("DrawTransSprite: Can't load background");
-	//if (!clutspr) engine->AbortGame ("Can't load CLUT spriteId into memory.");
-	if (!spritespr) engine->AbortGame("DrawTransSprite: Can't load overlay spriteId into memory.");
-	// Get its surface
-	int32 sprw, sprh, coldepth;
-	int32 bgw, bgh;
-	engine->GetBitmapDimensions(bgspr, &bgw, &bgh, &coldepth);
-	engine->GetBitmapDimensions(spritespr, &sprw, &sprh, &coldepth);
-
-	unsigned char **bgarray = engine->GetRawBitmapSurface(bgspr);
-	//unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
-	unsigned char **spritearray = engine->GetRawBitmapSurface(spritespr);
-	if (mask > 0) maskarray = engine->GetRawBitmapSurface(maskspr);
-	int tloffset = 255 - translevel;
-	int x = 0;
-	int y = 0;
-	//int transamount = 256 * translevel; //old
-	while (y < sprh) {
-		while (x < sprw) {
-			if (spritearray [y][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.
-				if (mask > 0) {
-					translevel = MAX(maskarray [y][x] - tloffset, 0);
-				}
-				//spritearray[y][x] = cycle_remap[clutarray [cycle_remap[bgarray[y][x]]+transamount][cycle_remap[spritearray [y][x]]]]; //old
-				if (blendmode == 0) spritearray[y][x] = Mix::MixColorAlpha(spritearray [y][x], bgarray[y][x], translevel, use_objpal);
-				else if (blendmode == 1) spritearray[y][x] = Mix::MixColorAdditive(spritearray [y][x], bgarray[y][x], translevel, use_objpal);
-			}
-			x++;
-		}
-		x = 0;
-		y++;
-	}
-
-	// Release the screen so that the engine can continue
-	engine->ReleaseBitmapSurface(bgspr);
-	//engine->ReleaseBitmapSurface (clutspr);
-	engine->ReleaseBitmapSurface(spritespr);
-	engine->NotifySpriteUpdated(spriteId);
-	return 0;
-}
-
-int DrawTranslucentOverlay(int spriteId, int translevel, int ox, int oy, int mask = 0, int blendmode = 0) {
-	if (translevel == 0) return 0;
-	BITMAP *maskspr = nullptr;
-	unsigned char **maskarray = nullptr;
-	// Get a reference to the screen we'll draw onto
-	BITMAP *virtsc = engine->GetVirtualScreen();
-	//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
-	BITMAP *spritespr = engine->GetSpriteGraphic(spriteId);
-	if (mask > 0) maskspr = engine->GetSpriteGraphic(mask);
-	if (!virtsc) engine->AbortGame("DrawTranslucentOverlay: Can't load virtual screen.");
-	//if (!clutspr) engine->AbortGame ("Can't load CLUT spriteId into memory.");
-	if (!spritespr) engine->AbortGame("DrawTranslucentOverlay: Can't load overlay spriteId into memory.");
-	// Get its surface
-	int32 sprw, sprh, coldepth;
-	int32 screenw, screenh;
-	engine->GetScreenDimensions(&screenw, &screenh, &coldepth);
-	engine->GetBitmapDimensions(spritespr, &sprw, &sprh, &coldepth);
-	unsigned char **charbuffer = engine->GetRawBitmapSurface(virtsc);
-	unsigned char **spritearray = engine->GetRawBitmapSurface(spritespr);
-	if (mask > 0) {
-		if (!maskspr && mask > 0) {
-			char maskerr [100];
-			snprintf(maskerr, 100, "DrawTransSprite: Can't load mask from slot %d.", mask);
-			engine->AbortGame(maskerr);
-		}
-		maskarray = engine->GetRawBitmapSurface(maskspr);
-	}
-	int tloffset = 255 - translevel;
-	int x = 0;
-	int y = 0;
-	//int transamount = 256 * translevel; //old
-	while (y < sprh) {
-		while (x < sprw) {
-			if (spritearray [y][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.
-				//charbuffer[y+oy][x+ox] = cycle_remap[clutarray [cycle_remap[charbuffer[y+oy][x+ox]]+transamount][cycle_remap[spritearray [y][x]]]]; //old
-				if (mask > 0) {
-					translevel = MAX(maskarray [y][x] - tloffset, 0);
-				}
-				if (blendmode == 0) {
-					if (translevel == 255) {
-						charbuffer[y + oy][x + ox] = spritearray [y][x];
-					} else charbuffer[y + oy][x + ox] = Mix::MixColorAlpha(spritearray [y][x], charbuffer[y + oy][x + ox], translevel);
-				} else if (blendmode == 1) charbuffer[y + oy][x + ox] = Mix::MixColorAdditive(spritearray [y][x], charbuffer[y + oy][x + ox], translevel);
-			}
-			x++;
-		}
-		x = 0;
-		y++;
-	}
-
-	// Release the screen so that the engine can continue
-	long dirtywidth = ox + sprw;
-	if (dirtywidth > screenw) dirtywidth = screenw - 1;
-	long dirtyheight = oy + sprh;
-	if (dirtyheight > screenh) dirtywidth = screenh - 1;
-	engine->ReleaseBitmapSurface(virtsc);
-	//engine->ReleaseBitmapSurface (clutspr);
-	engine->ReleaseBitmapSurface(spritespr);
-	if (mask > 0) engine->ReleaseBitmapSurface(maskspr);
-	engine->MarkRegionDirty(ox, oy, dirtywidth, dirtyheight);
-
-	return 0;
-}
-
-/*------------------------------------------------------------------*/
-
-AGSPalRender::AGSPalRender() : DLL() {
-	DLL_METHOD(AGS_GetPluginName);
-	DLL_METHOD(AGS_EngineStartup);
-	DLL_METHOD(AGS_EngineShutdown);
-	DLL_METHOD(AGS_EngineOnEvent);
-}
-
-const char *AGSPalRender::AGS_GetPluginName() {
-	return "PALgorithms Translucent Overlay Renderer";
-}
-
-void AGSPalRender::AGS_EngineStartup(IAGSEngine *lpEngine) {
-	engine = lpEngine;
-
-	// Make sure it's got the version with the features we need
-	if (engine->version < 3) {
-		engine->AbortGame("Engine interface is too old, need newer version of AGS.");
-	}
-	engine->RegisterScriptFunction("PALInternal::LoadCLUT^1", (void *)LoadCLUT);
-	engine->RegisterScriptFunction("PALInternal::CycleRemap^2", (void *)CycleRemap);
-	engine->RegisterScriptFunction("PALInternal::GetColor565^3", (void *)GetColor565);
-	engine->RegisterScriptFunction("PALInternal::GetLuminosityFromPalette^1", (void *)GetLuminosityFromPalette);
-	engine->RegisterScriptFunction("PALInternal::FastSin^1", (void *)AGSFastSin);
-	engine->RegisterScriptFunction("PALInternal::FastCos^1", (void *)AGSFastCos);
-	engine->RegisterScriptFunction("PALInternal::FastRoot^1", (void *)root);
-	engine->RegisterScriptFunction("PALInternal::GetRemappedSlot^1", (void *)GetRemappedSlot);
-	engine->RegisterScriptFunction("PALInternal::ResetRemapping^0", (void *)ResetRemapping);
-	engine->RegisterScriptFunction("PALInternal::GetModifiedBackgroundImage", (void *)GetModifiedBackgroundImage);
-	engine->RegisterScriptFunction("PALInternal::WriteObjectivePalette^4", (void *)WriteObjectivePalette);
-	engine->RegisterScriptFunction("PALInternal::ReadObjectivePaletteR^1", (void *)ReadObjectivePaletteR);
-	engine->RegisterScriptFunction("PALInternal::ReadObjectivePaletteB^1", (void *)ReadObjectivePaletteB);
-	engine->RegisterScriptFunction("PALInternal::ReadObjectivePaletteG^1", (void *)ReadObjectivePaletteG);
-
-	engine->RegisterScriptFunction("Raycast::Render^1", (void *)Raycast_Render);
-	engine->RegisterScriptFunction("Raycast::LoadMap^4", (void *)LoadMap);
-	engine->RegisterScriptFunction("Raycast::Initialize", (void *)Init_Raycaster);
-	engine->RegisterScriptFunction("Raycast::MakeTextures^1", (void *)MakeTextures);
-	engine->RegisterScriptFunction("Raycast::MoveForward^0", (void *)MoveForward);
-	engine->RegisterScriptFunction("Raycast::MoveBackward^0", (void *)MoveBackward);
-	engine->RegisterScriptFunction("Raycast::RotateLeft^0", (void *)RotateLeft);
-	engine->RegisterScriptFunction("Raycast::RotateRight^0", (void *)RotateRight);
-	engine->RegisterScriptFunction("Raycast::SetCameraPosition^2", (void *)Ray_SetPlayerPosition);
-	engine->RegisterScriptFunction("Raycast::GetCameraX^0", (void *)Ray_GetPlayerX);
-	engine->RegisterScriptFunction("Raycast::GetCameraY^0", (void *)Ray_GetPlayerY);
-	engine->RegisterScriptFunction("Raycast::GetCameraAngle^0", (void *)Ray_GetPlayerAngle);
-	engine->RegisterScriptFunction("Raycast::SetCameraAngle^1", (void *)Ray_SetPlayerAngle);
-	engine->RegisterScriptFunction("Raycast::InitSprite^9", (void *)Ray_InitSprite);
-	engine->RegisterScriptFunction("Raycast::UnloadEngine^0", (void *)QuitCleanup);
-	engine->RegisterScriptFunction("Raycast::GetHotspotAtXY^2", (void *)Ray_GetHotspotAt);
-	engine->RegisterScriptFunction("Raycast::GetObjectAtXY^2", (void *)Ray_GetObjectAt);
-	engine->RegisterScriptFunction("Raycast::SetSpriteInteractObj^2", (void *)Ray_SetSpriteInteractObj);
-	engine->RegisterScriptFunction("Raycast::GetSpriteInteractObj^1", (void *)Ray_GetSpriteInteractObj);
-	engine->RegisterScriptFunction("Raycast::SetSpritePosition^3", (void *)Ray_SetSpritePosition);
-	engine->RegisterScriptFunction("Raycast::SetSpriteVertOffset^2", (void *)Ray_SetSpriteVertOffset);
-	engine->RegisterScriptFunction("Raycast::GetSpriteVertOffset^1", (void *)Ray_GetSpriteVertOffset);
-	engine->RegisterScriptFunction("Raycast::GetSpriteX^1", (void *)Ray_GetSpriteX);
-	engine->RegisterScriptFunction("Raycast::GetSpriteY^1", (void *)Ray_GetSpriteY);
-	engine->RegisterScriptFunction("Raycast::SetWallHotspot^2", (void *)Ray_SetWallHotspot);
-	engine->RegisterScriptFunction("Raycast::SetWallTextures^5", (void *)Ray_SetWallTextures);
-	engine->RegisterScriptFunction("Raycast::SetWallSolid^5", (void *)Ray_SetWallSolid);
-	engine->RegisterScriptFunction("Raycast::SetWallIgnoreLighting^5", (void *)Ray_SetWallIgnoreLighting);
-	engine->RegisterScriptFunction("Raycast::SetWallAlpha^5", (void *)Ray_SetWallAlpha);
-	engine->RegisterScriptFunction("Raycast::SetWallBlendType^5", (void *)Ray_SetWallBlendType);
-	engine->RegisterScriptFunction("Raycast::GetMoveSpeed^0", (void *)Ray_GetMoveSpeed);
-	engine->RegisterScriptFunction("Raycast::SetMoveSpeed^1", (void *)Ray_SetMoveSpeed);
-	engine->RegisterScriptFunction("Raycast::GetRotSpeed^0", (void *)Ray_GetRotSpeed);
-	engine->RegisterScriptFunction("Raycast::SetRotSpeed^1", (void *)Ray_SetRotSpeed);
-	engine->RegisterScriptFunction("Raycast::GetWallAt^2", (void *)Ray_GetWallAt);
-	engine->RegisterScriptFunction("Raycast::GetLightAt^2", (void *)Ray_GetLightAt);
-	engine->RegisterScriptFunction("Raycast::SetLightAt^3", (void *)Ray_SetLightAt);
-	engine->RegisterScriptFunction("Raycast::SetWallAt^3", (void *)Ray_SetWallAt);
-	engine->RegisterScriptFunction("Raycast::SetPlaneY^1", (void *)Ray_SetPlaneY);
-	engine->RegisterScriptFunction("Raycast::GetDistanceAt^2", (void *)Ray_GetDistanceAt);
-	engine->RegisterScriptFunction("Raycast::GetSpriteAngle^1", (void *)Ray_GetSpriteAngle);
-	engine->RegisterScriptFunction("Raycast::SetSpriteAngle^2", (void *)Ray_SetSpriteAngle);
-	engine->RegisterScriptFunction("Raycast::SetSpriteView^2", (void *)Ray_SetSpriteView);
-	engine->RegisterScriptFunction("Raycast::GetSpriteView^1", (void *)Ray_GetSpriteView);
-	engine->RegisterScriptFunction("Raycast::SetSpriteFrame^2", (void *)Ray_SetSpriteFrame);
-	engine->RegisterScriptFunction("Raycast::GetSpriteFrame^1", (void *)Ray_GetSpriteFrame);
-	engine->RegisterScriptFunction("Raycast::SetSpritePic^2", (void *)Ray_SetSpritePic);
-	engine->RegisterScriptFunction("Raycast::GetSpritePic^1", (void *)Ray_GetSpritePic);
-	engine->RegisterScriptFunction("Raycast::SetSkyBox^1", (void *)Ray_SetSkyBox);
-	engine->RegisterScriptFunction("Raycast::SetSpriteAlpha^2", (void *)Ray_SetSpriteAlpha);
-	engine->RegisterScriptFunction("Raycast::GetSpriteAlpha^1", (void *)Ray_GetSpriteAlpha);
-	engine->RegisterScriptFunction("Raycast::GetSkyBox^1", (void *)Ray_GetSkyBox);
-	engine->RegisterScriptFunction("Raycast::SetAmbientLight^1", (void *)Ray_SetAmbientLight);
-	engine->RegisterScriptFunction("Raycast::SetAmbientColor^2", (void *)Ray_SetAmbientColor);
-	engine->RegisterScriptFunction("Raycast::GetAmbientLight^0", (void *)Ray_GetAmbientLight);
-	engine->RegisterScriptFunction("Raycast::GetAmbientWeight^0", (void *)Ray_GetAmbientWeight);
-	engine->RegisterScriptFunction("Raycast::GetTileX_At^2", (void *)Ray_GetTileX_At);
-	engine->RegisterScriptFunction("Raycast::GetTileY_At^2", (void *)Ray_GetTileY_At);
-	engine->RegisterScriptFunction("Raycast::DrawTile^2", (void *)Ray_DrawTile);
-	engine->RegisterScriptFunction("Raycast::DrawOntoTile^2", (void *)Ray_DrawOntoTile);
-	engine->RegisterScriptFunction("Raycast::SetNoClip^1", (void *)Ray_SetNoClip);
-	engine->RegisterScriptFunction("Raycast::GetNoClip^0", (void *)Ray_GetNoClip);
-	engine->RegisterScriptFunction("Raycast::GetSpriteScaleX^1", (void *)Ray_GetSpriteScaleX);
-	engine->RegisterScriptFunction("Raycast::SetSpriteScaleX^2", (void *)Ray_SetSpriteScaleX);
-	engine->RegisterScriptFunction("Raycast::GetSpriteScaleY^1", (void *)Ray_GetSpriteScaleY);
-	engine->RegisterScriptFunction("Raycast::SetSpriteScaleY^2", (void *)Ray_SetSpriteScaleY);
-	engine->RegisterScriptFunction("Raycast::GetSpriteBlendType^1", (void *)Ray_GetSpriteBlendType);
-	engine->RegisterScriptFunction("Raycast::SetSpriteBlendType^2", (void *)Ray_SetSpriteBlendType);
-
-
-	engine->RegisterScriptFunction("Raycast::SetFloorAt^3", (void *)Ray_SetFloorAt);
-	engine->RegisterScriptFunction("Raycast::SetCeilingAt^3", (void *)Ray_SetCeilingAt);
-	engine->RegisterScriptFunction("Raycast::GetCeilingAt^2", (void *)Ray_GetCeilingAt);
-	engine->RegisterScriptFunction("Raycast::GetFloorAt^2", (void *)Ray_GetFloorAt);
-	engine->RegisterScriptFunction("Raycast::GetLightingAt^2", (void *)Ray_GetLightingAt);
-	engine->RegisterScriptFunction("Raycast::SetLightingAt^3", (void *)Ray_SetLightingAt);
-	engine->RegisterScriptFunction("Raycast::GetWallHotspot^1", (void *)Ray_GetWallHotspot);
-	engine->RegisterScriptFunction("Raycast::GetWallTexture^2", (void *)Ray_GetWallTexture);
-	engine->RegisterScriptFunction("Raycast::GetWallSolid^2", (void *)Ray_GetWallSolid);
-	engine->RegisterScriptFunction("Raycast::GetWallIgnoreLighting^2", (void *)Ray_GetWallIgnoreLighting);
-	engine->RegisterScriptFunction("Raycast::GetWallAlpha^2", (void *)Ray_GetWallAlpha);
-	engine->RegisterScriptFunction("Raycast::GetWallBlendType^2", (void *)Ray_GetWallBlendType);
-	engine->RegisterScriptFunction("Raycast::SelectTile^3", (void *)Ray_SelectTile);
-	engine->RegisterScriptFunction("Raycast::HasSeenTile^2", (void *)Ray_HasSeenTile);
-
-	engine->RegisterScriptFunction("LensDistort::SetPos^2", (void *)SetLensPos);
-	engine->RegisterScriptFunction("LensDistort::GetX^0", (void *)GetLensX);
-	engine->RegisterScriptFunction("LensDistort::GetY^0", (void *)GetLensY);
-	engine->RegisterScriptFunction("LensDistort::Set^1", (void *)SetLensDrawn);
-	engine->RegisterScriptFunction("LensDistort::IsDrawn^0", (void *)GetLensDrawn);
-	engine->RegisterScriptFunction("LensDistort::SetOffsetClamp^1", (void *)SetLensOffsetClamp);
-	engine->RegisterScriptFunction("LensDistort::GetOffsetClamp^0", (void *)GetLensOffsetClamp);
-	engine->RegisterScriptFunction("LensDistort::GetLevel^0", (void *)GetLensLevel);
-	engine->RegisterScriptFunction("LensDistort::SetLevel^1", (void *)GetLensLevel);
-	engine->RegisterScriptFunction("LensDistort::Initialize^6", (void *)LensInitialize);
-
-	engine->RegisterScriptFunction("Translucence::CreateOverlay^8", (void *)CreateTranslucentOverlay);
-	engine->RegisterScriptFunction("Translucence::DeleteOverlay^1", (void *)DeleteTranslucentOverlay);
-	engine->RegisterScriptFunction("Translucence::Move^3", (void *)MoveTranslucentOverlay);
-	engine->RegisterScriptFunction("Translucence::GetOverlayX^1", (void *)GetTranslucentOverlayX);
-	engine->RegisterScriptFunction("Translucence::GetOverlayY^1", (void *)GetTranslucentOverlayY);
-	engine->RegisterScriptFunction("Translucence::GetOverlaySprite^1", (void *)GetTranslucentOverlaySprite);
-	engine->RegisterScriptFunction("Translucence::GetOverlayLevel^1", (void *)GetTranslucentOverlayLevel);
-	engine->RegisterScriptFunction("Translucence::GetOverlayEnabled^1", (void *)GetTranslucentOverlayEnabled);
-	engine->RegisterScriptFunction("Translucence::GetOverlayAlpha^1", (void *)GetTranslucentOverlayAlpha);
-	engine->RegisterScriptFunction("Translucence::SetOverlayAlpha^2", (void *)SetTranslucentOverlayAlpha);
-	engine->RegisterScriptFunction("Translucence::SetOverlayEnabled^2", (void *)SetTranslucentOverlayEnabled);
-	engine->RegisterScriptFunction("Translucence::DrawTransSprite^6", (void *)DrawTransSprite);
-
-	engine->RegisterScriptFunction("Starfield::GetOverscan^0", (void *)GetStarfieldOverscan);
-	engine->RegisterScriptFunction("Starfield::SetOverscan^1", (void *)SetStarfieldOverscan);
-	engine->RegisterScriptFunction("Starfield::GetOriginX^0", (void *)GetStarfieldOriginX);
-	engine->RegisterScriptFunction("Starfield::GetOriginY^0", (void *)GetStarfieldOriginY);
-	engine->RegisterScriptFunction("Starfield::SetDepthMultiplier^1", (void *)SetStarfieldDepthMultiplier);
-	engine->RegisterScriptFunction("Starfield::GetDepthMultiplier^0", (void *)GetStarfieldDepthMultiplier);
-	engine->RegisterScriptFunction("Starfield::GetMaxStars^0", (void *)GetStarfieldMaxStars);
-	engine->RegisterScriptFunction("Starfield::SetStarSpriteScaleBoost^1", (void *)SetStarSpriteScaleBoost);
-	engine->RegisterScriptFunction("Starfield::GetStarSpriteScaleBoost^0", (void *)GetStarSpriteScaleBoost);
-	engine->RegisterScriptFunction("Starfield::SetStarMaxRadius^2", (void *)SetStarMaxRadius);
-	engine->RegisterScriptFunction("Starfield::GetStarMaxRadius^0", (void *)GetStarMaxRadius);
-	engine->RegisterScriptFunction("Starfield::GetStarX^1", (void *)GetStarX);
-	engine->RegisterScriptFunction("Starfield::GetStarY^1", (void *)GetStarY);
-	engine->RegisterScriptFunction("Starfield::GetStarZ^1", (void *)GetStarZ);
-	engine->RegisterScriptFunction("Starfield::SetStarPosition^4", (void *)SetStarPosition);
-	engine->RegisterScriptFunction("Starfield::RotateStar^4", (void *)RotateStar);
-	engine->RegisterScriptFunction("Starfield::SetStarColor^2", (void *)SetStarColor);
-	engine->RegisterScriptFunction("Starfield::GetStarColor^1", (void *)GetStarColor);
-	engine->RegisterScriptFunction("Starfield::SetStarSprite^2", (void *)SetStarSprite);
-	engine->RegisterScriptFunction("Starfield::GetStarSprite^1", (void *)GetStarSprite);
-	engine->RegisterScriptFunction("Starfield::SetStarSpriteRange^3", (void *)SetStarSpriteRange);
-	engine->RegisterScriptFunction("Starfield::Initialize^2", (void *)InitializeStars);
-	engine->RegisterScriptFunction("Starfield::Iterate^1", (void *)IterateStars);
-	engine->RegisterScriptFunction("Starfield::Draw^2", (void *)DrawStars);
-	engine->RegisterScriptFunction("Starfield::SetOriginPoint^2", (void *)SetStarsOriginPoint);
-
-	engine->RegisterScriptFunction("Plasma::DoFire^8", (void *)DoFire);
-	engine->RegisterScriptFunction("Plasma::SetPlasmaType^5", (void *)SetPlasmaType);
-	engine->RegisterScriptFunction("Plasma::ResetPlasmaSettings^0", (void *)ResetPlasmaSettings);
-	engine->RegisterScriptFunction("Plasma::DrawPlasma^3", (void *)DrawPlasma);
-	engine->RegisterScriptFunction("Plasma::SetRootType^1", (void *)SetPlasmaRootType);
-	engine->RegisterScriptFunction("Plasma::GetRootType^0", (void *)GetPlasmaRootType);
-
-	engine->RegisterScriptFunction("Reflections::Set^1", (void *)SetReflections);
-	engine->RegisterScriptFunction("Reflections::IsReflecting^0", (void *)IsReflectionsOn);
-	engine->RegisterScriptFunction("Reflections::SetCharacterReflected^2", (void *)SetCharacterReflected);
-	engine->RegisterScriptFunction("Reflections::GetCharacterReflected^1", (void *)GetCharacterReflected);
-	engine->RegisterScriptFunction("Reflections::SetObjectReflected^2", (void *)SetObjectReflected);
-	engine->RegisterScriptFunction("Reflections::GetObjectReflected^1", (void *)GetObjectReflected);
-	engine->RegisterScriptFunction("Reflections::ReplaceCharacterReflectionView^2", (void *)ReplaceCharacterReflectionView);
-	engine->RegisterScriptFunction("Reflections::SetObjectReflectionIgnoreScaling^2", (void *)SetObjectReflectionIgnoreScaling);
-	engine->RequestEventHook(AGSE_PRESCREENDRAW);
-	engine->RequestEventHook(AGSE_PREGUIDRAW);
-	engine->RequestEventHook(AGSE_POSTSCREENDRAW);
-	engine->RequestEventHook(AGSE_SAVEGAME);
-	engine->RequestEventHook(AGSE_RESTOREGAME);
-	engine->RequestEventHook(AGSE_ENTERROOM);
-	stars = new starstype [MAX_STARS];
-	Starfield.maxstars = MAX_STARS;
-	Starfield.depthmultiplier = 256;
-	Starfield.speed = 0.5;
-	Starfield.originx = 160;
-	Starfield.originy = 100;
-	Reflection.Characters = new charrefopt [engine->GetNumCharacters()]();
-	lens = new LensDistort [LENS_WIDTH * LENS_WIDTH]();
-	//PreMultiply_Alphas ();
-	plasmaroottype = 0;
-	Make_Sin_Lut();
-	Init_Raycaster();
-}
-
-void AGSPalRender::AGS_EngineShutdown() {
-	// no work to do here - but if we had created any dynamic sprites,
-	// we should delete them here
-	delete[] Reflection.Characters;
-	delete[] Reflection.Objects;
-	//QuitCleanup();
-}
-
-NumberPtr AGSPalRender::AGS_EngineOnEvent(int event, NumberPtr data) {
-	if (event == AGSE_PRESCREENDRAW && clutslot > 0) {
-		if (drawreflections) {
-			int32 sh, sw = 0;
-			engine->GetScreenDimensions(&sw, &sh, nullptr);
-			reflectionmap = new long[sw * sh]();
-			rcolormap = engine->CreateBlankBitmap(sw, sh, 8);
-			ralphamap = engine->CreateBlankBitmap(sw, sh, 8);
-			for (int i = 0; i < engine->GetNumCharacters(); i++) {
-				if (Reflection.Characters[i].reflect == 0) continue;
-				AGSCharacter *tempchar = engine->GetCharacter(i);
-				if (tempchar->room != engine->GetCurrentRoom()) continue;  //if character isn't even in the room, go to next iteration.
-				int32 vx = tempchar->x;
-				int32 vy = tempchar->y;
-				engine->RoomToViewport(&vx, &vy);
-				AGSViewFrame *vf = engine->GetViewFrame(tempchar->view + 1, tempchar->loop, tempchar->frame);
-				int w = engine->GetSpriteWidth(vf->pic);
-				int h = engine->GetSpriteHeight(vf->pic);
-				vx = vx - (w / 2);
-				int32 vxmax = vx + w;
-				int32 vymax = vy + h;
-				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
-				DrawReflections(i, 0);
-			}
-			for (int i = 0; i < engine->GetNumObjects(); i++) {
-				if (Reflection.Objects[i].reflect == 0) continue;
-				AGSObject *tempobj = engine->GetObject(i);
-				if (!tempobj->on) continue;
-				int32 vx = tempobj->x;
-				int32 vy = tempobj->baseline - tempobj->y;
-				engine->RoomToViewport(&vx, &vy);
-				int32 w = engine->GetSpriteWidth(tempobj->num);
-				int32 h = engine->GetSpriteHeight(tempobj->num);
-				int32 vxmax = vx + w;
-				int32 vymax = vy + h;
-				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
-				DrawReflections(i, 1);
-			}
-			BITMAP *virtsc = engine->GetVirtualScreen();
-			unsigned char **screenbuffer = engine->GetRawBitmapSurface(virtsc);
-			unsigned char **colorbuffer = engine->GetRawBitmapSurface(rcolormap);
-			unsigned char **alphabuffer = engine->GetRawBitmapSurface(ralphamap);
-			for (int y = 0; y < sh; y++)
-				for (int x = 0; x < sw; x++)
-					screenbuffer[y][x] = Mix::MixColorAlpha(colorbuffer[y][x], screenbuffer[y][x], alphabuffer[y][x]);
-			engine->ReleaseBitmapSurface(rcolormap);
-			engine->ReleaseBitmapSurface(ralphamap);
-			engine->ReleaseBitmapSurface(virtsc);
-			engine->FreeBitmap(rcolormap);
-			engine->FreeBitmap(ralphamap);
-			delete [] reflectionmap;
-		}
-		int i = 0;
-		if (LensOption.draw == 1 && LensOption.level == 0) DrawLens(LensOption.x, LensOption.y);
-		while (i < MAX_OVERLAYS) {
-			if (overlay[i].enabled && overlay[i].level == 0) {
-				DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
-			}
-			i++;
-		}
-		if (LensOption.draw == 1 && LensOption.level == 1) DrawLens(LensOption.x, LensOption.y);
-	}
-	if (event == AGSE_PREGUIDRAW && clutslot > 0) {
-		int i = 0;
-		if (LensOption.draw == 1 && LensOption.level == 1) DrawLens(LensOption.x, LensOption.y);
-		while (i < MAX_OVERLAYS) {
-			if (overlay[i].enabled && overlay[i].level == 1) {
-				DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
-			}
-			i++;
-		}
-		if (LensOption.draw == 1 && LensOption.level == 2) DrawLens(LensOption.x, LensOption.y);
-	}
-	if (event == AGSE_POSTSCREENDRAW && clutslot > 0) {
-		int i = 0;
-		if (LensOption.draw == 1 && LensOption.level == 3) DrawLens(LensOption.x, LensOption.y);
-		while (i < MAX_OVERLAYS) {
-			if (overlay[i].enabled && overlay[i].level == 2) {
-				DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
-			}
-			i++;
-		}
-		if (LensOption.draw == 1 && LensOption.level == 4) DrawLens(LensOption.x, LensOption.y);
-	}
-	if (event == AGSE_SAVEGAME) {
-		for (int i = 0; i < MAX_OVERLAYS; ++i) {
-			engine->FWrite(&overlay[i].sprite, sizeof(int), data);
-			engine->FWrite(&overlay[i].spritemask, sizeof(int), data);
-			engine->FWrite(&overlay[i].x, sizeof(int), data);
-			engine->FWrite(&overlay[i].y, sizeof(int), data);
-			engine->FWrite(&overlay[i].level, sizeof(int), data);
-			engine->FWrite(&overlay[i].trans, sizeof(int), data);
-			engine->FWrite(&overlay[i].blendtype, sizeof(int), data);
-			engine->FWrite(&overlay[i].enabled, sizeof(bool), data);
-		}
-		engine->FWrite(&clutslot, sizeof(int), data);
-		engine->FWrite(&drawreflections, sizeof(int), data);
-		for (int j = 0; j < 256; ++j) {
-			engine->FWrite(&cycle_remap[j], sizeof(unsigned char), data);
-		}
-		for (int j = 0; j < 256; ++j) {
-			engine->FWrite(&objectivepal[j].r, sizeof(unsigned char), data);
-			engine->FWrite(&objectivepal[j].b, sizeof(unsigned char), data);
-			engine->FWrite(&objectivepal[j].g, sizeof(unsigned char), data);
-		}
-		for (int j = 0; j < 256; ++j) {
-			engine->FWrite(&sprite[j].x, sizeof(double), data);
-			engine->FWrite(&sprite[j].y, sizeof(double), data);
-			engine->FWrite(&sprite[j].texture, sizeof(int), data);
-			engine->FWrite(&sprite[j].alpha, sizeof(unsigned char), data);
-			engine->FWrite(&sprite[j].uDivW, sizeof(double), data);
-			engine->FWrite(&sprite[j].uDivH, sizeof(double), data);
-			engine->FWrite(&sprite[j].vMove, sizeof(double), data);
-			engine->FWrite(&sprite[j].hMove, sizeof(double), data);
-			engine->FWrite(&sprite[j].objectinteract, sizeof(char), data);
-			engine->FWrite(&sprite[j].view, sizeof(int), data);
-			engine->FWrite(&sprite[j].frame, sizeof(int), data);
-			engine->FWrite(&sprite[j].angle, sizeof(int), data);
-		}
-		for (int j = 0; j < 256; ++j) {
-			for (int k = 0; k < 4; ++k) {
-				engine->FWrite(&wallData[j].texture[k], sizeof(int), data);
-				engine->FWrite(&wallData[j].solid[k], sizeof(int), data);
-				engine->FWrite(&wallData[j].ignorelighting[k], sizeof(int), data);
-				engine->FWrite(&wallData[j].alpha[k], sizeof(int), data);
-				engine->FWrite(&wallData[j].blendtype[k], sizeof(int), data);
-				engine->FWrite(&wallData[j].mask[k], sizeof(int), data);
-			}
-			engine->FWrite(&wallData[j].hotspotinteract, sizeof(char), data);
-		}
-		engine->FWrite(&raycastOn, sizeof(bool), data);
-		engine->FWrite(&heightmapOn, sizeof(bool), data);
-		engine->FWrite(&posX, sizeof(double), data);
-		engine->FWrite(&posY, sizeof(double), data);
-		engine->FWrite(&dirX, sizeof(double), data);
-		engine->FWrite(&dirY, sizeof(double), data);
-		engine->FWrite(&planeX, sizeof(double), data);
-		engine->FWrite(&planeY, sizeof(double), data);
-		engine->FWrite(&moveSpeed, sizeof(double), data);
-		engine->FWrite(&rotSpeed, sizeof(double), data);
-		if (raycastOn) { //If the raycaster is active, we have additional data to save.
-			for (int i = 0; i < mapWidth; ++i)
-				for (int j = 0; j < mapHeight; ++j) {
-					engine->FWrite(&worldMap [i][j], sizeof(unsigned char), data);
-					engine->FWrite(&lightMap [i][j], sizeof(unsigned char), data);
-					engine->FWrite(&ceilingMap [i][j], sizeof(int), data);
-					engine->FWrite(&floorMap [i][j], sizeof(int), data);
-					engine->FWrite(&heightMap [i][j], sizeof(int), data);
-				}
-		}
-		engine->FWrite(&textureSlot, sizeof(int), data);
-		engine->FWrite(&skybox, sizeof(int), data);
-		engine->FWrite(&ambientlight, sizeof(int), data);
-	}
-	if (event == AGSE_RESTOREGAME) {
-
-
-		for (int i = 0; i < MAX_OVERLAYS; ++i) {
-			engine->FRead(&overlay[i].sprite, sizeof(int), data);
-			engine->FRead(&overlay[i].spritemask, sizeof(int), data);
-			engine->FRead(&overlay[i].x, sizeof(int), data);
-			engine->FRead(&overlay[i].y, sizeof(int), data);
-			engine->FRead(&overlay[i].level, sizeof(int), data);
-			engine->FRead(&overlay[i].trans, sizeof(int), data);
-			engine->FRead(&overlay[i].blendtype, sizeof(int), data);
-			engine->FRead(&overlay[i].enabled, sizeof(bool), data);
-		}
-		engine->FRead(&clutslot, sizeof(int), data);
-		engine->FRead(&drawreflections, sizeof(int), data);
-		for (int j = 0; j < 256; ++j) {
-			engine->FRead(&cycle_remap[j], sizeof(unsigned char), data);
-		}
-		for (int j = 0; j < 256; ++j) { //Save Objective Palette, for palette mixing.
-			engine->FRead(&objectivepal[j].r, sizeof(unsigned char), data);
-			engine->FRead(&objectivepal[j].b, sizeof(unsigned char), data);
-			engine->FRead(&objectivepal[j].g, sizeof(unsigned char), data);
-		}
-		for (int j = 0; j < 256; ++j) { //Save Raycaster Sprite struct, 256 instances.
-			engine->FRead(&sprite[j].x, sizeof(double), data);
-			engine->FRead(&sprite[j].y, sizeof(double), data);
-			engine->FRead(&sprite[j].texture, sizeof(int), data);
-			engine->FRead(&sprite[j].alpha, sizeof(unsigned char), data);
-			engine->FRead(&sprite[j].uDivW, sizeof(double), data);
-			engine->FRead(&sprite[j].uDivH, sizeof(double), data);
-			engine->FRead(&sprite[j].vMove, sizeof(double), data);
-			engine->FRead(&sprite[j].hMove, sizeof(double), data);
-			engine->FRead(&sprite[j].objectinteract, sizeof(char), data);
-			engine->FRead(&sprite[j].view, sizeof(int), data);
-			engine->FRead(&sprite[j].frame, sizeof(int), data);
-			engine->FRead(&sprite[j].angle, sizeof(int), data);
-		}
-		for (int j = 0; j < 256; ++j) { //Save Raycaster wall type data.
-			for (int k = 0; k < 4; ++k) {
-				engine->FRead(&wallData[j].texture[k], sizeof(int), data);
-				engine->FRead(&wallData[j].solid[k], sizeof(int), data);
-				engine->FRead(&wallData[j].ignorelighting[k], sizeof(int), data);
-				engine->FRead(&wallData[j].alpha[k], sizeof(int), data);
-				engine->FRead(&wallData[j].blendtype[k], sizeof(int), data);
-				engine->FRead(&wallData[j].mask[k], sizeof(int), data);
-			}
-			engine->FRead(&wallData[j].hotspotinteract, sizeof(char), data);
-		}
-		//Delete worldmap data if it exists.
-		engine->FRead(&raycastOn, sizeof(bool), data);
-		engine->FRead(&heightmapOn, sizeof(bool), data);
-		engine->FRead(&posX, sizeof(double), data);
-		engine->FRead(&posY, sizeof(double), data);
-		engine->FRead(&dirX, sizeof(double), data);
-		engine->FRead(&dirY, sizeof(double), data);
-		engine->FRead(&planeX, sizeof(double), data);
-		engine->FRead(&planeY, sizeof(double), data);
-		engine->FRead(&moveSpeed, sizeof(double), data);
-		engine->FRead(&rotSpeed, sizeof(double), data);
-		if (raycastOn) { //If the raycaster is currently running, we have additional data to load.
-			for (int i = 0; i < mapWidth; ++i) {
-				for (int j = 0; j < mapHeight; ++j) {
-					engine->FRead(&worldMap [i][j], sizeof(unsigned char), data);
-					engine->FRead(&lightMap [i][j], sizeof(unsigned char), data);
-					engine->FRead(&ceilingMap [i][j], sizeof(int), data);
-					engine->FRead(&floorMap [i][j], sizeof(int), data);
-					engine->FRead(&heightMap [i][j], sizeof(int), data);
-					seenMap [i][j] = 0;
-				}
-			}
-
-			//Reinitialize all the buffers and stuff.
-
-		}
-		engine->FRead(&textureSlot, sizeof(int), data);
-		if (textureSlot) MakeTextures(textureSlot);
-		engine->FRead(&skybox, sizeof(int), data);
-		engine->FRead(&ambientlight, sizeof(int), data);
-		LoadCLUT(clutslot);
-	}
-	if (event == AGSE_ENTERROOM) {
-		ResetRemapping();
-		delete[] Reflection.Objects;
-		Reflection.Objects = new objrefopt [engine->GetNumObjects()]();
-	}
-	return 0;
-}
-
-} // namespace AGSPalRender
-} // namespace Plugins
-} // namespace AGS3
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or(at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ags/lib/allegro.h"
+#include "ags/plugins/ags_pal_render/ags_pal_render.h"
+#include "ags/plugins/ags_pal_render/pal_render.h"
+#include "ags/plugins/ags_pal_render/raycast.h"
+#include "ags/ags.h"
+
+namespace AGS3 {
+namespace Plugins {
+namespace AGSPalRender {
+
+#define MAX_OVERLAYS 128
+#define MAX_STARS 1024
+#define MAX_DEPTH 64
+
+#define PI         (3.1415926535f)
+#define HALF_PI    (0.5f * PI)
+#define TWO_PI     (2.0f * PI)
+#define TWO_PI_INV (1.0f / TWO_PI)
+
+const float halfpi = (0.5f * PI);
+const float twopi  = (2.0f * PI);
+const float twopi_inv = (1.0f / TWO_PI);
+const float pisquared = PI * PI;
+const float picubed = PI * PI * PI;
+
+IAGSEngine *engine;
+
+//unsigned char clut[256][256];
+unsigned char clut[65536];
+
+struct transoverlaytype {
+	int sprite;
+	int spritemask;
+	int blendtype;
+	int x;
+	int y;
+	int trans;
+	int level;
+	bool enabled;
+} overlay[MAX_OVERLAYS];
+
+int clutslot;
+int drawreflections;
+unsigned char cycle_remap [256];
+
+struct starstype {
+	float x;
+	float y;
+	float z;
+	unsigned char color;
+	long sprite;
+	int maxrad;
+	int scaleboost;
+};
+starstype *stars;
+
+struct starsoptions {
+	float speed;
+	int maxstars;
+	int depthmultiplier;
+	int originx;
+	int originy;
+	int overscan;
+} Starfield;
+long *reflectionmap;
+BITMAP *rcolormap;
+BITMAP *ralphamap;
+
+struct charrefopt {
+	char reflect;
+	int replaceview;
+};
+
+struct objrefopt {
+	char reflect;
+	char ignorescaling;
+};
+
+struct reflectionopt {
+	charrefopt *Characters;
+	objrefopt *Objects;
+	int blendslot;
+	int blendamount;
+} Reflection;
+
+int dummy;
+
+#define LENS_WIDTH 150
+
+struct LensDistort {
+	int xoffset;
+	int yoffset;
+};
+
+LensDistort *lens;
+struct LensOpt {
+	bool draw;
+	int lenswidth;
+	int lenszoom;
+	int level;
+	int x;
+	int y;
+	int clampoffset;
+} LensOption;
+
+const int alphamultiply [4096] = {
+//#include "alphamultiply.txt"
+};
+float rot_sine_LUT[360];
+float rot_cos_LUT[360];
+
+BITMAP *backgroundimage;
+
+PALSTRUCT objectivepal[256];
+int bgimgspr;
+
+void WriteObjectivePalette(unsigned char index, unsigned char r, unsigned char b, unsigned char g) {
+	objectivepal[index].r = r;
+	objectivepal[index].b = b;
+	objectivepal[index].g = g;
+}
+
+int ReadObjectivePaletteR(unsigned char index) {
+	return objectivepal[index].r;
+}
+
+int ReadObjectivePaletteB(unsigned char index) {
+	return objectivepal[index].b;
+}
+int ReadObjectivePaletteG(unsigned char index) {
+	return objectivepal[index].g;
+}
+
+
+#define SQRT_MAGIC_F 0x5f3759df
+float  q3sqrt(const float x) {
+	const float xhalf = 0.5f * x;
+
+	union { // get bits for floating value
+		float x;
+		int i;
+	} u;
+	u.x = x;
+	u.i = SQRT_MAGIC_F - (u.i >> 1);  // gives initial guess y0
+	return x * u.x * (1.5f - xhalf * u.x * u.x); // Newton step, repeating increases accuracy
+}
+
+void Make_Sin_Lut() {
+	for (int angle = 0; angle < 360; angle++) {
+		double rad = (angle * PI) / 180.0;
+		rot_sine_LUT [angle] = static_cast<float>(sin(rad));
+		rot_cos_LUT [angle]  = static_cast<float>(cos(rad));
+	}
+}
+
+/*
+void PreMultiply_Alphas () //Ha ha, this isn't the kind of premultiplcation you're thinking of.
+{
+    for (int y=0;y<64;y++)
+        for (int x=0;x<64;x++)
+            alphamultiply [y*64+x] = y*x;
+}
+*/
+
+int GetModifiedBackgroundImage() {
+	return bgimgspr;
+}
+
+unsigned short root(unsigned short x) {
+	unsigned short a, b;
+	b = x;
+	a = x = 0x3f;
+	x = b / x;
+	a = x = (x + a) >> 1;
+	x = b / x;
+	a = x = (x + a) >> 1;
+	x = b / x;
+	x = (x + a) >> 1;
+	return (x);
+}
+
+
+float Hill(float x) {
+	const float a0 = 1.0f;
+	const float a2 = 2.0f / PI - 12.0f / (pisquared);
+	const float a3 = 16.0f / (picubed) - 4.0f / (pisquared);
+	const float xx = x * x;
+	const float xxx = xx * x;
+
+	return a0 + a2 * xx + a3 * xxx;
+}
+
+float FastSin(float x) {
+	// wrap x within [0, TWO_PI)
+	const float a = x * twopi_inv;
+	x -= static_cast<int>(a) * twopi;
+	if (x < 0.0f)
+		x += twopi;
+
+	// 4 pieces of hills
+	if (x < halfpi)
+		return Hill(halfpi - x);
+	else if (x < PI)
+		return Hill(x - halfpi);
+	else if (x < 3.0f * halfpi)
+		return -Hill(3.0f * halfpi - x);
+	else
+		return -Hill(x - 3.0f * halfpi);
+}
+
+float FastCos(float x) {
+	return FastSin(x + halfpi);
+}
+
+FLOAT_RETURN_TYPE AGSFastSin(SCRIPT_FLOAT(x)) {
+	INIT_SCRIPT_FLOAT(x);
+	x = FastSin(x);
+	RETURN_FLOAT(x);
+}
+
+FLOAT_RETURN_TYPE AGSFastCos(SCRIPT_FLOAT(x)) {
+	INIT_SCRIPT_FLOAT(x);
+	x = FastSin(x + halfpi);
+	RETURN_FLOAT(x);
+}
+
+
+void DrawLens(int ox, int oy) {
+	int32 sh, sw = 0;
+	engine->GetScreenDimensions(&sw, &sh, nullptr);
+	BITMAP *virtsc = engine->GetVirtualScreen();
+	if (!virtsc) engine->AbortGame("DrawLens: Cannot get virtual screen.");
+	BITMAP *lenswrite = engine->CreateBlankBitmap(LensOption.lenswidth, LensOption.lenswidth, 8);
+	unsigned char **vScreen = engine->GetRawBitmapSurface(virtsc);
+	unsigned char **lensarray = engine->GetRawBitmapSurface(lenswrite);
+	int radius = LensOption.lenswidth >> 1;
+	for (int y = 0; y < LensOption.lenswidth; y++) {
+		int ypos = y * LensOption.lenswidth;
+		for (int x = 0; x < LensOption.lenswidth; x++) {
+			int lenspos = ypos + x;
+			int coffx = lens[lenspos].xoffset;
+			int coffy = lens[lenspos].yoffset;
+			if (oy + coffy > 0 && oy + coffy < sh && ox + coffx > 0 && ox + coffx < sw) {
+				lensarray[y][x] = vScreen[oy + coffy][ox + coffx];
+				//vScreen[oy+coffy][ox+coffx] = ABS(coffy);
+			}
+		}
+	}
+	/*
+	for (int y=0;y<LensOption.lenswidth;y++)
+	{
+	    int ypos = y*LensOption.lenswidth;
+	    for (int x=0;x<LensOption.lenswidth;x++)
+	    {
+	        if (oy+y > 0 && oy+y < sh && ox+x > 0 && ox+x < sw)
+	        {
+	            vScreen[oy+y][ox+x] = lensarray[y][x];
+	        }
+	    }
+	}
+	*/
+	int radsq = radius * radius;
+	for (int cy = -radius; cy <= radius; cy++) { //Draw a circle around the point, for the mask.
+		int cysq = cy * cy;
+		for (int cx = -radius; cx <= radius; cx++) {
+			int cxsq = cx * cx;
+			int dx = cx + ox;
+			int dy = cy + oy;
+			if ((cxsq + cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0 && cy + radius < LensOption.lenswidth - 1 && cx + radius < LensOption.lenswidth - 1) {
+				//if (cy+radius < 0 || cx+radius < 0) engine->AbortGame ("I did something wrong");
+				vScreen[dy][dx] = lensarray[cy + radius][cx + radius];
+			}
+		}
+	}
+
+	engine->ReleaseBitmapSurface(lenswrite);
+	engine->ReleaseBitmapSurface(virtsc);
+	engine->FreeBitmap(lenswrite);
+}
+
+void SetLensPos(int x, int y) {
+	LensOption.x = x;
+	LensOption.y = y;
+}
+
+int GetLensX() {
+	return LensOption.x;
+}
+
+int GetLensY() {
+	return LensOption.y;
+}
+
+void SetLensDrawn(int toggle) {
+	if (toggle > 0) LensOption.draw = 1;
+	else LensOption.draw = 0;
+}
+
+int GetLensDrawn() {
+	return LensOption.draw;
+}
+
+void SetLensOffsetClamp(int clamp) {
+	if (clamp < 0) LensOption.clampoffset = LensOption.lenswidth;
+	else LensOption.clampoffset = clamp;
+}
+
+int GetLensOffsetClamp() {
+	return LensOption.clampoffset;
+}
+
+int GetLensLevel() {
+	return LensOption.level;
+}
+
+void SetLensLevel(int level) {
+	if (level < 0 || level > 4) engine->AbortGame("SetLensLevel: Invalid level.");
+	else LensOption.level = level;
+}
+
+void LensInitialize(int width, int zoom, int lensx, int lensy, int level, int clamp = -1) {
+	int32 sw, sh, radius;
+	if (width < 1) engine->AbortGame("Invalid lens dimension!");
+	radius = width >> 1;
+	lens = new LensDistort [width * width]();
+	engine->GetScreenDimensions(&sw, &sh, nullptr);
+	int radsq = radius * radius;
+	int zoomsq = zoom * zoom;
+	for (int y = 0; y < radius; y++) {
+		int ysq = y * y;
+		for (int x = 0; x < radius; x++) {
+			int lx, ly;
+			int xsq = x * x;
+			if ((xsq + ysq) < (radsq)) {
+				float shift = zoom / sqrt((float)(zoomsq - (xsq + ysq - radsq)));
+				lx = (int)(x * shift - x);
+				ly = (int)(y * shift - y);
+			} else {
+				lx = 0;
+				ly = 0;
+			}
+			lens[(radius - y)*width + (radius - x)].xoffset =  lx;
+			lens[(radius - y)*width + (radius - x)].yoffset =  ly;
+			lens[(radius + y)*width + (radius + x)].xoffset = -lx;
+			lens[(radius + y)*width + (radius + x)].yoffset = -ly;
+			lens[(radius + y)*width + (radius - x)].xoffset =  lx;
+			lens[(radius + y)*width + (radius - x)].yoffset = -ly;
+			lens[(radius - y)*width + (radius + x)].xoffset = -lx;
+			lens[(radius - y)*width + (radius + x)].yoffset =  ly;
+		}
+	}
+	LensOption.lenswidth = width;
+	LensOption.lenszoom = zoom;
+	if (clamp < 0) LensOption.clampoffset = width;
+	else LensOption.clampoffset = clamp;
+	LensOption.x = lensx;
+	LensOption.y = lensy;
+	if (level < 0 || level > 4) engine->AbortGame("SetLensLevel: Invalid level.");
+	else LensOption.level = level;
+}
+
+void ResetRemapping() {
+	for (int j = 0; j < 256; ++j) {
+		cycle_remap [j] = j;
+	}
+}
+
+#define MAX_PLASMA_COMPLEXITY 4
+int plasmatype[MAX_PLASMA_COMPLEXITY];
+int plasmadata [MAX_PLASMA_COMPLEXITY];
+int plasmadata2 [MAX_PLASMA_COMPLEXITY];
+int plasmadata3 [MAX_PLASMA_COMPLEXITY];
+int plasmaroottype;
+
+
+void SetPlasmaRootType(int real) {
+	if (real) plasmaroottype = 1;
+	else plasmaroottype = 0;
+}
+
+int GetPlasmaRootType() {
+	return plasmaroottype;
+}
+
+void SetPlasmaType(int component, int type, int data, int data2, int data3) {
+	if (component >= MAX_PLASMA_COMPLEXITY) engine->AbortGame("Plasma too complex!");
+	else {
+		plasmatype [component] = type;
+		plasmadata [component] = data;
+		plasmadata2[component] = data2;
+		plasmadata3[component] = data3;
+	}
+
+	//0 = None.
+	//1 = Horizontal Bars (data=width)
+	//2 = Vertical Bars (data=width)
+	//3 = Circle (data=x,data2=y,data3=width)
+	//4 = Diagonal Bars (data=width)
+}
+
+void ResetPlasmaSettings() {
+	int i = 0;
+	while (i < MAX_PLASMA_COMPLEXITY) {
+		plasmatype [i] = 0;
+		plasmadata [i] = 0;
+		plasmadata2[i] = 0;
+		plasmadata3[i] = 0;
+		i++;
+	}
+}
+
+void DrawPlasma(int slot, int palstart, int palend) {
+	BITMAP *plasmaspr = engine->GetSpriteGraphic(slot);
+	if (!plasmaspr) engine->AbortGame("Plasma: Not a sprite I can load.");
+	int32 w, h, basecol, range = 0;
+	if (palend > palstart) {
+		range = palend - palstart;
+		basecol = palstart;
+	} else {
+		range = palstart - palend;
+		basecol = palend;
+	}
+	engine->GetBitmapDimensions(plasmaspr, &w, &h, nullptr);
+	unsigned char **plasmarray = engine->GetRawBitmapSurface(plasmaspr);
+	double frange = range / 2.0;
+	int complex = 0;
+	int color = 0;
+	int i = 0;
+	while (i < MAX_PLASMA_COMPLEXITY) {
+		if (plasmatype[i] > 0) complex++;
+		i++;
+	}
+	for (int x = 0; x < w; x++) {
+		for (int y = 0; y < h; y++) {
+			color = 0;
+			for (int p = 0; p < MAX_PLASMA_COMPLEXITY; p++) {
+				if (plasmatype[p] == 1) { //1 = Horizontal Bars (data=width)
+					color += int(frange + (frange * FastSin(y / (float)plasmadata[p])));
+				} else if (plasmatype[p] == 2) { //2 = Vertical Bars (data=width)
+					color += int(frange + (frange * FastSin(x / (float)plasmadata[p])));
+				} else if (plasmatype[p] == 3) { //3 = Circle (data=x,data2=y,data3=width)
+					int cx, cy = 0;
+					cx = plasmadata [p];
+					cy = plasmadata2 [p];
+					if (plasmaroottype == 1) color += int(frange + (frange * FastSin(q3sqrt((float)((x - cx) * (x - cx) + (y - cy) * (y - cy)) / plasmadata3[p]))));
+					else color += int(frange + (frange * FastSin(root(((x - cx) * (x - cx) + (y - cy) * (y - cy)) / plasmadata3[p]))));
+				} else if (plasmatype[p] == 4) { //4 = Diagonal Bars (data=width)
+					color += int(frange + (frange * FastSin((x + y) / (float)plasmadata[p])));
+				}
+			}
+			if (color > 0 && complex > 0) color = color / complex;
+			plasmarray[y][x] = static_cast<unsigned char>(basecol + color);
+		}
+	}
+	engine->ReleaseBitmapSurface(plasmaspr);
+	engine->NotifySpriteUpdated(slot);
+}
+
+void DoFire(int spriteId, int masksprite, int palstart, int palend, int strength, int seed, int cutoff, int windspeed) {
+	BITMAP *firespr = engine->GetSpriteGraphic(masksprite);
+	BITMAP *firecolorspr = engine->GetSpriteGraphic(spriteId);
+	BITMAP *seedspr;
+	int32 w, h = 0;
+	int range, basecol, dir = 0;
+	if (palend > palstart) {
+		range = palend - palstart;
+		basecol = palstart;
+		dir = 1;
+	} else {
+		range = palstart - palend;
+		basecol = palend;
+		dir = -1;
+	}
+	int divider = 256 / range;
+	engine->GetBitmapDimensions(firespr, &w, &h, nullptr);
+	unsigned char **fire = engine->GetRawBitmapSurface(firespr);
+	unsigned char **color = engine->GetRawBitmapSurface(firecolorspr);
+	int sparky = 0;
+	//srand(time(NULL));
+	for (int y = 0; y < h - 1; y++) {
+		if ((int)::AGS::g_vm->getRandomNumber(9) > 7 - windspeed) { //Wind right
+			for (int x = w - 1; x > 1; x--) {
+				fire[y][x] = fire[y][x - 1];
+			}
+		} else if ((int)::AGS::g_vm->getRandomNumber(9) > 7 + windspeed) { // wind left
+			for (int x = 0; x < w - 1; x++) {
+				fire[y][x] = fire[y][x + 1];
+			}
+		}
+	}
+	for (int x = 0; x < w; x++) {
+		sparky = ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % (h - 2));
+		if (sparky < h && sparky > 0 && fire[h - sparky][x] > cutoff &&
+				ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % 10) > 7)
+			fire[h - sparky][x] = 255;
+		sparky = ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % (h - 2));
+		if (sparky < h && sparky > 0 && fire[h - sparky][x] > cutoff &&
+				ABS((int)::AGS::g_vm->getRandomNumber(0x7fffffff) % 10) > 7)
+			fire[h - sparky][x] = 0;
+	}
+	if (seed == 0) {
+		for (int x = 0; x < w; x++)
+			fire[h - 1][x] = 255;
+		for (int x = 0; x < w; x++)
+			fire[h - 2][x] = ::AGS::g_vm->getRandomNumber(255);
+	} else if (seed > 0) {
+		seedspr = engine->GetSpriteGraphic(seed);
+		BITMAP *virtsc = engine->GetVirtualScreen();
+		engine->SetVirtualScreen(firespr);
+		engine->BlitBitmap(0, 0, seedspr, 1);
+		engine->SetVirtualScreen(virtsc);
+		engine->ReleaseBitmapSurface(virtsc);
+		engine->ReleaseBitmapSurface(seedspr);
+		engine->NotifySpriteUpdated(spriteId);
+		engine->NotifySpriteUpdated(masksprite);
+	}
+
+	for (int y = 0; y < h - 1; y++) {
+		for (int x = 0; x < w; x++) {
+			fire[y][x] =
+			    ((fire[(y + 1) % h][(x - 1 + w) % w]
+			      + fire[(y + 1) % h][(x) % w]
+			      + fire[(y + 1) % h][(x + 1) % w]
+			      + fire[(y + 2) % h][(x) % w])
+			     * 100) / (400 + (100 - strength));
+			if (fire[y][x] < cutoff) fire[y][x] = 0;
+			//if (fire[y][x] ==255) color [y][x] = palend;
+			else color [y][x] = static_cast<unsigned char>(basecol + (fire[y][x] / divider) * dir);
+		}
+	}
+	engine->ReleaseBitmapSurface(firespr);
+	engine->ReleaseBitmapSurface(firecolorspr);
+	engine->NotifySpriteUpdated(spriteId);
+	engine->NotifySpriteUpdated(masksprite);
+}
+
+/*
+unsigned char MixColorAlpha (unsigned char fg,unsigned char bg,unsigned char alpha)
+{
+    //unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
+    //unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
+    //BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
+    //if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
+    //unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
+    AGSColor *palette = engine->GetPalette ();
+    int i=0;
+    int out_r = (palette[fg].r>>1) * alpha + (palette[bg].r>>1) * (255 - alpha);
+    int out_g = palette[fg].g * alpha + palette[bg].g * (255 - alpha);
+    int out_b = (palette[fg].b>>1) * alpha + (palette[bg].b>>1) * (255 - alpha);
+    //unsigned char ralpha = alpha>>2;
+    //unsigned char invralpha = 64-ralpha;
+    //if (ralpha > alpha) engine->AbortGame ("wtf");
+    //int out_r = alphamultiply[(palette[fg].r>>1)][ralpha] + alphamultiply[(palette[bg].r>>1)][(invralpha)];
+    //int out_g = alphamultiply[(palette[fg].g)][ralpha] + alphamultiply[(palette[bg].g)][(invralpha)];
+    //int out_b = alphamultiply[(palette[fg].b>>1)][ralpha] + alphamultiply[(palette[bg].b>>1)][(invralpha)];
+    out_r = (out_r + 1 + (out_r >> 8)) >> 8;
+    out_g = (out_g + 1 + (out_g >> 8)) >> 8;
+    out_b = (out_b + 1 + (out_b >> 8)) >> 8;
+    i = ((out_r << 11) | (out_g << 5) | out_b);
+    unsigned char (*clutp) = clut;
+    //unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
+    unsigned char result = cycle_remap [*(clutp+i)]; //Once again, to make sure that the palette slot used is the right one.
+    //engine->ReleaseBitmapSurface (clutspr);
+    return result;
+}
+
+unsigned char MixColorAdditive (unsigned char fg,unsigned char bg,unsigned char alpha)
+{
+    //unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
+    //unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
+    //BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
+    //if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
+    //unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
+    AGSColor *palette = engine->GetPalette ();
+    int i=0;
+    int add_r,add_b,add_g = 0;
+    char ralpha = alpha>>2;
+    //if (ralpha > alpha) engine->AbortGame ("wtf");
+    //add_r = (((palette[fg].r>>1) * (alpha))>>8);
+    //add_b = (((palette[fg].b>>1) * (alpha))>>8);
+    //add_g = (((palette[fg].g)    * (alpha))>>8);
+    add_r = ((alphamultiply[(palette[fg].r>>1)*64+ralpha])>>6);
+    add_b = ((alphamultiply[(palette[fg].b>>1)*64+ralpha])>>6);
+    add_g = ((alphamultiply[(palette[fg].g   )*64+ralpha])>>6);
+    int out_r = min(31,(palette[bg].r>>1) + add_r);
+    int out_g = min(63, palette[bg].g     + add_g);
+    int out_b = min(31,(palette[bg].b>>1) + add_b);
+    i = ((out_r << 11) | (out_g << 5) | out_b);
+    unsigned char (*clutp) = clut;
+    unsigned char result = cycle_remap [*(clutp+i)]; //Once again, to make sure that the palette slot used is the right one.
+    //unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
+    //engine->ReleaseBitmapSurface (clutspr);
+    return result;
+}
+*/
+unsigned char GetColor565(unsigned char r, unsigned char g, unsigned char b) {
+	//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
+	//if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
+	//unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
+	int i = ((r << 11) | (g << 5) | b);
+	unsigned char *clutp = clut;
+	unsigned char result = *(clutp + i);
+	result = cycle_remap [result]; //Once again, to make sure that the palette slot used is the right one.
+	//engine->ReleaseBitmapSurface (clutspr);
+	return result;
+}
+
+void CycleRemap(int start, int end) {
+	if (end > start) {
+		// Rotate left
+		int wraparound = cycle_remap [start];
+		for (; start < end; ++start) {
+			cycle_remap [start] = cycle_remap [start + 1];
+		}
+		cycle_remap [end] = wraparound;
+	} else if (end < start) {
+		// Rotate right
+		int wraparound = cycle_remap [start];
+		for (; start > end; --start) {
+			cycle_remap [start] = cycle_remap [start - 1];
+		}
+		cycle_remap [end] = wraparound;
+
+	}
+}
+
+unsigned char GetRemappedSlot(unsigned char slot) {
+	return cycle_remap [slot];
+}
+
+int LoadCLUT(int slot) {
+	if (engine->GetSpriteWidth(slot) != 256 || engine->GetSpriteHeight(slot) != 256) return 1;
+	BITMAP *clutimage = engine->GetSpriteGraphic(slot);
+	unsigned char **clutarray = engine->GetRawBitmapSurface(clutimage);
+	for (int y = 0; y < 256; y++) {
+		for (int x = 0; x < 256; x++) {
+			clut[y * 256 + x] = clutarray[y][x];
+		}
+	}
+	clutslot = slot;
+	engine->ReleaseBitmapSurface(clutimage);
+	return 0;
+}
+
+void SetReflections(int toggle) {
+	drawreflections = toggle;
+}
+
+int IsReflectionsOn() {
+	return drawreflections;
+}
+
+int GetLuminosityFromPalette(int slot) {
+	AGSColor *pal = engine->GetPalette();
+	int lum = (pal[slot].r +
+	           pal[slot].r +
+	           pal[slot].r +
+	           pal[slot].g +
+	           pal[slot].g +
+	           pal[slot].g +
+	           pal[slot].g +
+	           pal[slot].b) >> 3;
+	return lum;
+}
+
+
+
+void SetStarsOriginPoint(int x, int y) {
+	Starfield.originx = x;
+	Starfield.originy = y;
+}
+void InitializeStars(int slot, int maxstars) {
+	int32 sw, sh = 0;
+	BITMAP *canvas = engine->GetSpriteGraphic(slot);
+	engine->GetBitmapDimensions(canvas, &sw, &sh, nullptr);
+	Starfield.maxstars = maxstars;
+	Starfield.overscan = 20;
+	stars = new starstype [Starfield.maxstars];
+	for (int i = 0; i < Starfield.maxstars; i++) {
+		stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
+		if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
+		stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
+		if (stars[i].y < 1.0 && stars[i].y > -1.0) stars[i].y = (float)sh;
+		stars[i].z = (float)(MAX_DEPTH);
+		stars[i].color = (::AGS::g_vm->getRandomNumber(0x7fffffff) % 240);
+		stars[i].sprite = 0;
+		stars[i].maxrad = (::AGS::g_vm->getRandomNumber(0x7fffffff) % 5);
+	}
+}
+
+void IterateStars(int slot) {
+	long sw, sh = 0;
+	sw = engine->GetSpriteWidth(slot);
+	sh = engine->GetSpriteHeight(slot);
+	for (int i = 0; i < Starfield.maxstars; i++) {
+		stars[i].z -= Starfield.speed;
+		//if (stars[i].z < 1.0) stars[i].z = (double)MAX_DEPTH;
+		float k = Starfield.depthmultiplier / stars[i].z;
+		int px = static_cast<int>(stars[i].x * k + Starfield.originx);
+		int py = static_cast<int>(stars[i].y * k + Starfield.originy);
+		if (px >= sw + Starfield.overscan || px < 0 - Starfield.overscan || py >= sh + Starfield.overscan || py < 0 - Starfield.overscan) {
+			stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
+			if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
+			stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
+			if (stars[i].y < 1.0 && stars[i].y > 1.0) stars[i].y = (float)sh;
+			stars[i].z = (float)MAX_DEPTH;
+			//stars[i].color = (rand () %240);
+		}
+	}
+}
+int GetStarfieldOverscan() {
+	return Starfield.overscan;
+}
+void SetStarfieldOverscan(int overscan) {
+	Starfield.overscan = overscan;
+}
+
+int GetStarfieldOriginX() {
+	return Starfield.originx;
+}
+
+int GetStarfieldOriginY() {
+	return Starfield.originy;
+}
+
+void SetStarfieldDepthMultiplier(int multi) {
+	Starfield.depthmultiplier = multi;
+}
+
+int GetStarfieldDepthMultiplier() {
+	return Starfield.depthmultiplier;
+}
+
+int GetStarfieldMaxStars() {
+	return Starfield.maxstars;
+}
+
+void SetStarSpriteScaleBoost(int star, int boost) {
+	stars[star].scaleboost = boost;
+}
+
+int GetStarSpriteScaleBoost(int star) {
+	return stars[star].scaleboost;
+}
+
+void SetStarMaxRadius(int star, int radius) {
+	stars[star].maxrad = radius;
+}
+
+int GetStarMaxRadius(int star) {
+	return stars[star].maxrad;
+}
+
+void RotateStar(int star, int angle, int px, int py) {
+	float rsin = rot_sine_LUT[angle];
+	float rcos = rot_cos_LUT[angle];
+	float fPx = (float)px;
+	float fPy = (float)py;
+	float x1 = 0, y1 = 0, xRot = 0, yRot = 0;
+	int i = star;
+	x1 = stars[i].x;
+	y1 = stars[i].y;
+	xRot = fPx + rcos * (x1 - fPx) - rsin * (y1 - fPy);
+	yRot = fPy + rsin * (x1 - fPx) + rcos * (y1 - fPy);
+	stars[i].x = xRot;
+	stars[i].y = yRot;
+	i++;
+}
+
+FLOAT_RETURN_TYPE GetStarX(int i) {
+	float starx = (float)stars[i].x;
+	RETURN_FLOAT(starx);
+}
+
+FLOAT_RETURN_TYPE GetStarY(int i) {
+	float stary = (float)stars[i].y;
+	RETURN_FLOAT(stary);
+}
+
+FLOAT_RETURN_TYPE GetStarZ(int i) {
+	float starz = (float)stars[i].z;
+	RETURN_FLOAT(starz);
+}
+
+void SetStarPosition(int star, SCRIPT_FLOAT(x), SCRIPT_FLOAT(y), SCRIPT_FLOAT(z)) {
+	INIT_SCRIPT_FLOAT(x);
+	INIT_SCRIPT_FLOAT(y);
+	INIT_SCRIPT_FLOAT(z);
+	stars[star].x = x;
+	stars[star].y = y;
+	stars[star].z = z;
+}
+
+void SetStarColor(int star, unsigned char color) {
+	stars[star].color = color;
+}
+
+unsigned char GetStarColor(int star) {
+	return stars[star].color;
+}
+
+void SetStarSprite(int star, int slot) {
+	stars[star].sprite = slot;
+}
+
+int GetStarSprite(int star) {
+	return stars[star].sprite;
+}
+
+void SetStarSpriteRange(int start, int end, int slot) {
+	int sfix = start;
+	int efix = end;
+	if (start > Starfield.maxstars) sfix = Starfield.maxstars - 1;
+	if (end > Starfield.maxstars) efix = Starfield.maxstars;
+	for (int i = sfix; i < efix; i++)
+		stars[i].sprite = slot;
+}
+
+void DrawStars(int slot, int maskslot) {
+	int32 sw, sh = 0;
+	BITMAP *canvas = engine->GetSpriteGraphic(slot);
+	if (!canvas) engine->AbortGame("DrawStars: Can't load sprite slot.");
+	BITMAP *maskcanvas = engine->GetSpriteGraphic(maskslot);
+	if (!maskcanvas) engine->AbortGame("DrawStars: Can't load mask slot.");
+	engine->GetBitmapDimensions(canvas, &sw, &sh, nullptr);
+	unsigned char **screenarray = engine->GetRawBitmapSurface(canvas);
+	unsigned char **maskarray = engine->GetRawBitmapSurface(maskcanvas);
+	for (int i = 0; i < Starfield.maxstars; i++) {
+		//stars[i].z-= 0.5;
+		//if (stars[i].z < 1.0) stars[i].z = (double)MAX_DEPTH;
+		float k = (float)Starfield.depthmultiplier / stars[i].z;
+		int px = static_cast<int>(stars[i].x * k + Starfield.originx);
+		int py = static_cast<int>(stars[i].y * k + Starfield.originy);
+		if (px >= sw + Starfield.overscan || px < 0 - Starfield.overscan || py >= sh + Starfield.overscan || py < 0 - Starfield.overscan) {
+			stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
+			if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
+			stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
+			if (stars[i].y < 1.0 && stars[i].y > 1.0) stars[i].y = (float)sh;
+			stars[i].z = (float)MAX_DEPTH;
+			//stars[i].color = (rand () %240);
+		} else if (stars[i].z > 0) {
+			int ivalue = (63 - (int)stars[i].z);
+			if (ivalue > 63) ivalue = 63;
+			else if (ivalue < 0) ivalue = 0;
+			unsigned char value = (unsigned char)(ivalue);
+			unsigned char maskcolor = value << 2;
+			if (stars[i].sprite > 0) {
+				BITMAP *origspr = engine->GetSpriteGraphic(stars[i].sprite);
+				int scale = (ivalue + 1) * 100 >> 6;
+				//int scale = 50;
+				if (scale < 1) scale = 1;
+				/*
+				if (scale != 100)
+				{
+				unsigned char** orig = engine->GetRawBitmapSurface (origspr);
+				int32 h1,h2,w1,w2=0;
+				double fw2,fh2;
+				engine->GetBitmapDimensions (origspr,&w1,&h1,NULL);
+				fh2 = h1 * (scale / 100.0);
+				fw2 = w1 * (scale / 100.0);
+				h2 = static_cast<int>(fh2);
+				w2 = static_cast<int>(fw2);
+				if (w2 < 1) w2 = 1;
+				if (h2 < 1) h2 = 1;
+				resizspr = engine->CreateBlankBitmap (w2,h2,8);
+				unsigned char** resized = engine->GetRawBitmapSurface (resizspr);
+				int x_ratio = (int)((w1<<16)/w2) +1;
+				int y_ratio = (int)((h1<<16)/h2) +1;
+				int x2, y2 ;
+				for (int i=0;i<h2;i++)
+				{
+				    for (int j=0;j<w2;j++)
+				   {
+				       x2 = ((j*x_ratio)>>16) ;
+				       y2 = ((i*y_ratio)>>16) ;
+				       resized [i][j] = orig [y2][x2];
+				 }
+				}
+				engine->ReleaseBitmapSurface (resizspr);
+				}
+				//resizspr = origspr;
+				int32 w,h=0;
+				engine->GetBitmapDimensions (resizspr,&w,&h,NULL);
+				unsigned char **imagemap = engine->GetRawBitmapSurface (resizspr);
+				int ox = px - (w>>1);
+				int oy = py - (h>>1);
+				for (int dy=0;dy<h;dy++)
+				{
+				for (int dx=0;dx<w;dx++)
+				{
+				   int ex = ox+dx;
+				   int ey = oy+dy;
+				   if (ex < sw && ex >= 0 && ey < sh && ey >= 0)
+				   {
+				       if (maskcolor > maskarray [ey][ex] && imagemap[dy][dx] > 0)
+				       {
+				           maskarray [ey][ex] = maskcolor;
+				           screenarray [ey][ex] = imagemap[dy][dx];
+				       }
+				   }
+				}
+				}
+				*/
+
+				unsigned char **orig = engine->GetRawBitmapSurface(origspr);
+				int32 h1, h2, w1, w2 = 0;
+				double fw2, fh2;
+				engine->GetBitmapDimensions(origspr, &w1, &h1, nullptr);
+				fh2 = h1 * (scale / 100.0);
+				fw2 = w1 * (scale / 100.0);
+				h2 = static_cast<int>(fh2);
+				w2 = static_cast<int>(fw2);
+				if (w2 < 1) w2 = 1;
+				if (h2 < 1) h2 = 1;
+				int x_ratio = (int)((w1 << 16) / w2) + 1;
+				int y_ratio = (int)((h1 << 16) / h2) + 1;
+				int x2, y2 ;
+				int ox = px - (w2 >> 1);
+				int oy = py - (h2 >> 1);
+				for (int ii = 0; ii < h2; ii++) {
+					int temprzy = ii * y_ratio;
+					int ey = oy + ii;
+					for (int j = 0; j < w2; j++) {
+						x2 = ((j * x_ratio) >> 16);
+						y2 = ((temprzy) >> 16);
+						int ex = ox + j;
+						if (ex < sw && ex >= 0 && ey < sh && ey >= 0) {
+							if (maskcolor > maskarray [ey][ex] && orig[y2][x2] > 0) {
+								maskarray [ey][ex] = maskcolor;
+								screenarray [ey][ex] = orig[y2][x2];
+							}
+						}
+						//resized [ii][j] = orig [y2][x2];
+					}
+				}
+				engine->ReleaseBitmapSurface(origspr);
+			} else if (stars[i].sprite == 0) {
+				if (stars[i].maxrad == 1) {
+					if (px < sw && px >= 0 && py < sh && py >= 0) {
+						if (maskcolor > maskarray[py][px]) {
+							maskarray[py][px] = maskcolor;
+							screenarray[py][px] = stars[i].color;
+						}
+					}
+				} else {
+					int scale = ((((int)stars[i].z) * 100) / 63);
+					if (scale < 1) scale = 1;
+					int radius = (stars[i].maxrad * (100 - scale) / 100);
+					int radsq = radius * radius;
+					//unsigned char color = GetColor565 (value>>1,value,value>>1);
+					unsigned char color = stars[i].color;
+					for (int cy = -radius; cy <= radius; cy++) { //Draw a circle around the point, for the mask.
+						int cysq = cy * cy;
+						for (int cx = -radius; cx <= radius; cx++) {
+							int cxsq = cx * cx;
+							int dx = cx + px;
+							int dy = cy + py;
+							if ((cxsq + cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0) {
+								if (maskcolor > maskarray [dy][dx]) {
+									maskarray [dy][dx] = maskcolor;
+									screenarray [dy][dx] = color;
+								}
+							}
+						}
+					}
+					/*
+					for(int cy=-radius; cy<=radius; cy++) //Draw a circle around the point, for the color.
+					{
+					   int cysq = cy*cy;
+					for(int cx=-radius; cx<=radius; cx++)
+					   {
+					       int cxsq = cx*cx;
+					       int dx = cx+px;
+					       int dy = cy+py;
+					       if((cxsq+cysq <= radsq) && dx < sw && dx >= 0 && dy < sh && dy >= 0)
+					       {
+					           if (maskarray [dy][dx] == maskcolor)screenarray [dy][dx] = color;
+					       }
+					   }
+					}
+					*/
+				}
+			}
+		}
+	}
+	engine->ReleaseBitmapSurface(canvas);
+	engine->ReleaseBitmapSurface(maskcanvas);
+	engine->NotifySpriteUpdated(slot);
+	engine->NotifySpriteUpdated(maskslot);
+}
+
+
+int CreateTranslucentOverlay(int id, int spriteId, int alpha, int level, int ox, int oy, int mask = 0, int blendmode = 0) {
+	BITMAP *testspr = engine->GetSpriteGraphic(spriteId);
+	if (testspr) overlay[id].sprite = spriteId;
+	else engine->AbortGame("CreateTranslucentOverlay: Invalid spriteId.");
+	engine->ReleaseBitmapSurface(testspr);
+	overlay[id].level = MAX(0, MIN(level, 4));
+	overlay[id].trans = MAX(0, MIN(alpha, 255));
+	overlay[id].spritemask = mask;
+	overlay[id].x = ox;
+	overlay[id].y = oy;
+	overlay[id].enabled = true;
+	overlay[id].blendtype = blendmode;
+	return 0;
+}
+
+int DeleteTranslucentOverlay(int id) {
+	overlay[id].enabled = false;
+	overlay[id].sprite = 0;
+	overlay[id].x = 0;
+	overlay[id].y = 0;
+	overlay[id].level = 0;
+	overlay[id].trans = 0;
+	return 0;
+}
+
+int MoveTranslucentOverlay(int id, int ox, int oy) {
+	overlay[id].x = ox;
+	overlay[id].y = oy;
+	return 0;
+}
+
+int GetTranslucentOverlayX(int id) {
+	return overlay[id].x;
+}
+
+int GetTranslucentOverlayY(int id) {
+	return overlay[id].y;
+}
+
+int GetTranslucentOverlaySprite(int id) {
+	return overlay[id].sprite;
+}
+
+int GetTranslucentOverlayLevel(int id) {
+	return overlay[id].level;
+}
+
+int GetTranslucentOverlayEnabled(int id) {
+	return overlay[id].enabled;
+}
+
+int GetTranslucentOverlayAlpha(int id) {
+	return overlay[id].trans;
+}
+
+int SetTranslucentOverlayAlpha(int id, int alpha) {
+	if (alpha >= 0 && alpha < 256)
+		overlay[id].trans = alpha;
+	else
+		engine->AbortGame("CreateTranslucentOverlay: Invalid alpha selected.");
+	return 0;
+}
+
+int SetTranslucentOverlayEnabled(int id, int toggle) {
+	if (toggle > 0)
+		overlay[id].enabled = true;
+	else
+		overlay[id].enabled = false;
+	return 0;
+}
+
+void SetCharacterReflected(int id, int refl) {
+	if (refl > 0) Reflection.Characters[id].reflect = 1;
+	else Reflection.Characters[id].reflect = 0;
+}
+
+void SetObjectReflected(int id, int refl) {
+	if (refl > 0)
+		Reflection.Objects[id].reflect = 1;
+	else
+		Reflection.Objects[id].reflect = 0;
+}
+
+int GetCharacterReflected(int id) {
+	return Reflection.Characters[id].reflect;
+}
+
+int GetObjectReflected(int id) {
+	return Reflection.Objects[id].reflect;
+}
+
+void ReplaceCharacterReflectionView(int id, int view) {
+	Reflection.Characters[id].replaceview = view - 1;
+}
+
+void SetObjectReflectionIgnoreScaling(int id, int wb) {
+	if (wb) Reflection.Objects[id].ignorescaling = 1;
+	else    Reflection.Objects[id].ignorescaling = 0;
+}
+
+int DrawReflections(int id, int charobj = 0) {
+	int32 screenw, screenh;
+	int32 bgw, bgh;
+	engine->GetScreenDimensions(&screenw, &screenh, nullptr);
+	BITMAP *bgmask = engine->GetBackgroundScene(1);
+	if (bgmask == nullptr) return 1;
+	//BITMAP *virtsc = engine->GetVirtualScreen();
+	BITMAP *walkbehind = engine->GetRoomMask(MASK_WALKBEHIND);
+	//if (!virtsc) engine->AbortGame ("Can't load virtual screen.");
+	if (!walkbehind) engine->AbortGame("DrawRelfections: Can't load Walkbehind into memory.");
+	engine->GetBitmapDimensions(walkbehind, &bgw, &bgh, nullptr);
+	if (!bgmask) engine->AbortGame("DrawReflections: Can't load reflection mask.");
+	//unsigned char **charbuffer = engine->GetRawBitmapSurface (virtsc);
+	unsigned char **wbarray = engine->GetRawBitmapSurface(walkbehind);
+	unsigned char **maskarray = engine->GetRawBitmapSurface(bgmask);
+	//Initialize stuff
+	BITMAP *charsprite = nullptr;
+	BITMAP *charsprite2 = nullptr;
+	AGSCharacter *currchar = nullptr;
+	AGSObject *currobj;
+	int cox = 0, coy = 0, coz = 0;
+	int scale = 0;
+	//Get character, and their sprite.
+	if (charobj == 0) {
+		currchar = engine->GetCharacter(id);
+		/*int view = 0;
+		if (Reflection.Characters[id].replaceview == 0) view = currchar->view + 1;
+		else view = Reflection.Characters[id].replaceview;
+		*/
+		AGSViewFrame *vf = engine->GetViewFrame(currchar->view + 1, currchar->loop, currchar->frame);
+		charsprite = engine->GetSpriteGraphic(vf->pic);
+		long scaling = currchar->flags & CHF_NOSCALING;
+		if (!scaling)scale = engine->GetAreaScaling(currchar->x, currchar->y);
+		else scale = 100;
+		cox = currchar->x;
+		coy = currchar->y;
+		coz = currchar->z;
+	} else if (charobj == 1) {
+		currobj = engine->GetObject(id);
+
+		charsprite = engine->GetSpriteGraphic(currobj->num);
+		if (Reflection.Objects[id].ignorescaling) scale = 100;
+		else scale = engine->GetAreaScaling(currobj->x, currobj->y);
+		cox = currobj->x;
+		if (currobj->baseline < 0) coy = currobj->y;
+		else coy = currobj->baseline;
+		coz = 0;
+	}
+	bool scaled = false;
+	int32 w, h;
+	engine->GetBitmapDimensions(charsprite, &w, &h, nullptr);
+	if (scale != 100) {
+		unsigned char **orig = engine->GetRawBitmapSurface(charsprite);
+		int h1, h2, w1, w2;
+		double fw2, fh2;
+		h1 = h;
+		w1 = w;
+		fh2 = h1 * ((double)scale / 100.0);
+		fw2 = w1 * ((double)scale / 100.0);
+		h2 = static_cast<int>(fh2);
+		w2 = static_cast<int>(fw2);
+		charsprite2 = engine->CreateBlankBitmap(w2, h2, 8);
+		unsigned char **resized = engine->GetRawBitmapSurface(charsprite2);
+		int x_ratio = (int)((w1 << 16) / w2) + 1;
+		int y_ratio = (int)((h1 << 16) / h2) + 1;
+		int x2, y2 ;
+		for (int i = 0; i < h2; i++) {
+			for (int j = 0; j < w2; j++) {
+				x2 = ((j * x_ratio) >> 16) ;
+				y2 = ((i * y_ratio) >> 16) ;
+				resized [i][j] = orig [y2][x2];
+			}
+		}
+		engine->ReleaseBitmapSurface(charsprite2);
+		scaled = true;
+		w = w2;
+		h = h2;
+	} else {
+		charsprite2 = charsprite;
+	}
+	int transamount = 0;
+	unsigned char **spritearray = engine->GetRawBitmapSurface(charsprite2);
+	unsigned char **charbuffer = engine->GetRawBitmapSurface(rcolormap);
+	unsigned char **alphaarray = engine->GetRawBitmapSurface(ralphamap);
+	int i = h - 1, j = 0;
+	int32 ox = cox;
+	if (charobj == 0) ox = ox - (w / 2);
+	int32 oy = coy + coz - 1;
+	engine->RoomToViewport(&ox, &oy);
+	int yoffset = 0;
+	int translevel = 7;
+	//bool dither = false;
+	//bool dodither = false;
+	int counter = 0;
+	int rowcount = 101 - (int)(50.0 * ((double)(scale) / 100.0));
+	int delay = screenh / rowcount;
+	int *obst;
+	int flipped = 0;
+	if (charobj == 0) {
+		int (*sfGetGameParameter)(int, int, int, int);
+		sfGetGameParameter = ((int(*)(int, int, int, int)) engine->GetScriptFunctionAddress("GetGameParameter"));
+		flipped = sfGetGameParameter(13, currchar->view + 1, currchar->loop, currchar->frame);
+	} else flipped = 0;
+	obst = new int [w];
+	for (int k = 0; k < w; k++) {
+		obst[k] = 0;
+	}
+	while (i > 0) {
+		//if ((counter == delay/2-1 || counter == delay-1) && yoffset < 36) dodither = (!dodither);
+		if (counter == delay) {
+			counter = 0;
+			if (translevel > 0) translevel--;
+		} else counter++;
+		yoffset++;
+		while (j < w) {
+			int xoffset;
+			if (flipped == 1) xoffset = w - j - 1;
+			else xoffset = j;
+			int32 rx = ox + xoffset, ry = oy + yoffset;
+			int wbb = 0;
+			engine->ViewportToRoom(&rx, &ry);
+			if (ry > 0 && ry < bgh && rx > 0 && rx < bgw) {
+				if (wbarray [ry][rx] > 0) {
+					wbb = engine->GetWalkbehindBaseline(wbarray[ry][rx]);
+				}
+				if (maskarray[ry][rx] == 21) obst[j] = 1;
+			}
+
+			//dither = (!dither);
+			transamount = 32 * translevel;
+			if (spritearray [i][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.
+				if (wbb < ry && obst[j] == 0 && (oy > reflectionmap[(ox + xoffset) + (screenw * (oy + yoffset))])) {
+					//charbuffer[oy+yoffset][ox+xoffset] = MixColorAlpha (spritearray [i][j],charbuffer[oy+yoffset][ox+xoffset],transamount);
+					charbuffer [oy + yoffset][ox + xoffset] = spritearray [i][j];
+					alphaarray [oy + yoffset][ox + xoffset] = transamount;
+					reflectionmap[(ox + xoffset) + (screenw * (oy + yoffset))] = oy;
+				}
+			}
+			j++;
+		}
+		//if (w % 2 == 0) dither = (!dither);
+		i--;
+		j = 0;
+	}
+
+	delete [] obst;
+	if (scaled == true)engine->FreeBitmap(charsprite2);
+	engine->ReleaseBitmapSurface(charsprite);
+	//engine->ReleaseBitmapSurface (virtsc);
+	//engine->ReleaseBitmapSurface (clutspr);
+	engine->ReleaseBitmapSurface(bgmask);
+	engine->ReleaseBitmapSurface(walkbehind);
+	engine->ReleaseBitmapSurface(rcolormap);
+	engine->ReleaseBitmapSurface(ralphamap);
+	engine->MarkRegionDirty(ox, oy, ox + w, oy + h);
+	return 0;
+}
+
+
+int DrawTransSprite(int spriteId, int bg, int translevel, int mask = 0, int blendmode = 0, int use_objpal = 0) {
+	BITMAP *maskspr = nullptr;
+	unsigned char **maskarray = nullptr;
+	if (mask > 0) maskspr = engine->GetSpriteGraphic(mask);
+	if (!maskspr && mask > 0) {
+		char maskerr [100];
+		snprintf(maskerr, 100, "DrawTransSprite: Can't load mask from slot %d.", mask);
+		engine->AbortGame(maskerr);
+	}
+	// Get a reference to the screen we'll draw onto
+	BITMAP *bgspr = engine->GetSpriteGraphic(bg);
+	//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
+	BITMAP *spritespr = engine->GetSpriteGraphic(spriteId);
+	if (!bgspr) engine->AbortGame("DrawTransSprite: Can't load background");
+	//if (!clutspr) engine->AbortGame ("Can't load CLUT spriteId into memory.");
+	if (!spritespr) engine->AbortGame("DrawTransSprite: Can't load overlay spriteId into memory.");
+	// Get its surface
+	int32 sprw, sprh, coldepth;
+	int32 bgw, bgh;
+	engine->GetBitmapDimensions(bgspr, &bgw, &bgh, &coldepth);
+	engine->GetBitmapDimensions(spritespr, &sprw, &sprh, &coldepth);
+
+	unsigned char **bgarray = engine->GetRawBitmapSurface(bgspr);
+	//unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
+	unsigned char **spritearray = engine->GetRawBitmapSurface(spritespr);
+	if (mask > 0) maskarray = engine->GetRawBitmapSurface(maskspr);
+	int tloffset = 255 - translevel;
+	int x = 0;
+	int y = 0;
+	//int transamount = 256 * translevel; //old
+	while (y < sprh) {
+		while (x < sprw) {
+			if (spritearray [y][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.
+				if (mask > 0) {
+					translevel = MAX(maskarray [y][x] - tloffset, 0);
+				}
+				//spritearray[y][x] = cycle_remap[clutarray [cycle_remap[bgarray[y][x]]+transamount][cycle_remap[spritearray [y][x]]]]; //old
+				if (blendmode == 0) spritearray[y][x] = Mix::MixColorAlpha(spritearray [y][x], bgarray[y][x], translevel, use_objpal);
+				else if (blendmode == 1) spritearray[y][x] = Mix::MixColorAdditive(spritearray [y][x], bgarray[y][x], translevel, use_objpal);
+			}
+			x++;
+		}
+		x = 0;
+		y++;
+	}
+
+	// Release the screen so that the engine can continue
+	engine->ReleaseBitmapSurface(bgspr);
+	//engine->ReleaseBitmapSurface (clutspr);
+	engine->ReleaseBitmapSurface(spritespr);
+	engine->NotifySpriteUpdated(spriteId);
+	return 0;
+}
+
+int DrawTranslucentOverlay(int spriteId, int translevel, int ox, int oy, int mask = 0, int blendmode = 0) {
+	if (translevel == 0) return 0;
+	BITMAP *maskspr = nullptr;
+	unsigned char **maskarray = nullptr;
+	// Get a reference to the screen we'll draw onto
+	BITMAP *virtsc = engine->GetVirtualScreen();
+	//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
+	BITMAP *spritespr = engine->GetSpriteGraphic(spriteId);
+	if (mask > 0) maskspr = engine->GetSpriteGraphic(mask);
+	if (!virtsc) engine->AbortGame("DrawTranslucentOverlay: Can't load virtual screen.");
+	//if (!clutspr) engine->AbortGame ("Can't load CLUT spriteId into memory.");
+	if (!spritespr) engine->AbortGame("DrawTranslucentOverlay: Can't load overlay spriteId into memory.");
+	// Get its surface
+	int32 sprw, sprh, coldepth;
+	int32 screenw, screenh;
+	engine->GetScreenDimensions(&screenw, &screenh, &coldepth);
+	engine->GetBitmapDimensions(spritespr, &sprw, &sprh, &coldepth);
+	unsigned char **charbuffer = engine->GetRawBitmapSurface(virtsc);
+	unsigned char **spritearray = engine->GetRawBitmapSurface(spritespr);
+	if (mask > 0) {
+		if (!maskspr && mask > 0) {
+			char maskerr [100];
+			snprintf(maskerr, 100, "DrawTransSprite: Can't load mask from slot %d.", mask);
+			engine->AbortGame(maskerr);
+		}
+		maskarray = engine->GetRawBitmapSurface(maskspr);
+	}
+	int tloffset = 255 - translevel;
+	int x = 0;
+	int y = 0;
+	//int transamount = 256 * translevel; //old
+	while (y < sprh) {
+		while (x < sprw) {
+			if (spritearray [y][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.
+				//charbuffer[y+oy][x+ox] = cycle_remap[clutarray [cycle_remap[charbuffer[y+oy][x+ox]]+transamount][cycle_remap[spritearray [y][x]]]]; //old
+				if (mask > 0) {
+					translevel = MAX(maskarray [y][x] - tloffset, 0);
+				}
+				if (blendmode == 0) {
+					if (translevel == 255) {
+						charbuffer[y + oy][x + ox] = spritearray [y][x];
+					} else charbuffer[y + oy][x + ox] = Mix::MixColorAlpha(spritearray [y][x], charbuffer[y + oy][x + ox], translevel);
+				} else if (blendmode == 1) charbuffer[y + oy][x + ox] = Mix::MixColorAdditive(spritearray [y][x], charbuffer[y + oy][x + ox], translevel);
+			}
+			x++;
+		}
+		x = 0;
+		y++;
+	}
+
+	// Release the screen so that the engine can continue
+	long dirtywidth = ox + sprw;
+	if (dirtywidth > screenw) dirtywidth = screenw - 1;
+	long dirtyheight = oy + sprh;
+	if (dirtyheight > screenh) dirtywidth = screenh - 1;
+	engine->ReleaseBitmapSurface(virtsc);
+	//engine->ReleaseBitmapSurface (clutspr);
+	engine->ReleaseBitmapSurface(spritespr);
+	if (mask > 0) engine->ReleaseBitmapSurface(maskspr);
+	engine->MarkRegionDirty(ox, oy, dirtywidth, dirtyheight);
+
+	return 0;
+}
+
+/*------------------------------------------------------------------*/
+
+AGSPalRender::AGSPalRender() : DLL() {
+	DLL_METHOD(AGS_GetPluginName);
+	DLL_METHOD(AGS_EngineStartup);
+	DLL_METHOD(AGS_EngineShutdown);
+	DLL_METHOD(AGS_EngineOnEvent);
+}
+
+const char *AGSPalRender::AGS_GetPluginName() {
+	return "PALgorithms Translucent Overlay Renderer";
+}
+
+void AGSPalRender::AGS_EngineStartup(IAGSEngine *lpEngine) {
+	engine = lpEngine;
+
+	// Make sure it's got the version with the features we need
+	if (engine->version < 3) {
+		engine->AbortGame("Engine interface is too old, need newer version of AGS.");
+	}
+	engine->RegisterScriptFunction("PALInternal::LoadCLUT^1", (void *)LoadCLUT);
+	engine->RegisterScriptFunction("PALInternal::CycleRemap^2", (void *)CycleRemap);
+	engine->RegisterScriptFunction("PALInternal::GetColor565^3", (void *)GetColor565);
+	engine->RegisterScriptFunction("PALInternal::GetLuminosityFromPalette^1", (void *)GetLuminosityFromPalette);
+	engine->RegisterScriptFunction("PALInternal::FastSin^1", (void *)AGSFastSin);
+	engine->RegisterScriptFunction("PALInternal::FastCos^1", (void *)AGSFastCos);
+	engine->RegisterScriptFunction("PALInternal::FastRoot^1", (void *)root);
+	engine->RegisterScriptFunction("PALInternal::GetRemappedSlot^1", (void *)GetRemappedSlot);
+	engine->RegisterScriptFunction("PALInternal::ResetRemapping^0", (void *)ResetRemapping);
+	engine->RegisterScriptFunction("PALInternal::GetModifiedBackgroundImage", (void *)GetModifiedBackgroundImage);
+	engine->RegisterScriptFunction("PALInternal::WriteObjectivePalette^4", (void *)WriteObjectivePalette);
+	engine->RegisterScriptFunction("PALInternal::ReadObjectivePaletteR^1", (void *)ReadObjectivePaletteR);
+	engine->RegisterScriptFunction("PALInternal::ReadObjectivePaletteB^1", (void *)ReadObjectivePaletteB);
+	engine->RegisterScriptFunction("PALInternal::ReadObjectivePaletteG^1", (void *)ReadObjectivePaletteG);
+
+	engine->RegisterScriptFunction("Raycast::Render^1", (void *)Raycast_Render);
+	engine->RegisterScriptFunction("Raycast::LoadMap^4", (void *)LoadMap);
+	engine->RegisterScriptFunction("Raycast::Initialize", (void *)Init_Raycaster);
+	engine->RegisterScriptFunction("Raycast::MakeTextures^1", (void *)MakeTextures);
+	engine->RegisterScriptFunction("Raycast::MoveForward^0", (void *)MoveForward);
+	engine->RegisterScriptFunction("Raycast::MoveBackward^0", (void *)MoveBackward);
+	engine->RegisterScriptFunction("Raycast::RotateLeft^0", (void *)RotateLeft);
+	engine->RegisterScriptFunction("Raycast::RotateRight^0", (void *)RotateRight);
+	engine->RegisterScriptFunction("Raycast::SetCameraPosition^2", (void *)Ray_SetPlayerPosition);
+	engine->RegisterScriptFunction("Raycast::GetCameraX^0", (void *)Ray_GetPlayerX);
+	engine->RegisterScriptFunction("Raycast::GetCameraY^0", (void *)Ray_GetPlayerY);
+	engine->RegisterScriptFunction("Raycast::GetCameraAngle^0", (void *)Ray_GetPlayerAngle);
+	engine->RegisterScriptFunction("Raycast::SetCameraAngle^1", (void *)Ray_SetPlayerAngle);
+	engine->RegisterScriptFunction("Raycast::InitSprite^9", (void *)Ray_InitSprite);
+	engine->RegisterScriptFunction("Raycast::UnloadEngine^0", (void *)QuitCleanup);
+	engine->RegisterScriptFunction("Raycast::GetHotspotAtXY^2", (void *)Ray_GetHotspotAt);
+	engine->RegisterScriptFunction("Raycast::GetObjectAtXY^2", (void *)Ray_GetObjectAt);
+	engine->RegisterScriptFunction("Raycast::SetSpriteInteractObj^2", (void *)Ray_SetSpriteInteractObj);
+	engine->RegisterScriptFunction("Raycast::GetSpriteInteractObj^1", (void *)Ray_GetSpriteInteractObj);
+	engine->RegisterScriptFunction("Raycast::SetSpritePosition^3", (void *)Ray_SetSpritePosition);
+	engine->RegisterScriptFunction("Raycast::SetSpriteVertOffset^2", (void *)Ray_SetSpriteVertOffset);
+	engine->RegisterScriptFunction("Raycast::GetSpriteVertOffset^1", (void *)Ray_GetSpriteVertOffset);
+	engine->RegisterScriptFunction("Raycast::GetSpriteX^1", (void *)Ray_GetSpriteX);
+	engine->RegisterScriptFunction("Raycast::GetSpriteY^1", (void *)Ray_GetSpriteY);
+	engine->RegisterScriptFunction("Raycast::SetWallHotspot^2", (void *)Ray_SetWallHotspot);
+	engine->RegisterScriptFunction("Raycast::SetWallTextures^5", (void *)Ray_SetWallTextures);
+	engine->RegisterScriptFunction("Raycast::SetWallSolid^5", (void *)Ray_SetWallSolid);
+	engine->RegisterScriptFunction("Raycast::SetWallIgnoreLighting^5", (void *)Ray_SetWallIgnoreLighting);
+	engine->RegisterScriptFunction("Raycast::SetWallAlpha^5", (void *)Ray_SetWallAlpha);
+	engine->RegisterScriptFunction("Raycast::SetWallBlendType^5", (void *)Ray_SetWallBlendType);
+	engine->RegisterScriptFunction("Raycast::GetMoveSpeed^0", (void *)Ray_GetMoveSpeed);
+	engine->RegisterScriptFunction("Raycast::SetMoveSpeed^1", (void *)Ray_SetMoveSpeed);
+	engine->RegisterScriptFunction("Raycast::GetRotSpeed^0", (void *)Ray_GetRotSpeed);
+	engine->RegisterScriptFunction("Raycast::SetRotSpeed^1", (void *)Ray_SetRotSpeed);
+	engine->RegisterScriptFunction("Raycast::GetWallAt^2", (void *)Ray_GetWallAt);
+	engine->RegisterScriptFunction("Raycast::GetLightAt^2", (void *)Ray_GetLightAt);
+	engine->RegisterScriptFunction("Raycast::SetLightAt^3", (void *)Ray_SetLightAt);
+	engine->RegisterScriptFunction("Raycast::SetWallAt^3", (void *)Ray_SetWallAt);
+	engine->RegisterScriptFunction("Raycast::SetPlaneY^1", (void *)Ray_SetPlaneY);
+	engine->RegisterScriptFunction("Raycast::GetDistanceAt^2", (void *)Ray_GetDistanceAt);
+	engine->RegisterScriptFunction("Raycast::GetSpriteAngle^1", (void *)Ray_GetSpriteAngle);
+	engine->RegisterScriptFunction("Raycast::SetSpriteAngle^2", (void *)Ray_SetSpriteAngle);
+	engine->RegisterScriptFunction("Raycast::SetSpriteView^2", (void *)Ray_SetSpriteView);
+	engine->RegisterScriptFunction("Raycast::GetSpriteView^1", (void *)Ray_GetSpriteView);
+	engine->RegisterScriptFunction("Raycast::SetSpriteFrame^2", (void *)Ray_SetSpriteFrame);
+	engine->RegisterScriptFunction("Raycast::GetSpriteFrame^1", (void *)Ray_GetSpriteFrame);
+	engine->RegisterScriptFunction("Raycast::SetSpritePic^2", (void *)Ray_SetSpritePic);
+	engine->RegisterScriptFunction("Raycast::GetSpritePic^1", (void *)Ray_GetSpritePic);
+	engine->RegisterScriptFunction("Raycast::SetSkyBox^1", (void *)Ray_SetSkyBox);
+	engine->RegisterScriptFunction("Raycast::SetSpriteAlpha^2", (void *)Ray_SetSpriteAlpha);
+	engine->RegisterScriptFunction("Raycast::GetSpriteAlpha^1", (void *)Ray_GetSpriteAlpha);
+	engine->RegisterScriptFunction("Raycast::GetSkyBox^1", (void *)Ray_GetSkyBox);
+	engine->RegisterScriptFunction("Raycast::SetAmbientLight^1", (void *)Ray_SetAmbientLight);
+	engine->RegisterScriptFunction("Raycast::SetAmbientColor^2", (void *)Ray_SetAmbientColor);
+	engine->RegisterScriptFunction("Raycast::GetAmbientLight^0", (void *)Ray_GetAmbientLight);
+	engine->RegisterScriptFunction("Raycast::GetAmbientWeight^0", (void *)Ray_GetAmbientWeight);
+	engine->RegisterScriptFunction("Raycast::GetTileX_At^2", (void *)Ray_GetTileX_At);
+	engine->RegisterScriptFunction("Raycast::GetTileY_At^2", (void *)Ray_GetTileY_At);
+	engine->RegisterScriptFunction("Raycast::DrawTile^2", (void *)Ray_DrawTile);
+	engine->RegisterScriptFunction("Raycast::DrawOntoTile^2", (void *)Ray_DrawOntoTile);
+	engine->RegisterScriptFunction("Raycast::SetNoClip^1", (void *)Ray_SetNoClip);
+	engine->RegisterScriptFunction("Raycast::GetNoClip^0", (void *)Ray_GetNoClip);
+	engine->RegisterScriptFunction("Raycast::GetSpriteScaleX^1", (void *)Ray_GetSpriteScaleX);
+	engine->RegisterScriptFunction("Raycast::SetSpriteScaleX^2", (void *)Ray_SetSpriteScaleX);
+	engine->RegisterScriptFunction("Raycast::GetSpriteScaleY^1", (void *)Ray_GetSpriteScaleY);
+	engine->RegisterScriptFunction("Raycast::SetSpriteScaleY^2", (void *)Ray_SetSpriteScaleY);
+	engine->RegisterScriptFunction("Raycast::GetSpriteBlendType^1", (void *)Ray_GetSpriteBlendType);
+	engine->RegisterScriptFunction("Raycast::SetSpriteBlendType^2", (void *)Ray_SetSpriteBlendType);
+
+
+	engine->RegisterScriptFunction("Raycast::SetFloorAt^3", (void *)Ray_SetFloorAt);
+	engine->RegisterScriptFunction("Raycast::SetCeilingAt^3", (void *)Ray_SetCeilingAt);
+	engine->RegisterScriptFunction("Raycast::GetCeilingAt^2", (void *)Ray_GetCeilingAt);
+	engine->RegisterScriptFunction("Raycast::GetFloorAt^2", (void *)Ray_GetFloorAt);
+	engine->RegisterScriptFunction("Raycast::GetLightingAt^2", (void *)Ray_GetLightingAt);
+	engine->RegisterScriptFunction("Raycast::SetLightingAt^3", (void *)Ray_SetLightingAt);
+	engine->RegisterScriptFunction("Raycast::GetWallHotspot^1", (void *)Ray_GetWallHotspot);
+	engine->RegisterScriptFunction("Raycast::GetWallTexture^2", (void *)Ray_GetWallTexture);
+	engine->RegisterScriptFunction("Raycast::GetWallSolid^2", (void *)Ray_GetWallSolid);
+	engine->RegisterScriptFunction("Raycast::GetWallIgnoreLighting^2", (void *)Ray_GetWallIgnoreLighting);
+	engine->RegisterScriptFunction("Raycast::GetWallAlpha^2", (void *)Ray_GetWallAlpha);
+	engine->RegisterScriptFunction("Raycast::GetWallBlendType^2", (void *)Ray_GetWallBlendType);
+	engine->RegisterScriptFunction("Raycast::SelectTile^3", (void *)Ray_SelectTile);
+	engine->RegisterScriptFunction("Raycast::HasSeenTile^2", (void *)Ray_HasSeenTile);
+
+	engine->RegisterScriptFunction("LensDistort::SetPos^2", (void *)SetLensPos);
+	engine->RegisterScriptFunction("LensDistort::GetX^0", (void *)GetLensX);
+	engine->RegisterScriptFunction("LensDistort::GetY^0", (void *)GetLensY);
+	engine->RegisterScriptFunction("LensDistort::Set^1", (void *)SetLensDrawn);
+	engine->RegisterScriptFunction("LensDistort::IsDrawn^0", (void *)GetLensDrawn);
+	engine->RegisterScriptFunction("LensDistort::SetOffsetClamp^1", (void *)SetLensOffsetClamp);
+	engine->RegisterScriptFunction("LensDistort::GetOffsetClamp^0", (void *)GetLensOffsetClamp);
+	engine->RegisterScriptFunction("LensDistort::GetLevel^0", (void *)GetLensLevel);
+	engine->RegisterScriptFunction("LensDistort::SetLevel^1", (void *)GetLensLevel);
+	engine->RegisterScriptFunction("LensDistort::Initialize^6", (void *)LensInitialize);
+
+	engine->RegisterScriptFunction("Translucence::CreateOverlay^8", (void *)CreateTranslucentOverlay);
+	engine->RegisterScriptFunction("Translucence::DeleteOverlay^1", (void *)DeleteTranslucentOverlay);
+	engine->RegisterScriptFunction("Translucence::Move^3", (void *)MoveTranslucentOverlay);
+	engine->RegisterScriptFunction("Translucence::GetOverlayX^1", (void *)GetTranslucentOverlayX);
+	engine->RegisterScriptFunction("Translucence::GetOverlayY^1", (void *)GetTranslucentOverlayY);
+	engine->RegisterScriptFunction("Translucence::GetOverlaySprite^1", (void *)GetTranslucentOverlaySprite);
+	engine->RegisterScriptFunction("Translucence::GetOverlayLevel^1", (void *)GetTranslucentOverlayLevel);
+	engine->RegisterScriptFunction("Translucence::GetOverlayEnabled^1", (void *)GetTranslucentOverlayEnabled);
+	engine->RegisterScriptFunction("Translucence::GetOverlayAlpha^1", (void *)GetTranslucentOverlayAlpha);
+	engine->RegisterScriptFunction("Translucence::SetOverlayAlpha^2", (void *)SetTranslucentOverlayAlpha);
+	engine->RegisterScriptFunction("Translucence::SetOverlayEnabled^2", (void *)SetTranslucentOverlayEnabled);
+	engine->RegisterScriptFunction("Translucence::DrawTransSprite^6", (void *)DrawTransSprite);
+
+	engine->RegisterScriptFunction("Starfield::GetOverscan^0", (void *)GetStarfieldOverscan);
+	engine->RegisterScriptFunction("Starfield::SetOverscan^1", (void *)SetStarfieldOverscan);
+	engine->RegisterScriptFunction("Starfield::GetOriginX^0", (void *)GetStarfieldOriginX);
+	engine->RegisterScriptFunction("Starfield::GetOriginY^0", (void *)GetStarfieldOriginY);
+	engine->RegisterScriptFunction("Starfield::SetDepthMultiplier^1", (void *)SetStarfieldDepthMultiplier);
+	engine->RegisterScriptFunction("Starfield::GetDepthMultiplier^0", (void *)GetStarfieldDepthMultiplier);
+	engine->RegisterScriptFunction("Starfield::GetMaxStars^0", (void *)GetStarfieldMaxStars);
+	engine->RegisterScriptFunction("Starfield::SetStarSpriteScaleBoost^1", (void *)SetStarSpriteScaleBoost);
+	engine->RegisterScriptFunction("Starfield::GetStarSpriteScaleBoost^0", (void *)GetStarSpriteScaleBoost);
+	engine->RegisterScriptFunction("Starfield::SetStarMaxRadius^2", (void *)SetStarMaxRadius);
+	engine->RegisterScriptFunction("Starfield::GetStarMaxRadius^0", (void *)GetStarMaxRadius);
+	engine->RegisterScriptFunction("Starfield::GetStarX^1", (void *)GetStarX);
+	engine->RegisterScriptFunction("Starfield::GetStarY^1", (void *)GetStarY);
+	engine->RegisterScriptFunction("Starfield::GetStarZ^1", (void *)GetStarZ);
+	engine->RegisterScriptFunction("Starfield::SetStarPosition^4", (void *)SetStarPosition);
+	engine->RegisterScriptFunction("Starfield::RotateStar^4", (void *)RotateStar);
+	engine->RegisterScriptFunction("Starfield::SetStarColor^2", (void *)SetStarColor);
+	engine->RegisterScriptFunction("Starfield::GetStarColor^1", (void *)GetStarColor);
+	engine->RegisterScriptFunction("Starfield::SetStarSprite^2", (void *)SetStarSprite);
+	engine->RegisterScriptFunction("Starfield::GetStarSprite^1", (void *)GetStarSprite);
+	engine->RegisterScriptFunction("Starfield::SetStarSpriteRange^3", (void *)SetStarSpriteRange);
+	engine->RegisterScriptFunction("Starfield::Initialize^2", (void *)InitializeStars);
+	engine->RegisterScriptFunction("Starfield::Iterate^1", (void *)IterateStars);
+	engine->RegisterScriptFunction("Starfield::Draw^2", (void *)DrawStars);
+	engine->RegisterScriptFunction("Starfield::SetOriginPoint^2", (void *)SetStarsOriginPoint);
+
+	engine->RegisterScriptFunction("Plasma::DoFire^8", (void *)DoFire);
+	engine->RegisterScriptFunction("Plasma::SetPlasmaType^5", (void *)SetPlasmaType);
+	engine->RegisterScriptFunction("Plasma::ResetPlasmaSettings^0", (void *)ResetPlasmaSettings);
+	engine->RegisterScriptFunction("Plasma::DrawPlasma^3", (void *)DrawPlasma);
+	engine->RegisterScriptFunction("Plasma::SetRootType^1", (void *)SetPlasmaRootType);
+	engine->RegisterScriptFunction("Plasma::GetRootType^0", (void *)GetPlasmaRootType);
+
+	engine->RegisterScriptFunction("Reflections::Set^1", (void *)SetReflections);
+	engine->RegisterScriptFunction("Reflections::IsReflecting^0", (void *)IsReflectionsOn);
+	engine->RegisterScriptFunction("Reflections::SetCharacterReflected^2", (void *)SetCharacterReflected);
+	engine->RegisterScriptFunction("Reflections::GetCharacterReflected^1", (void *)GetCharacterReflected);
+	engine->RegisterScriptFunction("Reflections::SetObjectReflected^2", (void *)SetObjectReflected);
+	engine->RegisterScriptFunction("Reflections::GetObjectReflected^1", (void *)GetObjectReflected);
+	engine->RegisterScriptFunction("Reflections::ReplaceCharacterReflectionView^2", (void *)ReplaceCharacterReflectionView);
+	engine->RegisterScriptFunction("Reflections::SetObjectReflectionIgnoreScaling^2", (void *)SetObjectReflectionIgnoreScaling);
+	engine->RequestEventHook(AGSE_PRESCREENDRAW);
+	engine->RequestEventHook(AGSE_PREGUIDRAW);
+	engine->RequestEventHook(AGSE_POSTSCREENDRAW);
+	engine->RequestEventHook(AGSE_SAVEGAME);
+	engine->RequestEventHook(AGSE_RESTOREGAME);
+	engine->RequestEventHook(AGSE_ENTERROOM);
+	stars = new starstype [MAX_STARS];
+	Starfield.maxstars = MAX_STARS;
+	Starfield.depthmultiplier = 256;
+	Starfield.speed = 0.5;
+	Starfield.originx = 160;
+	Starfield.originy = 100;
+	Reflection.Characters = new charrefopt [engine->GetNumCharacters()]();
+	lens = new LensDistort [LENS_WIDTH * LENS_WIDTH]();
+	//PreMultiply_Alphas ();
+	plasmaroottype = 0;
+	Make_Sin_Lut();
+	Init_Raycaster();
+}
+
+void AGSPalRender::AGS_EngineShutdown() {
+	// no work to do here - but if we had created any dynamic sprites,
+	// we should delete them here
+	delete[] Reflection.Characters;
+	delete[] Reflection.Objects;
+	//QuitCleanup();
+}
+
+NumberPtr AGSPalRender::AGS_EngineOnEvent(int event, NumberPtr data) {
+	if (event == AGSE_PRESCREENDRAW && clutslot > 0) {
+		if (drawreflections) {
+			int32 sh, sw = 0;
+			engine->GetScreenDimensions(&sw, &sh, nullptr);
+			reflectionmap = new long[sw * sh]();
+			rcolormap = engine->CreateBlankBitmap(sw, sh, 8);
+			ralphamap = engine->CreateBlankBitmap(sw, sh, 8);
+			for (int i = 0; i < engine->GetNumCharacters(); i++) {
+				if (Reflection.Characters[i].reflect == 0) continue;
+				AGSCharacter *tempchar = engine->GetCharacter(i);
+				if (tempchar->room != engine->GetCurrentRoom()) continue;  //if character isn't even in the room, go to next iteration.
+				int32 vx = tempchar->x;
+				int32 vy = tempchar->y;
+				engine->RoomToViewport(&vx, &vy);
+				AGSViewFrame *vf = engine->GetViewFrame(tempchar->view + 1, tempchar->loop, tempchar->frame);
+				int w = engine->GetSpriteWidth(vf->pic);
+				int h = engine->GetSpriteHeight(vf->pic);
+				vx = vx - (w / 2);
+				int32 vxmax = vx + w;
+				int32 vymax = vy + h;
+				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
+				DrawReflections(i, 0);
+			}
+			for (int i = 0; i < engine->GetNumObjects(); i++) {
+				if (Reflection.Objects[i].reflect == 0) continue;
+				AGSObject *tempobj = engine->GetObject(i);
+				if (!tempobj->on) continue;
+				int32 vx = tempobj->x;
+				int32 vy = tempobj->baseline - tempobj->y;
+				engine->RoomToViewport(&vx, &vy);
+				int32 w = engine->GetSpriteWidth(tempobj->num);
+				int32 h = engine->GetSpriteHeight(tempobj->num);
+				int32 vxmax = vx + w;
+				int32 vymax = vy + h;
+				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
+				DrawReflections(i, 1);
+			}
+			BITMAP *virtsc = engine->GetVirtualScreen();
+			unsigned char **screenbuffer = engine->GetRawBitmapSurface(virtsc);
+			unsigned char **colorbuffer = engine->GetRawBitmapSurface(rcolormap);
+			unsigned char **alphabuffer = engine->GetRawBitmapSurface(ralphamap);
+			for (int y = 0; y < sh; y++)
+				for (int x = 0; x < sw; x++)
+					screenbuffer[y][x] = Mix::MixColorAlpha(colorbuffer[y][x], screenbuffer[y][x], alphabuffer[y][x]);
+			engine->ReleaseBitmapSurface(rcolormap);
+			engine->ReleaseBitmapSurface(ralphamap);
+			engine->ReleaseBitmapSurface(virtsc);
+			engine->FreeBitmap(rcolormap);
+			engine->FreeBitmap(ralphamap);
+			delete [] reflectionmap;
+		}
+		int i = 0;
+		if (LensOption.draw == 1 && LensOption.level == 0) DrawLens(LensOption.x, LensOption.y);
+		while (i < MAX_OVERLAYS) {
+			if (overlay[i].enabled && overlay[i].level == 0) {
+				DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
+			}
+			i++;
+		}
+		if (LensOption.draw == 1 && LensOption.level == 1) DrawLens(LensOption.x, LensOption.y);
+	}
+	if (event == AGSE_PREGUIDRAW && clutslot > 0) {
+		int i = 0;
+		if (LensOption.draw == 1 && LensOption.level == 1) DrawLens(LensOption.x, LensOption.y);
+		while (i < MAX_OVERLAYS) {
+			if (overlay[i].enabled && overlay[i].level == 1) {
+				DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
+			}
+			i++;
+		}
+		if (LensOption.draw == 1 && LensOption.level == 2) DrawLens(LensOption.x, LensOption.y);
+	}
+	if (event == AGSE_POSTSCREENDRAW && clutslot > 0) {
+		int i = 0;
+		if (LensOption.draw == 1 && LensOption.level == 3) DrawLens(LensOption.x, LensOption.y);
+		while (i < MAX_OVERLAYS) {
+			if (overlay[i].enabled && overlay[i].level == 2) {
+				DrawTranslucentOverlay(overlay[i].sprite, overlay[i].trans, overlay[i].x, overlay[i].y, overlay[i].spritemask, overlay[i].blendtype);
+			}
+			i++;
+		}
+		if (LensOption.draw == 1 && LensOption.level == 4) DrawLens(LensOption.x, LensOption.y);
+	}
+	if (event == AGSE_SAVEGAME) {
+		for (int i = 0; i < MAX_OVERLAYS; ++i) {
+			engine->FWrite(&overlay[i].sprite, sizeof(int), data);
+			engine->FWrite(&overlay[i].spritemask, sizeof(int), data);
+			engine->FWrite(&overlay[i].x, sizeof(int), data);
+			engine->FWrite(&overlay[i].y, sizeof(int), data);
+			engine->FWrite(&overlay[i].level, sizeof(int), data);
+			engine->FWrite(&overlay[i].trans, sizeof(int), data);
+			engine->FWrite(&overlay[i].blendtype, sizeof(int), data);
+			engine->FWrite(&overlay[i].enabled, sizeof(bool), data);
+		}
+		engine->FWrite(&clutslot, sizeof(int), data);
+		engine->FWrite(&drawreflections, sizeof(int), data);
+		for (int j = 0; j < 256; ++j) {
+			engine->FWrite(&cycle_remap[j], sizeof(unsigned char), data);
+		}
+		for (int j = 0; j < 256; ++j) {
+			engine->FWrite(&objectivepal[j].r, sizeof(unsigned char), data);
+			engine->FWrite(&objectivepal[j].b, sizeof(unsigned char), data);
+			engine->FWrite(&objectivepal[j].g, sizeof(unsigned char), data);
+		}
+		for (int j = 0; j < 256; ++j) {
+			engine->FWrite(&sprite[j].x, sizeof(double), data);
+			engine->FWrite(&sprite[j].y, sizeof(double), data);
+			engine->FWrite(&sprite[j].texture, sizeof(int), data);
+			engine->FWrite(&sprite[j].alpha, sizeof(unsigned char), data);
+			engine->FWrite(&sprite[j].uDivW, sizeof(double), data);
+			engine->FWrite(&sprite[j].uDivH, sizeof(double), data);
+			engine->FWrite(&sprite[j].vMove, sizeof(double), data);
+			engine->FWrite(&sprite[j].hMove, sizeof(double), data);
+			engine->FWrite(&sprite[j].objectinteract, sizeof(char), data);
+			engine->FWrite(&sprite[j].view, sizeof(int), data);
+			engine->FWrite(&sprite[j].frame, sizeof(int), data);
+			engine->FWrite(&sprite[j].angle, sizeof(int), data);
+		}
+		for (int j = 0; j < 256; ++j) {
+			for (int k = 0; k < 4; ++k) {
+				engine->FWrite(&wallData[j].texture[k], sizeof(int), data);
+				engine->FWrite(&wallData[j].solid[k], sizeof(int), data);
+				engine->FWrite(&wallData[j].ignorelighting[k], sizeof(int), data);
+				engine->FWrite(&wallData[j].alpha[k], sizeof(int), data);
+				engine->FWrite(&wallData[j].blendtype[k], sizeof(int), data);
+				engine->FWrite(&wallData[j].mask[k], sizeof(int), data);
+			}
+			engine->FWrite(&wallData[j].hotspotinteract, sizeof(char), data);
+		}
+		engine->FWrite(&raycastOn, sizeof(bool), data);
+		engine->FWrite(&heightmapOn, sizeof(bool), data);
+		engine->FWrite(&posX, sizeof(double), data);
+		engine->FWrite(&posY, sizeof(double), data);
+		engine->FWrite(&dirX, sizeof(double), data);
+		engine->FWrite(&dirY, sizeof(double), data);
+		engine->FWrite(&planeX, sizeof(double), data);
+		engine->FWrite(&planeY, sizeof(double), data);
+		engine->FWrite(&moveSpeed, sizeof(double), data);
+		engine->FWrite(&rotSpeed, sizeof(double), data);
+		if (raycastOn) { //If the raycaster is active, we have additional data to save.
+			for (int i = 0; i < mapWidth; ++i)
+				for (int j = 0; j < mapHeight; ++j) {
+					engine->FWrite(&worldMap [i][j], sizeof(unsigned char), data);
+					engine->FWrite(&lightMap [i][j], sizeof(unsigned char), data);
+					engine->FWrite(&ceilingMap [i][j], sizeof(int), data);
+					engine->FWrite(&floorMap [i][j], sizeof(int), data);
+					engine->FWrite(&heightMap [i][j], sizeof(int), data);
+				}
+		}
+		engine->FWrite(&textureSlot, sizeof(int), data);
+		engine->FWrite(&skybox, sizeof(int), data);
+		engine->FWrite(&ambientlight, sizeof(int), data);
+	}
+	if (event == AGSE_RESTOREGAME) {
+
+
+		for (int i = 0; i < MAX_OVERLAYS; ++i) {
+			engine->FRead(&overlay[i].sprite, sizeof(int), data);
+			engine->FRead(&overlay[i].spritemask, sizeof(int), data);
+			engine->FRead(&overlay[i].x, sizeof(int), data);
+			engine->FRead(&overlay[i].y, sizeof(int), data);
+			engine->FRead(&overlay[i].level, sizeof(int), data);
+			engine->FRead(&overlay[i].trans, sizeof(int), data);
+			engine->FRead(&overlay[i].blendtype, sizeof(int), data);
+			engine->FRead(&overlay[i].enabled, sizeof(bool), data);
+		}
+		engine->FRead(&clutslot, sizeof(int), data);
+		engine->FRead(&drawreflections, sizeof(int), data);
+		for (int j = 0; j < 256; ++j) {
+			engine->FRead(&cycle_remap[j], sizeof(unsigned char), data);
+		}
+		for (int j = 0; j < 256; ++j) { //Save Objective Palette, for palette mixing.
+			engine->FRead(&objectivepal[j].r, sizeof(unsigned char), data);
+			engine->FRead(&objectivepal[j].b, sizeof(unsigned char), data);
+			engine->FRead(&objectivepal[j].g, sizeof(unsigned char), data);
+		}
+		for (int j = 0; j < 256; ++j) { //Save Raycaster Sprite struct, 256 instances.
+			engine->FRead(&sprite[j].x, sizeof(double), data);
+			engine->FRead(&sprite[j].y, sizeof(double), data);
+			engine->FRead(&sprite[j].texture, sizeof(int), data);
+			engine->FRead(&sprite[j].alpha, sizeof(unsigned char), data);
+			engine->FRead(&sprite[j].uDivW, sizeof(double), data);
+			engine->FRead(&sprite[j].uDivH, sizeof(double), data);
+			engine->FRead(&sprite[j].vMove, sizeof(double), data);
+			engine->FRead(&sprite[j].hMove, sizeof(double), data);
+			engine->FRead(&sprite[j].objectinteract, sizeof(char), data);
+			engine->FRead(&sprite[j].view, sizeof(int), data);
+			engine->FRead(&sprite[j].frame, sizeof(int), data);
+			engine->FRead(&sprite[j].angle, sizeof(int), data);
+		}
+		for (int j = 0; j < 256; ++j) { //Save Raycaster wall type data.
+			for (int k = 0; k < 4; ++k) {
+				engine->FRead(&wallData[j].texture[k], sizeof(int), data);
+				engine->FRead(&wallData[j].solid[k], sizeof(int), data);
+				engine->FRead(&wallData[j].ignorelighting[k], sizeof(int), data);
+				engine->FRead(&wallData[j].alpha[k], sizeof(int), data);
+				engine->FRead(&wallData[j].blendtype[k], sizeof(int), data);
+				engine->FRead(&wallData[j].mask[k], sizeof(int), data);
+			}
+			engine->FRead(&wallData[j].hotspotinteract, sizeof(char), data);
+		}
+		//Delete worldmap data if it exists.
+		engine->FRead(&raycastOn, sizeof(bool), data);
+		engine->FRead(&heightmapOn, sizeof(bool), data);
+		engine->FRead(&posX, sizeof(double), data);
+		engine->FRead(&posY, sizeof(double), data);
+		engine->FRead(&dirX, sizeof(double), data);
+		engine->FRead(&dirY, sizeof(double), data);
+		engine->FRead(&planeX, sizeof(double), data);
+		engine->FRead(&planeY, sizeof(double), data);
+		engine->FRead(&moveSpeed, sizeof(double), data);
+		engine->FRead(&rotSpeed, sizeof(double), data);
+		if (raycastOn) { //If the raycaster is currently running, we have additional data to load.
+			for (int i = 0; i < mapWidth; ++i) {
+				for (int j = 0; j < mapHeight; ++j) {
+					engine->FRead(&worldMap [i][j], sizeof(unsigned char), data);
+					engine->FRead(&lightMap [i][j], sizeof(unsigned char), data);
+					engine->FRead(&ceilingMap [i][j], sizeof(int), data);
+					engine->FRead(&floorMap [i][j], sizeof(int), data);
+					engine->FRead(&heightMap [i][j], sizeof(int), data);
+					seenMap [i][j] = 0;
+				}
+			}
+
+			//Reinitialize all the buffers and stuff.
+
+		}
+		engine->FRead(&textureSlot, sizeof(int), data);
+		if (textureSlot) MakeTextures(textureSlot);
+		engine->FRead(&skybox, sizeof(int), data);
+		engine->FRead(&ambientlight, sizeof(int), data);
+		LoadCLUT(clutslot);
+	}
+	if (event == AGSE_ENTERROOM) {
+		ResetRemapping();
+		delete[] Reflection.Objects;
+		Reflection.Objects = new objrefopt [engine->GetNumObjects()]();
+	}
+	return 0;
+}
+
+} // namespace AGSPalRender
+} // namespace Plugins
+} // namespace AGS3
diff --git a/engines/ags/plugins/ags_pal_render/pal_render.h b/engines/ags/plugins/ags_pal_render/pal_render.h
index 1ea7951138..1f160791cd 100644
--- a/engines/ags/plugins/ags_pal_render/pal_render.h
+++ b/engines/ags/plugins/ags_pal_render/pal_render.h
@@ -1,193 +1,193 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef AGS_PLUGINS_AGS_PAL_RENDER_PAL_RENDER_H
-#define AGS_PLUGINS_AGS_PAL_RENDER_PAL_RENDER_H
-
-#include "ags/lib/allegro.h"
-#include "ags/plugins/agsplugin.h"
-#include "common/algorithm.h"
-
-namespace AGS3 {
-namespace Plugins {
-namespace AGSPalRender {
-
-#define SCRIPT_FLOAT(x) int32 __script_float##x
-#define INIT_SCRIPT_FLOAT(x) float x; memcpy(&x, &__script_float##x, sizeof(float))
-#define FLOAT_RETURN_TYPE int32
-#define RETURN_FLOAT(x) int32 __ret##x; memcpy(&__ret##x, &x, sizeof(float)); return __ret##x
-
-struct PALSTRUCT {
-	int r;
-	int b;
-	int g;
-};
-
-extern IAGSEngine *engine;
-extern unsigned char clut[65536];
-extern unsigned char cycle_remap [256];
-extern const int alphamultiply [4096];
-extern PALSTRUCT objectivepal[256];
-
-// this class exists solely to take advantage of g++'s
-// -fvisibility-inlines-hidden option, so that these
-// methods can be inlined without any trace or complaint
-class Mix {
-public:
-//unsigned char MixColorAlpha (unsigned char fg,unsigned char bg,unsigned char alpha);
-//unsigned char MixColorAdditive (unsigned char fg,unsigned char bg,unsigned char alpha);
-	static unsigned char MixColorAlpha(unsigned char fg, unsigned char bg, unsigned char alpha, int use_objpal = 0) {
-		unsigned char rfg = cycle_remap[fg]; //Automatic remapping of palette slots.
-		//unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
-		AGSColor *palette = engine->GetPalette();
-		int i = 0;
-		//int out_r = (palette[fg].r>>1) * alpha + (palette[bg].r>>1) * (255 - alpha);
-		//int out_g = palette[fg].g * alpha + palette[bg].g * (255 - alpha);
-		//int out_b = (palette[fg].b>>1) * alpha + (palette[bg].b>>1) * (255 - alpha);
-		int out_r, out_g, out_b;
-		if (use_objpal == 0) {
-			out_r = (objectivepal[rfg].r >> 1) *alpha + (palette[bg].r >> 1) *(255 - alpha);
-			out_g = objectivepal[rfg].g * alpha + palette[bg].g * (255 - alpha);
-			out_b = (objectivepal[rfg].b >> 1) *alpha + (palette[bg].b >> 1) *(255 - alpha);
-		} else {
-			out_r = (objectivepal[rfg].r >> 1) *alpha + (objectivepal[bg].r >> 1) *(255 - alpha);
-			out_g = objectivepal[rfg].g * alpha + objectivepal[bg].g * (255 - alpha);
-			out_b = (objectivepal[rfg].b >> 1) *alpha + (objectivepal[bg].b >> 1) *(255 - alpha);
-		}
-		//char ralpha = MAX(0,MIN(63,alpha>>2));
-		//unsigned char invralpha = 64-ralpha;
-		//if (ralpha > alpha) engine->AbortGame ("wtf");
-		//int out_r = alphamultiply[((palette[fg].r>>1)<<6) +ralpha] + alphamultiply[((palette[bg].r>>1)<<6) +(invralpha)];
-		//int out_g = alphamultiply[((palette[fg].g)   <<6) +ralpha] + alphamultiply[((palette[bg].g)   <<6) +(invralpha)];
-		//int out_b = alphamultiply[((palette[fg].b>>1)<<6) +ralpha] + alphamultiply[((palette[bg].b>>1)<<6) +(invralpha)];
-		out_r = (out_r + 1 + (out_r >> 8)) >> 8;
-		out_g = (out_g + 1 + (out_g >> 8)) >> 8;
-		out_b = (out_b + 1 + (out_b >> 8)) >> 8;
-		//out_r = (out_r + 1 + (out_r >> 6)) >> 6;
-		//out_g = (out_g + 1 + (out_g >> 6)) >> 6;
-		//out_b = (out_b + 1 + (out_b >> 6)) >> 6;
-		i = ((out_r << 11) | (out_g << 5) | out_b);
-		unsigned char(*clutp) = clut;
-		//unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
-		return cycle_remap[*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
-		//engine->ReleaseBitmapSurface (clutspr);
-	}
-
-	static unsigned char MixColorLightLevel(unsigned char fg, unsigned char intensity) {
-		unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
-		int i = 0;
-		//int dark_r = (((palette[fg].r>>1) * (intensity))>>8);
-		//int dark_b = (((palette[fg].b>>1) * (intensity))>>8);
-		//int dark_g = (((palette[fg].g)    * (intensity))>>8);
-		int dark_r = (((objectivepal[rfg].r >> 1) * (intensity)) >> 8);
-		int dark_b = (((objectivepal[rfg].b >> 1) * (intensity)) >> 8);
-		int dark_g = (((objectivepal[rfg].g)    * (intensity)) >> 8);
-		i = ((dark_r << 11) | (dark_g << 5) | dark_b);
-		unsigned char (*clutp) = clut;
-		return cycle_remap [*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
-	}
-
-	static unsigned char MixColorAdditive(unsigned char fg, unsigned char bg, unsigned char alpha, int use_objpal = 0) {
-		unsigned char rfg = cycle_remap[fg]; //Automatic remapping of palette slots.
-		//unsigned char rbg = cycle_remap[bg]; //Saves on typing elsewhere.
-		//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
-		//if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
-		//unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
-		AGSColor *palette = engine->GetPalette();
-		int i = 0;
-		int add_r, add_b, add_g = 0;
-		//char ralpha = MAX(0,MIN(63,alpha>>2));
-		//add_r = (((palette[fg].r>>1) * (alpha))>>8);
-		//add_b = (((palette[fg].b>>1) * (alpha))>>8);
-		//add_g = (((palette[fg].g)    * (alpha))>>8);
-		add_r = (((objectivepal[rfg].r >> 1) * (alpha)) >> 8);
-		add_b = (((objectivepal[rfg].b >> 1) * (alpha)) >> 8);
-		add_g = (((objectivepal[rfg].g)    * (alpha)) >> 8);
-		//int a_g = MAX(0,MIN(63,alpha>>2));
-		//add_r = ((alphamultiply[(palette[fg].r>>1)<<6)+ralpha])>>6);
-		//add_b = ((alphamultiply[(palette[fg].b>>1)<<6)+ralpha])>>6);
-		//add_g = ((alphamultiply[(palette[fg].g)   <<6)+ralpha])>>6);
-		//int out_r = MIN(31,(palette[bg].r>>1) + add_r);
-		//int out_g = MIN(63, palette[bg].g     + add_g);
-		//int out_b = MIN(31,(palette[bg].b>>1) + add_b);
-		int out_r, out_g, out_b;
-		if (use_objpal == 0) {
-			out_r = MIN(31, (palette[bg].r >> 1) + add_r);
-			out_g = MIN(63, palette[bg].g     + add_g);
-			out_b = MIN(31, (palette[bg].b >> 1) + add_b);
-		} else {
-			out_r = MIN(31, (objectivepal [bg].r >> 1) + add_r);
-			out_g = MIN(63, objectivepal [bg].g     + add_g);
-			out_b = MIN(31, (objectivepal [bg].b >> 1) + add_b);
-		}
-		i = ((out_r << 11) | (out_g << 5) | out_b);
-		unsigned char (*clutp) = clut;
-		unsigned char result = cycle_remap [*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
-		//unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
-		//engine->ReleaseBitmapSurface (clutspr);
-		return result;
-	}
-
-	static unsigned char MixColorMultiply(unsigned char fg, unsigned char bg, unsigned char alpha, int use_objpal = 0) {
-		unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
-		unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
-		AGSColor *palette = engine->GetPalette();
-		int i = 0;
-		int mul_r, mul_b, mul_g = 0;
-		int out_r, out_g, out_b = 0;
-		if (use_objpal == 0) {
-			mul_r = ((objectivepal[rfg].r >> 1) * (palette[rbg].r >> 1)) / 64;
-			mul_b = ((objectivepal[rfg].b >> 1) * (palette[rbg].b >> 1)) / 64;
-			mul_g = ((objectivepal[rfg].g * palette[rbg].g) / 64);
-			out_r = ((palette[rbg].r >> 1) * (63 - (alpha / 4)) + (mul_r * (alpha / 4))) / 63;
-			out_g = (palette[rbg].g * (63 - (alpha / 4)) + (mul_g * (alpha / 4))) / 63;
-			out_b = ((palette[rbg].b >> 1) * (63 - (alpha / 4)) + (mul_b * (alpha / 4))) / 63;
-		} else {
-			mul_r = ((objectivepal[rfg].r >> 1) * (objectivepal[rbg].r >> 1)) / 64;
-			mul_b = ((objectivepal[rfg].b >> 1) * (objectivepal[rbg].b >> 1)) / 64;
-			mul_g = ((objectivepal[rfg].g * objectivepal[rbg].g) / 64);
-
-			out_r = ((objectivepal[rbg].r >> 1) * (63 - (alpha / 4)) + (mul_r * (alpha / 4))) / 63;
-			out_g = (objectivepal[rbg].g * (63 - (alpha / 4)) + (mul_g * (alpha / 4))) / 63;
-			out_b = ((objectivepal[rbg].b >> 1) * (63 - (alpha / 4)) + (mul_b * (alpha / 4))) / 63;
-		}
-		i = ((out_r << 11) | (out_g << 5) | out_b);
-		unsigned char (*clutp) = clut;
-		unsigned char result = cycle_remap [*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
-		//unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
-		//engine->ReleaseBitmapSurface (clutspr);
-		return result;
-	}
-
-};
-
-unsigned char GetColor565(unsigned char r, unsigned char g, unsigned char b);
-
-unsigned short root(unsigned short x);
-float FastSin(float x);
-float FastCos(float x);
-
-} // namespace AGSPalRender
-} // namespace Plugins
-} // namespace AGS3
-
-#endif
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or(at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef AGS_PLUGINS_AGS_PAL_RENDER_PAL_RENDER_H
+#define AGS_PLUGINS_AGS_PAL_RENDER_PAL_RENDER_H
+
+#include "ags/lib/allegro.h"
+#include "ags/plugins/agsplugin.h"
+#include "common/algorithm.h"
+
+namespace AGS3 {
+namespace Plugins {
+namespace AGSPalRender {
+
+#define SCRIPT_FLOAT(x) int32 __script_float##x
+#define INIT_SCRIPT_FLOAT(x) float x; memcpy(&x, &__script_float##x, sizeof(float))
+#define FLOAT_RETURN_TYPE int32
+#define RETURN_FLOAT(x) int32 __ret##x; memcpy(&__ret##x, &x, sizeof(float)); return __ret##x
+
+struct PALSTRUCT {
+	int r;
+	int b;
+	int g;
+};
+
+extern IAGSEngine *engine;
+extern unsigned char clut[65536];
+extern unsigned char cycle_remap [256];
+extern const int alphamultiply [4096];
+extern PALSTRUCT objectivepal[256];
+
+// this class exists solely to take advantage of g++'s
+// -fvisibility-inlines-hidden option, so that these
+// methods can be inlined without any trace or complaint
+class Mix {
+public:
+//unsigned char MixColorAlpha (unsigned char fg,unsigned char bg,unsigned char alpha);
+//unsigned char MixColorAdditive (unsigned char fg,unsigned char bg,unsigned char alpha);
+	static unsigned char MixColorAlpha(unsigned char fg, unsigned char bg, unsigned char alpha, int use_objpal = 0) {
+		unsigned char rfg = cycle_remap[fg]; //Automatic remapping of palette slots.
+		//unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
+		AGSColor *palette = engine->GetPalette();
+		int i = 0;
+		//int out_r = (palette[fg].r>>1) * alpha + (palette[bg].r>>1) * (255 - alpha);
+		//int out_g = palette[fg].g * alpha + palette[bg].g * (255 - alpha);
+		//int out_b = (palette[fg].b>>1) * alpha + (palette[bg].b>>1) * (255 - alpha);
+		int out_r, out_g, out_b;
+		if (use_objpal == 0) {
+			out_r = (objectivepal[rfg].r >> 1) *alpha + (palette[bg].r >> 1) *(255 - alpha);
+			out_g = objectivepal[rfg].g * alpha + palette[bg].g * (255 - alpha);
+			out_b = (objectivepal[rfg].b >> 1) *alpha + (palette[bg].b >> 1) *(255 - alpha);
+		} else {
+			out_r = (objectivepal[rfg].r >> 1) *alpha + (objectivepal[bg].r >> 1) *(255 - alpha);
+			out_g = objectivepal[rfg].g * alpha + objectivepal[bg].g * (255 - alpha);
+			out_b = (objectivepal[rfg].b >> 1) *alpha + (objectivepal[bg].b >> 1) *(255 - alpha);
+		}
+		//char ralpha = MAX(0,MIN(63,alpha>>2));
+		//unsigned char invralpha = 64-ralpha;
+		//if (ralpha > alpha) engine->AbortGame ("wtf");
+		//int out_r = alphamultiply[((palette[fg].r>>1)<<6) +ralpha] + alphamultiply[((palette[bg].r>>1)<<6) +(invralpha)];
+		//int out_g = alphamultiply[((palette[fg].g)   <<6) +ralpha] + alphamultiply[((palette[bg].g)   <<6) +(invralpha)];
+		//int out_b = alphamultiply[((palette[fg].b>>1)<<6) +ralpha] + alphamultiply[((palette[bg].b>>1)<<6) +(invralpha)];
+		out_r = (out_r + 1 + (out_r >> 8)) >> 8;
+		out_g = (out_g + 1 + (out_g >> 8)) >> 8;
+		out_b = (out_b + 1 + (out_b >> 8)) >> 8;
+		//out_r = (out_r + 1 + (out_r >> 6)) >> 6;
+		//out_g = (out_g + 1 + (out_g >> 6)) >> 6;
+		//out_b = (out_b + 1 + (out_b >> 6)) >> 6;
+		i = ((out_r << 11) | (out_g << 5) | out_b);
+		unsigned char *clutp = clut;
+		//unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
+		return cycle_remap[*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
+		//engine->ReleaseBitmapSurface (clutspr);
+	}
+
+	static unsigned char MixColorLightLevel(unsigned char fg, unsigned char intensity) {
+		unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
+		int i = 0;
+		//int dark_r = (((palette[fg].r>>1) * (intensity))>>8);
+		//int dark_b = (((palette[fg].b>>1) * (intensity))>>8);
+		//int dark_g = (((palette[fg].g)    * (intensity))>>8);
+		int dark_r = (((objectivepal[rfg].r >> 1) * (intensity)) >> 8);
+		int dark_b = (((objectivepal[rfg].b >> 1) * (intensity)) >> 8);
+		int dark_g = (((objectivepal[rfg].g)    * (intensity)) >> 8);
+		i = ((dark_r << 11) | (dark_g << 5) | dark_b);
+		unsigned char *clutp = clut;
+		return cycle_remap [*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
+	}
+
+	static unsigned char MixColorAdditive(unsigned char fg, unsigned char bg, unsigned char alpha, int use_objpal = 0) {
+		unsigned char rfg = cycle_remap[fg]; //Automatic remapping of palette slots.
+		//unsigned char rbg = cycle_remap[bg]; //Saves on typing elsewhere.
+		//BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
+		//if (!clutspr) engine->AbortGame ("MixColorAlpha: Can't load CLUT sprite into memory.");
+		//unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
+		AGSColor *palette = engine->GetPalette();
+		int i = 0;
+		int add_r, add_b, add_g = 0;
+		//char ralpha = MAX(0,MIN(63,alpha>>2));
+		//add_r = (((palette[fg].r>>1) * (alpha))>>8);
+		//add_b = (((palette[fg].b>>1) * (alpha))>>8);
+		//add_g = (((palette[fg].g)    * (alpha))>>8);
+		add_r = (((objectivepal[rfg].r >> 1) * (alpha)) >> 8);
+		add_b = (((objectivepal[rfg].b >> 1) * (alpha)) >> 8);
+		add_g = (((objectivepal[rfg].g)    * (alpha)) >> 8);
+		//int a_g = MAX(0,MIN(63,alpha>>2));
+		//add_r = ((alphamultiply[(palette[fg].r>>1)<<6)+ralpha])>>6);
+		//add_b = ((alphamultiply[(palette[fg].b>>1)<<6)+ralpha])>>6);
+		//add_g = ((alphamultiply[(palette[fg].g)   <<6)+ralpha])>>6);
+		//int out_r = MIN(31,(palette[bg].r>>1) + add_r);
+		//int out_g = MIN(63, palette[bg].g     + add_g);
+		//int out_b = MIN(31,(palette[bg].b>>1) + add_b);
+		int out_r, out_g, out_b;
+		if (use_objpal == 0) {
+			out_r = MIN(31, (palette[bg].r >> 1) + add_r);
+			out_g = MIN(63, palette[bg].g     + add_g);
+			out_b = MIN(31, (palette[bg].b >> 1) + add_b);
+		} else {
+			out_r = MIN(31, (objectivepal [bg].r >> 1) + add_r);
+			out_g = MIN(63, objectivepal [bg].g     + add_g);
+			out_b = MIN(31, (objectivepal [bg].b >> 1) + add_b);
+		}
+		i = ((out_r << 11) | (out_g << 5) | out_b);
+		unsigned char *clutp = clut;
+		unsigned char result = cycle_remap [*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
+		//unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
+		//engine->ReleaseBitmapSurface (clutspr);
+		return result;
+	}
+
+	static unsigned char MixColorMultiply(unsigned char fg, unsigned char bg, unsigned char alpha, int use_objpal = 0) {
+		unsigned char rfg = cycle_remap [fg]; //Automatic remapping of palette slots.
+		unsigned char rbg = cycle_remap [bg]; //Saves on typing elsewhere.
+		AGSColor *palette = engine->GetPalette();
+		int i = 0;
+		int mul_r, mul_b, mul_g = 0;
+		int out_r, out_g, out_b = 0;
+		if (use_objpal == 0) {
+			mul_r = ((objectivepal[rfg].r >> 1) * (palette[rbg].r >> 1)) / 64;
+			mul_b = ((objectivepal[rfg].b >> 1) * (palette[rbg].b >> 1)) / 64;
+			mul_g = ((objectivepal[rfg].g * palette[rbg].g) / 64);
+			out_r = ((palette[rbg].r >> 1) * (63 - (alpha / 4)) + (mul_r * (alpha / 4))) / 63;
+			out_g = (palette[rbg].g * (63 - (alpha / 4)) + (mul_g * (alpha / 4))) / 63;
+			out_b = ((palette[rbg].b >> 1) * (63 - (alpha / 4)) + (mul_b * (alpha / 4))) / 63;
+		} else {
+			mul_r = ((objectivepal[rfg].r >> 1) * (objectivepal[rbg].r >> 1)) / 64;
+			mul_b = ((objectivepal[rfg].b >> 1) * (objectivepal[rbg].b >> 1)) / 64;
+			mul_g = ((objectivepal[rfg].g * objectivepal[rbg].g) / 64);
+
+			out_r = ((objectivepal[rbg].r >> 1) * (63 - (alpha / 4)) + (mul_r * (alpha / 4))) / 63;
+			out_g = (objectivepal[rbg].g * (63 - (alpha / 4)) + (mul_g * (alpha / 4))) / 63;
+			out_b = ((objectivepal[rbg].b >> 1) * (63 - (alpha / 4)) + (mul_b * (alpha / 4))) / 63;
+		}
+		i = ((out_r << 11) | (out_g << 5) | out_b);
+		unsigned char *clutp = clut;
+		unsigned char result = cycle_remap [*(clutp + i)]; //Once again, to make sure that the palette slot used is the right one.
+		//unsigned char result = cycle_remap [clut[i>>8][i%256]]; //Once again, to make sure that the palette slot used is the right one.
+		//engine->ReleaseBitmapSurface (clutspr);
+		return result;
+	}
+
+};
+
+unsigned char GetColor565(unsigned char r, unsigned char g, unsigned char b);
+
+unsigned short root(unsigned short x);
+float FastSin(float x);
+float FastCos(float x);
+
+} // namespace AGSPalRender
+} // namespace Plugins
+} // namespace AGS3
+
+#endif




More information about the Scummvm-git-logs mailing list