aboutsummaryrefslogtreecommitdiff
path: root/engines/sludge/backdrop.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sludge/backdrop.cpp')
-rw-r--r--engines/sludge/backdrop.cpp1753
1 files changed, 1753 insertions, 0 deletions
diff --git a/engines/sludge/backdrop.cpp b/engines/sludge/backdrop.cpp
new file mode 100644
index 0000000000..ed7177035e
--- /dev/null
+++ b/engines/sludge/backdrop.cpp
@@ -0,0 +1,1753 @@
+/* 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.
+ *
+ */
+
+#if 0
+#if defined __unix__ && !(defined __APPLE__)
+#include <png.h>
+#else
+#include <libpng/png.h>
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#if !defined(HAVE_GLES2)
+#include "GLee.h"
+#else
+#include <GLES2/gl2.h>
+#endif
+#endif
+
+#include "allfiles.h"
+#include "debug.h"
+#include "newfatal.h"
+#include "colours.h"
+#include "fileset.h"
+#include "cursors.h"
+#include "backdrop.h"
+#include "language.h"
+#include "moreio.h"
+#include "variable.h"
+#include "zbuffer.h"
+#include "graphics.h"
+#include "line.h"
+#include "people.h"
+#include "talk.h"
+#include "sludger.h"
+#include "statusba.h"
+
+#include "CommonCode/version.h"
+
+extern inputType input;
+
+
+bool freeze();
+void unfreeze(bool); // Because FREEZE.H needs a load of other includes
+
+#if 0
+GLubyte *backdropTexture = NULL;
+GLuint backdropTextureName = 0;
+bool backdropExists = false;
+GLfloat backdropTexW = 1.0;
+GLfloat backdropTexH = 1.0;
+
+texture lightMap;
+
+GLuint snapshotTextureName = 0;
+#endif
+
+float snapTexW = 1.0;
+float snapTexH = 1.0;
+
+int lightMapMode = LIGHTMAPMODE_PIXEL;
+parallaxLayer *parallaxStuff = NULL;
+int cameraPX = 0, cameraPY = 0;
+
+unsigned int sceneWidth, sceneHeight;
+int lightMapNumber;
+unsigned int currentBlankColour = makeColour(0, 0, 0);
+
+extern int cameraX, cameraY;
+extern float cameraZoom;
+
+void nosnapshot() {
+#if 0
+ deleteTextures(1, &snapshotTextureName);
+ snapshotTextureName = 0;
+#endif
+}
+
+#if ALLOW_FILE
+void saveSnapshot(FILE *fp) {
+ if (snapshotTextureName) {
+ fputc(1, fp); // 1 for snapshot follows
+ saveCoreHSI(fp, snapshotTextureName, winWidth, winHeight);
+ } else {
+ fputc(0, fp);
+ }
+}
+#endif
+
+bool snapshot() {
+
+ nosnapshot();
+ if (! freeze()) return false;
+#if 0
+ setPixelCoords(true);
+ glGenTextures(1, &snapshotTextureName);
+
+ int w = winWidth;
+ int h = winHeight;
+ if (! NPOT_textures) {
+ w = getNextPOT(winWidth);
+ h = getNextPOT(winHeight);
+ snapTexW = ((double)winWidth) / w;
+ snapTexH = ((double)winHeight) / h;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, snapshotTextureName);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, snapshotTextureName);
+
+ // Render scene
+ glDepthMask(GL_TRUE);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen
+ glDepthMask(GL_FALSE);
+
+ drawBackDrop(); // Draw the room
+ drawZBuffer(cameraX, cameraY, false);
+
+ glEnable(GL_DEPTH_TEST);
+
+ drawPeople(); // Then add any moving characters...
+
+ glDisable(GL_DEPTH_TEST);
+
+ viewSpeech(); // ...and anything being said
+ drawStatusBar();
+ // Copy Our ViewPort To The Texture
+ copyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewportOffsetX, viewportOffsetY, winWidth, winHeight, snapshotTextureName);
+
+ setPixelCoords(false);
+#endif
+ unfreeze(false);
+ return true;
+}
+
+#if ALLOW_FILE
+bool restoreSnapshot(FILE *fp) {
+ unsigned int picWidth = get2bytes(fp);
+ unsigned int picHeight = get2bytes(fp);
+
+ if ((picWidth != winWidth) || (picHeight != winHeight))
+ return false;
+
+ unsigned int t1, t2, n;
+ unsigned short c;
+
+ GLubyte *target;
+ if (! NPOT_textures) {
+ picWidth = getNextPOT(picWidth);
+ picHeight = getNextPOT(picHeight);
+ snapTexW = ((double)winWidth) / picWidth;
+ snapTexH = ((double)winHeight) / picHeight;
+ }
+ GLubyte *snapshotTexture = new GLubyte [picHeight * picWidth * 4];
+ if (! snapshotTexture) return fatal("Out of memory while restoring snapshot.");
+
+ for (t2 = 0; t2 < winHeight; t2 ++) {
+ t1 = 0;
+ while (t1 < winWidth) {
+ c = (unsigned short) get2bytes(fp);
+ if (c & 32) {
+ n = fgetc(fp) + 1;
+ c -= 32;
+ } else {
+ n = 1;
+ }
+ while (n --) {
+ target = snapshotTexture + 4 * picWidth * t2 + t1 * 4;
+ target[0] = (GLubyte) redValue(c);
+ target[1] = (GLubyte) greenValue(c);
+ target[2] = (GLubyte) blueValue(c);
+ target[3] = (GLubyte) 255;
+ t1++;
+ }
+ }
+ }
+
+ if (! snapshotTextureName) glGenTextures(1, &snapshotTextureName);
+ glBindTexture(GL_TEXTURE_2D, snapshotTextureName);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, picWidth, picHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, snapshotTexture, snapshotTextureName);
+
+ delete snapshotTexture;
+ snapshotTexture = NULL;
+
+ return true;
+}
+#endif
+
+void killBackDrop() {
+#if 0
+ deleteTextures(1, &backdropTextureName);
+ backdropTextureName = 0;
+ backdropExists = false;
+#endif
+}
+
+void killLightMap() {
+#if 0
+ deleteTextures(1, &lightMap.name);
+ lightMap.name = 0;
+ if (lightMap.data) {
+ delete lightMap.data;
+ lightMap.data = NULL;
+ }
+ lightMapNumber = 0;
+#endif
+}
+
+void killParallax() {
+#if 0
+ while (parallaxStuff) {
+
+ parallaxLayer *k = parallaxStuff;
+ parallaxStuff = k -> next;
+
+ // Now kill the image
+ deleteTextures(1, &k -> textureName);
+ delete k -> texture;
+ delete k;
+ k = NULL;
+ }
+#endif
+}
+
+bool reserveBackdrop() {
+ cameraX = 0;
+ cameraY = 0;
+ input.mouseX = (int)((float)input.mouseX * cameraZoom);
+ input.mouseY = (int)((float)input.mouseY * cameraZoom);
+ cameraZoom = 1.0;
+ input.mouseX = (int)((float)input.mouseX / cameraZoom);
+ input.mouseY = (int)((float)input.mouseY / cameraZoom);
+ setPixelCoords(false);
+ int picWidth = sceneWidth;
+ int picHeight = sceneHeight;
+#if 0
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ if (backdropTexture) delete backdropTexture;
+ if (! NPOT_textures) {
+ picWidth = getNextPOT(sceneWidth);
+ picHeight = getNextPOT(sceneHeight);
+ backdropTexW = ((double)sceneWidth) / picWidth;
+ backdropTexH = ((double)sceneHeight) / picHeight;
+ }
+ backdropTexture = new GLubyte [picWidth * picHeight * 4];
+ if (! checkNew(backdropTexture)) return false;
+
+ if (! backdropTextureName) glGenTextures(1, &backdropTextureName);
+ glBindTexture(GL_TEXTURE_2D, backdropTextureName);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if (gameSettings.antiAlias < 0) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ } else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+
+ texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, picWidth, picHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, backdropTexture, backdropTextureName);
+#endif
+ return true;
+}
+
+bool resizeBackdrop(int x, int y) {
+ killLightMap();
+ killBackDrop();
+ killParallax();
+ killZBuffer();
+ sceneWidth = x;
+ sceneHeight = y;
+ return reserveBackdrop();
+}
+
+void loadBackDrop(int fileNum, int x, int y) {
+ setResourceForFatal(fileNum);
+#if ALLOW_FILE
+ if (! openFileFromNum(fileNum)) {
+ fatal("Can't load overlay image");
+ return;
+ }
+
+ if (! loadHSI(bigDataFile, x, y, false)) {
+ char mess[200];
+ sprintf(mess, "Can't paste overlay image outside scene dimensions\n\nX = %i\nY = %i\nWidth = %i\nHeight = %i", x, y, sceneWidth, sceneHeight);
+ fatal(mess);
+ }
+
+ finishAccess();
+#endif
+ setResourceForFatal(-1);
+}
+
+void mixBackDrop(int fileNum, int x, int y) {
+#if ALLOW_FILE
+ setResourceForFatal(fileNum);
+ if (! openFileFromNum(fileNum)) {
+ fatal("Can't load overlay image");
+ return;
+ }
+
+ if (! mixHSI(bigDataFile, x, y)) {
+ fatal("Can't paste overlay image outside screen dimensions");
+ }
+
+ finishAccess();
+#endif
+ setResourceForFatal(-1);
+}
+
+void blankScreen(int x1, int y1, int x2, int y2) {
+
+ if (y1 < 0) y1 = 0;
+ if (x1 < 0) x1 = 0;
+ if (x2 > (int) sceneWidth) x2 = (int)sceneWidth;
+ if (y2 > (int) sceneHeight) y2 = (int)sceneHeight;
+
+ int picWidth = x2 - x1;
+ int picHeight = y2 - y1;
+#if 0
+ setPixelCoords(true);
+
+ int xoffset = 0;
+ while (xoffset < picWidth) {
+ int w = (picWidth - xoffset < viewportWidth) ? picWidth - xoffset : viewportWidth;
+
+ int yoffset = 0;
+ while (yoffset < picHeight) {
+ int h = (picHeight - yoffset < viewportHeight) ? picHeight - yoffset : viewportHeight;
+
+ // Render the scene
+
+
+
+ const GLfloat vertices[] = {
+ -10.325f, -1.325f, 0.0f,
+ w + 1.325f, -1.325f, 0.0f,
+ -10.325f, h + 1.325f, 0.0f,
+ w + 1.325f, h + 1.325f, 0.0f
+ };
+
+ glUseProgram(shader.color);
+
+ setPMVMatrix(shader.color);
+ setPrimaryColor(redValue(currentBlankColour) / 255.0f, greenValue(currentBlankColour) / 255.0f, blueValue(currentBlankColour) / 255.0f, 1.0f);
+ drawQuad(shader.color, vertices, 0);
+
+ glUseProgram(0);
+
+ // Copy Our ViewPort To The Texture
+ copyTexSubImage2D(GL_TEXTURE_2D, 0, x1 + xoffset, y1 + yoffset, viewportOffsetX, viewportOffsetY, w, h, backdropTextureName);
+
+ yoffset += viewportHeight;
+ }
+ xoffset += viewportWidth;
+ }
+
+ setPixelCoords(false);
+#endif
+}
+
+void hardScroll(int distance) {
+ if (abs(distance) >= sceneHeight) {
+ blankScreen(0, 0, sceneWidth, sceneHeight);
+ return;
+ }
+
+ if (! distance) return;
+#if 0
+ const GLfloat backdropTexCoords[] = {
+ 0.0f, 0.0f,
+ backdropTexW, 0.0f,
+ 0.0f, backdropTexH,
+ backdropTexW, backdropTexH
+ };
+
+ setPixelCoords(true);
+
+ unsigned int xoffset = 0;
+ while (xoffset < sceneWidth) {
+ int w = (sceneWidth - xoffset < viewportWidth) ? sceneWidth - xoffset : viewportWidth;
+
+ unsigned int yoffset = 0;
+ while (yoffset < sceneHeight) {
+ int h = (sceneHeight - yoffset < viewportHeight) ? sceneHeight - yoffset : viewportHeight;
+
+
+ glClear(GL_COLOR_BUFFER_BIT); // Clear The Screen
+
+ // Render the backdrop
+ glBindTexture(GL_TEXTURE_2D, backdropTextureName);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ const GLfloat vertices[] = {
+ (GLfloat) - xoffset, (GLfloat) - distance - yoffset, 0.,
+ (GLfloat)sceneWidth - xoffset, (GLfloat) - distance - yoffset, 0.,
+ (GLfloat) - xoffset, (GLfloat)sceneHeight - distance - yoffset, 0.,
+ (GLfloat)sceneWidth - xoffset, (GLfloat)sceneHeight - distance - yoffset, 0.
+ };
+
+
+ glUseProgram(shader.texture);
+
+ setPMVMatrix(shader.texture);
+
+ drawQuad(shader.texture, vertices, 1, backdropTexCoords);
+
+ glUseProgram(0);
+
+ // Copy Our ViewPort To The Texture
+ copyTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, viewportOffsetX, viewportOffsetY, w, h, backdropTextureName);
+
+ yoffset += viewportHeight;
+ }
+ xoffset += viewportWidth;
+ }
+ setPixelCoords(false);
+#endif
+}
+
+void drawVerticalLine(unsigned int x, unsigned int y1, unsigned int y2) {
+ drawLine(x, y1, x, y2);
+}
+
+void drawHorizontalLine(unsigned int x1, unsigned int y, unsigned int x2) {
+ drawLine(x1, y, x2, y);
+}
+
+void darkScreen() {
+ setPixelCoords(true);
+
+ int xoffset = 0;
+ while (xoffset < sceneWidth) {
+ int w = (sceneWidth - xoffset < viewportWidth) ? sceneWidth - xoffset : viewportWidth;
+
+ int yoffset = 0;
+ while (yoffset < sceneHeight) {
+ int h = (sceneHeight - yoffset < viewportHeight) ? sceneHeight - yoffset : viewportHeight;
+
+ // Render the scene - first the old backdrop
+#if 0
+ //glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glBindTexture(GL_TEXTURE_2D, backdropTextureName);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ const GLfloat vertices[] = {
+ (GLfloat) - xoffset, (GLfloat) - yoffset, 0.,
+ (GLfloat)sceneWidth - xoffset, (GLfloat) - yoffset, 0.,
+ (GLfloat) - xoffset, (GLfloat)sceneHeight - yoffset, 0.,
+ (GLfloat)sceneWidth - xoffset, (GLfloat)sceneHeight - yoffset, 0.
+ };
+
+ const GLfloat texCoords[] = {
+ 0.0f, 0.0f,
+ backdropTexW, 0.0f,
+ 0.0f, backdropTexH,
+ backdropTexW, backdropTexH
+ };
+
+
+ glUseProgram(shader.texture);
+
+ setPMVMatrix(shader.texture);
+
+ drawQuad(shader.texture, vertices, 1, texCoords);
+
+ // Then the darkness
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+
+ glEnable(GL_BLEND);
+
+ glUseProgram(shader.color);
+
+ setPMVMatrix(shader.color);
+ setPrimaryColor(0.0f, 0.0f, 0.0f, 0.5f);
+ drawQuad(shader.color, vertices, 0);
+
+ glUseProgram(0);
+
+ glDisable(GL_BLEND);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ // Copy Our ViewPort To The Texture
+ copyTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, viewportOffsetX, viewportOffsetY, w, h, backdropTextureName);
+
+ yoffset += h;
+
+ glClear(GL_COLOR_BUFFER_BIT);
+#endif
+ }
+ xoffset += w;
+ }
+
+
+ setPixelCoords(false);
+}
+
+
+
+inline int sortOutPCamera(int cX, int fX, int sceneMax, int boxMax) {
+ return (fX == 65535) ?
+ (sceneMax ? ((cX * boxMax) / sceneMax) : 0)
+ :
+ ((cX * fX) / 100);
+}
+
+
+void drawBackDrop() {
+#if 0
+ setPrimaryColor(1.0, 1.0, 1.0, 1.0);
+
+ //glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glEnable(GL_BLEND);
+
+ glUseProgram(shader.smartScaler);
+ GLuint uniform = glGetUniformLocation(shader.smartScaler, "useLightTexture");
+ if (uniform >= 0) glUniform1i(uniform, 0);
+
+ setPMVMatrix(shader.smartScaler);
+
+ if (gameSettings.antiAlias == 1) {
+ glUniform1i(glGetUniformLocation(shader.smartScaler, "antialias"), 1);
+ } else {
+ glUniform1i(glGetUniformLocation(shader.smartScaler, "antialias"), 0);
+ }
+
+ if (parallaxStuff) {
+ parallaxLayer *ps = parallaxStuff;
+
+ while (ps->next) ps = ps->next;
+
+ while (ps) {
+ ps -> cameraX = sortOutPCamera(cameraX, ps -> fractionX, (int)(sceneWidth - (float)winWidth / cameraZoom), (int)(ps -> width - (float)winWidth / cameraZoom));
+ ps -> cameraY = sortOutPCamera(cameraY, ps -> fractionY, (int)(sceneHeight - (float)winHeight / cameraZoom), (int)(ps -> height - (float)winHeight / cameraZoom));
+ glBindTexture(GL_TEXTURE_2D, ps->textureName);
+
+ float w = (ps->wrapS) ? sceneWidth : ps->width;
+ float h = (ps->wrapT) ? sceneHeight : ps->height;
+ float texw;
+ float texh;
+ if (! NPOT_textures) {
+ texw = (ps->wrapS) ? (float) sceneWidth / ps->width : (float) ps->width / getNextPOT(ps->width);
+ texh = (ps->wrapT) ? (float) sceneHeight / ps->height : (float) ps->height / getNextPOT(ps->height);
+ } else {
+ texw = (ps->wrapS) ? (float) sceneWidth / ps->width : 1.0;
+ texh = (ps->wrapT) ? (float) sceneHeight / ps->height : 1.0;
+ }
+
+ const GLfloat vertices[] = {
+ (GLfloat) - ps -> cameraX, (GLfloat) - ps -> cameraY, 0.1f,
+ w - ps -> cameraX, (GLfloat) - ps -> cameraY, 0.1f,
+ (GLfloat) - ps -> cameraX, h - ps -> cameraY, 0.1f,
+ w - ps -> cameraX, h - ps -> cameraY, 0.1f
+ };
+
+ const GLfloat texCoords[] = {
+ 0.0f, 0.0f,
+ texw, 0.0f,
+ 0.0f, texh,
+ texw, texh
+ };
+ drawQuad(shader.smartScaler, vertices, 1, texCoords);
+
+ ps = ps -> prev;
+ }
+ }
+
+ glBindTexture(GL_TEXTURE_2D, backdropTextureName);
+
+ const GLfloat backdropTexCoords[] = {
+ 0.0f, 0.0f,
+ backdropTexW, 0.0f,
+ 0.0f, backdropTexH,
+ backdropTexW, backdropTexH
+ };
+
+ const GLfloat vertices[] = {
+ (GLfloat) - cameraX, (GLfloat) - cameraY, 0.,
+ (GLfloat)sceneWidth - (GLfloat)cameraX, (GLfloat) - cameraY, 0.,
+ (GLfloat) - cameraX, (GLfloat)sceneHeight - (GLfloat)cameraY, 0.,
+ (GLfloat)sceneWidth - (GLfloat)cameraX, (GLfloat)sceneHeight - (GLfloat)cameraY, 0.
+ };
+
+ drawQuad(shader.smartScaler, vertices, 1, backdropTexCoords);
+
+ glDisable(GL_BLEND);
+
+ glUseProgram(0);
+#endif
+}
+
+bool loadLightMap(int v) {
+ int newPicWidth, newPicHeight;
+#if ALLOW_FILE
+ setResourceForFatal(v);
+ if (! openFileFromNum(v)) return fatal("Can't open light map.");
+ long file_pointer = ftell(bigDataFile);
+
+ png_structp png_ptr;
+ png_infop info_ptr, end_info;
+
+
+ int fileIsPNG = true;
+
+ // Is this a PNG file?
+
+ char tmp[10];
+ size_t bytes_read = fread(tmp, 1, 8, bigDataFile);
+ if (bytes_read != 8 && ferror(bigDataFile)) {
+ debugOut("Reading error in loadLightMap.\n");
+ }
+
+ if (png_sig_cmp((png_byte *) tmp, 0, 8)) {
+ // No, it's old-school HSI
+ fileIsPNG = false;
+ fseek(bigDataFile, file_pointer, SEEK_SET);
+
+ newPicWidth = lightMap.w = get2bytes(bigDataFile);
+ newPicHeight = lightMap.h = get2bytes(bigDataFile);
+ } else {
+ // Read the PNG header
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr) {
+ return false;
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
+ return false;
+ }
+
+ end_info = png_create_info_struct(png_ptr);
+ if (!end_info) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ return false;
+ }
+ png_init_io(png_ptr, bigDataFile); // Tell libpng which file to read
+ png_set_sig_bytes(png_ptr, 8); // 8 bytes already read
+
+ png_read_info(png_ptr, info_ptr);
+
+ png_uint_32 width, height;
+ int bit_depth, color_type, interlace_type, compression_type, filter_method;
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method);
+
+ newPicWidth = lightMap.w = width;
+ newPicHeight = lightMap.h = height;
+
+ if (bit_depth < 8) png_set_packing(png_ptr);
+ png_set_expand(png_ptr);
+ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr);
+ if (bit_depth == 16) png_set_strip_16(png_ptr);
+
+ png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
+
+ png_read_update_info(png_ptr, info_ptr);
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method);
+
+ //int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+
+ }
+
+ if (lightMapMode == LIGHTMAPMODE_HOTSPOT) {
+ if (lightMap.w != sceneWidth || lightMap.h != sceneHeight) {
+ return fatal("Light map width and height don't match scene width and height. That is required for lightmaps in HOTSPOT mode.");
+ }
+ }
+
+ if (! NPOT_textures) {
+ newPicWidth = getNextPOT(lightMap.w);
+ newPicHeight = getNextPOT(lightMap.h);
+ lightMap.texW = (double) lightMap.w / newPicWidth;
+ lightMap.texH = (double) lightMap.h / newPicHeight;
+ } else {
+ lightMap.texW = 1.0;
+ lightMap.texH = 1.0;
+ }
+
+ killLightMap();
+ lightMapNumber = v;
+#if 0
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+#endif
+ if (lightMap.data) delete [] lightMap.data;
+
+ lightMap.data = new GLubyte [newPicWidth * newPicHeight * 4];
+ if (! lightMap.data) {
+ return fatal("Out of memory loading light map.");
+ }
+
+ int t1, t2, n;
+ unsigned short c;
+ GLubyte *target;
+
+ if (fileIsPNG) {
+ unsigned char *row_pointers[lightMap.h];
+ for (int i = 0; i < lightMap.h; i++)
+ row_pointers[i] = lightMap.data + 4 * i * newPicWidth;
+
+ png_read_image(png_ptr, (png_byte **) row_pointers);
+ png_read_end(png_ptr, NULL);
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ } else {
+
+ for (t2 = 0; t2 < lightMap.h; t2 ++) {
+ t1 = 0;
+ while (t1 < lightMap.w) {
+ c = (unsigned short) get2bytes(bigDataFile);
+ if (c & 32) {
+ n = fgetc(bigDataFile) + 1;
+ c -= 32;
+ } else {
+ n = 1;
+ }
+ while (n --) {
+ target = lightMap.data + 4 * newPicWidth * t2 + t1 * 4;
+ target[0] = (GLubyte) redValue(c);
+ target[1] = (GLubyte) greenValue(c);
+ target[2] = (GLubyte) blueValue(c);
+ target[3] = (GLubyte) 255;
+ t1++;
+ }
+ }
+ }
+ }
+#if 0
+ if (! lightMap.name) glGenTextures(1, &lightMap.name);
+ glBindTexture(GL_TEXTURE_2D, lightMap.name);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+#endif
+ texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, newPicWidth, newPicHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, lightMap.data, lightMap.name);
+
+ finishAccess();
+
+#endif
+ setResourceForFatal(-1);
+
+ return true;
+}
+
+void reloadParallaxTextures() {
+#if 0
+ parallaxLayer *nP = parallaxStuff;
+ if (! nP) return;
+
+ while (nP) {
+ //fprintf (stderr, "Reloading parallax. (%d, %d) ", nP->width, nP->height);
+ nP->textureName = 0;
+
+ glGenTextures(1, &nP->textureName);
+ glBindTexture(GL_TEXTURE_2D, nP->textureName);
+ if (nP -> wrapS)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ else
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ if (nP -> wrapT)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ else
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ if (gameSettings.antiAlias < 0) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ } else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+
+ if (! NPOT_textures) {
+ texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getNextPOT(nP->width), getNextPOT(nP->height), 0, GL_RGBA, GL_UNSIGNED_BYTE, nP->texture, nP->textureName);
+ } else {
+ texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nP->width, nP->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nP->texture, nP->textureName);
+ }
+
+ nP = nP->next;
+ }
+#endif
+}
+
+bool loadParallax(unsigned short v, unsigned short fracX, unsigned short fracY) {
+
+#if ALLOW_FILE
+ setResourceForFatal(v);
+ if (! openFileFromNum(v)) return fatal("Can't open parallax image");
+
+ parallaxLayer *nP = new parallaxLayer;
+ if (! checkNew(nP)) return false;
+
+ nP -> next = parallaxStuff;
+ parallaxStuff = nP;
+ if (nP -> next) {
+ nP -> next -> prev = nP;
+ }
+ nP -> prev = NULL;
+
+ int picWidth;
+ int picHeight;
+
+ long file_pointer = ftell(bigDataFile);
+
+ png_structp png_ptr;
+ png_infop info_ptr, end_info;
+
+
+ int fileIsPNG = true;
+
+ // Is this a PNG file?
+
+ char tmp[10];
+ size_t bytes_read = fread(tmp, 1, 8, bigDataFile);
+ if (bytes_read != 8 && ferror(bigDataFile)) {
+ debugOut("Reading error in loadParallax.\n");
+ }
+ if (png_sig_cmp((png_byte *) tmp, 0, 8)) {
+ // No, it's old-school HSI
+ fileIsPNG = false;
+ fseek(bigDataFile, file_pointer, SEEK_SET);
+
+ picWidth = nP -> width = get2bytes(bigDataFile);
+ picHeight = nP -> height = get2bytes(bigDataFile);
+ } else {
+ // Read the PNG header
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr) {
+ return false;
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
+ return false;
+ }
+
+ end_info = png_create_info_struct(png_ptr);
+ if (!end_info) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ return false;
+ }
+ png_init_io(png_ptr, bigDataFile); // Tell libpng which file to read
+ png_set_sig_bytes(png_ptr, 8); // 8 bytes already read
+
+ png_read_info(png_ptr, info_ptr);
+
+ png_uint_32 width, height;
+ int bit_depth, color_type, interlace_type, compression_type, filter_method;
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method);
+
+ picWidth = nP -> width = width;
+ picHeight = nP -> height = height;
+
+ if (bit_depth < 8) png_set_packing(png_ptr);
+ png_set_expand(png_ptr);
+ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr);
+ if (bit_depth == 16) png_set_strip_16(png_ptr);
+
+ png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
+
+ png_read_update_info(png_ptr, info_ptr);
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method);
+
+ //int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+
+ }
+
+ if (! NPOT_textures) {
+ picWidth = getNextPOT(picWidth);
+ picHeight = getNextPOT(picHeight);
+ }
+
+ nP -> fileNum = v;
+ nP -> fractionX = fracX;
+ nP -> fractionY = fracY;
+
+ if (fracX == 65535) {
+ nP -> wrapS = false;
+ if (nP -> width < winWidth) {
+ fatal("For AUTOFIT parallax backgrounds, the image must be at least as wide as the game window/screen.");
+ return false;
+ }
+ } else {
+ nP -> wrapS = true;
+ }
+
+ if (fracY == 65535) {
+ nP -> wrapT = false;
+ if (nP -> height < winHeight) {
+ fatal("For AUTOFIT parallax backgrounds, the image must be at least as tall as the game window/screen.");
+ return false;
+ }
+ } else {
+ nP -> wrapT = true;
+ }
+
+ nP -> texture = new GLubyte [picHeight * picWidth * 4];
+ if (! checkNew(nP -> texture)) return false;
+
+ if (fileIsPNG) {
+ unsigned char *row_pointers[nP -> height];
+ for (int i = 0; i < nP -> height; i++)
+ row_pointers[i] = nP -> texture + 4 * i * picWidth;
+
+ png_read_image(png_ptr, (png_byte **) row_pointers);
+ png_read_end(png_ptr, NULL);
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ } else {
+
+ int t1, t2, n;
+ unsigned short c;
+ GLubyte *target;
+
+ for (t2 = 0; t2 < nP -> height; t2 ++) {
+ t1 = 0;
+ while (t1 < nP -> width) {
+ c = (unsigned short) get2bytes(bigDataFile);
+ if (c & 32) {
+ n = fgetc(bigDataFile) + 1;
+ c -= 32;
+ } else {
+ n = 1;
+ }
+ while (n--) {
+ target = nP -> texture + 4 * picWidth * t2 + t1 * 4;
+ if (c == 63519 || c == 2015) {
+ target[0] = (GLubyte) 0;
+ target[1] = (GLubyte) 0;
+ target[2] = (GLubyte) 0;
+ target[3] = (GLubyte) 0;
+ } else {
+ target[0] = (GLubyte) redValue(c);
+ target[1] = (GLubyte) greenValue(c);
+ target[2] = (GLubyte) blueValue(c);
+ target[3] = (GLubyte) 255;
+ }
+ t1 ++;
+ }
+ }
+ }
+ }
+
+ glGenTextures(1, &nP->textureName);
+ glBindTexture(GL_TEXTURE_2D, nP->textureName);
+ if (nP -> wrapS)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ else
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ if (nP -> wrapT)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ else
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ if (gameSettings.antiAlias < 0) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ } else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+
+ texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, picWidth, picHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nP->texture, nP->textureName);
+
+ finishAccess();
+#endif
+ setResourceForFatal(-1);
+ return true;
+}
+
+extern int viewportOffsetX, viewportOffsetY;
+
+#if ALLOW_FILE
+bool loadHSI(FILE *fp, int x, int y, bool reserve) {
+
+ int t1, t2, n;
+ unsigned short c;
+ GLubyte *target;
+ int32_t transCol = reserve ? -1 : 63519;
+ int picWidth;
+ int picHeight;
+ int realPicWidth, realPicHeight;
+ long file_pointer = ftell(fp);
+
+ png_structp png_ptr;
+ png_infop info_ptr, end_info;
+
+
+ int fileIsPNG = true;
+
+ // Is this a PNG file?
+
+ char tmp[10];
+ size_t bytes_read = fread(tmp, 1, 8, fp);
+ if (bytes_read != 8 && ferror(fp)) {
+ debugOut("Reading error in loadHSI.\n");
+ }
+ if (png_sig_cmp((png_byte *) tmp, 0, 8)) {
+ // No, it's old-school HSI
+ fileIsPNG = false;
+ fseek(fp, file_pointer, SEEK_SET);
+
+ picWidth = realPicWidth = get2bytes(fp);
+ picHeight = realPicHeight = get2bytes(fp);
+ } else {
+ // Read the PNG header
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr) {
+ return false;
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
+ return false;
+ }
+
+ end_info = png_create_info_struct(png_ptr);
+ if (!end_info) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ return false;
+ }
+ png_init_io(png_ptr, fp); // Tell libpng which file to read
+ png_set_sig_bytes(png_ptr, 8); // 8 bytes already read
+
+ png_read_info(png_ptr, info_ptr);
+
+ png_uint_32 width, height;
+ int bit_depth, color_type, interlace_type, compression_type, filter_method;
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method);
+
+ picWidth = realPicWidth = width;
+ picHeight = realPicHeight = height;
+
+ if (bit_depth < 8) png_set_packing(png_ptr);
+ png_set_expand(png_ptr);
+ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr);
+ if (bit_depth == 16) png_set_strip_16(png_ptr);
+
+ png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
+
+ png_read_update_info(png_ptr, info_ptr);
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method);
+
+ //int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+
+ }
+
+
+ GLfloat texCoordW = 1.0;
+ GLfloat texCoordH = 1.0;
+ if (! NPOT_textures) {
+ picWidth = getNextPOT(picWidth);
+ picHeight = getNextPOT(picHeight);
+ texCoordW = ((double)realPicWidth) / picWidth;
+ texCoordH = ((double)realPicHeight) / picHeight;
+ }
+
+ if (reserve) {
+ if (! resizeBackdrop(realPicWidth, realPicHeight)) return false;
+ }
+
+ if (x == IN_THE_CENTRE) x = (sceneWidth - realPicWidth) >> 1;
+ if (y == IN_THE_CENTRE) y = (sceneHeight - realPicHeight) >> 1;
+ if (x < 0 || x + realPicWidth > sceneWidth || y < 0 || y + realPicHeight > sceneHeight) return false;
+
+ if (fileIsPNG) {
+ unsigned char *row_pointers[realPicHeight];
+ for (int i = 0; i < realPicHeight; i++)
+ row_pointers[i] = backdropTexture + 4 * i * picWidth;
+
+ png_read_image(png_ptr, (png_byte **) row_pointers);
+ png_read_end(png_ptr, NULL);
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ } else {
+ for (t2 = 0; t2 < realPicHeight; t2 ++) {
+ t1 = 0;
+ while (t1 < realPicWidth) {
+ c = (unsigned short) get2bytes(fp);
+ if (c & 32) {
+ n = fgetc(fp) + 1;
+ c -= 32;
+ } else {
+ n = 1;
+ }
+ while (n --) {
+ target = backdropTexture + 4 * picWidth * t2 + t1 * 4;
+ if (c == transCol || c == 2015) {
+ target[0] = (GLubyte) 0;
+ target[1] = (GLubyte) 0;
+ target[2] = (GLubyte) 0;
+ target[3] = (GLubyte) 0;
+ } else {
+ target[0] = (GLubyte) redValue(c);
+ target[1] = (GLubyte) greenValue(c);
+ target[2] = (GLubyte) blueValue(c);
+ target[3] = (GLubyte) 255;
+ }
+ t1++;
+ }
+ }
+ }
+ }
+
+ GLuint tmpTex;
+#if 0
+ glGenTextures(1, &tmpTex);
+ glBindTexture(GL_TEXTURE_2D, tmpTex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if (gameSettings.antiAlias < 0) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ } else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+#endif
+ texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, picWidth, picHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, backdropTexture, tmpTex);
+
+
+ //glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+
+ float btx1;
+ float btx2;
+ float bty1;
+ float bty2;
+ if (! NPOT_textures) {
+ btx1 = backdropTexW * x / sceneWidth;
+ btx2 = backdropTexW * (x + realPicWidth) / sceneWidth;
+ bty1 = backdropTexH * y / sceneHeight;
+ bty2 = backdropTexH * (y + realPicHeight) / sceneHeight;
+ } else {
+ btx1 = (float) x / sceneWidth;
+ btx2 = (float)(x + realPicWidth) / sceneWidth;
+ bty1 = (float) y / sceneHeight;
+ bty2 = (float)(y + realPicHeight) / sceneHeight;
+ }
+
+ const GLfloat btexCoords[] = {
+ btx1, bty1,
+ btx2, bty1,
+ btx1, bty2,
+ btx2, bty2
+ };
+
+ setPixelCoords(true);
+
+ int xoffset = 0;
+ while (xoffset < realPicWidth) {
+ int w = (realPicWidth - xoffset < viewportWidth) ? realPicWidth - xoffset : viewportWidth;
+
+ int yoffset = 0;
+ while (yoffset < realPicHeight) {
+ int h = (realPicHeight - yoffset < viewportHeight) ? realPicHeight - yoffset : viewportHeight;
+#if 0
+ glClear(GL_COLOR_BUFFER_BIT); // Clear The Screen
+#endif
+ const GLfloat vertices[] = {
+ (GLfloat) - xoffset, (GLfloat) - yoffset, 0.,
+ (GLfloat)realPicWidth - xoffset, (GLfloat) - yoffset, 0.,
+ (GLfloat) - xoffset, (GLfloat) - yoffset + realPicHeight, 0.,
+ (GLfloat)realPicWidth - xoffset, (GLfloat) - yoffset + realPicHeight, 0.
+ };
+
+ const GLfloat texCoords[] = {
+ 0.0f, 0.0f,
+ texCoordW, 0.0f,
+ 0.0f, texCoordH,
+ texCoordW, texCoordH
+ };
+
+ if (backdropExists) {
+#if 0
+ // Render the sprite to the backdrop
+ // (using mulitexturing, so the old backdrop is seen where alpha < 1.0)
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, backdropTextureName);
+ glActiveTexture(GL_TEXTURE0);
+
+ glUseProgram(shader.paste);
+ GLint uniform = glGetUniformLocation(shader.paste, "useLightTexture");
+ if (uniform >= 0) glUniform1i(uniform, 0); // No lighting
+#endif
+ setPMVMatrix(shader.paste);
+
+ setPrimaryColor(1.0, 1.0, 1.0, 1.0);
+#if 0
+ glBindTexture(GL_TEXTURE_2D, tmpTex);
+ //glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+#endif
+ drawQuad(shader.paste, vertices, 3, texCoords, NULL, btexCoords);
+#if 0
+ glUseProgram(0);
+#endif
+ } else {
+ // It's all new - nothing special to be done.
+
+#if 0
+ glUseProgram(shader.texture);
+#endif
+ setPMVMatrix(shader.texture);
+#if 0
+ glBindTexture(GL_TEXTURE_2D, tmpTex);
+#endif
+ setPrimaryColor(1.0, 0.0, 0.0, 0.0);
+
+ drawQuad(shader.texture, vertices, 1, texCoords);
+
+#if 0
+ glUseProgram(0);
+#endif
+ }
+
+ // Copy Our ViewPort To The Texture
+ copyTexSubImage2D(GL_TEXTURE_2D, 0, x + xoffset, y + yoffset, viewportOffsetX, viewportOffsetY, w, h, backdropTextureName);
+
+ yoffset += viewportHeight;
+ }
+
+ xoffset += viewportWidth;
+ }
+ deleteTextures(1, &tmpTex);
+
+ setPixelCoords(false);
+
+ backdropExists = true;
+ return true;
+}
+
+bool mixHSI(FILE *fp, int x, int y) {
+ int realPicWidth, realPicHeight;
+ int picWidth;
+ int picHeight;
+
+ long file_pointer = ftell(fp);
+
+ png_structp png_ptr;
+ png_infop info_ptr, end_info;
+
+
+ int fileIsPNG = true;
+
+ // Is this a PNG file?
+ char tmp[10];
+ size_t bytes_read = fread(tmp, 1, 8, fp);
+ if (bytes_read != 8 && ferror(fp)) {
+ debugOut("Reading error in mixHSI.\n");
+ }
+ if (png_sig_cmp((png_byte *) tmp, 0, 8)) {
+ // No, it's old-school HSI
+ fileIsPNG = false;
+ fseek(fp, file_pointer, SEEK_SET);
+
+ picWidth = realPicWidth = get2bytes(fp);
+ picHeight = realPicHeight = get2bytes(fp);
+ } else {
+ // Read the PNG header
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr) {
+ return false;
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
+ return false;
+ }
+
+ end_info = png_create_info_struct(png_ptr);
+ if (!end_info) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ return false;
+ }
+ png_init_io(png_ptr, fp); // Tell libpng which file to read
+ png_set_sig_bytes(png_ptr, 8); // 8 bytes already read
+
+ png_read_info(png_ptr, info_ptr);
+
+ png_uint_32 width, height;
+ int bit_depth, color_type, interlace_type, compression_type, filter_method;
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method);
+
+ picWidth = realPicWidth = width;
+ picHeight = realPicHeight = height;
+
+ if (bit_depth < 8) png_set_packing(png_ptr);
+ png_set_expand(png_ptr);
+ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr);
+ if (bit_depth == 16) png_set_strip_16(png_ptr);
+
+ png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
+
+ png_read_update_info(png_ptr, info_ptr);
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method);
+
+ //int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+
+ }
+
+ if (x == IN_THE_CENTRE) x = (sceneWidth - realPicWidth) >> 1;
+ if (y == IN_THE_CENTRE) y = (sceneHeight - realPicHeight) >> 1;
+ if (x < 0 || x + realPicWidth > sceneWidth || y < 0 || y + realPicHeight > sceneHeight) return false;
+
+ float btx1, tx1;
+ float btx2, tx2;
+ float bty1, ty1;
+ float bty2, ty2;
+
+ if (! NPOT_textures) {
+ tx1 = 0.0;
+ ty1 = 0.0;
+ tx2 = ((double)picWidth) / getNextPOT(picWidth);
+ ty2 = ((double)picHeight) / getNextPOT(picHeight);
+ picWidth = getNextPOT(picWidth);
+ picHeight = getNextPOT(picHeight);
+ btx1 = backdropTexW * x / sceneWidth;
+ btx2 = backdropTexW * (x + realPicWidth) / sceneWidth;
+ bty1 = backdropTexH * y / sceneHeight;
+ bty2 = backdropTexH * (y + realPicHeight) / sceneHeight;
+ } else {
+ tx1 = 0.0;
+ ty1 = 0.0;
+ tx2 = 1.0;
+ ty2 = 1.0;
+ btx1 = (float) x / sceneWidth;
+ btx2 = (float)(x + picWidth) / sceneWidth;
+ bty1 = (float) y / sceneHeight;
+ bty2 = (float)(y + picHeight) / sceneHeight;
+ }
+
+ const GLfloat texCoords[] = {
+ tx1, ty1,
+ tx2, ty1,
+ tx1, ty2,
+ tx2, ty2
+ };
+
+ const GLfloat btexCoords[] = {
+ btx1, bty1,
+ btx2, bty1,
+ btx1, bty2,
+ btx2, bty2
+ };
+
+ int t1, t2, n;
+ unsigned short c;
+ GLubyte *target;
+ int32_t transCol = 63519;
+
+
+ if (fileIsPNG) {
+ unsigned char *row_pointers[realPicHeight];
+ for (int i = 0; i < realPicHeight; i++)
+ row_pointers[i] = backdropTexture + 4 * i * picWidth;
+
+ png_read_image(png_ptr, (png_byte **) row_pointers);
+ png_read_end(png_ptr, NULL);
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ } else {
+ for (t2 = 0; t2 < realPicHeight; t2 ++) {
+ t1 = 0;
+ while (t1 < realPicWidth) {
+ c = (unsigned short) get2bytes(fp);
+ if (c & 32) {
+ n = fgetc(fp) + 1;
+ c -= 32;
+ } else {
+ n = 1;
+ }
+ while (n --) {
+ target = backdropTexture + 4 * picWidth * t2 + t1 * 4;
+ if (c == transCol || c == 2015) {
+ target[0] = (GLubyte) 0;
+ target[1] = (GLubyte) 0;
+ target[2] = (GLubyte) 0;
+ target[3] = (GLubyte) 0;
+ } else {
+ target[0] = (GLubyte) redValue(c);
+ target[1] = (GLubyte) greenValue(c);
+ target[2] = (GLubyte) blueValue(c);
+ target[3] = (GLubyte) 255;
+ }
+ t1++;
+ }
+ }
+ }
+ }
+
+ GLuint tmpTex;
+#if 0
+ glGenTextures(1, &tmpTex);
+ glBindTexture(GL_TEXTURE_2D, tmpTex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if (gameSettings.antiAlias < 0) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ } else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+#endif
+ texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, picWidth, picHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, backdropTexture, tmpTex);
+
+
+ //glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ setPixelCoords(true);
+
+
+ int xoffset = 0;
+ while (xoffset < realPicWidth) {
+ int w = (realPicWidth - xoffset < viewportWidth) ? realPicWidth - xoffset : viewportWidth;
+
+ int yoffset = 0;
+ while (yoffset < realPicHeight) {
+ int h = (realPicHeight - yoffset < viewportHeight) ? realPicHeight - yoffset : viewportHeight;
+#if 0
+ glClear(GL_COLOR_BUFFER_BIT); // Clear The Screen
+
+ // Render the sprite to the backdrop
+ // (using mulitexturing, so the backdrop is seen where alpha < 1.0)
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, backdropTextureName);
+ glActiveTexture(GL_TEXTURE0);
+
+ glUseProgram(shader.paste);
+ GLint uniform = glGetUniformLocation(shader.paste, "useLightTexture");
+ if (uniform >= 0) glUniform1i(uniform, 0); // No lighting
+#endif
+ setPMVMatrix(shader.paste);
+
+ setPrimaryColor(1.0, 1.0, 1.0, 0.5);
+#if 0
+ glBindTexture(GL_TEXTURE_2D, tmpTex);
+ //glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+#endif
+ const GLfloat vertices[] = {
+ (GLfloat) - xoffset, (GLfloat) - yoffset, 0.,
+ (GLfloat)realPicWidth - xoffset, (GLfloat) - yoffset, 0.,
+ (GLfloat) - xoffset, (GLfloat) - yoffset + realPicHeight, 0.,
+ (GLfloat)realPicWidth - xoffset, (GLfloat) - yoffset + realPicHeight, 0.
+ };
+
+ drawQuad(shader.paste, vertices, 3, texCoords, NULL, btexCoords);
+#if 0
+ // Copy Our ViewPort To The Texture
+ glUseProgram(0);
+#endif
+ copyTexSubImage2D(GL_TEXTURE_2D, 0, (int)((x < 0) ? xoffset : x + xoffset), (int)((y < 0) ? yoffset : y + yoffset), (int)((x < 0) ? viewportOffsetX - x : viewportOffsetX), (int)((y < 0) ? viewportOffsetY - y : viewportOffsetY), w, h, backdropTextureName);
+
+ yoffset += viewportHeight;
+ }
+
+ xoffset += viewportWidth;
+ }
+ deleteTextures(1, &tmpTex);
+ setPixelCoords(false);
+ return true;
+}
+
+void saveCorePNG(FILE *writer, GLuint texture, int w, int h) {
+ GLint tw, th;
+#if 0
+ glBindTexture(GL_TEXTURE_2D, texture);
+#endif
+ getTextureDimensions(texture, &tw, &th);
+
+ GLubyte *image = new GLubyte [tw * th * 4];
+ if (! checkNew(image)) return;
+#if 0
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+// glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
+#endif
+#ifdef HAVE_GLES2
+#if 0
+ GLuint old_fbo, new_fbo;
+ GLint old_vp[4];
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&old_fbo);
+ glGetIntegerv(GL_VIEWPORT, old_vp);
+ glGenFramebuffers(1, &new_fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, new_fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+ glViewport(0, 0, tw, th);
+ glReadPixels(0, 0, tw, th, GL_RGBA, GL_UNSIGNED_BYTE, image);
+ glBindFramebuffer(GL_FRAMEBUFFER, old_fbo);
+ glViewport(old_vp[0], old_vp[1], old_vp[2], old_vp[3]);
+ glDeleteFramebuffers(1, &new_fbo);
+#endif
+#else
+ setPixelCoords(true);
+
+
+ //glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ const GLfloat texCoords[] = {
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f
+ };
+
+ int xoffset = 0;
+ while (xoffset < tw) {
+ int w = (tw - xoffset < viewportWidth) ? tw - xoffset : viewportWidth;
+
+ int yoffset = 0;
+ while (yoffset < th) {
+ int h = (th - yoffset < viewportHeight) ? th - yoffset : viewportHeight;
+#if 0
+ glClear(GL_COLOR_BUFFER_BIT); // Clear The Screen
+#endif
+ const GLfloat vertices[] = {
+ (GLfloat) - xoffset, (GLfloat) - yoffset, 0.,
+ (GLfloat)tw - xoffset, (GLfloat) - yoffset, 0.,
+ (GLfloat) - xoffset, (GLfloat) - yoffset + th, 0.,
+ (GLfloat)tw - xoffset, (GLfloat) - yoffset + th, 0.
+ };
+
+#if 0
+ glUseProgram(shader.texture);
+#endif
+ setPMVMatrix(shader.texture);
+
+ drawQuad(shader.texture, vertices, 1, texCoords);
+#if 0
+ glUseProgram(0);
+
+ for (int i = 0; i < h; i++) {
+ glReadPixels(viewportOffsetX, viewportOffsetY + i, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, image + xoffset * 4 + (yoffset + i) * 4 * tw);
+ }
+#endif
+ yoffset += viewportHeight;
+ }
+
+ xoffset += viewportWidth;
+ }
+ setPixelCoords(false);
+#endif
+
+
+
+ png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr) {
+ fatal("Error saving image!");
+ return;
+ }
+
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+ fatal("Error saving image!");
+ return;
+ }
+
+ png_init_io(png_ptr, writer);
+
+ png_set_IHDR(png_ptr, info_ptr, w, h,
+ 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+
+ unsigned char *row_pointers[h];
+
+ for (int i = 0; i < h; i++) {
+ row_pointers[i] = image + 4 * i * tw;
+ }
+
+ png_set_rows(png_ptr, info_ptr, row_pointers);
+ png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
+
+ delete [] image;
+ image = NULL;
+}
+
+void saveCoreHSI(FILE *writer, GLuint texture, int w, int h) {
+
+ GLint tw, th;
+#if 0
+ glBindTexture(GL_TEXTURE_2D, texture);
+#endif
+ getTextureDimensions(texture, &tw, &th);
+
+ GLushort *image = new GLushort [tw * th];
+ if (! checkNew(image)) return;
+#if 0
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+// glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, image);
+#endif
+ setPixelCoords(true);
+
+ //glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ const GLfloat texCoords[] = {
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f
+ };
+
+ int xoffset = 0;
+ while (xoffset < tw) {
+ int w = (tw - xoffset < viewportWidth) ? tw - xoffset : viewportWidth;
+
+ int yoffset = 0;
+ while (yoffset < th) {
+ int h = (th - yoffset < viewportHeight) ? th - yoffset : viewportHeight;
+#if 0
+ glClear(GL_COLOR_BUFFER_BIT); // Clear The Screen
+#endif
+ const GLfloat vertices[] = {
+ (GLfloat) - xoffset, (GLfloat) - yoffset, 0.,
+ (GLfloat)w - xoffset, (GLfloat) - yoffset, 0.,
+ (GLfloat) - xoffset, (GLfloat) - yoffset + h, 0.,
+ (GLfloat)w - xoffset, (GLfloat) - yoffset + h, 0.
+ };
+
+#if 0
+ glUseProgram(shader.texture);
+#endif
+ setPMVMatrix(shader.texture);
+ drawQuad(shader.texture, vertices, 1, texCoords);
+#if 0
+ glUseProgram(0);
+
+ for (int i = 0; i < h; i++) {
+ glReadPixels(viewportOffsetX, viewportOffsetY + i, w, 1, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, image + xoffset + (yoffset + i)*tw);
+ }
+#endif
+ yoffset += viewportHeight;
+ }
+
+ xoffset += viewportWidth;
+ }
+ //glReadPixels(viewportOffsetX, viewportOffsetY, tw, th, GL_RGBA, GL_UNSIGNED_BYTE, data);
+
+ setPixelCoords(false);
+
+
+
+ int x, y, lookAhead;
+ unsigned short int *fromHere, * lookPointer;
+
+ put2bytes(w, writer);
+ put2bytes(h, writer);
+
+ for (y = 0; y < h; y ++) {
+ fromHere = image + (y * tw);
+ x = 0;
+ while (x < w) {
+ lookPointer = fromHere + 1;
+ for (lookAhead = x + 1; lookAhead < w; lookAhead ++) {
+ if (lookAhead - x == 256) break;
+ if (* fromHere != * lookPointer) break;
+ lookPointer ++;
+ }
+ if (lookAhead == x + 1) {
+ put2bytes((* fromHere) & 65503, writer);
+ } else {
+ put2bytes(* fromHere | 32, writer);
+ fputc(lookAhead - x - 1, writer);
+ }
+ fromHere = lookPointer;
+ x = lookAhead;
+ }
+ }
+ delete [] image;
+ image = NULL;
+}
+
+void saveHSI(FILE *writer) {
+ saveCorePNG(writer, backdropTextureName, sceneWidth, sceneHeight);
+}
+
+
+void saveParallaxRecursive(parallaxLayer *me, FILE *fp) {
+ if (me) {
+ saveParallaxRecursive(me -> next, fp);
+ fputc(1, fp);
+ put2bytes(me->fileNum, fp);
+ put2bytes(me ->fractionX, fp);
+ put2bytes(me->fractionY, fp);
+ }
+}
+#endif
+
+bool getRGBIntoStack(unsigned int x, unsigned int y, stackHandler *sH) {
+#if 0
+ if (x >= sceneWidth || y >= sceneHeight) {
+ return fatal("Co-ordinates are outside current scene!");
+ }
+
+ variable newValue;
+
+ newValue.varType = SVT_NULL;
+
+ saveTexture(backdropTextureName, backdropTexture);
+
+ GLubyte *target;
+ if (! NPOT_textures) {
+ target = backdropTexture + 4 * getNextPOT(sceneWidth) * y + x * 4;
+ } else {
+ target = backdropTexture + 4 * sceneWidth * y + x * 4;
+ }
+
+ setVariable(newValue, SVT_INT, target[2]);
+ if (! addVarToStackQuick(newValue, sH -> first)) return false;
+ sH -> last = sH -> first;
+
+ setVariable(newValue, SVT_INT, target[1]);
+ if (! addVarToStackQuick(newValue, sH -> first)) return false;
+
+ setVariable(newValue, SVT_INT, target[0]);
+ if (! addVarToStackQuick(newValue, sH -> first)) return false;
+#endif
+ return true;
+}