/* 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 "cryo/cryo.h" #include "cryo/platdefs.h" #include "cryo/cryolib.h" #include "cryo/eden.h" #include "cryo/sound.h" #include "cryo/eden_graphics.h" #include "cryo/video.h" namespace Cryo { EdenGraphics::EdenGraphics(EdenGame *game, HnmPlayer *video) : _game(game), _video(video) { _glowH = _glowW = _glowY = _glowX = 0; _showVideoSubtitle = false; _showBlackBars = false; _mainView = nullptr; _mainViewBuf = nullptr; _hnmView = nullptr; _view2 = nullptr; _view2Buf = nullptr; _curCharacterRect = nullptr; _subtitlesViewBuf = nullptr; _underSubtitlesView = nullptr; _subtitlesView = nullptr; _underBarsView = nullptr; _needToFade = false; } void EdenGraphics::SendPalette2Screen(int16 value) { CLPalette_Send2Screen(_globalPalette, 0, value); } void EdenGraphics::setFade(bool value) { _needToFade = value; } bool EdenGraphics::getFade() { return _needToFade; } void EdenGraphics::setPaletteColor(byte *buffer) { for (int i = 0; i < 256; i++) { color3_t color; color.r = buffer[i * 3] << 8; color.g = buffer[i * 3 + 1] << 8; color.b = buffer[i * 3 + 2] << 8; CLPalette_SetRGBColor(_globalPalette, i, &color); } SendPalette2Screen(256); } void EdenGraphics::readPalette(byte *ptr) { bool doit = true; color3_t pal_entry; while (doit) { uint16 idx = *ptr++; if (idx != 0xFF) { uint16 cnt = *ptr++; while (cnt--) { if (idx == 0) { pal_entry.r = 0; pal_entry.g = 0; pal_entry.b = 0; ptr += 3; } else { pal_entry.r = *ptr++ << 10; pal_entry.g = *ptr++ << 10; pal_entry.b = *ptr++ << 10; } CLPalette_SetRGBColor(_globalPalette, idx, &pal_entry); idx++; } } else doit = false; } } // Original name: noclipax void EdenGraphics::drawSprite(int16 index, int16 x, int16 y, bool withBlack, bool onSubtitle) { uint16 width = (!onSubtitle) ? 640 : _subtitlesXWidth; byte *pix = _game->getBankData(); byte *buf = (!onSubtitle) ? _mainViewBuf : _subtitlesViewBuf; byte *scr = buf + x + y * width; if (_game->getCurBankNum() != 117 && (!_game->getNoPalette() || withBlack || onSubtitle)) { if (READ_LE_UINT16(pix) > 2) readPalette(pix + 2); } pix += READ_LE_UINT16(pix); pix += READ_LE_UINT16(pix + index * 2); // int16 height:9 // int16 pad:6; // int16 flag:1; byte h0 = *pix++; byte h1 = *pix++; int16 w = ((h1 & 1) << 8) | h0; int16 h = *pix++; byte mode = *pix++; if (mode != 0xFF && mode != 0xFE) return; if (y + h > 200 && !onSubtitle) h -= (y + h - 200); if (h1 & 0x80) { // compressed for (; h-- > 0;) { for (int16 ww = w; ww > 0;) { byte c = *pix++; if (c >= 0x80) { if (c == 0x80) { byte fill = *pix++; if (fill == 0 && !withBlack) { scr += 128 + 1; ww -= 128 + 1; } else { byte runVal; *scr++ = fill; //TODO: wha? *scr++ = fill; ww -= 128 + 1; for (runVal = 127; runVal--;) *scr++ = fill; } } else { byte fill = *pix++; byte runVal = 255 - c + 2; ww -= runVal; if (fill == 0 && !withBlack) scr += runVal; else for (; runVal--;) *scr++ = fill; } } else { byte runVal = c + 1; ww -= runVal; for (; runVal--;) { byte p = *pix++; if (p == 0 && !withBlack) scr++; else *scr++ = p; } } } scr += width - w; } } else { // uncompressed for (; h--;) { for (int16 ww = w; ww--;) { byte p = *pix++; if (p == 0 && !withBlack) scr++; else *scr++ = p; } scr += width - w; } } } void EdenGraphics::setCursKeepPos(int16 x, int16 y) { _cursKeepPos = Common::Point(-1, -1); } byte *EdenGraphics::getSubtitlesViewBuf() { return _subtitlesViewBuf; } View *EdenGraphics::getSubtitlesView() { return _subtitlesView; } void EdenGraphics::loadMouthRectFromCurChar() { _rect_src.left = _curCharacterRect->left; _rect_src.top = _curCharacterRect->top; _rect_src.right = _curCharacterRect->right; _rect_src.bottom = _curCharacterRect->bottom; _rect_dst.left = _curCharacterRect->left + 320; _rect_dst.top = _curCharacterRect->top; _rect_dst.right = _curCharacterRect->right + 320; _rect_dst.bottom = _curCharacterRect->bottom; } void EdenGraphics::paneltobuf() { setSrcRect(0, 16, 320 - 1, 169 - 1); setDestRect(320, 16, 640 - 1, 169 - 1); CLBlitter_CopyViewRect(getMainView(), getMainView(), &_rect_src, &_rect_dst); } void EdenGraphics::cursbuftopanel() { setSrcRect(434, 40, 525 - 1, 111 - 1); setDestRect(114, 40, 205 - 1, 111 - 1); CLBlitter_CopyViewRect(getMainView(), getMainView(), &_rect_src, &_rect_dst); } void EdenGraphics::langbuftopanel() { setSrcRect(328, 42, 407 - 1, 97 - 1); setDestRect(8, 42, 87 - 1, 97 - 1); CLBlitter_CopyViewRect(getMainView(), getMainView(), &_rect_src, &_rect_dst); } // Original name: sauvefondbouche void EdenGraphics::saveMouthBackground() { loadMouthRectFromCurChar(); CLBlitter_CopyViewRect(getMainView(), getMainView(), &_rect_src, &_rect_dst); } // Original name: restaurefondbouche void EdenGraphics::restoreMouthBackground() { loadMouthRectFromCurChar(); CLBlitter_CopyViewRect(getMainView(), getMainView(), &_rect_dst, &_rect_src); } void EdenGraphics::setGlowX(int16 value) { _glowX = value; } View *EdenGraphics::getMainView() { return _mainView; } void EdenGraphics::setGlowY(int16 value) { _glowY = value; } void EdenGraphics::setCurCharRect(Common::Rect * charRect) { _curCharacterRect = charRect; } void EdenGraphics::sundcurs(int16 x, int16 y) { byte *keep = _game->getCurKeepBuf(); x = CLIP(x - 4, 0, 640 - 48); y = CLIP(y - 4, 0, 200 - 48); _cursKeepPos = Common::Point(x, y); byte *scr = _mainViewBuf + _cursKeepPos.x + _cursKeepPos.y * 640; for (int16 h = 48; h--;) { for (int16 w = 48; w--;) *keep++ = *scr++; scr += 640 - 48; } _game->setCursorSaved(true);; } void EdenGraphics::rundcurs() { byte *keep = _game->getCurKeepBuf(); byte *scr = _mainViewBuf + _cursKeepPos.x + _cursKeepPos.y * 640; if (!_game->getCursorSaved() || (_cursKeepPos == Common::Point(-1, -1))) //TODO ... return; for (int16 h = 48; h--;) { for (int16 w = 48; w--;) *scr++ = *keep++; scr += 640 - 48; } } byte * EdenGraphics::getHnmViewBuf() { return _hnmViewBuf; } void EdenGraphics::getglow(int16 x, int16 y, int16 w, int16 h) { byte *scr = _mainViewBuf + x + y * 640; byte *gl = _game->getGlowBuffer(); _glowX = x; _glowY = y; _glowW = w; _glowH = h; for (; h--;) { for (int16 ww = w; ww--;) *gl++ = *scr++; scr += 640 - w; } } void EdenGraphics::unglow() { byte *gl = _game->getGlowBuffer(); byte *scr = _mainViewBuf + _glowX + _glowY * 640; if (_glowX < 0 || _glowY < 0) //TODO: move it up return; for (; _glowH--;) { for (int16 ww = _glowW; ww--;) *scr++ = *gl++; scr += 640 - _glowW; } } void EdenGraphics::glow(int16 index) { // byte pixbase; byte *pix = _game->getBankData(); index += 9; pix += READ_LE_UINT16(pix); pix += READ_LE_UINT16(pix + index * 2); // int16 height:9 // int16 pad:6; // int16 flag:1; byte h0 = *pix++; byte h1 = *pix++; int16 w = ((h1 & 1) << 8) | h0; int16 h = *pix++; byte mode = *pix++; if (mode != 0xFF && mode != 0xFE) return; int16 x = _game->getCurPosX() + _game->getScrollPos() - 38; int16 y = _game->getCurPosY() - 28; int16 ex = _game->_globals->_frescoeWidth + 320; if (x + w <= 0 || x >= ex || y + h <= 0 || y >= 176) return; int16 dx; if (x < 0) { dx = -x; x = 0; } else if (x + w > ex) dx = x + w - ex; else dx = 0; int16 dy = 0; if (y < 16) { dy = 16 - y; y = 16; } else if (y + h > 175) dy = y + h - 175; int16 pstride = dx; int16 sstride = 640 - (w - dx); if (y == 16) pix += w * dy; if (x == 0) pix += dx; byte *scr = _mainViewBuf + x + y * 640; w -= dx; h -= dy; getglow(x, y, w, h); for (; h--;) { for (int16 ww = w; ww--;) { byte p = *pix++; if (p == 0) scr++; else *scr++ += p << 4; } pix += pstride; scr += sstride; } } // Original name : blackbars void EdenGraphics::drawBlackBars() { byte *scr = _mainViewBuf; for (int16 y = 0; y < 16; y++) { for (int16 x = 0; x < 640; x++) *scr++ = 0; } scr += 640 * (200 - 16 - 24); for (int16 y = 0; y < 24; y++) { for (int16 x = 0; x < 640; x++) *scr++ = 0; } } // Original name: restaurefriseshaut void EdenGraphics::restoreTopFrieze() { _underTopBarScreenRect.left = _game->getScrollPos(); _underTopBarScreenRect.right = _game->getScrollPos() + 320 - 1; CLBlitter_CopyViewRect(_underBarsView, getMainView(), &_underTopBarBackupRect, &_underTopBarScreenRect); } // Original name: bars_out void EdenGraphics::hideBars() { if (_showBlackBars) return; _game->display(); _underTopBarScreenRect.left = _game->getScrollPos(); _underTopBarScreenRect.right = _game->getScrollPos() + 320 - 1; CLBlitter_CopyViewRect(_mainView, _underBarsView, &_underTopBarScreenRect, &_underTopBarBackupRect); _underBottomBarScreenRect.left = _underTopBarScreenRect.left; _underBottomBarScreenRect.right = _underTopBarScreenRect.right; CLBlitter_CopyViewRect(_mainView, _underBarsView, &_underBottomBarScreenRect, &_underBottomBarBackupRect); int16 r19 = 14; // TODO - init in decl? int16 r20 = 176; int16 r25 = 14; int16 r24 = 21; _underTopBarScreenRect.left = 0; _underTopBarScreenRect.right = 320 - 1; _underTopBarBackupRect.left = _game->getScrollPos(); _underTopBarBackupRect.right = _game->getScrollPos() + 320 - 1; unsigned int *scr40, *scr41, *scr42; while (r24 > 0) { if (r25 > 0) { _underTopBarScreenRect.top = 16 - r25; _underTopBarScreenRect.bottom = 16 - 1; _underTopBarBackupRect.top = 0; _underTopBarBackupRect.bottom = r25 - 1; CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarScreenRect, &_underTopBarBackupRect); scr40 = ((unsigned int *)_mainViewBuf) + r19 * 640 / 4; scr41 = scr40 + 640 / 4; for (int i = 0; i < 320; i += 4) { *scr40++ = 0; *scr41++ = 0; } } _underTopBarScreenRect.top = 16; _underTopBarScreenRect.bottom = r24 + 16 - 1; _underTopBarBackupRect.top = 200 - r24; _underTopBarBackupRect.bottom = 200 - 1; CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarScreenRect, &_underTopBarBackupRect); scr40 = ((unsigned int *)_mainViewBuf) + r20 * 640 / 4; scr41 = scr40 + 640 / 4; scr42 = scr41 + 640 / 4; for (int i = 0; i < 320; i += 4) { *scr40++ = 0; *scr41++ = 0; *scr42++ = 0; } r19 -= 2; r20 += 3; r25 -= 2; r24 -= 3; _game->display(); } scr40 = (unsigned int *)_mainViewBuf; scr41 = scr40 + 640 / 4; for (int i = 0; i < 320; i += 4) { *scr40++ = 0; *scr41++ = 0; } scr40 = ((unsigned int *)_mainViewBuf) + r20 * 640 / 4; scr41 = scr40 + 640 / 4; scr42 = scr41 + 640 / 4; for (int i = 0; i < 320; i += 4) { *scr40++ = 0; *scr41++ = 0; *scr42++ = 0; } _game->display(); initRects(); _showBlackBars = true; } void EdenGraphics::initRects() { _underTopBarScreenRect = Common::Rect(0, 0, 320 - 1, 16 - 1); _underTopBarBackupRect = Common::Rect(0, 0, 320 - 1, 16 - 1); _underBottomBarScreenRect = Common::Rect(0, 176, 320 - 1, 200 - 1); //TODO: original bug? this cause crash in copyrect (this, underBottomBarBackupRect) _underBottomBarBackupRect = Common::Rect(0, 16, 320 - 1, 40 - 1); } // Original name: bars_in void EdenGraphics::showBars() { if (!_showBlackBars) return; drawBlackBars(); int16 r29 = 2; int16 r28 = 2; _underTopBarScreenRect.left = 0; _underTopBarScreenRect.right = 320 - 1; _underTopBarBackupRect.left = _game->getScrollPos(); _underTopBarBackupRect.right = _game->getScrollPos() + 320 - 1; while (r28 < 24) { if (r29 <= 16) { _underTopBarScreenRect.top = 16 - r29; _underTopBarScreenRect.bottom = 16 - 1; _underTopBarBackupRect.top = 0; _underTopBarBackupRect.bottom = r29 - 1; CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarScreenRect, &_underTopBarBackupRect); } _underTopBarScreenRect.top = 16; _underTopBarScreenRect.bottom = 16 + r28; _underTopBarBackupRect.top = 200 - 1 - r28; _underTopBarBackupRect.bottom = 200 - 1; CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarScreenRect, &_underTopBarBackupRect); r29 += 2; r28 += 3; _game->display(); } initRects(); _showBlackBars = false; } // Original name: af_image void EdenGraphics::displayImage() { byte *img = _game->getImageDesc() + 200; int16 count = READ_LE_UINT16(img); if (!count) return; byte *img_start = img; byte *curimg = _game->getImageDesc(); img += 2; count *= 3; while (count--) *curimg++ = *img++; img = img_start; count = READ_LE_UINT16(img); img += 2; /////// draw it while (count--) { uint16 index = *img++; uint16 x = *img++ + _game->getGameIconX(0); uint16 y = *img++ + _game->getGameIconY(0); byte *pix = _game->getBankData(); byte *scr = _mainViewBuf + x + y * 640; index--; if (READ_LE_UINT16(pix) > 2) readPalette(pix + 2); pix += READ_LE_UINT16(pix); pix += READ_LE_UINT16(pix + index * 2); // int16 height:9 // int16 pad:6; // int16 flag:1; byte h0 = *pix++; byte h1 = *pix++; int16 w = ((h1 & 1) << 8) | h0; int16 h = *pix++; byte mode = *pix++; if (mode != 0xFF && mode != 0xFE) continue; //TODO: enclosing block? if (h1 & 0x80) { // compressed for (; h-- > 0;) { for (int16 ww = w; ww > 0;) { byte c = *pix++; if (c >= 0x80) { if (c == 0x80) { byte fill = *pix++; if (fill == 0) { scr += 128 + 1; ww -= 128 + 1; } else { byte runVal; *scr++ = fill; //TODO: wha? *scr++ = fill; ww -= 128 + 1; for (runVal = 127; runVal--;) *scr++ = fill; } } else { byte fill = *pix++; byte runVal = 255 - c + 2; ww -= runVal; if (fill == 0) scr += runVal; else { for (; runVal--;) *scr++ = fill; } } } else { byte runVal = c + 1; ww -= runVal; for (; runVal--;) { byte p = *pix++; if (p == 0) scr++; else *scr++ = p; } } } scr += 640 - w; } } else { // uncompressed for (; h--;) { for (int16 ww = w; ww--;) { byte p = *pix++; if (p == 0) scr++; else *scr++ = p; } scr += 640 - w; } } } } // Original name: af_subtitle void EdenGraphics::displaySubtitles() { byte *src = _subtitlesViewBuf; byte *dst = _mainViewBuf; int16 y; if (_game->_globals->_displayFlags & DisplayFlags::dfFlag2) { y = 174; if ((_game->_globals->_drawFlags & DrawFlags::drDrawMenu) && _game->getNumTextLines() == 1) y = 167; dst += 640 * (y - _game->getNumTextLines() * FONT_HEIGHT) + _subtitlesXScrMargin; } else { y = 174; dst += 640 * (y - _game->getNumTextLines() * FONT_HEIGHT) + _game->getScrollPos() + _subtitlesXScrMargin; } if (_game->animationIsActive() && !_game->personIsTalking()) return; saveUnderSubtitles(y); for (int16 h = 0; h < _game->getNumTextLines() * FONT_HEIGHT + 1; h++) { for (int16 w = 0; w < _subtitlesXWidth; w++) { byte c = *src++; if (c) *dst = c; dst++; } dst += 640 - _subtitlesXWidth; } } // Original name afsalle1 void EdenGraphics::displaySingleRoom(Room *room) { byte *ptr = (byte *)getElem(_game->getPlaceRawBuf(), room->_id - 1); ptr++; for (;;) { byte b0 = *ptr++; byte b1 = *ptr++; int16 index = (b1 << 8) | b0; if (index == -1) break; if (index > 0) { int16 x = *ptr++ | (((b1 & 0x2) >> 1) << 8); //TODO: check me int16 y = *ptr++; ptr++; index &= 0x1FF; if (!(_game->_globals->_displayFlags & 0x80)) { if (index == 1 || _game->_globals->_varF7) drawSprite(index - 1, x, y, true); } _game->_globals->_varF7 = 0; continue; } if (b1 & 0x40) { if (b1 & 0x20) { bool addIcon = false; Icon *icon = _game->_globals->_nextRoomIcon; if (b0 < 4) { if (_game->_globals->_roomPtr->_exits[b0]) addIcon = true; } else if (b0 > 229) { if (_game->_globals->_partyOutside & (1 << (b0 - 230))) addIcon = true; } else if (b0 >= 100) { debug("add object %d", b0 - 100); if (_game->isObjectHere(b0 - 100)) { addIcon = true; _game->_globals->_varF7 = 1; } } else addIcon = true; if (addIcon) { icon->_actionId = b0; icon->_objectId = b0; icon->_cursorId = _game->getActionCursor(b0); int16 x = READ_LE_UINT16(ptr); ptr += 2; int16 y = READ_LE_UINT16(ptr); ptr += 2; int16 ex = READ_LE_UINT16(ptr); ptr += 2; int16 ey = READ_LE_UINT16(ptr); ptr += 2; x += _game->_globals->_roomBaseX; ex += _game->_globals->_roomBaseX; debug("add hotspot at %3d:%3d - %3d:%3d, action = %d", x, y, ex, ey, b0); if (_game->_vm->_showHotspots) { for (int iii = x; iii < ex; iii++) _mainViewBuf[y * 640 + iii] = _mainViewBuf[ey * 640 + iii] = (iii % 2) ? 0 : 255; for (int iii = y; iii < ey; iii++) _mainViewBuf[iii * 640 + x] = _mainViewBuf[iii * 640 + ex] = (iii % 2) ? 0 : 255; } icon->sx = x; icon->sy = y; icon->ex = ex; icon->ey = ey; _game->_globals->_nextRoomIcon = ++icon; icon->sx = -1; } else ptr += 8; } else ptr += 8; } else ptr += 8; } } // Original name: restaurefrisesbas void EdenGraphics::restoreBottomFrieze() { _underBottomBarScreenRect.left = _game->getScrollPos(); _underBottomBarScreenRect.right = _game->getScrollPos() + 320 - 1; CLBlitter_CopyViewRect(_underBarsView, getMainView(), &_underBottomBarBackupRect, &_underBottomBarScreenRect); } // Original name: sauvefriseshaut void EdenGraphics::saveTopFrieze(int16 x) { // Save top bar _underTopBarScreenRect = Common::Rect(x, 0, x + 320 - 1, 15); _underTopBarBackupRect = Common::Rect(0, 0, 320 - 1, 15); CLBlitter_CopyViewRect(getMainView(), _underBarsView, &_underTopBarScreenRect, &_underTopBarBackupRect); } // Original name: sauvefrisesbas void EdenGraphics::saveBottomFrieze() { // Save bottom bar _underBottomBarScreenRect.left = 0; _underBottomBarScreenRect.right = 320 - 1; CLBlitter_CopyViewRect(getMainView(), _underBarsView, &_underBottomBarScreenRect, &_underBottomBarBackupRect); } // Original name: afsalle void EdenGraphics::displayRoom() { Room *room = _game->_globals->_roomPtr; _game->_globals->_displayFlags = DisplayFlags::dfFlag1; _game->_globals->_roomBaseX = 0; _game->_globals->_roomBackgroundBankNum = room->_backgroundBankNum; if (room->_flags & RoomFlags::rf08) { _game->_globals->_displayFlags |= DisplayFlags::dfFlag80; if (room->_flags & RoomFlags::rfPanable) { // Scrollable room on 2 screens _game->_globals->_displayFlags |= DisplayFlags::dfPanable; _game->_globals->_varF4 = 0; rundcurs(); _game->saveFriezes(); _game->useBank(room->_bank - 1); drawSprite(0, 0, 16, true); _game->useBank(room->_bank); drawSprite(0, 320, 16, true); displaySingleRoom(room); _game->_globals->_roomBaseX = 320; displaySingleRoom(room + 1); } else displaySingleRoom(room); } else { //TODO: roomImgBank is garbage here! debug("displayRoom: room 0x%X using bank %d", _game->_globals->_roomNum, _game->_globals->_roomImgBank); _game->useBank(_game->_globals->_roomImgBank); displaySingleRoom(room); assert(_game->_vm->_screenView->_pitch == 320); } } View *EdenGraphics::getUnderBarsView() { return _underBarsView; } void EdenGraphics::openWindow() { _underBarsView = new View(320, 40); //TODO: Who deletes these? _underBarsView->_normal._width = 320; _view2 = new View(32, 32); _view2Buf = _view2->_bufferPtr; _subtitlesView = new View(_subtitlesXWidth, 60); _subtitlesViewBuf = _subtitlesView->_bufferPtr; _underSubtitlesView = new View(_subtitlesXWidth, 60); _underSubtitlesViewBuf = _underSubtitlesView->_bufferPtr; _mainView = new View(640, 200); _mainView->_normal._width = 320; CLBlitter_FillView(_mainView, 0xFFFFFFFF); _mainView->setSrcZoomValues(0, 0); _mainView->setDisplayZoomValues(640, 400); _mainView->centerIn(_game->_vm->_screenView); _mainViewBuf = _mainView->_bufferPtr; _game->setMouseCenterX(_mainView->_normal._dstLeft + _mainView->_normal._width / 2); _game->setMouseCenterY(_mainView->_normal._dstTop + _mainView->_normal._height / 2); _game->_vm->setMousePosition(_game->getMouseCenterX(), _game->getMouseCenterY()); _game->_vm->hideMouse(); _game->setCurPosX(320 / 2); _game->setCurPosY(200 / 2); } // Original name: effet1 void EdenGraphics::displayEffect1() { blackRect32(); setSrcRect(0, 0, 16 - 1, 4 - 1); int y = _mainView->_normal._dstTop; for (int16 i = 16; i <= 96; i += 4) { for (int x = _mainView->_normal._dstLeft; x < _mainView->_normal._dstLeft + 320; x += 16) { setDestRect(x, y + i, x + 16 - 1, y + i + 4 - 1); CLBlitter_CopyViewRect(_view2, _game->_vm->_screenView, &_rect_src, &_rect_dst); setDestRect(x, y + 192 - i, x + 16 - 1, y + 192 - i + 4 - 1); CLBlitter_CopyViewRect(_view2, _game->_vm->_screenView, &_rect_src, &_rect_dst); } CLBlitter_UpdateScreen(); _game->wait(1); } CLPalette_Send2Screen(_globalPalette, 0, 256); _mainView->_normal._height = 2; _mainView->_zoom._height = 4; int16 ny = _mainView->_normal._dstTop; int16 dy = _mainView->_zoom._dstTop; for (int16 i = 0; i < 100; i += 2) { _mainView->_normal._srcTop = 99 - i; _mainView->_zoom._srcTop = 99 - i; _mainView->_normal._dstTop = 99 - i + ny; _mainView->_zoom._dstTop = (99 - i) * 2 + dy; CLBlitter_CopyView2Screen(_mainView); _mainView->_normal._srcTop = 100 + i; _mainView->_zoom._srcTop = 100 + i; _mainView->_normal._dstTop = 100 + i + ny; _mainView->_zoom._dstTop = (100 + i) * 2 + dy; CLBlitter_CopyView2Screen(_mainView); CLBlitter_UpdateScreen(); _game->wait(1); } _mainView->_normal._height = 200; _mainView->_zoom._height = 400; _mainView->_normal._srcTop = 0; _mainView->_zoom._srcTop = 0; _mainView->_normal._dstTop = ny; _mainView->_zoom._dstTop = dy; _game->_globals->_varF1 = 0; } // Original name: effet2 void EdenGraphics::displayEffect2() { static int16 pattern1[] = { 0, 1, 2, 3, 7, 11, 15, 14, 13, 12, 8, 4, 5, 6, 10, 9 }; static int16 pattern2[] = { 0, 15, 1, 14, 2, 13, 3, 12, 7, 8, 11, 4, 5, 10, 6, 9 }; static int16 pattern3[] = { 0, 2, 5, 7, 8, 10, 13, 15, 1, 3, 4, 6, 9, 11, 12, 14 }; static int16 pattern4[] = { 0, 3, 15, 12, 1, 7, 14, 8, 2, 11, 13, 4, 5, 6, 10, 9 }; static int eff2pat = 0; if (_game->_globals->_var103 == 69) { displayEffect4(); return; } switch (++eff2pat) { case 1: colimacon(pattern1); break; case 2: colimacon(pattern2); break; case 3: colimacon(pattern3); break; case 4: default: colimacon(pattern4); eff2pat = 0; break; } } // Original name: effet3 void EdenGraphics::displayEffect3() { CLPalette_GetLastPalette(_oldPalette); for (uint16 i = 0; i < 6; i++) { for (uint16 c = 0; c < 256; c++) { _newColor.r = _oldPalette[c].r >> i; _newColor.g = _oldPalette[c].g >> i; _newColor.b = _oldPalette[c].b >> i; CLPalette_SetRGBColor(_newPalette, c, &_newColor); } CLPalette_Send2Screen(_newPalette, 0, 256); _game->wait(1); } CLBlitter_CopyView2Screen(_mainView); for (uint16 i = 0; i < 6; i++) { for (uint16 c = 0; c < 256; c++) { _newColor.r = _globalPalette[c].r >> (5 - i); _newColor.g = _globalPalette[c].g >> (5 - i); _newColor.b = _globalPalette[c].b >> (5 - i); CLPalette_SetRGBColor(_newPalette, c, &_newColor); } CLPalette_Send2Screen(_newPalette, 0, 256); _game->wait(1); } } // Original name: effet4 void EdenGraphics::displayEffect4() { byte *scr, *pix, *r24, *r25, *r30, c; int16 r17, r23, r16, r18, r19, r22, r27, r31; CLPalette_Send2Screen(_globalPalette, 0, 256); int16 ww = _game->_vm->_screenView->_pitch; int16 x = _mainView->_normal._dstLeft; int16 y = _mainView->_normal._dstTop; for (int16 i = 32; i > 0; i -= 2) { scr = _game->_vm->_screenView->_bufferPtr; scr += (y + 16) * ww + x; pix = _mainView->_bufferPtr + 16 * 640; r17 = 320 / i; r23 = 320 - 320 / i * i; //TODO: 320 % i ? r16 = 160 / i; r18 = 160 - 160 / i * i; //TODO: 160 % i ? for (r19 = r16; r19 > 0; r19--) { r24 = scr; r25 = pix; for (r22 = r17; r22 > 0; r22--) { c = *r25; r25 += i; r30 = r24; for (r27 = i; r27 > 0; r27--) { for (r31 = i; r31 > 0; r31--) *r30++ = c; r30 += ww - i; } r24 += i; } if (r23) { c = *r25; r30 = r24; for (r27 = i; r27 > 0; r27--) { for (r31 = r23; r31 > 0; r31--) *r30++ = c; r30 += ww - r23; } } scr += i * ww; pix += i * 640; } if (r18) { r24 = scr; r25 = pix; for (r22 = r17; r22 > 0; r22--) { c = *r25; r25 += i; r30 = r24; for (r27 = r18; r27 > 0; r27--) { for (r31 = i; r31 > 0; r31--) *r30++ = c; r30 += ww - i; } r24 += i; } if (r23) { c = *r25; r30 = r24; for (r27 = r18; r27 > 0; r27--) { for (r31 = r23; r31 > 0; r31--) *r30++ = c; r30 += ww - r23; } } } CLBlitter_UpdateScreen(); _game->wait(3); } CLBlitter_CopyView2Screen(_mainView); } void EdenGraphics::clearScreen() { int16 ww = _game->_vm->_screenView->_pitch; int16 x = _mainView->_normal._dstLeft; int16 y = _mainView->_normal._dstTop; byte *scr = _game->_vm->_screenView->_bufferPtr; scr += (y + 16) * ww + x; for (int16 yy = 0; yy < 160; yy++) { for (int16 xx = 0; xx < 320; xx++) *scr++ = 0; scr += ww - 320; } CLBlitter_UpdateScreen(); } void EdenGraphics::colimacon(int16 pattern[16]) { int16 p, r27, r25; int16 ww = _game->_vm->_screenView->_pitch; int16 x = _mainView->_normal._dstLeft; int16 y = _mainView->_normal._dstTop; byte *scr = _game->_vm->_screenView->_bufferPtr; scr += (y + 16) * ww + x; for (int16 i = 0; i < 16; i++) { p = pattern[i]; r27 = p % 4 + p / 4 * ww; for (int16 j = 0; j < 320 * 160 / 16; j++) scr[j / (320 / 4) * ww * 4 + j % (320 / 4) * 4 + r27] = 0; CLBlitter_UpdateScreen(); _game->wait(1); } CLPalette_Send2Screen(_globalPalette, 0, 256); byte *pix = _mainView->_bufferPtr; x = _mainView->_normal._dstLeft; y = _mainView->_normal._dstTop; pix += 640 * 16; scr = _game->_vm->_screenView->_bufferPtr; scr += (y + 16) * ww + x; for (int16 i = 0; i < 16; i++) { p = pattern[i]; r25 = p % 4 + p / 4 * 640; r27 = p % 4 + p / 4 * ww; for (int16 j = 0; j < 320 * 160 / 16; j++) scr[j / (320 / 4) * ww * 4 + j % (320 / 4) * 4 + r27] = pix[j / (320 / 4) * 640 * 4 + j % (320 / 4) * 4 + r25]; CLBlitter_UpdateScreen(); _game->wait(1); } } void EdenGraphics::fadeToBlack(int delay) { CLPalette_GetLastPalette(_oldPalette); for (int16 i = 0; i < 6; i++) { for (int16 j = 0; j < 256; j++) { _newColor.r = _oldPalette[j].r >> i; _newColor.g = _oldPalette[j].g >> i; _newColor.b = _oldPalette[j].b >> i; CLPalette_SetRGBColor(_newPalette, j, &_newColor); } CLPalette_Send2Screen(_newPalette, 0, 256); _game->wait(delay); } } // Original name: fadetoblack128 void EdenGraphics::fadeToBlackLowPalette(int delay) { CLPalette_GetLastPalette(_oldPalette); for (int16 i = 0; i < 6; i++) { for (int16 j = 0; j < 129; j++) { //CHECKME: Should be 128? _newColor.r = _oldPalette[j].r >> i; _newColor.g = _oldPalette[j].g >> i; _newColor.b = _oldPalette[j].b >> i; CLPalette_SetRGBColor(_newPalette, j, &_newColor); } CLPalette_Send2Screen(_newPalette, 0, 128); _game->wait(delay); } } // Original name: fadefromblack128 void EdenGraphics::fadeFromBlackLowPalette(int delay) { for (int16 i = 0; i < 6; i++) { for (int16 j = 0; j < 129; j++) { //CHECKME: Should be 128? _newColor.r = _globalPalette[j].r >> (5 - i); _newColor.g = _globalPalette[j].g >> (5 - i); _newColor.b = _globalPalette[j].b >> (5 - i); CLPalette_SetRGBColor(_newPalette, j, &_newColor); } CLPalette_Send2Screen(_newPalette, 0, 128); _game->wait(delay); } } // Original name: rectanglenoir32 void EdenGraphics::blackRect32() { // blacken 32x32 rectangle int *pix = (int *)_view2Buf; for (int16 i = 0; i < 32; i++) { pix[0] = 0; pix[1] = 0; pix[2] = 0; pix[3] = 0; pix[4] = 0; pix[5] = 0; pix[6] = 0; pix[7] = 0; pix += 32 / 4; } } void EdenGraphics::setSrcRect(int16 sx, int16 sy, int16 ex, int16 ey) { _rect_src = Common::Rect(sx, sy, ex, ey); } void EdenGraphics::setDestRect(int16 sx, int16 sy, int16 ex, int16 ey) { _rect_dst = Common::Rect(sx, sy, ex, ey); } void EdenGraphics::effetpix() { uint16 r25, r18, r31, r30; //TODO: change to xx/yy uint16 ww = _game->_vm->_screenView->_pitch; r25 = ww * 80; r18 = 640 * 80; byte *pix = _mainView->_bufferPtr + 16 * 640; int x = _mainView->_normal._dstLeft; int y = _mainView->_normal._dstTop; byte *scr = _game->_vm->_screenView->_bufferPtr; scr += (y + 16) * ww + x; int16 r20 = 0x4400; //TODO int16 r27 = 1; int16 r26 = 0; do { char r8 = r27 & 1; r27 >>= 1; if (r8) r27 ^= r20; if (r27 < 320 * 80) { r31 = r27 / 320; r30 = r27 % 320; scr[r31 * ww + r30] = 0; scr[r31 * ww + r25 + r30] = 0; if (++r26 == 960) { CLBlitter_UpdateScreen(); _game->wait(1); r26 = 0; } } } while (r27 != 1); CLPalette_Send2Screen(_globalPalette, 0, 256); r20 = 0x4400; r27 = 1; r26 = 0; do { char r8 = r27 & 1; r27 >>= 1; if (r8) r27 ^= r20; if (r27 < 320 * 80) { r31 = r27 / 320; r30 = r27 % 320; byte p0 = pix[r31 * 640 + r30]; byte p1 = pix[r31 * 640 + r18 + r30]; scr[r31 * ww + r30] = p0; scr[r31 * ww + r25 + r30] = p1; if (++r26 == 960) { CLBlitter_UpdateScreen(); _game->wait(1); r26 = 0; } } } while (r27 != 1); assert(_game->_vm->_screenView->_pitch == 320); } ////// film.c // Original name: showfilm void EdenGraphics::showMovie(char arg1) { _video->readHeader(); if (_game->_globals->_curVideoNum == 92) { // _hnmContext->_header._unusedFlag2 = 0; CHECKME: Useless? _game->setVolume(0); } if (_video->getVersion() != 4) return; bool playing = true; _video->allocMemory(); _hnmView = new View(_video->_header._width, _video->_header._height); _hnmView->setSrcZoomValues(0, 0); _hnmView->setDisplayZoomValues(_video->_header._width * 2, _video->_header._height * 2); _hnmView->centerIn(_game->_vm->_screenView); _hnmViewBuf = _hnmView->_bufferPtr; if (arg1) { _hnmView->_normal._height = 160; _hnmView->_zoom._height = 320; //TODO: width?? _hnmView->_normal._dstTop = _mainView->_normal._dstTop + 16; _hnmView->_zoom._dstTop = _mainView->_zoom._dstTop + 32; } _video->setFinalBuffer(_hnmView->_bufferPtr); do { _hnmFrameNum = _video->getFrameNum(); _video->waitLoop(); playing = _video->nextElement(); if (_game->getSpecialTextMode()) handleHNMSubtitles(); else _game->musicspy(); CLBlitter_CopyView2Screen(_hnmView); assert(_game->_vm->_screenView->_pitch == 320); _game->_vm->pollEvents(); if (arg1) { if (_game->_vm->isMouseButtonDown()) { if (!_game->isMouseHeld()) { _game->setMouseHeld(); _videoCanceledFlag = true; } } else _game->setMouseNotHeld(); } } while (playing && !_videoCanceledFlag); delete _hnmView; _video->deallocMemory(); } bool EdenGraphics::getShowBlackBars() { return _showBlackBars; } void EdenGraphics::setShowBlackBars(bool value) { _showBlackBars = value; } void EdenGraphics::playHNM(int16 num) { perso_t *perso = nullptr; int16 oldDialogType = -1; _game->_globals->_curVideoNum = num; if (num != 2001 && num != 2012 && num != 98 && num != 171) { byte oldMusicType = _game->_globals->_newMusicType; _game->_globals->_newMusicType = MusicType::mtEvent; _game->musique(); _game->musicspy(); _game->_globals->_newMusicType = oldMusicType; } _game->_globals->_videoSubtitleIndex = 1; if (_game->getSpecialTextMode()) { perso = _game->_globals->_characterPtr; oldDialogType = _game->_globals->_dialogType; _game->preloadDialogs(num); _game->fademusica0(1); _game->stopMusic(); } _showVideoSubtitle = false; _videoCanceledFlag = false; _game->loadHnm(num); _video->reset(); if (_needToFade) { fadeToBlack(4); clearScreen(); _needToFade = false; } if (num == 2012 || num == 98 || num == 171) showMovie(0); else showMovie(1); _cursKeepPos = Common::Point(-1, -1); if (_game->getSpecialTextMode()) { _game->setMusicFade(3);; _game->musicspy(); _game->_globals->_characterPtr = perso; _game->_globals->_dialogType = oldDialogType; _game->setSpecialTextMode(false); } if (_videoCanceledFlag) _game->_globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; if (_game->_globals->_curVideoNum == 167) _game->_globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; if (_game->_globals->_curVideoNum == 104) _game->_globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; if (_game->_globals->_curVideoNum == 102) _game->_globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; if (_game->_globals->_curVideoNum == 77) _game->_globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; if (_game->_globals->_curVideoNum == 149) _game->_globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; } void EdenGraphics::initGlobals() { _underSubtitlesScreenRect.top = 0; _underSubtitlesScreenRect.left = _subtitlesXScrMargin; _underSubtitlesScreenRect.right = _subtitlesXScrMargin + _subtitlesXWidth - 1; _underSubtitlesScreenRect.bottom = 176 - 1; _underSubtitlesBackupRect.top = 0; _underSubtitlesBackupRect.left = _subtitlesXScrMargin; _underSubtitlesBackupRect.right = _subtitlesXScrMargin + _subtitlesXWidth - 1; _underSubtitlesBackupRect.bottom = 60 - 1; } // Original name: sauvefondbulle void EdenGraphics::saveUnderSubtitles(int16 y) { _underSubtitlesScreenRect.top = y - _game->getNumTextLines() * FONT_HEIGHT; _underSubtitlesScreenRect.left = _game->getScrollPos() + _subtitlesXScrMargin; _underSubtitlesScreenRect.right = _game->getScrollPos() + _subtitlesXScrMargin + _subtitlesXWidth - 1; _underSubtitlesScreenRect.bottom = y; _underSubtitlesBackupRect.top = 0; _underSubtitlesBackupRect.bottom = _game->getNumTextLines() * FONT_HEIGHT; CLBlitter_CopyViewRect(getMainView(), _underSubtitlesView, &_underSubtitlesScreenRect, &_underSubtitlesBackupRect); _savedUnderSubtitles = true; } void EdenGraphics::setSavedUnderSubtitles(bool value) { _savedUnderSubtitles = value; } // Original name: restaurefondbulle void EdenGraphics::restoreUnderSubtitles() { if (!_savedUnderSubtitles) return; CLBlitter_CopyViewRect(_underSubtitlesView, getMainView(), &_underSubtitlesBackupRect, &_underSubtitlesScreenRect); _savedUnderSubtitles = false; } // Original name: af_subtitlehnm void EdenGraphics::displayHNMSubtitle() { byte *src = getSubtitlesViewBuf(); byte *dst = getHnmViewBuf() + _subtitlesXScrMargin + (158 - _game->getNumTextLines() * FONT_HEIGHT) * 320; for (int16 y = 0; y < _game->getNumTextLines() * FONT_HEIGHT; y++) { for (int16 x = 0; x < _subtitlesXWidth; x++) { char c = *src++; if (c) *dst = c; dst++; } dst += 320 - _subtitlesXWidth; } } // Original name bullehnm void EdenGraphics::handleHNMSubtitles() { #define SUB_LINE(start, end) \ (start), (end) | 0x8000 static uint16 kFramesVid170[] = { SUB_LINE(68, 120), SUB_LINE(123, 196), SUB_LINE(199, 274), SUB_LINE(276, 370), SUB_LINE(799, 885), SUB_LINE(888, 940), SUB_LINE(947, 1000), SUB_LINE(1319, 1378), SUB_LINE(1380, 1440), SUB_LINE(1854, 1898), SUB_LINE(1900, 1960), SUB_LINE(2116, 2184), SUB_LINE(2186, 2252), SUB_LINE(2254, 2320), SUB_LINE(3038, 3094), SUB_LINE(3096, 3160), 0xFFFF }; static uint16 kFramesVid83[] = { SUB_LINE(99, 155), SUB_LINE(157, 256), 0xFFFF }; static uint16 kFramesVid88[] = { SUB_LINE(106, 173), SUB_LINE(175, 244), SUB_LINE(246, 350), SUB_LINE(352, 467), 0xFFFF }; static uint16 kFramesVid89[] = { SUB_LINE(126, 176), SUB_LINE(178, 267), SUB_LINE(269, 342), SUB_LINE(344, 398), SUB_LINE(400, 458), SUB_LINE(460, 558), 0xFFFF }; static uint16 kFramesVid94[] = { SUB_LINE(101, 213), SUB_LINE(215, 353), SUB_LINE(355, 455), SUB_LINE(457, 518), SUB_LINE(520, 660), SUB_LINE(662, 768), 0xFFFF }; #undef SUB_LINE uint16 *frames = nullptr; perso_t *perso = nullptr; switch (_game->_globals->_curVideoNum) { case 170: frames = kFramesVid170; break; case 83: frames = kFramesVid83; break; case 88: frames = kFramesVid88; break; case 89: frames = kFramesVid89; break; case 94: frames = kFramesVid94; break; default: return; } perso = _game->personSubtitles(); assert(perso != nullptr); assert(frames != nullptr); uint16 *frames_start = frames; uint16 frame; while ((frame = *frames++) != 0xFFFF) { if ((frame & ~0x8000) == _hnmFrameNum) break; } if (frame == 0xFFFF) { if (_showVideoSubtitle) displayHNMSubtitle(); return; } if (frame & 0x8000) _showVideoSubtitle = false; else { _game->_globals->_videoSubtitleIndex = (frames - frames_start) / 2 + 1; _game->_globals->_characterPtr = perso; _game->_globals->_dialogType = DialogType::dtInspect; int16 num = (perso->_id << 3) | _game->_globals->_dialogType; _game->dialoscansvmas((Dialog *)getElem(_game->getGameDialogs(), num)); _showVideoSubtitle = true; } if (_showVideoSubtitle) displayHNMSubtitle(); } } // namespace Cryo