aboutsummaryrefslogtreecommitdiff
path: root/engines/hopkins/graphics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/hopkins/graphics.cpp')
-rw-r--r--engines/hopkins/graphics.cpp2507
1 files changed, 2507 insertions, 0 deletions
diff --git a/engines/hopkins/graphics.cpp b/engines/hopkins/graphics.cpp
new file mode 100644
index 0000000000..718a428ba6
--- /dev/null
+++ b/engines/hopkins/graphics.cpp
@@ -0,0 +1,2507 @@
+/* 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 "common/system.h"
+#include "graphics/palette.h"
+#include "common/file.h"
+#include "common/rect.h"
+#include "engines/util.h"
+#include "hopkins/files.h"
+#include "hopkins/globals.h"
+#include "hopkins/graphics.h"
+#include "hopkins/hopkins.h"
+
+namespace Hopkins {
+
+GraphicsManager::GraphicsManager() {
+ _lockCtr = 0;
+ SDL_MODEYES = false;
+ SDL_ECHELLE = 0;
+ XSCREEN = YSCREEN = 0;
+ WinScan = 0;
+ Winbpp = 0;
+ PAL_PIXELS = NULL;
+ nbrligne = 0;
+ Linear = false;
+ VideoPtr = NULL;
+ ofscroll = 0;
+ SCROLL = 0;
+ PCX_L = PCX_H = 0;
+ DOUBLE_ECRAN = false;
+ OLD_SCROLL = 0;
+ MANU_SCROLL = 1;
+ SPEED_SCROLL = 16;
+ nbrligne2 = 0;
+ Agr_x = Agr_y = 0;
+ Agr_Flag_x = Agr_Flag_y = 0;
+ FADESPD = 15;
+ FADE_LINUX = 0;
+ NOLOCK = false;
+ no_scroll = 0;
+ REDRAW = false;
+ min_x = 0;
+ min_y = 20;
+ max_x = SCREEN_WIDTH * 2;
+ max_y = SCREEN_HEIGHT - 20;
+ clip_x = clip_y = 0;
+ clip_x1 = clip_y1 = 0;
+ clip_flag = false;
+ SDL_NBLOCS = 0;
+ Red_x = Red_y = 0;
+ Red = 0;
+ Largeur = 0;
+ Compteur_y = 0;
+ spec_largeur = 0;
+
+ Common::fill(&SD_PIXELS[0], &SD_PIXELS[PALETTE_SIZE * 2], 0);
+ Common::fill(&TABLE_COUL[0], &TABLE_COUL[PALETTE_EXT_BLOCK_SIZE], 0);
+ Common::fill(&cmap[0], &cmap[PALETTE_BLOCK_SIZE], 0);
+ Common::fill(&Palette[0], &Palette[PALETTE_EXT_BLOCK_SIZE], 0);
+ Common::fill(&OLD_PAL[0], &OLD_PAL[PALETTE_EXT_BLOCK_SIZE], 0);
+}
+
+GraphicsManager::~GraphicsManager() {
+ _vm->_globals.dos_free2(VESA_SCREEN);
+ _vm->_globals.dos_free2(VESA_BUFFER);
+}
+
+void GraphicsManager::setParent(HopkinsEngine *vm) {
+ _vm = vm;
+}
+
+void GraphicsManager::SET_MODE(int width, int height) {
+ if (!SDL_MODEYES) {
+ SDL_ECHELLE = 0;
+
+ if (_vm->_globals.XSETMODE == 1)
+ SDL_ECHELLE = 0;
+ if (_vm->_globals.XSETMODE == 2)
+ SDL_ECHELLE = 25;
+ if (_vm->_globals.XSETMODE == 3)
+ SDL_ECHELLE = 50;
+ if (_vm->_globals.XSETMODE == 4)
+ SDL_ECHELLE = 75;
+ if (_vm->_globals.XSETMODE == 5)
+ SDL_ECHELLE = _vm->_globals.XZOOM;
+
+ int bpp = 8;
+ if (_vm->_globals.XFORCE8 == true)
+ bpp = 8;
+ if (_vm->_globals.XFORCE16 == true)
+ bpp = 16;
+
+ if (SDL_ECHELLE) {
+ width = Reel_Zoom(width, SDL_ECHELLE);
+ height = Reel_Zoom(height, SDL_ECHELLE);
+ }
+
+ Graphics::PixelFormat pixelFormat16(2, 5, 6, 5, 0, 11, 5, 0, 0);
+
+ if (bpp == 8) {
+ initGraphics(width, height, true);
+ } else {
+ initGraphics(width, height, true, &pixelFormat16);
+ }
+
+ // Init surfaces
+ VESA_SCREEN = _vm->_globals.dos_malloc2(SCREEN_WIDTH * 2 * SCREEN_HEIGHT);
+ VESA_BUFFER = _vm->_globals.dos_malloc2(SCREEN_WIDTH * 2 * SCREEN_HEIGHT);
+
+ VideoPtr = NULL;
+ XSCREEN = width;
+ YSCREEN = height;
+
+ Linear = true;
+ Winbpp = bpp / 8;
+ WinScan = width * Winbpp;
+
+ PAL_PIXELS = SD_PIXELS;
+ nbrligne = width;
+
+ Common::fill(&cmap[0], &cmap[256 * 3], 0);
+ SDL_MODEYES = true;
+ } else {
+ error("Called SET_MODE multiple times");
+ }
+}
+
+void GraphicsManager::DD_Lock() {
+ if (!NOLOCK) {
+ if (_lockCtr++ == 0)
+ VideoPtr = g_system->lockScreen();
+ }
+}
+
+void GraphicsManager::DD_Unlock() {
+ assert(VideoPtr);
+ if (--_lockCtr == 0) {
+ g_system->unlockScreen();
+ VideoPtr = NULL;
+ }
+}
+
+// Clear Screen
+void GraphicsManager::Cls_Video() {
+ assert(VideoPtr);
+
+ VideoPtr->fillRect(Common::Rect(0, 0, XSCREEN, YSCREEN), 0);
+}
+
+void GraphicsManager::LOAD_IMAGE(const Common::String &file) {
+ Common::String filename = Common::String::format("%s.PCX", file.c_str());
+ CHARGE_ECRAN(filename);
+ INIT_TABLE(165, 170, Palette);
+}
+
+// Load Screen
+void GraphicsManager::CHARGE_ECRAN(const Common::String &file) {
+ bool flag;
+ Common::File f;
+
+ _vm->_fileManager.DMESS1();
+
+ flag = true;
+ if (_vm->_fileManager.RECHERCHE_CAT(file, 6)) {
+ _vm->_fileManager.CONSTRUIT_FICHIER(_vm->_globals.HOPIMAGE, file);
+ if (!f.open(_vm->_globals.NFICHIER))
+ error("CHARGE_ECRAN - %s", file.c_str());
+
+ f.seek(0, SEEK_END);
+ f.close();
+ flag = false;
+ }
+
+ SCROLL_ECRAN(0);
+ A_PCX640_480((byte *)VESA_SCREEN, file, Palette, flag);
+
+ SCROLL = 0;
+ OLD_SCROLL = 0;
+ Cls_Pal();
+
+ if (!DOUBLE_ECRAN) {
+ _vm->_eventsManager.souris_max();
+ SCANLINE(SCREEN_WIDTH);
+ max_x = SCREEN_WIDTH;
+ DD_Lock();
+ Cls_Video();
+ if (Winbpp == 2) {
+ if (SDL_ECHELLE)
+ m_scroll16A(VESA_SCREEN, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ else
+ m_scroll16(VESA_SCREEN, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ } else if (Winbpp == 1) {
+ if (!SDL_ECHELLE)
+ m_scroll2(VESA_SCREEN, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ else
+ m_scroll2A(VESA_SCREEN, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ }
+
+ DD_Unlock();
+ } else {
+ SCANLINE(SCREEN_WIDTH * 2);
+ max_x = SCREEN_WIDTH * 2;
+ DD_Lock();
+ Cls_Video();
+ DD_Unlock();
+
+ if (MANU_SCROLL == 1) {
+ DD_Lock();
+ if (Winbpp == 2) {
+ if (SDL_ECHELLE)
+ m_scroll16A(VESA_SCREEN, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ else
+ m_scroll16(VESA_SCREEN, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ }
+ if (Winbpp == 1) {
+ if (!SDL_ECHELLE)
+ m_scroll2(VESA_SCREEN, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ else
+ m_scroll2A(VESA_SCREEN, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ }
+
+ DD_Unlock();
+ }
+ }
+
+ memcpy(VESA_BUFFER, VESA_SCREEN, SCREEN_WIDTH * 2 * SCREEN_HEIGHT);
+}
+
+void GraphicsManager::INIT_TABLE(int minIndex, int maxIndex, byte *palette) {
+ for (int idx = 0; idx < 256; ++idx)
+ TABLE_COUL[idx] = idx;
+
+ Trans_bloc(TABLE_COUL, palette, 256, minIndex, maxIndex);
+
+ for (int idx = 0; idx < 256; ++idx) {
+ byte v = TABLE_COUL[idx];
+ if (v > 27)
+ TABLE_COUL[idx] = 0;
+ if (!v)
+ TABLE_COUL[idx] = 0;
+ }
+
+ TABLE_COUL[0] = 1;
+}
+
+// Scroll Screen
+int GraphicsManager::SCROLL_ECRAN(int amount) {
+ int result = CLIP(amount, 0, SCREEN_WIDTH);
+ _vm->_eventsManager.start_x = result;
+ ofscroll = result;
+ SCROLL = result;
+ return result;
+}
+
+void GraphicsManager::Trans_bloc(byte *destP, const byte *srcP, int count, int minThreshold, int maxThreshold) {
+ byte *destPosP;
+ int palIndex;
+ int srcOffset;
+ int col1, col2;
+
+ destPosP = destP;
+ for (int idx = 0; idx < count; ++idx) {
+ palIndex = *(byte *)destPosP++;
+ srcOffset = 3 * palIndex;
+ col1 = *(srcP + srcOffset) + *(srcP + srcOffset + 1) + *(srcP + srcOffset + 2);
+
+ for (int idx2 = 0; idx2 < 38; ++idx2) {
+ srcOffset = 3 * idx2;
+ col2 = *(srcP + srcOffset) + *(srcP + srcOffset + 1) + *(srcP + srcOffset + 2);
+
+ col2 += minThreshold;
+ if (col2 < col1)
+ continue;
+
+ col2 -= maxThreshold;
+ if (col2 > col1)
+ continue;
+
+ *(destPosP - 1) = (idx2 == 0) ? 1 : idx2;
+ break;
+ }
+ }
+}
+
+void GraphicsManager::Trans_bloc2(byte *surface, byte *col, int size) {
+ byte *dataP;
+ int count;
+ byte dataVal;
+
+ dataP = surface;
+ count = size - 1;
+ do {
+ dataVal = *dataP++;
+ *(dataP - 1) = *(dataVal + col);
+ --count;
+ } while (count);
+}
+
+// TODO: See if it's feasible and/or desirable to change this to use the Common PCX decoder
+void GraphicsManager::A_PCX640_480(byte *surface, const Common::String &file, byte *palette, bool typeFlag) {
+ int filesize;
+ int v6;
+ int v7;
+ int v8;
+ int v9;
+ int v10;
+ int v11;
+ byte v12;
+ int v13;
+ int v14;
+ char v15;
+ int v18;
+ int v19;
+ int v20;
+ unsigned int v21;
+ int v22;
+ int32 v23;
+ byte *ptr;
+ Common::File f;
+
+ // Clear the passed surface
+ memset(surface, 0, SCREEN_WIDTH * 2 * SCREEN_HEIGHT);
+
+ if (typeFlag) {
+ _vm->_fileManager.CONSTRUIT_FICHIER(_vm->_globals.HOPIMAGE, "PIC.RES");
+ if (!f.open(_vm->_globals.NFICHIER))
+ error("(nom)Erreur en cours de lecture.");
+ f.seek(_vm->_globals.CAT_POSI);
+
+ v7 = _vm->_globals.CAT_TAILLE - 896;
+ v8 = f.read(HEADER_PCX, 128);
+
+ v6 = (int16)READ_LE_UINT16(&HEADER_PCX[8]) + 1;
+ v20 = (int16)READ_LE_UINT16(&HEADER_PCX[10]) + 1;
+ if (((int16)READ_LE_UINT16(&HEADER_PCX[8]) + 1) <= SCREEN_WIDTH) {
+ DOUBLE_ECRAN = false;
+ } else {
+ v6 = SCREEN_WIDTH * 2;
+ DOUBLE_ECRAN = true;
+ }
+ if (v20 > SCREEN_HEIGHT)
+ v20 = SCREEN_HEIGHT;
+ PCX_L = v6;
+ PCX_H = v20;
+ if (v8 == -1)
+ error("Erreur en cours de lecture.");
+ } else {
+ _vm->_fileManager.CONSTRUIT_FICHIER(_vm->_globals.HOPIMAGE, file);
+ if (!f.open(_vm->_globals.NFICHIER))
+ error("(nom)Erreur en cours de lecture.");
+
+ filesize = f.size();
+ int bytesRead = f.read(HEADER_PCX, 128);
+ if (bytesRead < 128)
+ error("Erreur en cours de lecture.");
+
+ v6 = (int16)READ_LE_UINT16(&HEADER_PCX[8]) + 1;
+ v20 = (int16)READ_LE_UINT16(&HEADER_PCX[10]) + 1;
+ if (v6 <= SCREEN_WIDTH) {
+ DOUBLE_ECRAN = false;
+ } else {
+ v6 = SCREEN_WIDTH * 2;
+ DOUBLE_ECRAN = true;
+ }
+ if (v20 > SCREEN_HEIGHT)
+ v20 = SCREEN_HEIGHT;
+ PCX_L = v6;
+ PCX_H = v20;
+ v7 = filesize - 896;
+ }
+
+ ptr = _vm->_globals.dos_malloc2(0xEE60u);
+ if (v7 >= 60000) {
+ v21 = v7 / 60000 + 1;
+ v23 = 60000 * (v7 / 60000) - v7;
+
+ if (((uint32)v23 & 0x80000000u) != 0)
+ v23 = -v23;
+ f.read(ptr, 60000);
+ v7 = 60000;
+ } else {
+ v21 = 1;
+ v23 = v7;
+ f.read(ptr, v7);
+ }
+ v22 = v21 - 1;
+ v18 = 0;
+ v9 = 0;
+ v10 = 0;
+ v19 = v6;
+
+ do {
+ if (v9 == v7) {
+ v9 = 0;
+ --v22;
+ v7 = 60000;
+ if ( !v22 )
+ v7 = v23;
+ v11 = v10;
+ f.read(ptr, v7);
+ v10 = v11;
+ }
+
+ v12 = *((byte *)ptr + v9++);
+ if (v12 > 0xC0u) {
+ v13 = v12 - 192;
+ if (v9 == v7) {
+ v9 = 0;
+ --v22;
+ v7 = 60000;
+ if ( v22 == 1 )
+ v7 = v23;
+ v14 = v10;
+ f.read(ptr, v7);
+ v10 = v14;
+ }
+ v15 = *((byte *)ptr + v9++);
+
+ do {
+ *((byte *)surface + v10++) = v15;
+ ++v18;
+ --v13;
+ } while (v13);
+ } else {
+ *((byte *)surface + v10++) = v12;
+ ++v18;
+ }
+ } while (v18 < v19 * v20);
+
+ if (typeFlag) {
+ f.seek(_vm->_globals.CAT_TAILLE + _vm->_globals.CAT_POSI - 768);
+ } else {
+ filesize = f.size();
+ f.seek(filesize - 768);
+ }
+
+ if (f.read(palette, PALETTE_BLOCK_SIZE) != (PALETTE_BLOCK_SIZE))
+ error("A_PCX640_480");
+
+ f.close();
+ _vm->_globals.dos_free2(ptr);
+}
+
+// Clear Palette
+void GraphicsManager::Cls_Pal() {
+ Common::fill(&cmap[0], &cmap[PALETTE_BLOCK_SIZE], 0);
+ SD_PIXELS[0] = 0;
+
+ if (Winbpp == 1) {
+ g_system->getPaletteManager()->setPalette(cmap, 0, 256);
+ }
+}
+
+void GraphicsManager::SCANLINE(int pitch) {
+ nbrligne = nbrligne2 = pitch;
+}
+
+void GraphicsManager::m_scroll(const byte *surface, int xs, int ys, int width, int height, int destX, int destY) {
+ const byte *srcP;
+ byte *destP;
+ int yNext;
+ int yCtr;
+ byte *dest2P;
+ const byte *src2P;
+ unsigned int widthRemaining;
+
+ assert(VideoPtr);
+ srcP = xs + nbrligne2 * ys + surface;
+ destP = destX + WinScan * destY + (byte *)VideoPtr->pixels;
+ yNext = height;
+ do {
+ yCtr = yNext;
+ memcpy((byte *)destP, (const byte *)srcP, 4 * (width >> 2));
+ src2P = (const byte *)(srcP + 4 * (width >> 2));
+ dest2P = (byte *)(destP + 4 * (width >> 2));
+ widthRemaining = width - 4 * (width >> 2);
+ memcpy(dest2P, src2P, widthRemaining);
+ destP = dest2P + widthRemaining + WinScan - width;
+ srcP = src2P + widthRemaining + nbrligne2 - width;
+ yNext = yCtr - 1;
+ } while (yCtr != 1);
+}
+
+void GraphicsManager::m_scroll2(const byte *surface, int xs, int ys, int width, int height, int destX, int destY) {
+ const byte *srcP;
+ byte *destP;
+ int destPitch;
+ int srcPitch;
+ int yCtr;
+
+ assert(VideoPtr);
+ srcP = xs + nbrligne2 * ys + surface;
+ destP = destX + WinScan * destY + (byte *)VideoPtr->pixels;
+ destPitch = WinScan - SCREEN_WIDTH;
+ srcPitch = nbrligne2 - SCREEN_WIDTH;
+ yCtr = height;
+
+ do {
+ memcpy(destP, srcP, SCREEN_WIDTH);
+ destP = destP + destPitch + SCREEN_WIDTH;
+ srcP = srcP + srcPitch + SCREEN_WIDTH;
+ --yCtr;
+ } while (yCtr);
+}
+
+void GraphicsManager::m_scroll2A(const byte *surface, int xs, int ys, int width, int height, int destX, int destY) {
+ const byte *srcP;
+ byte *destP;
+ int yCtr;
+ int xCtr;
+ byte srcByte;
+ const byte *srcCopyP;
+ byte *destCopyP;
+
+ assert(VideoPtr);
+ srcP = xs + nbrligne2 * ys + surface;
+ destP = destX + WinScan * destY + (byte *)VideoPtr->pixels;
+ yCtr = height;
+ Agr_x = 0;
+ Agr_y = 0;
+ Agr_Flag_y = 0;
+ do {
+ for (;;) {
+ destCopyP = destP;
+ srcCopyP = srcP;
+ xCtr = width;
+ Agr_x = 0;
+ do {
+ srcByte = *srcP;
+ *destP++ = *srcP++;
+ Agr_x += SDL_ECHELLE;
+ if ((unsigned int)Agr_x >= 100) {
+ Agr_x -= 100;
+ *destP++ = srcByte;
+ }
+ --xCtr;
+ } while ( xCtr );
+
+ srcP = srcCopyP;
+ destP = WinScan + destCopyP;
+ if (Agr_Flag_y)
+ break;
+
+ Agr_y += SDL_ECHELLE;
+ if ((unsigned int)Agr_y < 100)
+ break;
+
+ Agr_y -= 100;
+ Agr_Flag_y = 1;
+ }
+
+ Agr_Flag_y = 0;
+ srcP = nbrligne2 + srcCopyP;
+ --yCtr;
+ } while (yCtr);
+}
+
+/**
+ * Copies data from a 8-bit palette surface into the 16-bit screen
+ */
+void GraphicsManager::m_scroll16(const byte *surface, int xs, int ys, int width, int height, int destX, int destY) {
+ DD_Lock();
+
+ assert(VideoPtr);
+ const byte *srcP = xs + nbrligne2 * ys + surface;
+ uint16 *destP = (uint16 *)((byte *)VideoPtr->pixels + destX * 2 + WinScan * destY);
+
+ for (int yp = 0; yp < height; ++yp) {
+ // Copy over the line, using the source pixels as lookups into the pixels palette
+ const byte *lineSrcP = srcP;
+ uint16 *lineDestP = destP;
+
+ for (int xp = 0; xp < width; ++xp)
+ *lineDestP++ = *(uint16 *)&PAL_PIXELS[*lineSrcP++ * 2];
+
+ // Move to the start of the next line
+ srcP += nbrligne2;
+ destP += WinScan / 2;
+ }
+
+ DD_Unlock();
+}
+
+// TODO: See if PAL_PIXELS can be converted to a uint16 array
+void GraphicsManager::m_scroll16A(const byte *surface, int xs, int ys, int width, int height, int destX, int destY) {
+ const byte *srcP;
+ const byte *destP;
+ int yNext;
+ int xCtr;
+ const byte *palette;
+ int pixelWord;
+ int yCtr;
+ const byte *srcCopyP;
+ const byte *destCopyP;
+
+ assert(VideoPtr);
+ srcP = xs + nbrligne2 * ys + surface;
+ destP = destX + destX + WinScan * destY + (byte *)VideoPtr->pixels;
+ yNext = height;
+ Agr_x = 0;
+ Agr_y = 0;
+ Agr_Flag_y = 0;
+
+ do {
+ for (;;) {
+ destCopyP = destP;
+ srcCopyP = srcP;
+ xCtr = width;
+ yCtr = yNext;
+ palette = PAL_PIXELS;
+ Agr_x = 0;
+
+ do {
+ pixelWord = *(uint16 *)(palette + 2 * *srcP);
+ *(uint16 *)destP = pixelWord;
+ ++srcP;
+ destP += 2;
+ Agr_x += SDL_ECHELLE;
+ if ((unsigned int)Agr_x >= 100) {
+ Agr_x -= 100;
+ *(uint16 *)destP = pixelWord;
+ destP += 2;
+ }
+
+ --xCtr;
+ } while (xCtr);
+
+ yNext = yCtr;
+ srcP = srcCopyP;
+ destP = WinScan + destCopyP;
+ if (Agr_Flag_y == 1)
+ break;
+
+ Agr_y += SDL_ECHELLE;
+
+ if ((unsigned int)Agr_y < 100)
+ break;
+
+ Agr_y -= 100;
+ Agr_Flag_y = 1;
+ }
+
+ Agr_Flag_y = 0;
+ srcP = nbrligne2 + srcCopyP;
+ yNext = yCtr - 1;
+ } while (yCtr != 1);
+}
+
+void GraphicsManager::Copy_Vga(const byte *surface, int xp, int yp, int width, int height, int destX, int destY) {
+ const byte *srcP;
+ byte *destP;
+ int yCount;
+ int xCount;
+ byte srcByte;
+ byte *loopDestP;
+ byte *loopSrcP;
+ byte *loopSrc2P;
+ byte *tempDestP;
+ const byte *tempSrcP;
+ int yCtr;
+
+ assert(VideoPtr);
+ srcP = xp + 320 * yp + surface;
+ destP = 30 * WinScan + destX + destX + WinScan * 2 * destY + (byte *)VideoPtr->pixels;
+ yCount = height;
+
+ do {
+ yCtr = yCount;
+ xCount = width;
+ tempSrcP = srcP;
+ tempDestP = destP;
+ do {
+ srcByte = *srcP;
+ *destP = *srcP;
+ loopDestP = WinScan + destP;
+ *loopDestP = srcByte;
+ loopSrcP = loopDestP - WinScan + 1;
+ *loopSrcP = srcByte;
+ loopSrc2P = WinScan + loopSrcP;
+ *loopSrc2P = srcByte;
+ ++srcP;
+ destP = loopSrc2P - WinScan + 1;
+ --xCount;
+ } while (xCount);
+
+ destP = WinScan + WinScan + tempDestP;
+ srcP = tempSrcP + 320;
+ yCount = yCtr - 1;
+ } while (yCtr != 1);
+}
+
+void GraphicsManager::Copy_Vga16(const byte *surface, int xp, int yp, int width, int height, int destX, int destY) {
+ const byte *srcP;
+ uint16 *destP;
+ int yCount;
+ int xCount;
+ int xCtr;
+ const byte *palette;
+ uint16 *tempSrcP;
+ uint16 srcByte;
+ uint16 *tempDestP;
+ int savedXCount;
+ uint16 *loopDestP;
+ const byte *loopSrcP;
+ int yCtr;
+
+ assert(VideoPtr);
+ srcP = xp + 320 * yp + surface;
+ destP = (uint16 *)(30 * WinScan + destX + destX + destX + destX + WinScan * 2 * destY + (byte *)VideoPtr->pixels);
+ yCount = height;
+ xCount = width;
+
+ do {
+ yCtr = yCount;
+ xCtr = xCount;
+ loopSrcP = srcP;
+ loopDestP = destP;
+ savedXCount = xCount;
+ palette = PAL_PIXELS;
+
+ do {
+ tempSrcP = (uint16 *)(palette + 2 * *srcP);
+ srcByte = *tempSrcP;
+ *destP = *tempSrcP;
+ *(destP + 1) = srcByte;
+
+ tempDestP = (uint16 *)((byte *)destP + WinScan);
+ *tempDestP = srcByte;
+ *(tempDestP + 1) = srcByte;
+ ++srcP;
+ destP = (uint16 *)((byte *)tempDestP - WinScan + 4);
+ --xCtr;
+ } while (xCtr);
+
+ xCount = savedXCount;
+ destP = (uint16 *)((byte *)loopDestP + WinScan * 2);
+ srcP = loopSrcP + 320;
+ yCount = yCtr - 1;
+ } while (yCtr != 1);
+}
+
+void GraphicsManager::fade_in(const byte *palette, int step, const byte *surface) {
+ uint16 palData1[PALETTE_BLOCK_SIZE * 2];
+ byte palData2[PALETTE_BLOCK_SIZE];
+
+ // Initialise temporary palettes
+ Common::fill(&palData1[0], &palData1[PALETTE_BLOCK_SIZE], 0);
+ Common::fill(&palData2[0], &palData2[PALETTE_BLOCK_SIZE], 0);
+
+ // Set current palette to black
+ setpal_vga256(palData2);
+
+ // Loop through fading in the palette
+ uint16 *pTemp1 = &palData1[1];
+ for (int fadeIndex = 0; fadeIndex < FADESPD; ++fadeIndex) {
+ uint16 *pTemp2 = &palData1[2];
+
+ for (int palOffset = 0; palOffset < PALETTE_BLOCK_SIZE; palOffset += 3) {
+ if (palData2[palOffset] < palette[palOffset]) {
+ uint16 v = (palette[palOffset] & 0xff) * 256 / FADESPD;
+ palData1[palOffset] = v;
+ palData2[palOffset] = (v >> 8) & 0xff;
+ }
+
+ if (palData2[palOffset + 1] < palette[palOffset + 1]) {
+ uint16 *pDest = &pTemp1[palOffset];
+ uint16 v = (palette[palOffset] & 0xff) * 256 / FADESPD + *pDest;
+ *pDest = v;
+ palData2[palOffset + 1] = (v >> 8) & 0xff;
+ }
+
+ if (palData2[palOffset + 2] < palette[palOffset + 2]) {
+ uint16 *pDest = &pTemp2[palOffset];
+ uint16 v = (palette[palOffset] & 0xff) * 256 / FADESPD + *pDest;
+ *pDest = v;
+ palData2[palOffset + 2] = (v >> 8) & 0xff;
+ }
+ }
+
+ setpal_vga256(palData2);
+ if (Winbpp == 2) {
+ if (SDL_ECHELLE)
+ m_scroll16A(surface, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ else
+ m_scroll16(surface, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ DD_VBL();
+ }
+ }
+
+ // Set the final palette
+ setpal_vga256(palette);
+
+ // Refresh the screen
+ if (Winbpp == 2) {
+ if (SDL_ECHELLE)
+ m_scroll16A(surface, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ else
+ m_scroll16(surface, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ DD_VBL();
+ }
+}
+
+void GraphicsManager::fade_out(const byte *palette, int step, const byte *surface) {
+ int palByte;
+ int palIndex;
+ int palDataIndex;
+ int palCtr3;
+ int palCtr4;
+ int palCtr5;
+ int palValue;
+ int palCtr2;
+ int palCtr1;
+ uint16 palMax;
+ byte palData[PALETTE_BLOCK_SIZE];
+ int tempPalette[PALETTE_BLOCK_SIZE];
+
+ palMax = palByte = FADESPD;
+ if (palette) {
+ palIndex = 0;
+ do {
+ palDataIndex = palIndex;
+ palByte = *(palIndex + palette);
+ palByte <<= 8;
+ tempPalette[palDataIndex] = palByte;
+ palData[palDataIndex] = *(palIndex++ + palette);
+ } while (palIndex < PALETTE_BLOCK_SIZE);
+
+ setpal_vga256(palData);
+ if (Winbpp == 2) {
+ if (SDL_ECHELLE)
+ m_scroll16A(surface, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ else
+ m_scroll16(surface, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ DD_VBL();
+ }
+
+ palCtr3 = 0;
+ if (palMax > 0) {
+ do {
+ palCtr4 = 0;
+ do {
+ palCtr5 = palCtr4;
+ palValue = tempPalette[palCtr4] - (*(palCtr4 + palette) << 8) / palMax;
+ tempPalette[palCtr5] = palValue;
+ palData[palCtr5] = (palValue >> 8) & 0xff;
+ ++palCtr4;
+ } while (palCtr4 < (PALETTE_BLOCK_SIZE));
+
+ setpal_vga256(palData);
+ if (Winbpp == 2) {
+ if (SDL_ECHELLE)
+ m_scroll16A(surface, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ else
+ m_scroll16(surface, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+
+ DD_VBL();
+ }
+ ++palCtr3;
+ } while (palMax > palCtr3);
+ }
+
+ palCtr2 = 0;
+ do {
+ palData[palCtr2++] = 0;
+ } while (palCtr2 < (PALETTE_BLOCK_SIZE));
+
+ setpal_vga256(palData);
+
+ if (Winbpp == 2) {
+ if (!SDL_ECHELLE) {
+ m_scroll16(surface, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ return DD_VBL();
+ }
+ goto LABEL_28;
+ }
+ } else {
+ palCtr1 = 0;
+ do {
+ palData[palCtr1++] = 0;
+ } while (palCtr1 < (PALETTE_BLOCK_SIZE));
+
+ setpal_vga256(palData);
+ if (Winbpp == 2) {
+ if (!SDL_ECHELLE) {
+ m_scroll16(surface, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ return DD_VBL();
+ }
+
+LABEL_28:
+ m_scroll16A(surface, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ return DD_VBL();
+ }
+ }
+}
+
+void GraphicsManager::FADE_INS() {
+ FADESPD = 1;
+ fade_in(Palette, 1, (const byte *)VESA_BUFFER);
+}
+
+void GraphicsManager::FADE_OUTS() {
+ FADESPD = 1;
+ fade_out(Palette, 1, (const byte *)VESA_BUFFER);
+}
+
+void GraphicsManager::FADE_INW() {
+ FADESPD = 15;
+ fade_in(Palette, 20, (const byte *)VESA_BUFFER);
+}
+
+void GraphicsManager::FADE_OUTW() {
+ FADESPD = 15;
+ fade_out(Palette, 20, (const byte *)VESA_BUFFER);
+}
+
+void GraphicsManager::setpal_vga256(const byte *palette) {
+ CHANGE_PALETTE(palette);
+}
+
+void GraphicsManager::setpal_vga256_linux(const byte *palette, const byte *surface) {
+ CHANGE_PALETTE(palette);
+
+ if (Winbpp == 2) {
+ if (SDL_ECHELLE)
+ m_scroll16A(surface, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ else
+ m_scroll16(surface, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+
+ DD_VBL();
+ }
+}
+
+void GraphicsManager::SETCOLOR(int palIndex, int r, int g, int b) {
+ _vm->_graphicsManager.Palette[palIndex * 3] = 255 * r / 100;
+ _vm->_graphicsManager.Palette[palIndex * 3 + 1] = 255 * g / 100;
+ _vm->_graphicsManager.Palette[palIndex * 3 + 2] = 255 * b / 100;
+
+ setpal_vga256(Palette);
+}
+
+void GraphicsManager::SETCOLOR2(int palIndex, int r, int g, int b) {
+ return SETCOLOR(palIndex, r, g, b);
+}
+
+void GraphicsManager::SETCOLOR3(int palIndex, int r, int g, int b) {
+ Palette[palIndex * 3] = 255 * r / 100;
+ Palette[palIndex * 3 + 1] = 255 * g / 100;
+ Palette[palIndex * 3 + 2] = 255 * b / 100;
+}
+
+void GraphicsManager::SETCOLOR4(int palIndex, int r, int g, int b) {
+ int rv, gv, bv;
+ int palOffset;
+ int v8;
+
+ rv = 255 * r / 100;
+ gv = 255 * g / 100;
+ bv = 255 * b / 100;
+ palOffset = 3 * palIndex;
+ Palette[palOffset] = 255 * r / 100;
+ Palette[palOffset + 1] = gv;
+ Palette[palOffset + 2] = bv;
+
+ v8 = 4 * palIndex;
+ cmap[v8] = rv;
+ cmap[v8 + 1] = gv;
+ cmap[v8 + 2] = bv;
+
+ WRITE_LE_UINT16(&SD_PIXELS[2 * palIndex], MapRGB(rv, gv, bv));
+
+ if (Winbpp == 1)
+ g_system->getPaletteManager()->setPalette(cmap, palIndex, 1);
+}
+
+void GraphicsManager::CHANGE_PALETTE(const byte *palette) {
+ // Copy the palette into the PALPCX block
+// TODO: Likely either one or both of the destination arrays can be removed,
+// since PALPCX is only used in SAVE_IMAGE, and cmap in the original was a RGBA
+// array specifically intended just for passing to the SDL palette setter
+ Common::copy(&palette[0], &palette[PALETTE_BLOCK_SIZE], &PALPCX[0]);
+ Common::copy(&palette[0], &palette[PALETTE_BLOCK_SIZE], &cmap[0]);
+
+ const byte *srcP = &palette[0];
+ for (int idx = 0; idx < PALETTE_SIZE; ++idx, srcP += 3) {
+ *(uint16 *)&SD_PIXELS[2 * idx] = MapRGB(*srcP, *(srcP + 1), *(srcP + 2));
+ }
+
+ if (Winbpp == 1)
+ g_system->getPaletteManager()->setPalette(cmap, 0, PALETTE_SIZE);
+}
+
+uint16 GraphicsManager::MapRGB(byte r, byte g, byte b) {
+ if (Winbpp == 1) {
+ error("TODO: Support in 8-bit graphics mode");
+ } else {
+ Graphics::PixelFormat format = g_system->getScreenFormat();
+
+ return (r >> format.rLoss) << format.rShift
+ | (g >> format.gLoss) << format.gShift
+ | (b >> format.bLoss) << format.bShift;
+ }
+}
+
+void GraphicsManager::DD_VBL() {
+ // TODO: Is this okay here?
+ g_system->updateScreen();
+}
+
+void GraphicsManager::FADE_OUTW_LINUX(const byte *surface) {
+ assert(surface);
+ fade_out(Palette, FADESPD, surface);
+}
+
+void GraphicsManager::FADE_INW_LINUX(const byte *surface) {
+ assert(surface);
+ fade_in(Palette, FADESPD, surface);
+}
+
+void GraphicsManager::Copy_WinScan_Vbe3(const byte *srcData, byte *destSurface) {
+ int rleValue;
+ int destOffset;
+ const byte *srcP;
+ byte srcByte;
+ byte destLen1;
+ byte *destSlice1P;
+ byte destLen2;
+ byte *destSlice2P;
+
+ rleValue = 0;
+ destOffset = 0;
+ srcP = srcData;
+ for (;;) {
+ srcByte = *srcP;
+ if (*srcP < 0xDEu)
+ goto Video_Cont3_wVbe;
+ if (srcByte == (byte)-4)
+ return;
+
+ if (srcByte < 0xFBu) {
+ destOffset += (byte)(*srcP + 35);
+ srcByte = *(srcP++ + 1);
+ } else if (srcByte == (byte)-3) {
+ destOffset += *(srcP + 1);
+ srcByte = *(srcP + 2);
+ srcP += 2;
+ } else if (srcByte == (byte)-2) {
+ destOffset += READ_LE_UINT16(srcP + 1);
+ srcByte = *(srcP + 3);
+ srcP += 3;
+ } else {
+ destOffset += READ_LE_UINT32(srcP + 1);
+ srcByte = *(srcP + 5);
+ srcP += 5;
+ }
+Video_Cont3_wVbe:
+ if (srcByte > 0xD2u) {
+ if (srcByte == (byte)-45) {
+ destLen1 = *(srcP + 1);
+ rleValue = *(srcP + 2);
+ destSlice1P = destOffset + destSurface;
+ destOffset += destLen1;
+ memset(destSlice1P, rleValue, destLen1);
+ srcP += 3;
+ } else {
+ destLen2 = (byte)(*srcP + 45);
+ rleValue = *(srcP + 1);
+ destSlice2P = destOffset + destSurface;
+ destOffset += destLen2;
+ memset(destSlice2P, rleValue, destLen2);
+ srcP += 2;
+ }
+ } else {
+ *(destOffset + destSurface) = srcByte;
+ ++srcP;
+ ++destOffset;
+ }
+ }}
+
+void GraphicsManager::Copy_Video_Vbe3(const byte *srcData) {
+ int rleValue;
+ int destOffset;
+ const byte *srcP;
+ uint8 srcByte;
+ int destLen1;
+ byte *destSlice1P;
+ int destLen2;
+ byte *destSlice2P;
+
+ assert(VideoPtr);
+ rleValue = 0;
+ destOffset = 0;
+ srcP = srcData;
+ for (;;) {
+ srcByte = *srcP;
+ if (*srcP < 222)
+ goto Video_Cont3_Vbe;
+
+ if (srcByte == 252)
+ return;
+ if (srcByte < 251) {
+ destOffset += *srcP + 35;
+ srcByte = *(srcP++ + 1);
+ } else if (srcByte == (byte)-3) {
+ destOffset += *(srcP + 1);
+ srcByte = *(srcP + 2);
+ srcP += 2;
+ } else if (srcByte == (byte)-2) {
+ destOffset += READ_LE_UINT16(srcP + 1);
+ srcByte = *(srcP + 3);
+ srcP += 3;
+ } else {
+ destOffset += READ_LE_UINT32(srcP + 1);
+ srcByte = *(srcP + 5);
+ srcP += 5;
+ }
+Video_Cont3_Vbe:
+ if (srcByte > 210) {
+ if (srcByte == 211) {
+ destLen1 = *(srcP + 1);
+ rleValue = *(srcP + 2);
+ destSlice1P = destOffset + (byte *)VideoPtr->pixels;
+ destOffset += destLen1;
+ memset(destSlice1P, rleValue, destLen1);
+ srcP += 3;
+ } else {
+ destLen2 = (byte)(*srcP + 45);
+ rleValue = *(srcP + 1);
+ destSlice2P = (byte *)(destOffset + (byte *)VideoPtr->pixels);
+ destOffset += destLen2;
+ memset(destSlice2P, rleValue, destLen2);
+ srcP += 2;
+ }
+ } else {
+ *(destOffset + (byte *)VideoPtr->pixels) = srcByte;
+ ++srcP;
+ ++destOffset;
+ }
+ }
+}
+
+void GraphicsManager::Copy_Video_Vbe16(const byte *srcData) {
+ const byte *srcP = srcData;
+ int destOffset = 0;
+ assert(VideoPtr);
+
+ for (;;) {
+ byte srcByte = *srcP;
+ if (srcByte >= 222) {
+ if (srcByte == 252)
+ return;
+ if (srcByte < 251) {
+ destOffset += srcByte - 221;
+ srcByte = *++srcP;
+ } else if (srcByte == 253) {
+ destOffset += *(const byte *)(srcP + 1);
+ srcByte = *(const byte *)(srcP + 2);
+ srcP += 2;
+ } else if (srcByte == 254) {
+ destOffset += READ_LE_UINT16(srcP + 1);
+ srcByte = *(const byte *)(srcP + 3);
+ srcP += 3;
+ } else {
+ destOffset += READ_LE_UINT32(srcP + 1);
+ srcByte = *(const byte *)(srcP + 5);
+ srcP += 5;
+ }
+ }
+
+ if (srcByte > 210) {
+ if (srcByte == 211) {
+ int pixelCount = *(srcP + 1);
+ int pixelIndex = *(srcP + 2);
+ uint16 *destP = (uint16 *)((byte *)VideoPtr->pixels + destOffset * 2);
+ uint16 pixelValue = *(uint16 *)(PAL_PIXELS + 2 * pixelIndex);
+ destOffset += pixelCount;
+
+ while (pixelCount--)
+ *destP++ = pixelValue;
+
+ srcP += 3;
+ } else {
+ int pixelCount = srcByte - 211;
+ int pixelIndex = *(srcP + 1);
+ uint16 *destP = (uint16 *)((byte *)VideoPtr->pixels + destOffset * 2);
+ uint16 pixelValue = *(uint16 *)(PAL_PIXELS + 2 * pixelIndex);
+ destOffset += pixelCount;
+
+ while (pixelCount--)
+ *destP++ = pixelValue;
+
+ srcP += 2;
+ }
+ } else {
+ *((uint16 *)VideoPtr->pixels + destOffset) = *(uint16 *)(PAL_PIXELS + 2 * srcByte);
+ ++srcP;
+ ++destOffset;
+ }
+ }
+}
+
+void GraphicsManager::Copy_Video_Vbe16a(const byte *srcData) {
+ int destOffset;
+ const byte *srcP;
+ byte pixelIndex;
+
+ destOffset = 0;
+ srcP = srcData;
+ for (;;) {
+ pixelIndex = *srcP;
+ if (*srcP < 0xFCu)
+ goto Video_Cont_Vbe16a;
+ if (pixelIndex == (byte)-4)
+ return;
+ if (pixelIndex == (byte)-3) {
+ destOffset += *(srcP + 1);
+ pixelIndex = *(srcP + 2);
+ srcP += 2;
+ } else if (pixelIndex == (byte)-2) {
+ destOffset += READ_LE_UINT16(srcP + 1);
+ pixelIndex = *(srcP + 3);
+ srcP += 3;
+ } else {
+ destOffset += READ_LE_UINT32(srcP + 1);
+ pixelIndex = *(srcP + 5);
+ srcP += 5;
+ }
+Video_Cont_Vbe16a:
+ WRITE_LE_UINT16((byte *)VideoPtr->pixels + destOffset * 2, READ_LE_UINT16(PAL_PIXELS + 2 * pixelIndex));
+ ++srcP;
+ ++destOffset;
+ }
+}
+
+void GraphicsManager::Capture_Mem(const byte *srcSurface, byte *destSurface, int xs, int ys, int width, int height) {
+ const byte *srcP;
+ byte *destP;
+ int rowCount;
+ int i;
+ int rowCount2;
+
+ // TODO: This code in the original is potentially dangerous, as it doesn't clip the area to within
+ // the screen, and so thus can read areas outside of the allocated surface buffer
+ srcP = xs + nbrligne2 * ys + srcSurface;
+ destP = destSurface;
+ rowCount = height;
+ do {
+ rowCount2 = rowCount;
+ if (width & 1) {
+ memcpy(destP, srcP, width);
+ srcP += width;
+ destP += width;
+ } else if (width & 2) {
+ for (i = width >> 1; i; --i) {
+ *(uint16 *)destP = *(uint16 *)srcP;
+ srcP += 2;
+ destP += 2;
+ }
+ } else {
+ memcpy(destP, srcP, 4 * (width >> 2));
+ srcP += 4 * (width >> 2);
+ destP += 4 * (width >> 2);
+ }
+ srcP = nbrligne2 + srcP - width;
+ rowCount = rowCount2 - 1;
+ } while (rowCount2 != 1);
+}
+
+void GraphicsManager::Sprite_Vesa(byte *surface, const byte *spriteData, int xp, int yp, int spriteIndex) {
+ // Get a pointer to the start of the desired sprite
+ const byte *spriteP = spriteData + 3;
+ for (int i = spriteIndex; i; --i)
+ spriteP += READ_LE_UINT32(spriteP) + 16;
+
+ clip_x = 0;
+ clip_y = 0;
+ clip_flag = false;
+
+ spriteP += 4;
+ int width = READ_LE_UINT16(spriteP);
+ spriteP += 2;
+ int height = READ_LE_UINT16(spriteP);
+
+ // Clip X
+ clip_x1 = width;
+ if ((xp + width) <= (min_x + 300))
+ return;
+ if (xp < (min_x + 300)) {
+ clip_x = min_x + 300 - xp;
+ clip_flag = true;
+ }
+
+ // Clip Y
+ // TODO: This is weird, but it's that way in the original. Original game bug?
+ if ((yp + height) <= height)
+ return;
+ if (yp < (min_y + 300)) {
+ clip_y = min_y + 300 - yp;
+ clip_flag = true;
+ }
+
+ // Clip X1
+ if (xp >= (max_x + 300))
+ return;
+ if ((xp + width) > (max_x + 300)) {
+ int xAmount = width + 10 - (xp + width - (max_x + 300));
+ if (xAmount <= 10)
+ return;
+
+ clip_x1 = xAmount - 10;
+ clip_flag = true;
+ }
+
+ // Clip Y1
+ if (yp >= (max_y + 300))
+ return;
+ if ((yp + height) > (max_y + 300)) {
+ int yAmount = height + 10 - (yp + height - (max_y + 300));
+ if (yAmount <= 10)
+ return;
+
+ clip_y1 = yAmount - 10;
+ clip_flag = true;
+ }
+
+ // Sprite display
+
+ // Set up source
+ spriteP += 6;
+ int srcOffset = READ_LE_UINT16(spriteP);
+ spriteP += 4;
+ const byte *srcP = spriteP;
+ spriteP += srcOffset;
+
+ // Set up surface destination
+ byte *destP = surface + (yp - 300) * nbrligne2 + (xp - 300);
+
+ // Handling for clipped versus non-clipped
+ if (clip_flag) {
+ // Clipped version
+ for (int yc = 0; yc < height; ++yc, destP += nbrligne2) {
+ byte *tempDestP = destP;
+ byte byteVal;
+ int xc = 0;
+
+ while ((byteVal = *srcP) != 253) {
+ ++srcP;
+ width = READ_LE_UINT16(srcP);
+ srcP += 2;
+
+ if (byteVal == 254) {
+ // Copy pixel range
+ for (int xv = 0; xv < width; ++xv, ++xc, ++spriteP, ++tempDestP) {
+ if (clip_y == 0 && xc >= clip_x && xc < clip_x1)
+ *tempDestP = *spriteP;
+ }
+ } else {
+ // Skip over bytes
+ tempDestP += width;
+ xc += width;
+ }
+ }
+
+ if (clip_y > 0)
+ --clip_y;
+ srcP += 3;
+ }
+ } else {
+ // Non-clipped
+ for (int yc = 0; yc < height; ++yc, destP += nbrligne2) {
+ byte *tempDestP = destP;
+ byte byteVal;
+
+ while ((byteVal = *srcP) != 253) {
+ ++srcP;
+ width = READ_LE_UINT16(srcP);
+ srcP += 2;
+
+ if (byteVal == 254) {
+ // Copy pixel range
+ Common::copy(spriteP, spriteP + width, tempDestP);
+ spriteP += width;
+ }
+
+ tempDestP += width;
+ }
+
+ // Skip over control byte and width
+ srcP += 3;
+ }
+ }
+}
+
+void GraphicsManager::FIN_VISU() {
+ for (int idx = 1; idx <= 20; ++idx) {
+ if (_vm->_globals.Bqe_Anim[idx].field4 == 1)
+ _vm->_objectsManager.BOB_OFF(idx);
+ }
+
+ _vm->_eventsManager.VBL();
+ _vm->_eventsManager.VBL();
+
+ for (int idx = 1; idx <= 20; ++idx) {
+ if (_vm->_globals.Bqe_Anim[idx].field4 == 1)
+ _vm->_objectsManager.BOB_ZERO(idx);
+ }
+
+ for (int idx = 1; idx <= 29; ++idx) {
+ _vm->_globals.BL_ANIM[idx].v1 = 0;
+ }
+
+ for (int idx = 1; idx <= 20; ++idx) {
+ _vm->_globals.Bqe_Anim[idx].field4 = 0;
+ }
+}
+
+void GraphicsManager::VISU_ALL() {
+ for (int idx = 1; idx <= 20; ++idx) {
+ if (_vm->_globals.Bqe_Anim[idx].field4 == 1)
+ _vm->_objectsManager.BOB_VISU(idx);
+ }
+}
+
+void GraphicsManager::RESET_SEGMENT_VESA() {
+ int idx;
+ int blocCount;
+
+ if (_vm->_globals.NBBLOC > 0) {
+ idx = 0;
+ blocCount = _vm->_globals.NBBLOC;
+ do {
+ _vm->_globals.BLOC[idx++].field0 = 0;
+ } while (idx != blocCount);
+
+ _vm->_globals.NBBLOC = 0;
+ }
+}
+
+// Add VESA Segment
+void GraphicsManager::Ajoute_Segment_Vesa(int x1, int y1, int x2, int y2) {
+ int tempX;
+ int blocCount;
+ int16 blocIndex;
+ bool addFlag;
+
+ tempX = x1;
+ addFlag = true;
+ if (x2 > max_x)
+ x2 = max_x;
+ if (y2 > max_y)
+ y2 = max_y;
+ if (x1 < min_x)
+ tempX = min_x;
+ if (y1 < min_y)
+ y1 = min_y;
+
+ blocCount = _vm->_globals.NBBLOC;
+ if (_vm->_globals.NBBLOC > 1) {
+
+ blocIndex = 0;
+ do {
+ BlocItem &bloc = _vm->_globals.BLOC[blocIndex];
+
+ if (bloc.field0 == 1
+ && tempX >= bloc.x1 && x2 <= bloc.x2
+ && y1 >= bloc.y1 && y2 <= bloc.y2)
+ addFlag = false;
+ ++blocIndex;
+ blocCount = blocIndex;
+ } while (_vm->_globals.NBBLOC + 1 != blocIndex);
+ }
+
+ if (addFlag) {
+ assert(_vm->_globals.NBBLOC < 50);
+ BlocItem &bloc = _vm->_globals.BLOC[++_vm->_globals.NBBLOC];
+
+ bloc.field0 = 1;
+ bloc.x1 = tempX;
+ bloc.x2 = x2;
+ bloc.y1 = y1;
+ bloc.y2 = y2;
+ }
+}
+
+int GraphicsManager::Magic_Number(signed int v) {
+ int result = v;
+
+ if (!v)
+ result = 4;
+ if (result & 1)
+ ++result;
+ if (result & 2)
+ result += 2;
+
+ return result;
+}
+
+// Display VESA Segment
+void GraphicsManager::Affiche_Segment_Vesa() {
+ if (_vm->_globals.NBBLOC == 0)
+ return;
+
+ SDL_NBLOCS = _vm->_globals.NBBLOC;
+ DD_Lock();
+
+ for (int idx = 1; idx <= _vm->_globals.NBBLOC; ++idx) {
+ BlocItem &bloc = _vm->_globals.BLOC[idx];
+ Common::Rect &dstRect = dstrect[idx - 1];
+ if (bloc.field0 != 1)
+ continue;
+
+ if (_vm->_eventsManager.CASSE != false) {
+ if (Winbpp == 1) {
+ Copy_Vga(VESA_BUFFER, bloc.x1, bloc.y1, bloc.x2 - bloc.x1, bloc.y2 - bloc.y1, bloc.x1, bloc.y1);
+ } else if (Winbpp == 2) {
+ Copy_Vga16(VESA_BUFFER, bloc.x1, bloc.y1, bloc.x2 - bloc.x1, bloc.y2 - bloc.y1, bloc.x1, bloc.y1);
+ }
+
+ dstRect.left = bloc.x1 * 2;
+ dstRect.top = bloc.y1 * 2 + 30;
+ dstRect.setWidth((bloc.x2 - bloc.x1) * 2);
+ dstRect.setHeight((bloc.y2 - bloc.y1) * 2);
+ } else if (bloc.x2 > _vm->_eventsManager.start_x && bloc.x1 < (_vm->_eventsManager.start_x + SCREEN_WIDTH)) {
+ if (bloc.x1 < _vm->_eventsManager.start_x)
+ bloc.x1 = _vm->_eventsManager.start_x;
+ if (bloc.x2 > (_vm->_eventsManager.start_x + SCREEN_WIDTH))
+ bloc.x2 = _vm->_eventsManager.start_x + SCREEN_WIDTH;
+
+ if (SDL_ECHELLE) {
+ // Calculate the bounds
+ int xp = Magic_Number(bloc.x1) - 4;
+ if (xp < _vm->_eventsManager.start_x)
+ xp = _vm->_eventsManager.start_x;
+ int yp = Magic_Number(bloc.y1) - 4;
+ if (yp < 0)
+ yp = 0;
+ int width = Magic_Number(bloc.x2) + 4 - xp;
+ if (width < 4)
+ width = 4;
+ int height = Magic_Number(bloc.y2) + 4 - yp;
+ if (height < 4)
+ height = 4;
+
+ if ((xp - _vm->_eventsManager.start_x + width) > SCREEN_WIDTH)
+ xp -= 4;
+ if ((height - yp) > (SCREEN_HEIGHT - 40))
+ yp -= 4;
+
+ // WORKAROUND: Original didn't lock the screen for access
+ DD_Lock();
+
+ if (Winbpp == 2) {
+ m_scroll16A(VESA_BUFFER, xp, yp, width, height,
+ Reel_Zoom(xp - _vm->_eventsManager.start_x, SDL_ECHELLE), Reel_Zoom(yp, SDL_ECHELLE));
+ } else {
+ m_scroll2A(VESA_BUFFER, xp, yp, width, height,
+ Reel_Zoom(xp - _vm->_eventsManager.start_x, SDL_ECHELLE), Reel_Zoom(yp, SDL_ECHELLE));
+ }
+
+ DD_Unlock();
+
+ dstRect.left = Reel_Zoom(xp - _vm->_eventsManager.start_x, SDL_ECHELLE);
+ dstRect.top = Reel_Zoom(yp, SDL_ECHELLE);
+ dstRect.setWidth(Reel_Zoom(width, SDL_ECHELLE));
+ dstRect.setHeight(Reel_Zoom(height, SDL_ECHELLE));
+ } else {
+ // WORKAROUND: Original didn't lock the screen for access
+ DD_Lock();
+
+ if (Winbpp == 2) {
+ m_scroll16(VESA_BUFFER, bloc.x1, bloc.y1, bloc.x2 - bloc.x1, bloc.y2 - bloc.y1,
+ bloc.x1 - _vm->_eventsManager.start_x, bloc.y1);
+ } else {
+ m_scroll(VESA_BUFFER, bloc.x1, bloc.y1, bloc.x2 - bloc.x1, bloc.y2 - bloc.y1,
+ bloc.x1 - _vm->_eventsManager.start_x, bloc.y1);
+ }
+
+ dstRect.left = bloc.x1 - _vm->_eventsManager.start_x;
+ dstRect.top = bloc.y1;
+ dstRect.setWidth(bloc.x2 - bloc.x1);
+ dstRect.setHeight(bloc.y2 - bloc.y1);
+
+ DD_Unlock();
+ }
+ }
+
+ _vm->_globals.BLOC[idx].field0 = 0;
+ }
+
+ _vm->_globals.NBBLOC = 0;
+ DD_Unlock();
+ if (!_vm->_globals.BPP_NOAFF) {
+// SDL_UpdateRects(LinuxScr, SDL_NBLOCS, dstrect);
+ }
+ SDL_NBLOCS = 0;
+}
+
+void GraphicsManager::CopyAsm(const byte *surface) {
+ const byte *srcP;
+ byte srcByte;
+ byte *destP;
+ int yCtr;
+ int xCtr;
+ byte *dest1P;
+ byte *dest2P;
+ byte *dest3P;
+ byte *destPitch;
+ const byte *srcPitch;
+
+ assert(VideoPtr);
+ srcP = surface;
+ srcByte = 30 * WinScan;
+ destP = (byte *)VideoPtr->pixels + 30 * WinScan;
+ yCtr = 200;
+ do {
+ srcPitch = srcP;
+ destPitch = destP;
+ xCtr = 320;
+
+ do {
+ srcByte = *srcP;
+ *destP = *srcP;
+ dest1P = WinScan + destP;
+ *dest1P = srcByte;
+ dest2P = dest1P - WinScan + 1;
+ *dest2P = srcByte;
+ dest3P = WinScan + dest2P;
+ *dest3P = srcByte;
+ destP = dest3P - WinScan + 1;
+ ++srcP;
+ --xCtr;
+ } while (xCtr);
+
+ srcP = srcPitch + 320;
+ destP = WinScan + WinScan + destPitch;
+ --yCtr;
+ } while (yCtr);
+}
+
+void GraphicsManager::Restore_Mem(byte *destSurface, const byte *src, int xp, int yp, int width, int height) {
+ byte *destP;
+ int yNext;
+ const byte *srcP;
+ int i;
+ int yCtr;
+
+ destP = xp + nbrligne2 * yp + destSurface;
+ yNext = height;
+ srcP = src;
+ do {
+ yCtr = yNext;
+ if (width & 1) {
+ memcpy(destP, srcP, width);
+ srcP += width;
+ destP += width;
+ } else if (width & 2) {
+ for (i = width >> 1; i; --i) {
+ *(uint16 *)destP = *(uint16 *)srcP;
+ srcP += 2;
+ destP += 2;
+ }
+ } else {
+ memcpy(destP, srcP, 4 * (width >> 2));
+ srcP += 4 * (width >> 2);
+ destP += 4 * (width >> 2);
+ }
+ destP = nbrligne2 + destP - width;
+ yNext = yCtr - 1;
+ } while (yCtr != 1);
+}
+
+int GraphicsManager::Reel_Zoom(int v, int percentage) {
+ return Asm_Zoom(v, percentage);
+}
+
+int GraphicsManager::Asm_Zoom(int v, int percentage) {
+ if (v)
+ v += percentage * (long int)v / 100;
+
+ return v;
+}
+
+int GraphicsManager::Reel_Reduc(int v, int percentage) {
+ return Asm_Reduc(v, percentage);
+}
+
+int GraphicsManager::Asm_Reduc(int v, int percentage) {
+ if (v)
+ v -= percentage * (long int)v / 100;
+
+ return v;
+}
+
+// Display 'Perfect?'
+void GraphicsManager::Affiche_Perfect(byte *surface, const byte *srcData, int xp300, int yp300, int frameIndex, int a6, int a7, int a8) {
+ const byte *spriteStartP;
+ int i;
+ const byte *spriteSizeP;
+ int spriteWidth;
+ int spriteHeight1;
+ const byte *spritePixelsP;
+ byte *dest1P;
+ int xCtr1;
+ byte *dest2P;
+ int xLeft;
+ int clippedWidth;
+ int xCtr2;
+ int v20;
+ int v21 = 0;
+ int v22;
+ int v23;
+ int v24;
+ int v25;
+ int v26;
+ int v27;
+ int v28;
+ byte *v29;
+ int v30;
+ int v31;
+ int v32;
+ int v33;
+ int v34;
+ int v35;
+ int spriteHeight2;
+ int v37;
+ int v38;
+ uint16 v39;
+ byte *v40;
+ int v41;
+ uint16 v42;
+ const byte *spritePixelsCopyP;
+ const byte *spritePixelsCopy2P;
+ const byte *v45;
+ const byte *v46;
+ byte *dest1CopyP;
+ byte *destCopy2P;
+ int v49;
+ int v50;
+ byte *v51;
+ int v52;
+ byte *v53;
+ byte *v54;
+ byte *v55;
+ int yCtr1;
+ int yCtr2;
+ int v58;
+ int v59;
+ int v60;
+ int v61;
+ int v62;
+ int v63;
+ int v64;
+ int v65;
+
+ spriteStartP = srcData + 3;
+ for (i = frameIndex; i; --i)
+ spriteStartP += READ_LE_UINT32(spriteStartP) + 16;
+
+ spriteWidth = 0;
+ spriteHeight1 = 0;
+ spriteSizeP = spriteStartP + 4;
+ spriteWidth = (int16)READ_LE_UINT16(spriteSizeP);
+ spriteSizeP += 2;
+ spriteHeight1 = spriteHeight2 = (int16)READ_LE_UINT16(spriteSizeP);
+ spritePixelsP = spriteSizeP + 10;
+ clip_x = 0;
+ clip_y = 0;
+ clip_x1 = 0;
+ clip_y1 = 0;
+ if ((uint16)xp300 > min_x) {
+ if ((uint16)xp300 < (uint16)(min_x + 300))
+ clip_x = min_x + 300 - xp300;
+ if ((uint16)yp300 > min_y) {
+ if ((uint16)yp300 < (uint16)(min_y + 300))
+ clip_y = min_y + 300 - yp300;
+ if ((uint16)xp300 < (uint16)(max_x + 300)) {
+ clip_x1 = max_x + 300 - xp300;
+ if ((uint16)yp300 < (uint16)(max_y + 300)) {
+ clip_y1 = max_y + 300 - yp300;
+ dest1P = xp300 + nbrligne2 * (yp300 - 300) - 300 + surface;
+ if (a7) {
+ Compteur_y = 0;
+ Agr_x = 0;
+ Agr_y = 0;
+ Agr_Flag_y = 0;
+ Agr_Flag_x = 0;
+ Largeur = spriteWidth;
+ v20 = Asm_Zoom(spriteWidth, a7);
+ v22 = Asm_Zoom(v21, a7);
+ if (a8) {
+ v29 = v20 + dest1P;
+ if (clip_y) {
+ if ((uint16)clip_y >= v22)
+ return;
+ v61 = v22;
+ v52 = v20;
+ v30 = 0;
+ v31 = (uint16)clip_y;
+ while (Asm_Zoom(v30 + 1, a7) < v31)
+ ;
+ v20 = v52;
+ spritePixelsP += Largeur * v30;
+ v29 += nbrligne2 * (uint16)clip_y;
+ v22 = v61 - (uint16)clip_y;
+ }
+ if (v22 > (uint16)clip_y1)
+ v22 = (uint16)clip_y1;
+ if (clip_x) {
+ if ((uint16)clip_x >= v20)
+ return;
+ v20 -= (uint16)clip_x;
+ }
+ if (v20 > (uint16)clip_x1) {
+ v32 = v20 - (uint16)clip_x1;
+ v29 -= v32;
+ v62 = v22;
+ v33 = 0;
+ while (Asm_Zoom(v33 + 1, a7) < v32)
+ ;
+ v34 = v33;
+ v22 = v62;
+ spritePixelsP += v34;
+ v20 = (uint16)clip_x1;
+ }
+ do {
+ while (1) {
+ v63 = v22;
+ v53 = v29;
+ v46 = spritePixelsP;
+ Agr_Flag_x = 0;
+ Agr_x = 0;
+ v35 = v20;
+ do {
+ while (1) {
+ if (*spritePixelsP)
+ *v29 = *spritePixelsP;
+ --v29;
+ ++spritePixelsP;
+ if (!Agr_Flag_x)
+ Agr_x = a7 + Agr_x;
+ if ((uint16)Agr_x < 0x64u)
+ break;
+ Agr_x = Agr_x - 100;
+ --spritePixelsP;
+ Agr_Flag_x = 1;
+ --v35;
+ if (!v35)
+ goto R_Aff_Zoom_Larg_Cont1;
+ }
+ Agr_Flag_x = 0;
+ --v35;
+ } while (v35);
+R_Aff_Zoom_Larg_Cont1:
+ spritePixelsP = Largeur + v46;
+ v29 = nbrligne2 + v53;
+ ++Compteur_y;
+ if (!Agr_Flag_y)
+ Agr_y = a7 + Agr_y;
+ if ((uint16)Agr_y < 0x64u)
+ break;
+ Agr_y = Agr_y - 100;
+ spritePixelsP = v46;
+ Agr_Flag_y = 1;
+ v22 = v63 - 1;
+ if (v63 == 1)
+ return;
+ }
+ Agr_Flag_y = 0;
+ v22 = v63 - 1;
+ } while (v63 != 1);
+ } else {
+ if (clip_y) {
+ if ((uint16)clip_y >= v22)
+ return;
+ v58 = v22;
+ v49 = v20;
+ v23 = 0;
+ v24 = (uint16)clip_y;
+ while (Asm_Zoom(v23 + 1, a7) < v24)
+ ;
+ v20 = v49;
+ spritePixelsP += Largeur * v23;
+ dest1P += nbrligne2 * (uint16)clip_y;
+ v22 = v58 - (uint16)clip_y;
+ }
+ if (v22 > (uint16)clip_y1)
+ v22 = (uint16)clip_y1;
+ if (clip_x) {
+ if ((uint16)clip_x >= v20)
+ return;
+ v59 = v22;
+ v50 = v20;
+ v25 = (uint16)clip_x;
+ v26 = 0;
+ while (Asm_Zoom(v26 + 1, a7) < v25)
+ ;
+ v27 = v26;
+ v22 = v59;
+ spritePixelsP += v27;
+ dest1P += (uint16)clip_x;
+ v20 = v50 - (uint16)clip_x;
+ }
+ if (v20 > (uint16)clip_x1)
+ v20 = (uint16)clip_x1;
+ do {
+ while (1) {
+ v60 = v22;
+ v51 = dest1P;
+ v45 = spritePixelsP;
+ v28 = v20;
+ Agr_Flag_x = 0;
+ Agr_x = 0;
+ do {
+ while (1) {
+ if (*spritePixelsP)
+ *dest1P = *spritePixelsP;
+ ++dest1P;
+ ++spritePixelsP;
+ if (!Agr_Flag_x)
+ Agr_x = a7 + Agr_x;
+ if ((uint16)Agr_x < 0x64u)
+ break;
+ Agr_x = Agr_x - 100;
+ --spritePixelsP;
+ Agr_Flag_x = 1;
+ --v28;
+ if (!v28)
+ goto Aff_Zoom_Larg_Cont1;
+ }
+ Agr_Flag_x = 0;
+ --v28;
+ } while (v28);
+Aff_Zoom_Larg_Cont1:
+ spritePixelsP = Largeur + v45;
+ dest1P = nbrligne2 + v51;
+ if (!Agr_Flag_y)
+ Agr_y = a7 + Agr_y;
+ if ((uint16)Agr_y < 0x64u)
+ break;
+ Agr_y = Agr_y - 100;
+ spritePixelsP = v45;
+ Agr_Flag_y = 1;
+ v22 = v60 - 1;
+ if (v60 == 1)
+ return;
+ }
+ Agr_Flag_y = 0;
+ v22 = v60 - 1;
+ } while (v60 != 1);
+ }
+ } else if (a6) {
+ Compteur_y = 0;
+ Red_x = 0;
+ Red_y = 0;
+ Largeur = spriteWidth;
+ Red = a6;
+ if (a6 < 100) {
+ v37 = Asm_Reduc(spriteWidth, Red);
+ if (a8) {
+ v40 = v37 + dest1P;
+ do {
+ v65 = spriteHeight2;
+ v55 = v40;
+ Red_y = Red + Red_y;
+ if ((uint16)Red_y < 0x64u) {
+ Red_x = 0;
+ v41 = Largeur;
+ v42 = v37;
+ do {
+ Red_x = Red + Red_x;
+ if ((uint16)Red_x < 0x64u) {
+ if (v42 >= clip_x && v42 < clip_x1 && *spritePixelsP)
+ *v40 = *spritePixelsP;
+ --v40;
+ ++spritePixelsP;
+ --v42;
+ } else {
+ Red_x = Red_x - 100;
+ ++spritePixelsP;
+ }
+ --v41;
+ } while (v41);
+ spriteHeight2 = v65;
+ v40 = nbrligne2 + v55;
+ } else {
+ Red_y = Red_y - 100;
+ spritePixelsP += Largeur;
+ }
+ --spriteHeight2;
+ } while (spriteHeight2);
+ } else {
+ do {
+ v64 = spriteHeight2;
+ v54 = dest1P;
+ Red_y = Red + Red_y;
+ if ((uint16)Red_y < 0x64u) {
+ Red_x = 0;
+ v38 = Largeur;
+ v39 = 0;
+ do {
+ Red_x = Red + Red_x;
+ if ((uint16)Red_x < 0x64u) {
+ if (v39 >= clip_x && v39 < clip_x1 && *spritePixelsP)
+ *dest1P = *spritePixelsP;
+ ++dest1P;
+ ++spritePixelsP;
+ ++v39;
+ } else {
+ Red_x = Red_x - 100;
+ ++spritePixelsP;
+ }
+ --v38;
+ } while (v38);
+ spriteHeight2 = v64;
+ dest1P = nbrligne2 + v54;
+ } else {
+ Red_y = Red_y - 100;
+ spritePixelsP += Largeur;
+ }
+ --spriteHeight2;
+ } while (spriteHeight2);
+ }
+ }
+ } else {
+ Largeur = spriteWidth;
+ Compteur_y = 0;
+ if (a8) {
+ dest2P = spriteWidth + dest1P;
+ spec_largeur = spriteWidth;
+ if (clip_y) {
+ if ((uint16)clip_y >= (unsigned int)spriteHeight1)
+ return;
+ spritePixelsP += spriteWidth * (uint16)clip_y;
+ dest2P += nbrligne2 * (uint16)clip_y;
+ spriteHeight1 -= (uint16)clip_y;
+ }
+ xLeft = (uint16)clip_y1;
+ if (spriteHeight1 > clip_y1)
+ spriteHeight1 = clip_y1;
+ xLeft = clip_x;
+ if (clip_x) {
+ if (xLeft >= spriteWidth)
+ return;
+ spriteWidth -= xLeft;
+ }
+ if (spriteWidth > (uint16)clip_x1) {
+ clippedWidth = spriteWidth - (uint16)clip_x1;
+ spritePixelsP += clippedWidth;
+ dest2P -= clippedWidth;
+ spriteWidth = (uint16)clip_x1;
+ }
+ do {
+ yCtr2 = spriteHeight1;
+ destCopy2P = dest2P;
+ spritePixelsCopy2P = spritePixelsP;
+ xCtr2 = spriteWidth;
+ do {
+ if (*spritePixelsP)
+ *dest2P = *spritePixelsP;
+ ++spritePixelsP;
+ --dest2P;
+ --xCtr2;
+ } while (xCtr2);
+ spritePixelsP = spec_largeur + spritePixelsCopy2P;
+ dest2P = nbrligne2 + destCopy2P;
+ spriteHeight1 = yCtr2 - 1;
+ } while (yCtr2 != 1);
+ } else {
+ spec_largeur = spriteWidth;
+ if (clip_y) {
+ if ((uint16)clip_y >= (unsigned int)spriteHeight1)
+ return;
+ spritePixelsP += spriteWidth * (uint16)clip_y;
+ dest1P += nbrligne2 * (uint16)clip_y;
+ spriteHeight1 -= (uint16)clip_y;
+ }
+ if (spriteHeight1 > clip_y1)
+ spriteHeight1 = clip_y1;
+ if (clip_x) {
+ if ((uint16)clip_x >= spriteWidth)
+ return;
+ spritePixelsP += (uint16)clip_x;
+ dest1P += (uint16)clip_x;
+ spriteWidth -= (uint16)clip_x;
+ }
+ if (spriteWidth > (uint16)clip_x1)
+ spriteWidth = (uint16)clip_x1;
+ do {
+ yCtr1 = spriteHeight1;
+ dest1CopyP = dest1P;
+ spritePixelsCopyP = spritePixelsP;
+ xCtr1 = spriteWidth;
+ do {
+ if (*spritePixelsP)
+ *dest1P = *spritePixelsP;
+ ++dest1P;
+ ++spritePixelsP;
+ --xCtr1;
+ } while (xCtr1);
+ spritePixelsP = spec_largeur + spritePixelsCopyP;
+ dest1P = nbrligne2 + dest1CopyP;
+ spriteHeight1 = yCtr1 - 1;
+ } while (yCtr1 != 1);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// Display Speed
+void GraphicsManager::AFFICHE_SPEED(const byte *spriteData, int xp, int yp, int spriteIndex) {
+ int width, height;
+
+ width = _vm->_objectsManager.Get_Largeur(spriteData, spriteIndex);
+ height = _vm->_objectsManager.Get_Hauteur(spriteData, spriteIndex);
+ if (*spriteData == 78) {
+ Affiche_Perfect(VESA_SCREEN, spriteData, xp + 300, yp + 300, spriteIndex, 0, 0, 0);
+ Affiche_Perfect(VESA_BUFFER, spriteData, xp + 300, yp + 300, spriteIndex, 0, 0, 0);
+ } else {
+ Sprite_Vesa(VESA_BUFFER, spriteData, xp + 300, yp + 300, spriteIndex);
+ Sprite_Vesa(VESA_SCREEN, spriteData, xp + 300, yp + 300, spriteIndex);
+ }
+ if (!_vm->_globals.NO_VISU)
+ Ajoute_Segment_Vesa(xp, yp, xp + width, yp + height);
+}
+
+void GraphicsManager::SCOPY(const byte *surface, int x1, int y1, int width, int height, byte *destSurface, int destX, int destY) {
+ int top;
+ int croppedWidth;
+ int croppedHeight;
+ int xRight;
+ int height2;
+ int top2;
+ int left;
+
+ left = x1;
+ top = y1;
+ croppedWidth = width;
+ croppedHeight = height;
+
+ if (x1 < min_x) {
+ croppedWidth = width - (min_x - x1);
+ left = min_x;
+ }
+ if (y1 < min_y) {
+ croppedHeight = height - (min_y - y1);
+ top = min_y;
+ }
+ top2 = top;
+ if (top + croppedHeight > max_y)
+ croppedHeight = max_y - top;
+ xRight = left + croppedWidth;
+ if (xRight > max_x)
+ croppedWidth = max_x - left;
+
+ if (croppedWidth > 0 && croppedHeight > 0) {
+ height2 = croppedHeight;
+ Copy_Mem(surface, left, top2, croppedWidth, croppedHeight, destSurface, destX, destY);
+ Ajoute_Segment_Vesa(left, top2, left + croppedWidth, top2 + height2);
+ }
+}
+
+void GraphicsManager::Copy_Mem(const byte *srcSurface, int x1, int y1, unsigned int width, int height, byte *destSurface, int destX, int destY) {
+ const byte *srcP;
+ byte *destP;
+ int yp;
+ int yCurrent;
+ byte *dest2P;
+ const byte *src2P;
+ unsigned int pitch;
+
+ srcP = x1 + nbrligne2 * y1 + srcSurface;
+ destP = destX + nbrligne2 * destY + destSurface;
+ yp = height;
+ do {
+ yCurrent = yp;
+ memcpy(destP, srcP, 4 * (width >> 2));
+ src2P = (srcP + 4 * (width >> 2));
+ dest2P = (destP + 4 * (width >> 2));
+ pitch = width - 4 * (width >> 2);
+ memcpy(dest2P, src2P, pitch);
+ destP = (dest2P + pitch + nbrligne2 - width);
+ srcP = (src2P + pitch + nbrligne2 - width);
+ yp = yCurrent - 1;
+ } while (yCurrent != 1);
+}
+
+// Display Font
+void GraphicsManager::Affiche_Fonte(byte *surface, const byte *spriteData, int xp, int yp,
+ int characterIndex, int colour) {
+ const byte *spriteDataP;
+ int i;
+ const byte *spriteSizeP;
+ int spriteWidth;
+ int spriteHeight;
+ const byte *spritePixelsP;
+ byte *destP;
+ int xCtr;
+ byte destByte;
+ byte *destLineP;
+ int yCtr;
+
+ spriteDataP = spriteData + 3;
+ for (i = characterIndex; i; --i)
+ spriteDataP += READ_LE_UINT32(spriteDataP) + 16;
+
+ spriteWidth = 0;
+ spriteHeight = 0;
+ spriteSizeP = spriteDataP + 4;
+ spriteWidth = (int16)READ_LE_UINT16(spriteSizeP);
+ spriteSizeP += 2;
+ spriteHeight = (int16)READ_LE_UINT16(spriteSizeP);
+ spritePixelsP = spriteSizeP + 10;
+ destP = surface + xp + nbrligne2 * yp;
+ Largeur = spriteWidth;
+
+ do {
+ yCtr = spriteHeight;
+ destLineP = destP;
+ xCtr = spriteWidth;
+ do {
+ destByte = *spritePixelsP;
+ if (*spritePixelsP) {
+ if (destByte == (byte)-4)
+ destByte = colour;
+ *destP = destByte;
+ }
+
+ ++destP;
+ ++spritePixelsP;
+ --xCtr;
+ } while (xCtr);
+ destP = nbrligne2 + destLineP;
+ spriteHeight = yCtr - 1;
+ } while (yCtr != 1);
+}
+
+// Init Screen
+void GraphicsManager::INI_ECRAN(const Common::String &file) {
+ OPTI_INI(file, 0);
+}
+
+// Init Screen 2
+void GraphicsManager::INI_ECRAN2(const Common::String &file) {
+ OPTI_INI(file, 2);
+}
+
+void GraphicsManager::OPTI_INI(const Common::String &file, int mode) {
+ int dataOffset;
+ int dataVal1;
+ bool doneFlag;
+ byte *ptr;
+ Common::String filename;
+
+ dataOffset = 1;
+
+ filename = file + ".ini";
+ ptr = _vm->_fileManager.RECHERCHE_CAT(filename, 1);
+ if (ptr == g_PTRNUL) {
+ _vm->_fileManager.CONSTRUIT_FICHIER(_vm->_globals.HOPLINK, filename);
+ ptr = _vm->_fileManager.CHARGE_FICHIER(_vm->_globals.NFICHIER);
+ }
+ if (!mode) {
+ filename = file + ".spr";
+ if (g_PTRNUL != _vm->_globals.SPRITE_ECRAN)
+ _vm->_globals.SPRITE_ECRAN = _vm->_fileManager.LIBERE_FICHIER(_vm->_globals.SPRITE_ECRAN);
+ if (!_vm->_globals.NOSPRECRAN) {
+ _vm->_globals.SPRITE_ECRAN = _vm->_fileManager.RECHERCHE_CAT(filename, 8);
+ if (_vm->_globals.SPRITE_ECRAN) {
+ _vm->_globals.CAT_FLAG = false;
+ _vm->_fileManager.CONSTRUIT_FICHIER(_vm->_globals.HOPLINK, filename);
+ } else {
+ _vm->_globals.CAT_FLAG = true;
+ _vm->_fileManager.CONSTRUIT_FICHIER(_vm->_globals.HOPLINK, "RES_SLI.RES");
+ }
+ _vm->_globals.SPRITE_ECRAN = _vm->_fileManager.CHARGE_FICHIER(_vm->_globals.NFICHIER);
+ _vm->_globals.CAT_FLAG = false;
+ }
+ }
+ if (*ptr != 'I' || *(ptr + 1) != 'N' || *(ptr + 2) != 'I') {
+ error("Error, file not ini");
+ } else {
+ doneFlag = false;
+ do {
+ dataVal1 = _vm->_scriptManager.Traduction(ptr + 20 * dataOffset);
+ if (_vm->shouldQuit())
+ return;
+
+ if (dataVal1 == 2)
+ dataOffset = _vm->_scriptManager.Control_Goto((ptr + 20 * dataOffset));
+ if (dataVal1 == 3)
+ dataOffset = _vm->_scriptManager.Control_If(ptr, dataOffset);
+ if (dataOffset == -1)
+ error("Error, defective IFF");
+ if (dataVal1 == 1 || dataVal1 == 4)
+ ++dataOffset;
+ if (!dataVal1 || dataVal1 == 5)
+ doneFlag = true;
+ } while (!doneFlag);
+ }
+ _vm->_globals.dos_free2(ptr);
+ if (mode != 1) {
+ if (g_PTRNUL != _vm->_globals.COUCOU)
+ _vm->_globals.COUCOU = _vm->_globals.dos_free2(_vm->_globals.COUCOU);
+
+ filename = file + ".rep";
+ byte *dataP = _vm->_fileManager.RECHERCHE_CAT(filename, 2);
+ _vm->_globals.COUCOU = dataP;
+ if (g_PTRNUL == dataP) {
+ _vm->_fileManager.CONSTRUIT_FICHIER(_vm->_globals.HOPLINK, filename);
+ dataP = _vm->_fileManager.CHARGE_FICHIER(_vm->_globals.NFICHIER);
+ _vm->_globals.COUCOU = dataP;
+ }
+ }
+ _vm->_objectsManager.FORCEZONE = 1;
+ _vm->_objectsManager.CHANGEVERBE = 0;
+}
+
+void GraphicsManager::NB_SCREEN() {
+ byte *destP;
+ const byte *srcP;
+
+ if (!_vm->_globals.NECESSAIRE)
+ INIT_TABLE(50, 65, Palette);
+ if (nbrligne == SCREEN_WIDTH)
+ Trans_bloc2(VESA_BUFFER, TABLE_COUL, 307200);
+ if (nbrligne == 1280)
+ Trans_bloc2(VESA_BUFFER, TABLE_COUL, 614400);
+ _vm->_graphicsManager.DD_Lock();
+ if (Winbpp == 2) {
+ if (SDL_ECHELLE)
+ m_scroll16A(VESA_BUFFER, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ else
+ m_scroll16(VESA_BUFFER, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ }
+ if (Winbpp == 1) {
+ if (SDL_ECHELLE)
+ m_scroll2A(VESA_BUFFER, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ else
+ m_scroll2(VESA_BUFFER, _vm->_eventsManager.start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
+ }
+ _vm->_graphicsManager.DD_Unlock();
+
+ destP = VESA_SCREEN;
+ srcP = VESA_BUFFER;
+ memcpy(VESA_SCREEN, VESA_BUFFER, 0x95FFCu);
+ srcP = srcP + 614396;
+ destP = destP + 614396;
+ *destP = *srcP;
+ *(destP + 2) = *(srcP + 2);
+ DD_VBL();
+}
+
+void GraphicsManager::SHOW_PALETTE() {
+ setpal_vga256(Palette);
+}
+
+void GraphicsManager::videkey() {
+ // Empty in original
+}
+
+void GraphicsManager::Copy_WinScan_Vbe(const byte *src, byte *dest) {
+ int result;
+ int destOffset;
+ const byte *srcPtr;
+ byte byteVal;
+
+ result = 0;
+ destOffset = 0;
+ srcPtr = src;
+ while (1) {
+ byteVal = *srcPtr;
+ if (*srcPtr < 0xFCu)
+ goto Video_Cont_wVbe;
+ if (byteVal == (byte)-4)
+ return;
+ if (byteVal == (byte)-3) {
+ destOffset += *(srcPtr + 1);
+ byteVal = *(srcPtr + 2);
+ srcPtr += 2;
+ } else if (byteVal == (byte)-2) {
+ destOffset += READ_LE_UINT16(srcPtr + 1);
+ byteVal = *(srcPtr + 3);
+ srcPtr += 3;
+ } else {
+ destOffset += READ_LE_UINT32(srcPtr + 1);
+ byteVal = *(srcPtr + 5);
+ srcPtr += 5;
+ }
+Video_Cont_wVbe:
+ *(dest + destOffset) = byteVal;
+ ++srcPtr;
+ ++destOffset;
+ }
+}
+
+void GraphicsManager::Copy_Video_Vbe(const byte *src) {
+ int destOffset;
+ const byte *srcP;
+ byte byteVal;
+
+ assert(VideoPtr);
+ destOffset = 0;
+ srcP = src;
+ while (1) {
+ byteVal = *srcP;
+ if (*srcP < 0xFCu)
+ goto Video_Cont_Vbe;
+ if (byteVal == (byte)-4)
+ return;
+ if (byteVal == (byte)-3) {
+ destOffset += *(srcP + 1);
+ byteVal = *(srcP + 2);
+ srcP += 2;
+ } else if (byteVal == (byte)-2) {
+ destOffset += READ_LE_UINT16(srcP + 1);
+ byteVal = *(srcP + 3);
+ srcP += 3;
+ } else {
+ destOffset += READ_LE_UINT32(srcP + 1);
+ byteVal = *(srcP + 5);
+ srcP += 5;
+ }
+Video_Cont_Vbe:
+ *((byte *)VideoPtr->pixels + destOffset) = byteVal;
+ ++srcP;
+ ++destOffset;
+ }
+}
+
+// Reduce Screen
+void GraphicsManager::Reduc_Ecran(const byte *srcSurface, byte *destSurface, int xp, int yp, int width, int height, int zoom) {
+ const byte *srcP;
+ byte *destP;
+ const byte *lineSrcP;
+
+ srcP = xp + nbrligne2 * yp + srcSurface;
+ destP = destSurface;
+ Red = zoom;
+ Largeur = width;
+ Red_x = 0;
+ Red_y = 0;
+ if (zoom < 100) {
+ Reduc_Ecran_L = Asm_Reduc(width, Red);
+ Reduc_Ecran_H = Asm_Reduc(height, Red);
+
+ for (int yCtr = 0; yCtr < height; ++yCtr, srcP += nbrligne2) {
+ Red_y += Red;
+ if (Red_y < 100) {
+ Red_x = 0;
+ lineSrcP = srcP;
+
+ for (int xCtr = 0; xCtr < Largeur; ++xCtr) {
+ Red_x += Red;
+ if (Red_x < 100) {
+ *destP++ = *lineSrcP++;
+ } else {
+ Red_x -= 100;
+ ++lineSrcP;
+ }
+ }
+ } else {
+ Red_y -= 100;
+ }
+ }
+ }
+}
+
+void GraphicsManager::Plot_Hline(byte *surface, int xp, int yp, unsigned int width, byte col) {
+ memset(surface + xp + nbrligne2 * yp, col, width);
+}
+
+void GraphicsManager::Plot_Vline(byte *surface, int xp, int yp, int height, byte col) {
+ byte *destP;
+ int yCtr;
+
+ destP = surface + xp + nbrligne2 * yp;
+ yCtr = height;
+ do {
+ *destP = col;
+ destP += nbrligne2;
+ --yCtr;
+ } while (yCtr);
+}
+
+
+} // End of namespace Hopkins