/* 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; start_x = 0; 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 * 2; clip_x = clip_y = 0; clip_x1 = clip_y1 = 0; clip_flag = false; Common::fill(&SD_PIXELS[0], &SD_PIXELS[PALETTE_SIZE * 2], 0); Common::fill(&TABLE_COUL[0], &TABLE_COUL[PALETTE_SIZE], 0); Common::fill(&cmap[0], &cmap[PALETTE_BLOCK_SIZE], 0); Common::fill(&Palette[0], &Palette[PALETTE_BLOCK_SIZE], 0); } GraphicsManager::~GraphicsManager() { GLOBALS.dos_free2(VESA_SCREEN); 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 (GLOBALS.XSETMODE == 1) SDL_ECHELLE = 0; if (GLOBALS.XSETMODE == 2) SDL_ECHELLE = 25; if (GLOBALS.XSETMODE == 3) SDL_ECHELLE = 50; if (GLOBALS.XSETMODE == 4) SDL_ECHELLE = 75; if (GLOBALS.XSETMODE == 5) SDL_ECHELLE = GLOBALS.XZOOM; int bpp = 8; if (GLOBALS.XFORCE8 == 1) bpp = 8; if (GLOBALS.XFORCE16 == 1) bpp = 16; if (SDL_ECHELLE) { width = Reel_Zoom(width, SDL_ECHELLE); height = Reel_Zoom(height, SDL_ECHELLE); } //Graphics::PixelFormat pixelFormat16(2, 5, 5, 5, 0, 10, 5, 0, 0); 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 = GLOBALS.dos_malloc2(SCREEN_WIDTH * 2 * SCREEN_HEIGHT); VESA_BUFFER = 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; } } 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); GraphicsManager::INIT_TABLE(165, 170, Palette); } void GraphicsManager::CHARGE_ECRAN(const Common::String &file) { bool flag; Common::File f; FileManager::DMESS1(); flag = true; if (FileManager::RECHERCHE_CAT(file, 6)) { FileManager::CONSTRUIT_FICHIER(GLOBALS.HOPIMAGE, file); if (!f.open(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) { souris_max(); SCANLINE(SCREEN_WIDTH); _vm->_graphicsManager.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); _vm->_graphicsManager.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 a1, int a2, byte *palette) { for (int idx = 0; idx < 256; ++idx) TABLE_COUL[idx] = idx; Trans_bloc(TABLE_COUL, palette, 256, a1, a2); 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; } int GraphicsManager::SCROLL_ECRAN(int amount) { int result = CLIP(amount, 0, SCREEN_WIDTH); start_x = result; ofscroll = result; SCROLL = result; return result; } void GraphicsManager::Trans_bloc(byte *destP, byte *srcP, int count, int param1, int param2) { byte *v5; int v6; int v7; int v8; unsigned int v11; int v12; int v13; int v14; int v15; int v16; int v17; unsigned int v18; char v19; int v20; bool breakFlag; v5 = destP; v6 = count - 1; do { breakFlag = v6; v7 = *(byte *)v5++; v8 = (unsigned int)(3 * v7); // TODO: Ensure this is the right calculation v11 = *(byte *)(v8 + srcP) + *(byte *)(v8 + srcP + 1) + *(byte *)(v8 + srcP + 2); v12 = 0; for (;;) { v13 = v12 + 1; if ( v13 == 38 ) break; v20 = v13; v8 = 3 * v8; v14 = *(byte *)(v8 + srcP); v15 = v14; v14 = *(byte *)(v8 + srcP + 1); v16 = v14 + v15; v14 = *(byte *)(v8 + srcP + 2); v17 = v14 + v16; v12 = v20; v18 = param1 + v17; if (v18 >= v11 && (unsigned int)(v18 - param2) <= v11) { v19 = v20; if (!v20) v19 = 1; *(byte *)(v5 - 1) = v19; break; } } v6 = breakFlag - 1; } while ( !breakFlag); } // 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; signed __int16 v6; int v7; __int16 v8; int v9; int v10; int v11; unsigned __int8 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) { FileManager::CONSTRUIT_FICHIER(GLOBALS.HOPIMAGE, "PIC.RES"); if (!f.open(GLOBALS.NFICHIER)) error("(nom)Erreur en cours de lecture."); f.seek(GLOBALS.CAT_POSI); v7 = GLOBALS.CAT_TAILLE - 896; v8 = f.read(HEADER_PCX, 128); v6 = READ_LE_UINT16(&HEADER_PCX[8]) + 1; v20 = READ_LE_UINT16(&HEADER_PCX[10]) + 1; if ((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 { FileManager::CONSTRUIT_FICHIER(GLOBALS.HOPIMAGE, file); if (!f.open(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 = READ_LE_UINT16(&HEADER_PCX[8]) + 1; v20 = 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 = 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(GLOBALS.CAT_TAILLE + 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(); GLOBALS.dos_free2(ptr); } 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::souris_max() { // Original has no implementation } 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 *v7; byte *v8; int v9; int v10; byte *v11; const byte *v12; unsigned int v13; assert(VideoPtr); v7 = xs + nbrligne2 * ys + surface; v8 = destX + WinScan * destY + (byte *)VideoPtr->pixels; v9 = height; do { v10 = v9; memcpy((byte *)v8, (const byte *)v7, 4 * (width >> 2)); v12 = (const byte *)(v7 + 4 * (width >> 2)); v11 = (byte *)(v8 + 4 * (width >> 2)); v13 = width - 4 * (width >> 2); memcpy(v11, v12, v13); v8 = ((byte *)v11 + v13 + WinScan - width); v7 = ((byte *)v12 + v13 + nbrligne2 - width); v9 = v10 - 1; } while (v10 != 1); } void GraphicsManager::m_scroll2(const byte *surface, int xs, int ys, int width, int height, int destX, int destY) { const byte *v7; byte *v8; int v9; int v10; int v11; assert(VideoPtr); v7 = (const byte *)(xs + nbrligne2 * ys + surface); v8 = (byte *)(destX + WinScan * destY + (byte *)VideoPtr->pixels); v9 = WinScan - SCREEN_WIDTH; v10 = nbrligne2 - SCREEN_WIDTH; v11 = height; do { memcpy(v8, v7, SCREEN_WIDTH); v8 = (byte *)v8 + v9 + SCREEN_WIDTH; v7 = (const byte *)v7 + v10 + SCREEN_WIDTH; --v11; } while (v11); } void GraphicsManager::m_scroll2A(const byte *surface, int xs, int ys, int width, int height, int destX, int destY) { const byte *v7; const byte *v8; int v9; int v10; byte v11; const byte *v12; const byte *v13; assert(VideoPtr); v7 = xs + nbrligne2 * ys + surface; v8 = destX + WinScan * destY + (byte *)VideoPtr->pixels; v9 = height; Agr_x = 0; Agr_y = 0; Agr_Flag_y = 0; do { for (;;) { v13 = v8; v12 = v7; v10 = width; Agr_x = 0; do { v11 = *(byte *)v7; *(byte *)v8++ = *(byte *)v7++; Agr_x += SDL_ECHELLE; if ((unsigned int)Agr_x >= 100) { Agr_x -= 100; *(byte *)v8++ = v11; } --v10; } while ( v10 ); v7 = v12; v8 = WinScan + v13; 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; v7 = nbrligne2 + v12; --v9; } while (v9); } /** * 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(); } void GraphicsManager::m_scroll16A(const byte *surface, int xs, int ys, int width, int height, int destX, int destY) { const byte *v7; const byte *v8; int v9; int v10; const byte *v11; int v12; int v13; const byte *v14; const byte *v15; assert(VideoPtr); v7 = xs + nbrligne2 * ys + surface; v8 = destX + destX + WinScan * destY + (byte *)VideoPtr->pixels; v9 = height; Agr_x = 0; Agr_y = 0; Agr_Flag_y = 0; do { for (;;) { v15 = v8; v14 = v7; v10 = width; v13 = v9; v11 = PAL_PIXELS; Agr_x = 0; do { v12 = *(uint16 *)(v11 + 2 * *(byte *)v7); *(uint16 *)v8 = v12; ++v7; v8 += 2; Agr_x += SDL_ECHELLE; if ((unsigned int)Agr_x >= 100) { Agr_x -= 100; *(uint16 *)v8 = v12; v8 += 2; } --v10; } while (v10); v9 = v13; v7 = v14; v8 = WinScan + v15; 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; v7 = nbrligne2 + v14; v9 = v13 - 1; } while (v13 != 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[2]; for (int fadeIndex = 0; fadeIndex < FADESPD; ++fadeIndex) { uint16 *pTemp2 = &palData1[4]; 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 + 1] < palette[palOffset + 1]) { uint16 *pDest = &pTemp2[palOffset]; uint16 v = (palette[palOffset] & 0xff) * 256 / FADESPD + *pDest; *pDest = v; palData2[palOffset + 1] = (v >> 8) & 0xff; } } setpal_vga256(palData2); if (Winbpp == 2) { if (SDL_ECHELLE) m_scroll16A(surface, start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); else m_scroll16(surface, 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, start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); else m_scroll16(surface, start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); DD_VBL(); } } void GraphicsManager::fade_out(const byte *palette, int step, const byte *surface) { __int16 v3; __int16 v4; int v5; signed __int16 v6; __int16 v7; int v8; __int16 v9; __int16 v10; __int16 v12; uint16 v13; byte palData[PALETTE_BLOCK_SIZE]; __int16 v15[PALETTE_BLOCK_SIZE]; v13 = v3 = FADESPD; if (palette) { v4 = 0; do { v5 = v4; v3 = *(byte *)(v4 + palette); v3 <<= 8; v15[v5] = v3; palData[v5] = *(byte *)(v4++ + palette); } while (v4 < PALETTE_BLOCK_SIZE); setpal_vga256(palData); if (Winbpp == 2) { if (SDL_ECHELLE) m_scroll16A(surface, start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); else m_scroll16(surface, start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); DD_VBL(); } v6 = 0; if ((signed __int16)v13 > 0) { do { v7 = 0; do { v8 = v7; v9 = v15[v7] - ((unsigned int)*(byte *)(v7 + palette) << 8) / (signed __int16)v13; v15[v8] = v9; palData[v8] = (v9 >> 8) & 0xff; ++v7; } while (v7 < (PALETTE_BLOCK_SIZE)); setpal_vga256(palData); if (Winbpp == 2) { if (SDL_ECHELLE) m_scroll16A(surface, start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); else m_scroll16(surface, start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); DD_VBL(); } ++v6; } while ((signed __int16)v13 > v6); } v10 = 0; do { palData[v10++] = 0; } while (v10 < (PALETTE_BLOCK_SIZE)); setpal_vga256(palData); if (Winbpp == 2) { if (!SDL_ECHELLE) { m_scroll16(surface, start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); return DD_VBL(); } goto LABEL_28; } } else { v12 = 0; do { palData[v12++] = 0; } while (v12 < (PALETTE_BLOCK_SIZE)); setpal_vga256(palData); if (Winbpp == 2) { if (!SDL_ECHELLE) { m_scroll16(surface, start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); return DD_VBL(); } LABEL_28: m_scroll16A(surface, 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, start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); else m_scroll16(surface, start_x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); DD_VBL(); } } void GraphicsManager::SETCOLOR3(int palIndex, int r, int g, int b) { int offset = palIndex * 3; Palette[offset] = 255 * r / 100; Palette[offset + 1] = 255 * g / 100; Palette[offset + 2] = 255 * b / 100; } 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) { fade_out(Palette, FADESPD, surface); } void GraphicsManager::FADE_INW_LINUX(const byte *surface) { return fade_in(Palette, FADESPD, surface); } void GraphicsManager::Copy_WinScan_Vbe3(const byte *sourceSurface, byte *destSurface) { int result; int v3; int v4; const byte *v5; uint8 v6; int v7; unsigned int v8; byte *v9; int v10; unsigned int v11; byte *v12; result = 0; v3 = 0; v4 = 0; v5 = sourceSurface; for (;;) { v6 = *v5; if (*(byte *)v5 < 222) goto Video_Cont3_wVbe; if (v6 == 252) return; if (v6 < 251) { v3 += (unsigned __int8)(*(byte *)v5 + 35); v6 = *(v5++ + 1); } else if (v6 == 253) { v3 += *(v5 + 1); v6 = *(v5 + 2); v5 += 2; } else if (v6 == 254) { v3 += READ_LE_UINT16(v5 + 1); v6 = *(v5 + 3); v5 += 3; } else { v3 += READ_LE_UINT32(v5 + 1); v6 = *(v5 + 5); v5 += 5; } Video_Cont3_wVbe: if (v6 > 210) { if (v6 == 211) { v7 = v4; v8 = *(v5 + 1); result = *(v5 + 2); v9 = v3 + destSurface; v3 += v8; memset(v9, result, v8); v5 += 3; v4 = v7; } else { v10 = v4; v11 = *v5 + 45; result = *(v5 + 1); v12 = v3 + destSurface; v3 += v11; memset(v12, result, v11); v5 += 2; v4 = v10; } } else { *(v3 + destSurface) = v6; ++v5; ++v3; } } } void GraphicsManager::Copy_Video_Vbe3(const byte *surface) { int result; // eax@1 int v2; // ebx@1 int v3; // ecx@1 const byte *v4; // esi@1 uint8 v5; // dl@2 int v6; // ST00_4@9 unsigned int v7; // ecx@9 byte *v8; // edi@9 int v9; // ST00_4@10 unsigned int v10; // ecx@10 byte *v11; // edi@10 assert(VideoPtr); result = 0; v2 = 0; v3 = 0; v4 = surface; for (;;) { v5 = *v4; if (*v4 < 222) goto Video_Cont3_Vbe; if (v5 == 252) return; if (v5 < 251) { v2 += (unsigned __int8)(*v4 + 35); v5 = *(v4++ + 1); } else if (v5 == -3) { v2 += *(v4 + 1); v5 = *(v4 + 2); v4 += 2; } else if (v5 == -2) { v2 += READ_LE_UINT16(v4 + 1); v5 = *(v4 + 3); v4 += 3; } else { v2 += READ_LE_UINT32(v4 + 1); v5 = *(v4 + 5); v4 += 5; } Video_Cont3_Vbe: if (v5 > 210) { if (v5 == 211) { v6 = v3; v7 = *(v4 + 1); result = *(v4 + 2); v8 = v2 + (byte *)VideoPtr->pixels; v2 += v7; memset(v8, result, v7); v4 += 3; v3 = v6; } else { v9 = v3; v10 = (unsigned __int8)(*v4 + 45); result = *(v4 + 1); v11 = (byte *)(v2 + (byte *)VideoPtr->pixels); v2 += v10; memset(v11, result, v10); v4 += 2; v3 = v9; } } else { *(v2 + (byte *)VideoPtr->pixels) = v5; ++v4; ++v2; } } } void GraphicsManager::Copy_Video_Vbe16(const byte *surface) { const byte *srcP = surface; 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::Capture_Mem(const byte *srcSurface, byte *destSurface, int xs, int ys, unsigned int width, int height) { const byte *srcP; byte *destP; int yCtr; unsigned int i; int yTemp; srcP = srcSurface + xs + nbrligne2 * ys; destP = destSurface; yCtr = height; do { yTemp = yCtr; 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 = (byte *)destP + 2; } } else { memcpy(destP, srcP, 4 * (width >> 2)); srcP += 4 * (width >> 2); destP = (byte *)destP + 4 * (width >> 2); } srcP = nbrligne2 + srcP - width; yCtr = yTemp - 1; } while (yTemp != 1); } void GraphicsManager::Sprite_Vesa(byte *a1, byte *a2, int a3, int a4, int a5) { byte *v5; int i; byte *v7; uint16 v8; byte *v9; int v10; uint16 v11; uint16 v12; uint16 v13; uint16 v14; byte *v15; byte *v16; const byte *v17; byte *v18; int v19; byte *v20; byte *v21; int v22; unsigned int v23; byte *v24; const byte *v25; byte *v26; byte *v27; byte *v28; byte *v29; int v30; int v31; v5 = a2 + 3; for (i = a5; i; --i) v5 += READ_LE_UINT32(v5) + 16; v10 = 0; v7 = v5 + 4; v8 = READ_LE_UINT16(v7); v9 = v7 + 2; v10 = READ_LE_UINT16(v9); clip_x = 0; clip_y = 0; clip_flag = false; clip_x1 = v8; if ((uint16)(v8 + a3) > v8) { if ((uint16)a3 < (uint16)(min_x + 300)) { clip_x = min_x + 300 - a3; clip_flag = true; } if ((uint16)(v10 + (uint16)a4) > (uint16)v10) { if ((uint16)a4 < (uint16)(min_y + 300)) { clip_y = min_y + 300 - a4; clip_flag = true; } v11 = max_x + 300; if ((uint16)a3 < (uint16)(max_x + 300)) { if ((uint16)(v8 + a3) > v11) { v12 = v8 + 10 - (v8 + a3 - v11); if (v12 <= 10) return; clip_x1 = v12 - 10; clip_flag = true; } v13 = max_y + 300; if ((uint16)a4 < (uint16)(max_y + 300)) { if ((uint16)(v10 + (uint16)a4) > v13) { v14 = v10 + 10 - (v10 + (uint16)a4 - v13); if (v14 <= 10) return; v10 -= 10; clip_y1 = v10; clip_flag = true; } v15 = v9 + 6; v16 = v15 + 4; v17 = READ_LE_UINT32(v15) + v15 + 4; v18 = a3 + nbrligne2 * (a4 - 300) - 300 + a1; v19 = 0; if (clip_flag) { do { v31 = v10; v29 = v18; v19 = 0; while (*v16 != -3) { if (*v16 == -2) { v27 = v16 + 1; v10 = READ_LE_UINT16(v27); do { if (!clip_y && (uint16)v19 >= clip_x && (uint16)v19 < clip_x1) *v18 = *v17; ++v17; ++v18; ++v19; --v10; } while (v10); v16 = v27 + 2; } else { v26 = v16 + 1; v10 = *(uint16 *)v26; v18 += v10; v19 += v10; v16 = v26 + 2; } } if (clip_y) --clip_y; v16 += 3; v18 = nbrligne2 + v29; v10 = v31 - 1; } while (v31 != 1); } else { do { v30 = v10; v28 = v18; while (*v16 != -3) { if (*v16 == -2) { v21 = v16 + 1; v10 = READ_LE_UINT16(v21); v22 = v10; v23 = (unsigned int)v10 >> 2; memcpy(v18, v17, 4 * v23); v25 = (v17 + 4 * v23); v24 = (v18 + 4 * v23); v10 = v22 - 4 * v23; memcpy(v24, v25, v10); v17 = v25 + v10; v18 = v24 + v10; v10 = 0; v16 = v21 + 2; } else { v20 = v16 + 1; v10 = READ_LE_UINT16(v20); v18 += v10; v16 = v20 + 2; } } v16 += 3; v18 = nbrligne2 + v28; v10 = v30 - 1; } while (v30 != 1); } } } } } } 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() { warning("TODO: RESET_SEGMENT_VESA"); } void GraphicsManager::Ajoute_Segment_Vesa(int a1, int a2, int a3, int a4) { warning("TODO: Ajoute_Segment_Vesa"); } 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; } void GraphicsManager::Affiche_Segment_Vesa() { warning("TODO: Affiche_Segment_Vesa"); } void GraphicsManager::CopyAsm(const byte *surface) { const byte *v1; byte srcByte; byte *v3; signed int v4; signed int v5; byte *v6; byte *v7; byte *v8; byte *v9; const byte *v10; assert(VideoPtr); v1 = surface; srcByte = 30 * WinScan; v3 = (byte *)VideoPtr->pixels + 30 * WinScan; v4 = 200; do { v10 = v1; v9 = v3; v5 = 320; do { srcByte = *(byte *)v1; *(byte *)v3 = *(byte *)v1; v6 = WinScan + v3; *(byte *)v6 = srcByte; v7 = v6 - WinScan + 1; *(byte *)v7 = srcByte; v8 = WinScan + v7; *(byte *)v8 = srcByte; v3 = v8 - WinScan + 1; ++v1; --v5; } while (v5); v1 = v10 + 320; v3 = WinScan + WinScan + v9; --v4; } while (v4); } void GraphicsManager::Restore_Mem(byte *a1, const byte *a2, int a3, int a4, unsigned int a5, int a6) { byte *v6; int v7; const byte *v8; unsigned int i; int v10; v6 = a3 + nbrligne2 * a4 + a1; v7 = a6; v8 = a2; do { v10 = v7; if (a5 & 1) { memcpy(v6, v8, a5); v8 += a5; v6 += a5; } else if (a5 & 2) { for (i = a5 >> 1; i; --i) { *(uint16 *)v6 = *(uint16 *)v8; v8 += 2; v6 += 2; } } else { memcpy(v6, v8, 4 * (a5 >> 2)); v8 += 4 * (a5 >> 2); v6 += 4 * (a5 >> 2); } v6 = nbrligne2 + v6 - a5; v7 = v10 - 1; } while (v10 != 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; } void GraphicsManager::AFF_SPRITES() { warning("TODO: AFF_SPRITES"); } void GraphicsManager::Affiche_Perfect(const byte *a1, const byte *a2, int a3, int a4, int a5, int a6, int a7, int a8) { warning("TODO: Affice_Perfect"); } } // End of namespace Hopkins