From d3d5ff2a888e7134b299db7fcb928735089f908e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 12 Feb 2017 00:39:07 +0200 Subject: CRYO: Split graphics and resource-related functions into separate files --- engines/cryo/eden.cpp | 1683 --------------------------------------------- engines/cryo/graphics.cpp | 1219 ++++++++++++++++++++++++++++++++ engines/cryo/module.mk | 2 + engines/cryo/resource.cpp | 555 +++++++++++++++ 4 files changed, 1776 insertions(+), 1683 deletions(-) create mode 100644 engines/cryo/graphics.cpp create mode 100644 engines/cryo/resource.cpp diff --git a/engines/cryo/eden.cpp b/engines/cryo/eden.cpp index a108ea2169..0d4cb7478a 100644 --- a/engines/cryo/eden.cpp +++ b/engines/cryo/eden.cpp @@ -48,7 +48,6 @@ namespace Cryo { -#define CRYO_DAT_VER 1 // 1 byte #define Z_RESET -3400 #define Z_STEP 200 #define Z_UP 1 @@ -1090,208 +1089,6 @@ void EdenGame::useBank(int16 bank) { } } -void EdenGame::sundcurs(int16 x, int16 y) { - byte *keep = _cursKeepBuf; - 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; - } - _cursorSaved = true; -} - -void EdenGame::rundcurs() { - byte *keep = _cursKeepBuf; - byte *scr = _mainViewBuf + _cursKeepPos.x + _cursKeepPos.y * 640; - if (!_cursorSaved || (_cursKeepPos == Common::Point(-1, -1))) //TODO ... - return; - - for (int16 h = 48; h--;) { - for (int16 w = 48; w--;) - *scr++ = *keep++; - scr += 640 - 48; - } - -} - -// Original name: noclipax -void EdenGame::drawSprite(int16 index, int16 x, int16 y, bool withBlack) { - byte *pix = _bankData; - byte *scr = _mainViewBuf + x + y * 640; - if (_curBankNum != 117 && (!_noPalette || withBlack)) { - 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) - 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 += 640 - w; - } - } else { - // uncompressed - for (; h--;) { - for (int16 ww = w; ww--;) { - byte p = *pix++; - if (p == 0 && !withBlack) - scr++; - else - *scr++ = p; - } - scr += 640 - w; - } - } -} - -void EdenGame::getglow(int16 x, int16 y, int16 w, int16 h) { - byte *scr = _mainViewBuf + x + y * 640; - byte *gl = _glowBuffer; - _glowX = x; - _glowY = y; - _glowW = w; - _glowH = h; - for (; h--;) { - for (int16 ww = w; ww--;) - *gl++ = *scr++; - scr += 640 - w; - } -} - -void EdenGame::unglow() { - byte *gl = _glowBuffer; - 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 EdenGame::glow(int16 index) { - // byte pixbase; - byte *pix = _bankData; - - 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 = _cursorPosX + _scrollPos - 38; - int16 y = _cursorPosY - 28; - int16 ex = _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; - } -} - void EdenGame::readPalette(byte *ptr) { bool doit = true; color3_t pal_entry; @@ -1396,112 +1193,6 @@ void EdenGame::spriteOnSubtitle(int16 index, int16 x, int16 y) { } } -// Original name: bars_out -void EdenGame::hideBars() { - if (_showBlackBars) - return; - - display(); - _underTopBarScreenRect.left = _scrollPos; - _underTopBarScreenRect.right = _scrollPos + 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 = _scrollPos; - _underTopBarBackupRect.right = _scrollPos + 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; - 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; - } - display(); - initRects(); - _showBlackBars = true; -} - -// Original name: bars_in -void EdenGame::showBars() { - if (!_showBlackBars) - return; - - drawBlackBars(); - int16 r29 = 2; - int16 r28 = 2; - _underTopBarScreenRect.left = 0; - _underTopBarScreenRect.right = 320 - 1; - _underTopBarBackupRect.left = _scrollPos; - _underTopBarBackupRect.right = _scrollPos + 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; - display(); - } - initRects(); - _showBlackBars = false; -} - // Original name: sauvefondbouche void EdenGame::saveMouthBackground() { rect_src.left = _curCharacterRect->left; @@ -1529,21 +1220,6 @@ void EdenGame::restoreMouthBackground() { CLBlitter_CopyViewRect(_mainView, _mainView, &rect_dst, &rect_src); } -// Original name : blackbars -void EdenGame::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; - } -} - void EdenGame::drawTopScreen() { // Draw top bar (location / party / map) _globals->_drawFlags &= ~DrawFlags::drDrawTopScreen; useBank(314); @@ -2372,106 +2048,6 @@ void EdenGame::setCharacterSprite(byte *spr) { _imageDesc[201] = count >> 8; } -// Original name: af_image -void EdenGame::displayImage() { - byte *img = _imageDesc + 200; - - int16 count = READ_LE_UINT16(img); - if (!count) - return; - - byte *img_start = img; - byte *curimg = _imageDesc; - - 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++ + _gameIcons[0].sx; - uint16 y = *img++ + _gameIcons[0].sy; - byte *pix = _bankData; - 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_perso1 void EdenGame::displayCharacter1() { setCharacterSprite(_globals->_persoSpritePtr + READ_LE_UINT16(_globals->_persoSpritePtr)); @@ -2989,34 +2565,6 @@ void EdenGame::drawSubtitleChar(byte c, byte color, int16 width) { } } -// Original name: af_subtitle -void EdenGame::displaySubtitles() { - byte *src = _subtitlesViewBuf; - byte *dst = _mainViewBuf; - int16 y; - if (_globals->_displayFlags & DisplayFlags::dfFlag2) { - y = 174; - if ((_globals->_drawFlags & DrawFlags::drDrawMenu) && _numTextLines == 1) - y = 167; - dst += 640 * (y - _numTextLines * FONT_HEIGHT) + _subtitlesXScrMargin; - } else { - y = 174; - dst += 640 * (y - _numTextLines * FONT_HEIGHT) + _scrollPos + _subtitlesXScrMargin; - } - if (_animationActive && !_personTalking) - return; - saveUnderSubtitles(y); - for (int16 h = 0; h < _numTextLines * FONT_HEIGHT + 1; h++) { - for (int16 w = 0; w < _subtitlesXWidth; w++) { - byte c = *src++; - if (c) - *dst = c; - dst++; - } - dst += 640 - _subtitlesXWidth; - } -} - // Original name: sauvefondbulle void EdenGame::saveUnderSubtitles(int16 y) { _underSubtitlesScreenRect.top = y - _numTextLines * FONT_HEIGHT; @@ -4100,306 +3648,6 @@ void EdenGame::setChrono(int16 t) { _globals->_chronoFlag = 1; } -// Original name: prechargephrases -void EdenGame::preloadDialogs(int16 vid) { - perso_t *perso = &_persons[PER_MORKUS]; - if (vid == 170) - perso = &_persons[PER_UNKN_156]; - _globals->_characterPtr = perso; - _globals->_dialogType = DialogType::dtInspect; - int num = (perso->_id << 3) | _globals->_dialogType; - Dialog *dial = (Dialog *)getElem(_gameDialogs, num); - dialoscansvmas(dial); -} - -// Original name: effet1 -void EdenGame::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, _vm->_screenView, &rect_src, &rect_dst); - setDestRect(x, y + 192 - i, x + 16 - 1, y + 192 - i + 4 - 1); - CLBlitter_CopyViewRect(_view2, _vm->_screenView, &rect_src, &rect_dst); - } - CLBlitter_UpdateScreen(); - 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(); - 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; - _globals->_varF1 = 0; -} - -// Original name: effet2 -void EdenGame::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 (_globals->_var103 == 69) { - displayEffect4(); - return; - } - switch (++eff2pat) { - case 1: - colimacon(pattern1); - break; - case 2: - colimacon(pattern2); - break; - case 3: - colimacon(pattern3); - break; - case 4: - colimacon(pattern4); - eff2pat = 0; - break; - } -} - -// Original name: effet3 -void EdenGame::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); - 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); - wait(1); - } -} - -// Original name: effet4 -void EdenGame::displayEffect4() { - byte *scr, *pix, *r24, *r25, *r30, c; - int16 r17, r23, r16, r18, r19, r22, r27, r31; - CLPalette_Send2Screen(_globalPalette, 0, 256); - - int16 ww = _vm->_screenView->_pitch; - int16 x = _mainView->_normal._dstLeft; - int16 y = _mainView->_normal._dstTop; - for (int16 i = 32; i > 0; i -= 2) { - scr = _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(); - wait(3); - } - CLBlitter_CopyView2Screen(_mainView); -} - -void EdenGame::clearScreen() { - int16 ww = _vm->_screenView->_pitch; - int16 x = _mainView->_normal._dstLeft; - int16 y = _mainView->_normal._dstTop; - byte *scr = _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 EdenGame::colimacon(int16 pattern[16]) { - int16 p, r27, r25; - - int16 ww = _vm->_screenView->_pitch; - int16 x = _mainView->_normal._dstLeft; - int16 y = _mainView->_normal._dstTop; - byte *scr = _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(); - wait(1); - } - CLPalette_Send2Screen(_globalPalette, 0, 256); - byte *pix = _mainView->_bufferPtr; - x = _mainView->_normal._dstLeft; - y = _mainView->_normal._dstTop; - pix += 640 * 16; - scr = _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(); - wait(1); - } -} - -void EdenGame::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); - wait(delay); - } -} - -// Original name: fadetoblack128 -void EdenGame::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); - wait(delay); - } -} - -// Original name: fadefromblack128 -void EdenGame::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); - wait(delay); - } -} - -// Original name: rectanglenoir32 -void EdenGame::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 EdenGame::setSrcRect(int16 sx, int16 sy, int16 ex, int16 ey) { - rect_src = Common::Rect(sx, sy, ex, ey); -} - -void EdenGame::setDestRect(int16 sx, int16 sy, int16 ex, int16 ey) { - rect_dst = Common::Rect(sx, sy, ex, ey); -} - void EdenGame::wait(int howlong) { int t = g_system->getMillis(); @@ -4407,554 +3655,6 @@ void EdenGame::wait(int howlong) { g_system->delayMillis(10); // waste time } -void EdenGame::effetpix() { - uint16 r25, r18, r31, r30; //TODO: change to xx/yy - - uint16 ww = _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 = _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(); - 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(); - wait(1); - r26 = 0; - } - } - } while (r27 != 1); - assert(_vm->_screenView->_pitch == 320); -} - -////// datfile.c -void EdenGame::verifh(byte *ptr) { - byte sum = 0; - byte *head = ptr; - - for (int8 i = 0; i < 6; i++) - sum += *head++; - - if (sum != 0xAB) - return; - - debug("* Begin unpacking resource"); - head -= 6; - uint16 h0 = READ_LE_UINT16(head); - // 3 = 2 bytes for the uint16 and 1 byte for an unused char - head += 3; - uint16 h3 = READ_LE_UINT16(head); - head += 2; - byte *data = h0 + head + 26; - h3 -= 6; - head += h3; - for (; h3; h3--) - *data-- = *head--; - head = data + 1; - data = ptr; - expandHSQ(head, data); -} - -void EdenGame::openbigfile() { - _bigfile.open("EDEN.DAT"); - - char buf[16]; - int count = _bigfile.readUint16LE(); - _bigfileHeader = new PakHeaderNode(count); - for (int j = 0; j < count; j++) { - for (int k = 0; k < 16; k++) - buf[k] = _bigfile.readByte(); - _bigfileHeader->_files[j]._name = Common::String(buf); - _bigfileHeader->_files[j]._size = _bigfile.readUint32LE(); - _bigfileHeader->_files[j]._offs = _bigfile.readUint32LE(); - _bigfileHeader->_files[j]._flag = _bigfile.readByte(); - } - - _vm->_video->resetInternals(); - _vm->_video->setFile(&_bigfile); -} - -void EdenGame::closebigfile() { - _bigfile.close(); -} - -void EdenGame::loadRawFile(uint16 num, byte *buffer) { - if (_vm->getPlatform() == Common::kPlatformDOS) { - if ((_vm->isDemo() && num > 2204) || num > 2472) - error("Trying to read invalid game resource"); - } - - assert(num < _bigfileHeader->_count); - PakHeaderItem *file = &_bigfileHeader->_files[num]; - int32 size = file->_size; - int32 offs = file->_offs; - - _bigfile.seek(offs, SEEK_SET); - _bigfile.read(buffer, size); -} - -void EdenGame::loadIconFile(uint16 num, Icon *buffer) { - if (_vm->getPlatform() == Common::kPlatformDOS) { - if ((_vm->isDemo() && num > 2204) || num > 2472) - error("Trying to read invalid game resource"); - } - - assert(num < _bigfileHeader->_count); - PakHeaderItem *file = &_bigfileHeader->_files[num]; - int32 size = file->_size; - int32 offs = file->_offs; - debug("* Loading icon - Resource %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), offs, size); - _bigfile.seek(offs, SEEK_SET); - - int count = size / 18; // sizeof(Icon) - for (int i = 0; i < count; i++) { - if (_vm->getPlatform() == Common::kPlatformMacintosh) { - buffer[i].sx = _bigfile.readSint16BE(); - buffer[i].sy = _bigfile.readSint16BE(); - buffer[i].ex = _bigfile.readSint16BE(); - buffer[i].ey = _bigfile.readSint16BE(); - buffer[i]._cursorId = _bigfile.readUint16BE();; - buffer[i]._actionId= _bigfile.readUint32BE();; - buffer[i]._objectId= _bigfile.readUint32BE();; - } else { - buffer[i].sx = _bigfile.readSint16LE(); - buffer[i].sy = _bigfile.readSint16LE(); - buffer[i].ex = _bigfile.readSint16LE(); - buffer[i].ey = _bigfile.readSint16LE(); - buffer[i]._cursorId = _bigfile.readUint16LE();; - buffer[i]._actionId= _bigfile.readUint32LE();; - buffer[i]._objectId= _bigfile.readUint32LE();; - } - } -} - -void EdenGame::loadRoomFile(uint16 num, Room *buffer) { - if (_vm->getPlatform() == Common::kPlatformDOS) { - if ((_vm->isDemo() && num > 2204) || num > 2472) - error("Trying to read invalid game resource"); - } - - assert(num < _bigfileHeader->_count); - PakHeaderItem *file = &_bigfileHeader->_files[num]; - int32 size = file->_size; - int32 offs = file->_offs; - debug("* Loading room - Resource %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), offs, size); - _bigfile.seek(offs, SEEK_SET); - - int count = size / 14; // sizeof(Room) - for (int i = 0; i < count; i++) { - buffer[i]._id = _bigfile.readByte(); - for (int j = 0; j < 4; j++) - buffer[i]._exits[j] = _bigfile.readByte(); - buffer[i]._flags = _bigfile.readByte(); - if (_vm->getPlatform() == Common::kPlatformMacintosh) { - buffer[i]._bank = _bigfile.readUint16BE(); - buffer[i]._party = _bigfile.readUint16BE(); - } else { - buffer[i]._bank = _bigfile.readUint16LE(); - buffer[i]._party = _bigfile.readUint16LE(); - } - buffer[i]._level = _bigfile.readByte(); - buffer[i]._video = _bigfile.readByte(); - buffer[i]._location = _bigfile.readByte(); - buffer[i]._backgroundBankNum = _bigfile.readByte(); - } -} - -// Original name: shnmfl -void EdenGame::loadHnm(uint16 num) { - unsigned int resNum = num - 1 + 485; - assert(resNum < _bigfileHeader->_count); - PakHeaderItem *file = &_bigfileHeader->_files[resNum]; - int size = file->_size; - int offs = file->_offs; - debug("* Loading movie %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), (uint)offs, size); - _vm->_video->_file->seek(offs, SEEK_SET); -} - -// Original name: ssndfl -int EdenGame::loadSound(uint16 num) { - unsigned int resNum = num - 1 + ((_vm->getPlatform() == Common::kPlatformDOS && _vm->isDemo()) ? 656 : 661); - assert(resNum < _bigfileHeader->_count); - PakHeaderItem *file = &_bigfileHeader->_files[resNum]; - int32 size = file->_size; - int32 offs = file->_offs; - debug("* Loading sound %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), (uint)offs, size); - if (_soundAllocated) { - free(_voiceSamplesBuffer); - _voiceSamplesBuffer = nullptr; - _soundAllocated = false; //TODO: bug??? no alloc - } else { - _voiceSamplesBuffer = (byte *)malloc(size); - _soundAllocated = true; - } - - _bigfile.seek(offs, SEEK_SET); - //For PC loaded data is a VOC file, on Mac version this is a raw samples - if (_vm->getPlatform() == Common::kPlatformMacintosh) - _bigfile.read(_voiceSamplesBuffer, size); - else { - // VOC files also include extra information for lipsync - // 1. Standard VOC header - _bigfile.read(_voiceSamplesBuffer, 0x1A); - - // 2. Lipsync? - unsigned char chunkType = _bigfile.readByte(); - - uint32 val = 0; - _bigfile.read(&val, 3); - unsigned int chunkLen = LE32(val); - - if (chunkType == 5) { - _bigfile.read(_gameLipsync + 7260, chunkLen); - chunkType = _bigfile.readByte(); - _bigfile.read(&val, 3); - chunkLen = LE32(val); - } - - // 3. Normal sound data - if (chunkType == 1) { - _bigfile.readUint16LE(); - size = chunkLen - 2; - _bigfile.read(_voiceSamplesBuffer, size); - } - } - - return size; -} - -void EdenGame::convertMacToPC() { - // Convert all mac (big-endian) resources to native format - // Array of longs - int *p = (int *)_gameLipsync; - for (int i = 0; i < 7240 / 4; i++) - p[i] = BE32(p[i]); -} - -void EdenGame::loadpermfiles() { - Common::File f; - const int kNumIcons = 136; - const int kNumRooms = 424; - const int kNumFollowers = 15; - const int kNumLabyrinthPath = 70; - const int kNumDinoSpeedForCitaLevel = 16; - const int kNumTabletView = 12; - const int kNumPersoRoomBankTable = 84; - const int kNumGotos = 130; - const int kNumObjects = 42; - const int kNumObjectLocations = 45; - const int kNumPersons = 58; - const int kNumCitadel = 7; - const int kNumCharacterRects = 19; - const int kNumCharacters = 20; - const int kNumAreas = 12; - // tab_2CEF0 - // tab_2CF70 - const int kNumActionCursors = 299; - - const int expectedDataSize = - kNumIcons * 18 + // sizeof(Icon) - kNumRooms * 14 + // sizeof(Room) - kNumFollowers * 16 + // sizeof(Follower) - kNumLabyrinthPath + - kNumDinoSpeedForCitaLevel + - kNumTabletView + - kNumPersoRoomBankTable + - kNumGotos * 5 + // sizeof(Goto) - kNumObjects * 12 + // sizeof(object_t) - kNumObjectLocations * 2 + - kNumPersons * 18 + // sizeof(perso_t) - kNumCitadel * 34 + // sizeof(Citadel) - kNumCharacterRects * 8 + - kNumCharacters * 5 + - kNumAreas * 10 + // (sizeof(Area) - 4) - 64 * 2 + - 64 * 2 + - kNumActionCursors + - 12 + - 3 * 6 * 2 * 3 * 2; - - if (f.open("cryo.dat")) { - const int dataSize = f.size() - 8 - 4; // CRYODATA + version - char headerId[9]; - - f.read(headerId, 8); - headerId[8] = '\0'; - if (strcmp(headerId, "CRYODATA")) - error("Invalid cryo.dat aux data file"); - - if (f.readUint32LE() != CRYO_DAT_VER) - error("Incorrect data version for cryo.dat"); - - if (dataSize != expectedDataSize) - error("Mismatching data in cryo.dat aux data file (got %d, expected %d)", dataSize, expectedDataSize); - } else - error("Can not load cryo.dat"); - - switch (_vm->getPlatform()) { - case Common::kPlatformDOS: - // Since PC version stores hotspots and rooms info in the executable, load them from premade resource file - for (int i = 0; i < kNumIcons; i++) { - _gameIcons[i].sx = f.readSint16LE(); - _gameIcons[i].sy = f.readSint16LE(); - _gameIcons[i].ex = f.readSint16LE(); - _gameIcons[i].ey = f.readSint16LE(); - _gameIcons[i]._cursorId = f.readUint16LE(); - _gameIcons[i]._actionId = f.readUint32LE(); - _gameIcons[i]._objectId = f.readUint32LE(); - } - - for (int i = 0; i < kNumRooms; i++) { - _gameRooms[i]._id = f.readByte(); - for (int j = 0; j < 4; j++) - _gameRooms[i]._exits[j] = f.readByte(); - _gameRooms[i]._flags = f.readByte(); - _gameRooms[i]._bank = f.readUint16LE(); - _gameRooms[i]._party = f.readUint16LE(); - _gameRooms[i]._level = f.readByte(); - _gameRooms[i]._video = f.readByte(); - _gameRooms[i]._location = f.readByte(); - _gameRooms[i]._backgroundBankNum = f.readByte(); - } - break; - case Common::kPlatformMacintosh: - loadIconFile(2498, _gameIcons); - loadRoomFile(2497, _gameRooms); - loadRawFile(2486, _gameLipsync); - convertMacToPC(); - - // Skip the icons and rooms of the DOS version - f.skip(kNumIcons * 14 + kNumRooms * 11); - break; - default: - error("Unsupported platform"); - } - - // Read the common static data - - for (int i = 0; i < kNumFollowers; i++) { - _followerList[i]._id = f.readSByte(); - _followerList[i]._spriteNum = f.readSByte(); - _followerList[i].sx = f.readSint16LE(); - _followerList[i].sy = f.readSint16LE(); - _followerList[i].ex = f.readSint16LE(); - _followerList[i].ey = f.readSint16LE(); - _followerList[i]._spriteBank = f.readSint16LE(); - _followerList[i].ff_C = f.readSint16LE(); - _followerList[i].ff_E = f.readSint16LE(); - } - - f.read(_labyrinthPath, kNumLabyrinthPath); - f.read(_dinoSpeedForCitadelLevel, kNumDinoSpeedForCitaLevel); - f.read(_tabletView, kNumTabletView); - f.read(_personRoomBankTable, kNumPersoRoomBankTable); - f.read(_gotos, kNumGotos * 5); // sizeof(Goto) - - for (int i = 0; i < kNumObjects; i++) { - _objects[i]._id = f.readByte(); - _objects[i]._flags = f.readByte(); - _objects[i]._locations = f.readUint32LE(); - _objects[i]._itemMask = f.readUint16LE(); - _objects[i]._powerMask = f.readUint16LE(); - _objects[i]._count = f.readSint16LE(); - } - - for (int i = 0; i < kNumObjectLocations; i++) { - _objectLocations[i] = f.readUint16LE(); - } - - for (int i = 0; i < kNumPersons; i++) { - _persons[i]._roomNum = f.readUint16LE(); - _persons[i]._actionId = f.readUint16LE(); - _persons[i]._partyMask = f.readUint16LE(); - _persons[i]._id = f.readByte(); - _persons[i]._flags = f.readByte(); - _persons[i]._roomBankId = f.readByte(); - _persons[i]._spriteBank = f.readByte(); - _persons[i]._items = f.readUint16LE(); - _persons[i]._powers = f.readUint16LE(); - _persons[i]._targetLoc = f.readByte(); - _persons[i]._lastLoc = f.readByte(); - _persons[i]._speed = f.readByte(); - _persons[i]._steps = f.readByte(); - } - - for (int i = 0; i < kNumCitadel; i++) { - _citadelList[i]._id = f.readSint16LE(); - for (int j = 0; j < 8; j++) - _citadelList[i]._bank[j] = f.readSint16LE(); - for (int j = 0; j < 8; j++) - _citadelList[i]._video[j] = f.readSint16LE(); - } - - for (int i = 0; i < kNumCharacterRects; i++) { - _characterRects[i].left = f.readSint16LE(); - _characterRects[i].top = f.readSint16LE(); - _characterRects[i].right = f.readSint16LE(); - _characterRects[i].bottom = f.readSint16LE(); - } - - f.read(_characterArray, kNumCharacters * 5); - - for (int i = 0; i < kNumAreas; i++) { - _areasTable[i]._num = f.readByte(); - _areasTable[i]._type = f.readByte(); - _areasTable[i]._flags = f.readUint16LE(); - _areasTable[i]._firstRoomIdx = f.readUint16LE(); - _areasTable[i]._citadelLevel = f.readByte(); - _areasTable[i]._placeNum = f.readByte(); - _areasTable[i]._citadelRoomPtr = nullptr; - _areasTable[i]._visitCount = f.readSint16LE(); - } - - for (int i = 0; i < 64; i++) { - tab_2CEF0[i] = f.readSint16LE(); - } - - for (int i = 0; i < 64; i++) { - tab_2CF70[i] = f.readSint16LE(); - } - - f.read(_actionCursors, kNumActionCursors); - f.read(_mapMode, 12); - f.read(_cubeTextureCoords, 3 * 6 * 2 * 3 * 2); - - f.close(); - - loadRawFile(0, _mainBankBuf); - loadRawFile(402, _gameFont); - loadRawFile(404, _gameDialogs); - loadRawFile(403, _gameConditions); -} - -bool EdenGame::ReadDataSyncVOC(unsigned int num) { - unsigned int resNum = num - 1 + ((_vm->getPlatform() == Common::kPlatformDOS && _vm->isDemo()) ? 656 : 661); - unsigned char vocHeader[0x1A]; - int filePos = 0; - loadpartoffile(resNum, vocHeader, filePos, sizeof(vocHeader)); - filePos += sizeof(vocHeader); - unsigned char chunkType = 0; - loadpartoffile(resNum, &chunkType, sizeof(vocHeader), 1); - filePos++; - if (chunkType == 5) { - uint32 chunkLen = 0; - loadpartoffile(resNum, &chunkLen, filePos, 3); - filePos += 3; - chunkLen = LE32(chunkLen); - loadpartoffile(resNum, _gameLipsync + 7260, filePos, chunkLen); - return true; - } - return false; -} - -bool EdenGame::ReadDataSync(uint16 num) { - if (_vm->getPlatform() == Common::kPlatformMacintosh) { - long pos = READ_LE_UINT32(_gameLipsync + num * 4); - if (pos != -1) { - long len = 1024; - loadpartoffile(1936, _gameLipsync + 7260, pos, len); - return true; - } - } else - return ReadDataSyncVOC(num + 1); //TODO: remove -1 in caller - return false; -} - -void EdenGame::loadpartoffile(uint16 num, void *buffer, int32 pos, int32 len) { - assert(num < _bigfileHeader->_count); - PakHeaderItem *file = &_bigfileHeader->_files[num]; - int32 offs = READ_LE_UINT32(&file->_offs); - debug("* Loading partial resource %d (%s) at 0x%X(+0x%X), %d bytes", num, file->_name.c_str(), offs, pos, len); - _bigfile.seek(offs + pos, SEEK_SET); - _bigfile.read(buffer, len); -} - -void EdenGame::expandHSQ(byte *input, byte *output) { - byte *src = input; - byte *dst = output; - byte *ptr; - uint16 bit; // bit - uint16 queue = 0; // queue - uint16 len = 0; - int16 ofs; -#define GetBit \ - bit = queue & 1; \ - queue >>= 1; \ - if (!queue) { \ - queue = (src[1] << 8) | src[0]; src += 2; \ - bit = queue & 1; \ - queue = (queue >> 1) | 0x8000; \ - } - - for (;;) { - GetBit; - if (bit) - *dst++ = *src++; - else { - len = 0; - GetBit; - if (!bit) { - GetBit; - len = (len << 1) | bit; - GetBit; - len = (len << 1) | bit; - ofs = 0xFF00 | *src++; //TODO: -256 - } else { - ofs = (src[1] << 8) | src[0]; - src += 2; - len = ofs & 7; - ofs = (ofs >> 3) | 0xE000; - if (!len) { - len = *src++; - if (!len) - break; - } - } - ptr = dst + ofs; - len += 2; - while (len--) - *dst++ = *ptr++; - } - } -} - ////// // Original name: ajouinfo @@ -5185,116 +3885,6 @@ void EdenGame::closeRoom() { } } -// Original name afsalle1 -void EdenGame::displaySingleRoom(Room *room) { - byte *ptr = (byte *)getElem(_placeRawBuf, 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 (!(_globals->_displayFlags & 0x80)) { - if (index == 1 || _globals->_varF7) - drawSprite(index - 1, x, y, true); - } - _globals->_varF7 = 0; - continue; - } - if (b1 & 0x40) { - if (b1 & 0x20) { - bool addIcon = false; - Icon *icon = _globals->_nextRoomIcon; - if (b0 < 4) { - if (_globals->_roomPtr->_exits[b0]) - addIcon = true; - } else if (b0 > 229) { - if (_globals->_partyOutside & (1 << (b0 - 230))) - addIcon = true; - } else if (b0 >= 100) { - debug("add object %d", b0 - 100); - if (isObjectHere(b0 - 100)) { - addIcon = true; - _globals->_varF7 = 1; - } - } else - addIcon = true; - if (addIcon) { - icon->_actionId = b0; - icon->_objectId = b0; - icon->_cursorId = _actionCursors[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 += _globals->_roomBaseX; - ex += _globals->_roomBaseX; - debug("add hotspot at %3d:%3d - %3d:%3d, action = %d", x, y, ex, ey, b0); - - if (_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; - _globals->_nextRoomIcon = ++icon; - icon->sx = -1; - } else - ptr += 8; - } else - ptr += 8; - } else - ptr += 8; - } -} - -// Original name: afsalle -void EdenGame::displayRoom() { - Room *room = _globals->_roomPtr; - _globals->_displayFlags = DisplayFlags::dfFlag1; - _globals->_roomBaseX = 0; - _globals->_roomBackgroundBankNum = room->_backgroundBankNum; - if (room->_flags & RoomFlags::rf08) { - _globals->_displayFlags |= DisplayFlags::dfFlag80; - if (room->_flags & RoomFlags::rfPanable) { - // Scrollable room on 2 screens - _globals->_displayFlags |= DisplayFlags::dfPanable; - _globals->_varF4 = 0; - rundcurs(); - saveFriezes(); - useBank(room->_bank - 1); - drawSprite(0, 0, 16, true); - useBank(room->_bank); - drawSprite(0, 320, 16, true); - displaySingleRoom(room); - _globals->_roomBaseX = 320; - displaySingleRoom(room + 1); - } else - displaySingleRoom(room); - } else { - //TODO: roomImgBank is garbage here! - debug("displayRoom: room 0x%X using bank %d", _globals->_roomNum, _globals->_roomImgBank); - useBank(_globals->_roomImgBank); - displaySingleRoom(room); - assert(_vm->_screenView->_pitch == 320); - } -} - // Original name: aflieu void EdenGame::displayPlace() { no_perso(); @@ -5600,36 +4190,6 @@ void EdenGame::freebuf() { free(_musicBuf); } -void EdenGame::openWindow() { - _underBarsView = new View(320, 40); - _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(_vm->_screenView); - _mainViewBuf = _mainView->_bufferPtr; - - _mouseCenterX = _mainView->_normal._dstLeft + _mainView->_normal._width / 2; - _mouseCenterY = _mainView->_normal._dstTop + _mainView->_normal._height / 2; - _vm->setMousePosition(_mouseCenterX, _mouseCenterY); - _vm->hideMouse(); - - _cursorPosX = 320 / 2; - _cursorPosY = 200 / 2; -} - void EdenGame::EmergencyExit() { SysBeep(1); } @@ -6262,237 +4822,6 @@ void EdenGame::mouse() { (this->*mouse_actions[_currSpot->_actionId])(); } -////// film.c -// Original name: showfilm -void EdenGame::showMovie(char arg1) { - _vm->_video->readHeader(); - if (_globals->_curVideoNum == 92) { - // _hnmContext->_header._unusedFlag2 = 0; CHECKME: Useless? - _hnmSoundChannel->setVolumeLeft(0); - _hnmSoundChannel->setVolumeRight(0); - } - - if (_vm->_video->getVersion() != 4) - return; - - bool playing = true; - _vm->_video->allocMemory(); - _hnmView = new View(_vm->_video->_header._width, _vm->_video->_header._height); - _hnmView->setSrcZoomValues(0, 0); - _hnmView->setDisplayZoomValues(_vm->_video->_header._width * 2, _vm->_video->_header._height * 2); - _hnmView->centerIn(_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; - } - _vm->_video->setFinalBuffer(_hnmView->_bufferPtr); - do { - _hnmFrameNum = _vm->_video->getFrameNum(); - _vm->_video->waitLoop(); - playing = _vm->_video->nextElement(); - if (_specialTextMode) - handleHNMSubtitles(); - else - musicspy(); - CLBlitter_CopyView2Screen(_hnmView); - assert(_vm->_screenView->_pitch == 320); - _vm->pollEvents(); - -#if 0 // CLKeyboard_IsScanCodeDown currently always returns false - if (_vm->isScanCodeDown(0x30)) { //TODO: const - if (!_keyboardHeld) { - _doubledScreen = !_doubledScreen; - _hnmView->_doubled = _doubledScreen; //TODO: but mainview ? - CLBlitter_FillScreenView(0); - _keyboardHeld = true; - } - } else -#endif - _keyboardHeld = false; - - if (arg1) { - if (_vm->isMouseButtonDown()) { - if (!_mouseHeld) { - _mouseHeld = true; - _videoCanceledFlag = true; - } - } else - _mouseHeld = false; - } - } while (playing && !_videoCanceledFlag); - delete _hnmView; - _vm->_video->deallocMemory(); -} - -void EdenGame::playHNM(int16 num) { - perso_t *perso = nullptr; - int16 oldDialogType = -1; - _globals->_curVideoNum = num; - if (num != 2001 && num != 2012 && num != 98 && num != 171) { - byte oldMusicType = _globals->_newMusicType; - _globals->_newMusicType = MusicType::mtEvent; - musique(); - musicspy(); - _globals->_newMusicType = oldMusicType; - } - _globals->_videoSubtitleIndex = 1; - if (_specialTextMode) { - perso = _globals->_characterPtr; - oldDialogType = _globals->_dialogType; - preloadDialogs(num); - fademusica0(1); - _musicChannel->stop(); - } - _showVideoSubtitle = false; - _videoCanceledFlag = false; - loadHnm(num); - _vm->_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 (_specialTextMode) { - _musicFadeFlag = 3; - musicspy(); - _globals->_characterPtr = perso; - _globals->_dialogType = oldDialogType; - _specialTextMode = false; - } - if (_videoCanceledFlag) - _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; - if (_globals->_curVideoNum == 167) - _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; - if (_globals->_curVideoNum == 104) - _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; - if (_globals->_curVideoNum == 102) - _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; - if (_globals->_curVideoNum == 77) - _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; - if (_globals->_curVideoNum == 149) - _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; -} - -// Original name bullehnm -void EdenGame::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; - perso_t *perso; - switch (_globals->_curVideoNum) { - case 170: - frames = kFramesVid170; - perso = &_persons[PER_UNKN_156]; - break; - case 83: - frames = kFramesVid83; - perso = &_persons[PER_MORKUS]; - break; - case 88: - frames = kFramesVid88; - perso = &_persons[PER_MORKUS]; - break; - case 89: - frames = kFramesVid89; - perso = &_persons[PER_MORKUS]; - break; - case 94: - frames = kFramesVid94; - perso = &_persons[PER_MORKUS]; - break; - default: - return; - } - 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 { - _globals->_videoSubtitleIndex = (frames - frames_start) / 2 + 1; - _globals->_characterPtr = perso; - _globals->_dialogType = DialogType::dtInspect; - int16 num = (perso->_id << 3) | _globals->_dialogType; - dialoscansvmas((Dialog *)getElem(_gameDialogs, num)); - _showVideoSubtitle = true; - } - if (_showVideoSubtitle) - displayHNMSubtitle(); -} - ////// sound.c void EdenGame::musique() { if (_globals->_newMusicType == MusicType::mtDontChange) @@ -6568,18 +4897,6 @@ void EdenGame::musicspy() { } } -int EdenGame::loadmusicfile(int16 num) { - PakHeaderItem *file = &_bigfileHeader->_files[num + 435]; - int32 size = file->_size; - int32 offs = file->_offs; - _bigfile.seek(offs, SEEK_SET); - uint32 numread = size; - if (numread > kMaxMusicSize) - error("Music file %s is too big", file->_name.c_str()); - _bigfile.read(_musicBuf, numread); - return size; -} - void EdenGame::persovox() { int16 num = _globals->_textNum; if (_globals->_textBankIndex != 1) diff --git a/engines/cryo/graphics.cpp b/engines/cryo/graphics.cpp new file mode 100644 index 0000000000..29ebffc7a6 --- /dev/null +++ b/engines/cryo/graphics.cpp @@ -0,0 +1,1219 @@ +/* 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/defs.h" +#include "cryo/cryo.h" +#include "cryo/platdefs.h" +#include "cryo/cryolib.h" +#include "cryo/eden.h" +#include "cryo/sound.h" + +namespace Cryo { + +// Original name: noclipax +void EdenGame::drawSprite(int16 index, int16 x, int16 y, bool withBlack) { + byte *pix = _bankData; + byte *scr = _mainViewBuf + x + y * 640; + if (_curBankNum != 117 && (!_noPalette || withBlack)) { + 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) + 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 += 640 - w; + } + } + else { + // uncompressed + for (; h--;) { + for (int16 ww = w; ww--;) { + byte p = *pix++; + if (p == 0 && !withBlack) + scr++; + else + *scr++ = p; + } + scr += 640 - w; + } + } +} + +void EdenGame::sundcurs(int16 x, int16 y) { + byte *keep = _cursKeepBuf; + 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; + } + _cursorSaved = true; +} + +void EdenGame::rundcurs() { + byte *keep = _cursKeepBuf; + byte *scr = _mainViewBuf + _cursKeepPos.x + _cursKeepPos.y * 640; + if (!_cursorSaved || (_cursKeepPos == Common::Point(-1, -1))) //TODO ... + return; + + for (int16 h = 48; h--;) { + for (int16 w = 48; w--;) + *scr++ = *keep++; + scr += 640 - 48; + } +} + +void EdenGame::getglow(int16 x, int16 y, int16 w, int16 h) { + byte *scr = _mainViewBuf + x + y * 640; + byte *gl = _glowBuffer; + _glowX = x; + _glowY = y; + _glowW = w; + _glowH = h; + for (; h--;) { + for (int16 ww = w; ww--;) + *gl++ = *scr++; + scr += 640 - w; + } +} + +void EdenGame::unglow() { + byte *gl = _glowBuffer; + 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 EdenGame::glow(int16 index) { + // byte pixbase; + byte *pix = _bankData; + + 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 = _cursorPosX + _scrollPos - 38; + int16 y = _cursorPosY - 28; + int16 ex = _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 EdenGame::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: bars_out +void EdenGame::hideBars() { + if (_showBlackBars) + return; + + display(); + _underTopBarScreenRect.left = _scrollPos; + _underTopBarScreenRect.right = _scrollPos + 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 = _scrollPos; + _underTopBarBackupRect.right = _scrollPos + 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; + 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; + } + display(); + initRects(); + _showBlackBars = true; +} + +// Original name: bars_in +void EdenGame::showBars() { + if (!_showBlackBars) + return; + + drawBlackBars(); + int16 r29 = 2; + int16 r28 = 2; + _underTopBarScreenRect.left = 0; + _underTopBarScreenRect.right = 320 - 1; + _underTopBarBackupRect.left = _scrollPos; + _underTopBarBackupRect.right = _scrollPos + 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; + display(); + } + initRects(); + _showBlackBars = false; +} + +// Original name: af_image +void EdenGame::displayImage() { + byte *img = _imageDesc + 200; + + int16 count = READ_LE_UINT16(img); + if (!count) + return; + + byte *img_start = img; + byte *curimg = _imageDesc; + + 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++ + _gameIcons[0].sx; + uint16 y = *img++ + _gameIcons[0].sy; + byte *pix = _bankData; + 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 EdenGame::displaySubtitles() { + byte *src = _subtitlesViewBuf; + byte *dst = _mainViewBuf; + int16 y; + if (_globals->_displayFlags & DisplayFlags::dfFlag2) { + y = 174; + if ((_globals->_drawFlags & DrawFlags::drDrawMenu) && _numTextLines == 1) + y = 167; + dst += 640 * (y - _numTextLines * FONT_HEIGHT) + _subtitlesXScrMargin; + } + else { + y = 174; + dst += 640 * (y - _numTextLines * FONT_HEIGHT) + _scrollPos + _subtitlesXScrMargin; + } + if (_animationActive && !_personTalking) + return; + saveUnderSubtitles(y); + for (int16 h = 0; h < _numTextLines * 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 EdenGame::displaySingleRoom(Room *room) { + byte *ptr = (byte *)getElem(_placeRawBuf, 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 (!(_globals->_displayFlags & 0x80)) { + if (index == 1 || _globals->_varF7) + drawSprite(index - 1, x, y, true); + } + _globals->_varF7 = 0; + continue; + } + if (b1 & 0x40) { + if (b1 & 0x20) { + bool addIcon = false; + Icon *icon = _globals->_nextRoomIcon; + if (b0 < 4) { + if (_globals->_roomPtr->_exits[b0]) + addIcon = true; + } + else if (b0 > 229) { + if (_globals->_partyOutside & (1 << (b0 - 230))) + addIcon = true; + } + else if (b0 >= 100) { + debug("add object %d", b0 - 100); + if (isObjectHere(b0 - 100)) { + addIcon = true; + _globals->_varF7 = 1; + } + } + else + addIcon = true; + if (addIcon) { + icon->_actionId = b0; + icon->_objectId = b0; + icon->_cursorId = _actionCursors[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 += _globals->_roomBaseX; + ex += _globals->_roomBaseX; + debug("add hotspot at %3d:%3d - %3d:%3d, action = %d", x, y, ex, ey, b0); + + if (_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; + _globals->_nextRoomIcon = ++icon; + icon->sx = -1; + } + else + ptr += 8; + } + else + ptr += 8; + } + else + ptr += 8; + } +} + +// Original name: afsalle +void EdenGame::displayRoom() { + Room *room = _globals->_roomPtr; + _globals->_displayFlags = DisplayFlags::dfFlag1; + _globals->_roomBaseX = 0; + _globals->_roomBackgroundBankNum = room->_backgroundBankNum; + if (room->_flags & RoomFlags::rf08) { + _globals->_displayFlags |= DisplayFlags::dfFlag80; + if (room->_flags & RoomFlags::rfPanable) { + // Scrollable room on 2 screens + _globals->_displayFlags |= DisplayFlags::dfPanable; + _globals->_varF4 = 0; + rundcurs(); + saveFriezes(); + useBank(room->_bank - 1); + drawSprite(0, 0, 16, true); + useBank(room->_bank); + drawSprite(0, 320, 16, true); + displaySingleRoom(room); + _globals->_roomBaseX = 320; + displaySingleRoom(room + 1); + } + else + displaySingleRoom(room); + } + else { + //TODO: roomImgBank is garbage here! + debug("displayRoom: room 0x%X using bank %d", _globals->_roomNum, _globals->_roomImgBank); + useBank(_globals->_roomImgBank); + displaySingleRoom(room); + assert(_vm->_screenView->_pitch == 320); + } +} + +void EdenGame::openWindow() { + _underBarsView = new View(320, 40); + _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(_vm->_screenView); + _mainViewBuf = _mainView->_bufferPtr; + + _mouseCenterX = _mainView->_normal._dstLeft + _mainView->_normal._width / 2; + _mouseCenterY = _mainView->_normal._dstTop + _mainView->_normal._height / 2; + _vm->setMousePosition(_mouseCenterX, _mouseCenterY); + _vm->hideMouse(); + + _cursorPosX = 320 / 2; + _cursorPosY = 200 / 2; +} + +// Original name: effet1 +void EdenGame::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, _vm->_screenView, &rect_src, &rect_dst); + setDestRect(x, y + 192 - i, x + 16 - 1, y + 192 - i + 4 - 1); + CLBlitter_CopyViewRect(_view2, _vm->_screenView, &rect_src, &rect_dst); + } + CLBlitter_UpdateScreen(); + 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(); + 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; + _globals->_varF1 = 0; +} + +// Original name: effet2 +void EdenGame::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 (_globals->_var103 == 69) { + displayEffect4(); + return; + } + switch (++eff2pat) { + case 1: + colimacon(pattern1); + break; + case 2: + colimacon(pattern2); + break; + case 3: + colimacon(pattern3); + break; + case 4: + colimacon(pattern4); + eff2pat = 0; + break; + } +} + +// Original name: effet3 +void EdenGame::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); + 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); + wait(1); + } +} + +// Original name: effet4 +void EdenGame::displayEffect4() { + byte *scr, *pix, *r24, *r25, *r30, c; + int16 r17, r23, r16, r18, r19, r22, r27, r31; + CLPalette_Send2Screen(_globalPalette, 0, 256); + + int16 ww = _vm->_screenView->_pitch; + int16 x = _mainView->_normal._dstLeft; + int16 y = _mainView->_normal._dstTop; + for (int16 i = 32; i > 0; i -= 2) { + scr = _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(); + wait(3); + } + CLBlitter_CopyView2Screen(_mainView); +} + +void EdenGame::clearScreen() { + int16 ww = _vm->_screenView->_pitch; + int16 x = _mainView->_normal._dstLeft; + int16 y = _mainView->_normal._dstTop; + byte *scr = _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 EdenGame::colimacon(int16 pattern[16]) { + int16 p, r27, r25; + + int16 ww = _vm->_screenView->_pitch; + int16 x = _mainView->_normal._dstLeft; + int16 y = _mainView->_normal._dstTop; + byte *scr = _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(); + wait(1); + } + CLPalette_Send2Screen(_globalPalette, 0, 256); + byte *pix = _mainView->_bufferPtr; + x = _mainView->_normal._dstLeft; + y = _mainView->_normal._dstTop; + pix += 640 * 16; + scr = _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(); + wait(1); + } +} + +void EdenGame::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); + wait(delay); + } +} + +// Original name: fadetoblack128 +void EdenGame::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); + wait(delay); + } +} + +// Original name: fadefromblack128 +void EdenGame::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); + wait(delay); + } +} + +// Original name: rectanglenoir32 +void EdenGame::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 EdenGame::setSrcRect(int16 sx, int16 sy, int16 ex, int16 ey) { + rect_src = Common::Rect(sx, sy, ex, ey); +} + +void EdenGame::setDestRect(int16 sx, int16 sy, int16 ex, int16 ey) { + rect_dst = Common::Rect(sx, sy, ex, ey); +} + +void EdenGame::effetpix() { + uint16 r25, r18, r31, r30; //TODO: change to xx/yy + + uint16 ww = _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 = _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(); + 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(); + wait(1); + r26 = 0; + } + } + } while (r27 != 1); + assert(_vm->_screenView->_pitch == 320); +} + +////// film.c +// Original name: showfilm +void EdenGame::showMovie(char arg1) { + _vm->_video->readHeader(); + if (_globals->_curVideoNum == 92) { + // _hnmContext->_header._unusedFlag2 = 0; CHECKME: Useless? + _hnmSoundChannel->setVolumeLeft(0); + _hnmSoundChannel->setVolumeRight(0); + } + + if (_vm->_video->getVersion() != 4) + return; + + bool playing = true; + _vm->_video->allocMemory(); + _hnmView = new View(_vm->_video->_header._width, _vm->_video->_header._height); + _hnmView->setSrcZoomValues(0, 0); + _hnmView->setDisplayZoomValues(_vm->_video->_header._width * 2, _vm->_video->_header._height * 2); + _hnmView->centerIn(_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; + } + _vm->_video->setFinalBuffer(_hnmView->_bufferPtr); + do { + _hnmFrameNum = _vm->_video->getFrameNum(); + _vm->_video->waitLoop(); + playing = _vm->_video->nextElement(); + if (_specialTextMode) + handleHNMSubtitles(); + else + musicspy(); + CLBlitter_CopyView2Screen(_hnmView); + assert(_vm->_screenView->_pitch == 320); + _vm->pollEvents(); + +#if 0 // CLKeyboard_IsScanCodeDown currently always returns false + if (_vm->isScanCodeDown(0x30)) { //TODO: const + if (!_keyboardHeld) { + _doubledScreen = !_doubledScreen; + _hnmView->_doubled = _doubledScreen; //TODO: but mainview ? + CLBlitter_FillScreenView(0); + _keyboardHeld = true; + } + } + else +#endif + _keyboardHeld = false; + + if (arg1) { + if (_vm->isMouseButtonDown()) { + if (!_mouseHeld) { + _mouseHeld = true; + _videoCanceledFlag = true; + } + } + else + _mouseHeld = false; + } + } while (playing && !_videoCanceledFlag); + delete _hnmView; + _vm->_video->deallocMemory(); +} + +void EdenGame::playHNM(int16 num) { + perso_t *perso = nullptr; + int16 oldDialogType = -1; + _globals->_curVideoNum = num; + if (num != 2001 && num != 2012 && num != 98 && num != 171) { + byte oldMusicType = _globals->_newMusicType; + _globals->_newMusicType = MusicType::mtEvent; + musique(); + musicspy(); + _globals->_newMusicType = oldMusicType; + } + _globals->_videoSubtitleIndex = 1; + if (_specialTextMode) { + perso = _globals->_characterPtr; + oldDialogType = _globals->_dialogType; + preloadDialogs(num); + fademusica0(1); + _musicChannel->stop(); + } + _showVideoSubtitle = false; + _videoCanceledFlag = false; + loadHnm(num); + _vm->_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 (_specialTextMode) { + _musicFadeFlag = 3; + musicspy(); + _globals->_characterPtr = perso; + _globals->_dialogType = oldDialogType; + _specialTextMode = false; + } + if (_videoCanceledFlag) + _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; + if (_globals->_curVideoNum == 167) + _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; + if (_globals->_curVideoNum == 104) + _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; + if (_globals->_curVideoNum == 102) + _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; + if (_globals->_curVideoNum == 77) + _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; + if (_globals->_curVideoNum == 149) + _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; +} + +// Original name bullehnm +void EdenGame::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; + perso_t *perso; + switch (_globals->_curVideoNum) { + case 170: + frames = kFramesVid170; + perso = &_persons[PER_UNKN_156]; + break; + case 83: + frames = kFramesVid83; + perso = &_persons[PER_MORKUS]; + break; + case 88: + frames = kFramesVid88; + perso = &_persons[PER_MORKUS]; + break; + case 89: + frames = kFramesVid89; + perso = &_persons[PER_MORKUS]; + break; + case 94: + frames = kFramesVid94; + perso = &_persons[PER_MORKUS]; + break; + default: + return; + } + 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 { + _globals->_videoSubtitleIndex = (frames - frames_start) / 2 + 1; + _globals->_characterPtr = perso; + _globals->_dialogType = DialogType::dtInspect; + int16 num = (perso->_id << 3) | _globals->_dialogType; + dialoscansvmas((Dialog *)getElem(_gameDialogs, num)); + _showVideoSubtitle = true; + } + if (_showVideoSubtitle) + displayHNMSubtitle(); +} + +} // namespace Cryo diff --git a/engines/cryo/module.mk b/engines/cryo/module.mk index aa9649ff82..1fcb0ae6fd 100644 --- a/engines/cryo/module.mk +++ b/engines/cryo/module.mk @@ -6,6 +6,8 @@ MODULE_OBJS = \ debugger.o \ detection.o \ eden.o \ + graphics.o \ + resource.o \ sound.o \ video.o diff --git a/engines/cryo/resource.cpp b/engines/cryo/resource.cpp new file mode 100644 index 0000000000..7698de0906 --- /dev/null +++ b/engines/cryo/resource.cpp @@ -0,0 +1,555 @@ +/* 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/defs.h" +#include "cryo/cryo.h" +#include "cryo/platdefs.h" +#include "cryo/cryolib.h" +#include "cryo/eden.h" +#include "cryo/sound.h" + +namespace Cryo { + +#define CRYO_DAT_VER 1 // 32-bit integer + +// Original name: prechargephrases +void EdenGame::preloadDialogs(int16 vid) { + perso_t *perso = &_persons[PER_MORKUS]; + if (vid == 170) + perso = &_persons[PER_UNKN_156]; + _globals->_characterPtr = perso; + _globals->_dialogType = DialogType::dtInspect; + int num = (perso->_id << 3) | _globals->_dialogType; + Dialog *dial = (Dialog *)getElem(_gameDialogs, num); + dialoscansvmas(dial); +} + +////// datfile.c +void EdenGame::verifh(byte *ptr) { + byte sum = 0; + byte *head = ptr; + + for (int8 i = 0; i < 6; i++) + sum += *head++; + + if (sum != 0xAB) + return; + + debug("* Begin unpacking resource"); + head -= 6; + uint16 h0 = READ_LE_UINT16(head); + // 3 = 2 bytes for the uint16 and 1 byte for an unused char + head += 3; + uint16 h3 = READ_LE_UINT16(head); + head += 2; + byte *data = h0 + head + 26; + h3 -= 6; + head += h3; + for (; h3; h3--) + *data-- = *head--; + head = data + 1; + data = ptr; + expandHSQ(head, data); +} + +void EdenGame::openbigfile() { + _bigfile.open("EDEN.DAT"); + + char buf[16]; + int count = _bigfile.readUint16LE(); + _bigfileHeader = new PakHeaderNode(count); + for (int j = 0; j < count; j++) { + for (int k = 0; k < 16; k++) + buf[k] = _bigfile.readByte(); + _bigfileHeader->_files[j]._name = Common::String(buf); + _bigfileHeader->_files[j]._size = _bigfile.readUint32LE(); + _bigfileHeader->_files[j]._offs = _bigfile.readUint32LE(); + _bigfileHeader->_files[j]._flag = _bigfile.readByte(); + } + + _vm->_video->resetInternals(); + _vm->_video->setFile(&_bigfile); +} + +void EdenGame::closebigfile() { + _bigfile.close(); +} + +int EdenGame::loadmusicfile(int16 num) { + PakHeaderItem *file = &_bigfileHeader->_files[num + 435]; + int32 size = file->_size; + int32 offs = file->_offs; + _bigfile.seek(offs, SEEK_SET); + uint32 numread = size; + if (numread > kMaxMusicSize) + error("Music file %s is too big", file->_name.c_str()); + _bigfile.read(_musicBuf, numread); + return size; +} + +void EdenGame::loadRawFile(uint16 num, byte *buffer) { + if (_vm->getPlatform() == Common::kPlatformDOS) { + if ((_vm->isDemo() && num > 2204) || num > 2472) + error("Trying to read invalid game resource"); + } + + assert(num < _bigfileHeader->_count); + PakHeaderItem *file = &_bigfileHeader->_files[num]; + int32 size = file->_size; + int32 offs = file->_offs; + + _bigfile.seek(offs, SEEK_SET); + _bigfile.read(buffer, size); +} + +void EdenGame::loadIconFile(uint16 num, Icon *buffer) { + if (_vm->getPlatform() == Common::kPlatformDOS) { + if ((_vm->isDemo() && num > 2204) || num > 2472) + error("Trying to read invalid game resource"); + } + + assert(num < _bigfileHeader->_count); + PakHeaderItem *file = &_bigfileHeader->_files[num]; + int32 size = file->_size; + int32 offs = file->_offs; + debug("* Loading icon - Resource %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), offs, size); + _bigfile.seek(offs, SEEK_SET); + + int count = size / 18; // sizeof(Icon) + for (int i = 0; i < count; i++) { + if (_vm->getPlatform() == Common::kPlatformMacintosh) { + buffer[i].sx = _bigfile.readSint16BE(); + buffer[i].sy = _bigfile.readSint16BE(); + buffer[i].ex = _bigfile.readSint16BE(); + buffer[i].ey = _bigfile.readSint16BE(); + buffer[i]._cursorId = _bigfile.readUint16BE();; + buffer[i]._actionId = _bigfile.readUint32BE();; + buffer[i]._objectId = _bigfile.readUint32BE();; + } + else { + buffer[i].sx = _bigfile.readSint16LE(); + buffer[i].sy = _bigfile.readSint16LE(); + buffer[i].ex = _bigfile.readSint16LE(); + buffer[i].ey = _bigfile.readSint16LE(); + buffer[i]._cursorId = _bigfile.readUint16LE();; + buffer[i]._actionId = _bigfile.readUint32LE();; + buffer[i]._objectId = _bigfile.readUint32LE();; + } + } +} + +void EdenGame::loadRoomFile(uint16 num, Room *buffer) { + if (_vm->getPlatform() == Common::kPlatformDOS) { + if ((_vm->isDemo() && num > 2204) || num > 2472) + error("Trying to read invalid game resource"); + } + + assert(num < _bigfileHeader->_count); + PakHeaderItem *file = &_bigfileHeader->_files[num]; + int32 size = file->_size; + int32 offs = file->_offs; + debug("* Loading room - Resource %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), offs, size); + _bigfile.seek(offs, SEEK_SET); + + int count = size / 14; // sizeof(Room) + for (int i = 0; i < count; i++) { + buffer[i]._id = _bigfile.readByte(); + for (int j = 0; j < 4; j++) + buffer[i]._exits[j] = _bigfile.readByte(); + buffer[i]._flags = _bigfile.readByte(); + if (_vm->getPlatform() == Common::kPlatformMacintosh) { + buffer[i]._bank = _bigfile.readUint16BE(); + buffer[i]._party = _bigfile.readUint16BE(); + } + else { + buffer[i]._bank = _bigfile.readUint16LE(); + buffer[i]._party = _bigfile.readUint16LE(); + } + buffer[i]._level = _bigfile.readByte(); + buffer[i]._video = _bigfile.readByte(); + buffer[i]._location = _bigfile.readByte(); + buffer[i]._backgroundBankNum = _bigfile.readByte(); + } +} + +// Original name: shnmfl +void EdenGame::loadHnm(uint16 num) { + unsigned int resNum = num - 1 + 485; + assert(resNum < _bigfileHeader->_count); + PakHeaderItem *file = &_bigfileHeader->_files[resNum]; + int size = file->_size; + int offs = file->_offs; + debug("* Loading movie %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), (uint)offs, size); + _vm->_video->_file->seek(offs, SEEK_SET); +} + +// Original name: ssndfl +int EdenGame::loadSound(uint16 num) { + unsigned int resNum = num - 1 + ((_vm->getPlatform() == Common::kPlatformDOS && _vm->isDemo()) ? 656 : 661); + assert(resNum < _bigfileHeader->_count); + PakHeaderItem *file = &_bigfileHeader->_files[resNum]; + int32 size = file->_size; + int32 offs = file->_offs; + debug("* Loading sound %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), (uint)offs, size); + if (_soundAllocated) { + free(_voiceSamplesBuffer); + _voiceSamplesBuffer = nullptr; + _soundAllocated = false; //TODO: bug??? no alloc + } + else { + _voiceSamplesBuffer = (byte *)malloc(size); + _soundAllocated = true; + } + + _bigfile.seek(offs, SEEK_SET); + //For PC loaded data is a VOC file, on Mac version this is a raw samples + if (_vm->getPlatform() == Common::kPlatformMacintosh) + _bigfile.read(_voiceSamplesBuffer, size); + else { + // VOC files also include extra information for lipsync + // 1. Standard VOC header + _bigfile.read(_voiceSamplesBuffer, 0x1A); + + // 2. Lipsync? + unsigned char chunkType = _bigfile.readByte(); + + uint32 val = 0; + _bigfile.read(&val, 3); + unsigned int chunkLen = LE32(val); + + if (chunkType == 5) { + _bigfile.read(_gameLipsync + 7260, chunkLen); + chunkType = _bigfile.readByte(); + _bigfile.read(&val, 3); + chunkLen = LE32(val); + } + + // 3. Normal sound data + if (chunkType == 1) { + _bigfile.readUint16LE(); + size = chunkLen - 2; + _bigfile.read(_voiceSamplesBuffer, size); + } + } + + return size; +} + +void EdenGame::convertMacToPC() { + // Convert all mac (big-endian) resources to native format + // Array of longs + int *p = (int *)_gameLipsync; + for (int i = 0; i < 7240 / 4; i++) + p[i] = BE32(p[i]); +} + +void EdenGame::loadpermfiles() { + Common::File f; + const int kNumIcons = 136; + const int kNumRooms = 424; + const int kNumFollowers = 15; + const int kNumLabyrinthPath = 70; + const int kNumDinoSpeedForCitaLevel = 16; + const int kNumTabletView = 12; + const int kNumPersoRoomBankTable = 84; + const int kNumGotos = 130; + const int kNumObjects = 42; + const int kNumObjectLocations = 45; + const int kNumPersons = 58; + const int kNumCitadel = 7; + const int kNumCharacterRects = 19; + const int kNumCharacters = 20; + const int kNumAreas = 12; + // tab_2CEF0 + // tab_2CF70 + const int kNumActionCursors = 299; + + const int expectedDataSize = + kNumIcons * 18 + // sizeof(Icon) + kNumRooms * 14 + // sizeof(Room) + kNumFollowers * 16 + // sizeof(Follower) + kNumLabyrinthPath + + kNumDinoSpeedForCitaLevel + + kNumTabletView + + kNumPersoRoomBankTable + + kNumGotos * 5 + // sizeof(Goto) + kNumObjects * 12 + // sizeof(object_t) + kNumObjectLocations * 2 + + kNumPersons * 18 + // sizeof(perso_t) + kNumCitadel * 34 + // sizeof(Citadel) + kNumCharacterRects * 8 + + kNumCharacters * 5 + + kNumAreas * 10 + // (sizeof(Area) - 4) + 64 * 2 + + 64 * 2 + + kNumActionCursors + + 12 + + 3 * 6 * 2 * 3 * 2; + + if (f.open("cryo.dat")) { + const int dataSize = f.size() - 8 - 4; // CRYODATA + version + char headerId[9]; + + f.read(headerId, 8); + headerId[8] = '\0'; + if (strcmp(headerId, "CRYODATA")) + error("Invalid cryo.dat aux data file"); + + if (f.readUint32LE() != CRYO_DAT_VER) + error("Incorrect data version for cryo.dat"); + + if (dataSize != expectedDataSize) + error("Mismatching data in cryo.dat aux data file (got %d, expected %d)", dataSize, expectedDataSize); + } + else + error("Can not load cryo.dat"); + + switch (_vm->getPlatform()) { + case Common::kPlatformDOS: + // Since PC version stores hotspots and rooms info in the executable, load them from premade resource file + for (int i = 0; i < kNumIcons; i++) { + _gameIcons[i].sx = f.readSint16LE(); + _gameIcons[i].sy = f.readSint16LE(); + _gameIcons[i].ex = f.readSint16LE(); + _gameIcons[i].ey = f.readSint16LE(); + _gameIcons[i]._cursorId = f.readUint16LE(); + _gameIcons[i]._actionId = f.readUint32LE(); + _gameIcons[i]._objectId = f.readUint32LE(); + } + + for (int i = 0; i < kNumRooms; i++) { + _gameRooms[i]._id = f.readByte(); + for (int j = 0; j < 4; j++) + _gameRooms[i]._exits[j] = f.readByte(); + _gameRooms[i]._flags = f.readByte(); + _gameRooms[i]._bank = f.readUint16LE(); + _gameRooms[i]._party = f.readUint16LE(); + _gameRooms[i]._level = f.readByte(); + _gameRooms[i]._video = f.readByte(); + _gameRooms[i]._location = f.readByte(); + _gameRooms[i]._backgroundBankNum = f.readByte(); + } + break; + case Common::kPlatformMacintosh: + loadIconFile(2498, _gameIcons); + loadRoomFile(2497, _gameRooms); + loadRawFile(2486, _gameLipsync); + convertMacToPC(); + + // Skip the icons and rooms of the DOS version + f.skip(kNumIcons * 14 + kNumRooms * 11); + break; + default: + error("Unsupported platform"); + } + + // Read the common static data + + for (int i = 0; i < kNumFollowers; i++) { + _followerList[i]._id = f.readSByte(); + _followerList[i]._spriteNum = f.readSByte(); + _followerList[i].sx = f.readSint16LE(); + _followerList[i].sy = f.readSint16LE(); + _followerList[i].ex = f.readSint16LE(); + _followerList[i].ey = f.readSint16LE(); + _followerList[i]._spriteBank = f.readSint16LE(); + _followerList[i].ff_C = f.readSint16LE(); + _followerList[i].ff_E = f.readSint16LE(); + } + + f.read(_labyrinthPath, kNumLabyrinthPath); + f.read(_dinoSpeedForCitadelLevel, kNumDinoSpeedForCitaLevel); + f.read(_tabletView, kNumTabletView); + f.read(_personRoomBankTable, kNumPersoRoomBankTable); + f.read(_gotos, kNumGotos * 5); // sizeof(Goto) + + for (int i = 0; i < kNumObjects; i++) { + _objects[i]._id = f.readByte(); + _objects[i]._flags = f.readByte(); + _objects[i]._locations = f.readUint32LE(); + _objects[i]._itemMask = f.readUint16LE(); + _objects[i]._powerMask = f.readUint16LE(); + _objects[i]._count = f.readSint16LE(); + } + + for (int i = 0; i < kNumObjectLocations; i++) { + _objectLocations[i] = f.readUint16LE(); + } + + for (int i = 0; i < kNumPersons; i++) { + _persons[i]._roomNum = f.readUint16LE(); + _persons[i]._actionId = f.readUint16LE(); + _persons[i]._partyMask = f.readUint16LE(); + _persons[i]._id = f.readByte(); + _persons[i]._flags = f.readByte(); + _persons[i]._roomBankId = f.readByte(); + _persons[i]._spriteBank = f.readByte(); + _persons[i]._items = f.readUint16LE(); + _persons[i]._powers = f.readUint16LE(); + _persons[i]._targetLoc = f.readByte(); + _persons[i]._lastLoc = f.readByte(); + _persons[i]._speed = f.readByte(); + _persons[i]._steps = f.readByte(); + } + + for (int i = 0; i < kNumCitadel; i++) { + _citadelList[i]._id = f.readSint16LE(); + for (int j = 0; j < 8; j++) + _citadelList[i]._bank[j] = f.readSint16LE(); + for (int j = 0; j < 8; j++) + _citadelList[i]._video[j] = f.readSint16LE(); + } + + for (int i = 0; i < kNumCharacterRects; i++) { + _characterRects[i].left = f.readSint16LE(); + _characterRects[i].top = f.readSint16LE(); + _characterRects[i].right = f.readSint16LE(); + _characterRects[i].bottom = f.readSint16LE(); + } + + f.read(_characterArray, kNumCharacters * 5); + + for (int i = 0; i < kNumAreas; i++) { + _areasTable[i]._num = f.readByte(); + _areasTable[i]._type = f.readByte(); + _areasTable[i]._flags = f.readUint16LE(); + _areasTable[i]._firstRoomIdx = f.readUint16LE(); + _areasTable[i]._citadelLevel = f.readByte(); + _areasTable[i]._placeNum = f.readByte(); + _areasTable[i]._citadelRoomPtr = nullptr; + _areasTable[i]._visitCount = f.readSint16LE(); + } + + for (int i = 0; i < 64; i++) { + tab_2CEF0[i] = f.readSint16LE(); + } + + for (int i = 0; i < 64; i++) { + tab_2CF70[i] = f.readSint16LE(); + } + + f.read(_actionCursors, kNumActionCursors); + f.read(_mapMode, 12); + f.read(_cubeTextureCoords, 3 * 6 * 2 * 3 * 2); + + f.close(); + + loadRawFile(0, _mainBankBuf); + loadRawFile(402, _gameFont); + loadRawFile(404, _gameDialogs); + loadRawFile(403, _gameConditions); +} + +bool EdenGame::ReadDataSyncVOC(unsigned int num) { + unsigned int resNum = num - 1 + ((_vm->getPlatform() == Common::kPlatformDOS && _vm->isDemo()) ? 656 : 661); + unsigned char vocHeader[0x1A]; + int filePos = 0; + loadpartoffile(resNum, vocHeader, filePos, sizeof(vocHeader)); + filePos += sizeof(vocHeader); + unsigned char chunkType = 0; + loadpartoffile(resNum, &chunkType, sizeof(vocHeader), 1); + filePos++; + if (chunkType == 5) { + uint32 chunkLen = 0; + loadpartoffile(resNum, &chunkLen, filePos, 3); + filePos += 3; + chunkLen = LE32(chunkLen); + loadpartoffile(resNum, _gameLipsync + 7260, filePos, chunkLen); + return true; + } + return false; +} + +bool EdenGame::ReadDataSync(uint16 num) { + if (_vm->getPlatform() == Common::kPlatformMacintosh) { + long pos = READ_LE_UINT32(_gameLipsync + num * 4); + if (pos != -1) { + long len = 1024; + loadpartoffile(1936, _gameLipsync + 7260, pos, len); + return true; + } + } + else + return ReadDataSyncVOC(num + 1); //TODO: remove -1 in caller + return false; +} + +void EdenGame::loadpartoffile(uint16 num, void *buffer, int32 pos, int32 len) { + assert(num < _bigfileHeader->_count); + PakHeaderItem *file = &_bigfileHeader->_files[num]; + int32 offs = READ_LE_UINT32(&file->_offs); + debug("* Loading partial resource %d (%s) at 0x%X(+0x%X), %d bytes", num, file->_name.c_str(), offs, pos, len); + _bigfile.seek(offs + pos, SEEK_SET); + _bigfile.read(buffer, len); +} + +void EdenGame::expandHSQ(byte *input, byte *output) { + byte *src = input; + byte *dst = output; + byte *ptr; + uint16 bit; // bit + uint16 queue = 0; // queue + uint16 len = 0; + int16 ofs; +#define GetBit \ +bit = queue & 1; \ +queue >>= 1; \ +if (!queue) { \ + queue = (src[1] << 8) | src[0]; src += 2; \ + bit = queue & 1; \ + queue = (queue >> 1) | 0x8000; \ + } + + for (;;) { + GetBit; + if (bit) + *dst++ = *src++; + else { + len = 0; + GetBit; + if (!bit) { + GetBit; + len = (len << 1) | bit; + GetBit; + len = (len << 1) | bit; + ofs = 0xFF00 | *src++; //TODO: -256 + } + else { + ofs = (src[1] << 8) | src[0]; + src += 2; + len = ofs & 7; + ofs = (ofs >> 3) | 0xE000; + if (!len) { + len = *src++; + if (!len) + break; + } + } + ptr = dst + ofs; + len += 2; + while (len--) + *dst++ = *ptr++; + } + } +} + +} // namespace Cryo -- cgit v1.2.3