diff options
Diffstat (limited to 'engines/kyra')
66 files changed, 3131 insertions, 1509 deletions
diff --git a/engines/kyra/animator_mr.cpp b/engines/kyra/animator_mr.cpp index d7139a9e70..faf1b150a2 100644 --- a/engines/kyra/animator_mr.cpp +++ b/engines/kyra/animator_mr.cpp @@ -119,7 +119,7 @@ void KyraEngine_MR::drawSceneAnimObject(AnimObj *obj, int x, int y, int layer) { flags |= 0x8000; x = obj->xPos2 - _sceneAnimMovie[obj->animNum]->xAdd(); y = obj->yPos2 - _sceneAnimMovie[obj->animNum]->yAdd(); - _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, 2, x, y, flags | layer); + _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, 2, x, y, flags | layer, 0, 0); } } } diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp index e0c2c0aa77..d71f7b8b25 100644 --- a/engines/kyra/debugger.cpp +++ b/engines/kyra/debugger.cpp @@ -69,7 +69,7 @@ bool Debugger::cmd_setScreenDebug(int argc, const char **argv) { } bool Debugger::cmd_loadPalette(int argc, const char **argv) { - uint8 palette[768]; + Palette palette(_vm->screen()->getPalette(0).getNumColors()); if (argc <= 1) { DebugPrintf("Use load_palette <file> [start_col] [end_col]\n"); @@ -80,7 +80,7 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) { uint8 buffer[320*200]; _vm->screen()->copyRegionToBuffer(5, 0, 0, 320, 200, buffer); _vm->screen()->loadBitmap(argv[1], 5, 5, 0); - memcpy(palette, _vm->screen()->getCPagePtr(5), 768); + palette.copy(_vm->screen()->getCPagePtr(5), 0, 256); _vm->screen()->copyBlockToPage(5, 0, 0, 320, 200, buffer); } else if (!_vm->screen()->loadPalette(argv[1], palette)) { DebugPrintf("ERROR: Palette '%s' not found!\n", argv[1]); @@ -88,16 +88,16 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) { } int startCol = 0; - int endCol = 255; + int endCol = palette.getNumColors(); if (argc > 2) - startCol = MIN(255, MAX(0, atoi(argv[2]))); + startCol = MIN(palette.getNumColors(), MAX(0, atoi(argv[2]))); if (argc > 3) - endCol = MIN(255, MAX(0, atoi(argv[3]))); + endCol = MIN(palette.getNumColors(), MAX(0, atoi(argv[3]))); if (startCol > 0) - memcpy(palette, _vm->screen()->getScreenPalette(), startCol*3); - if (endCol < 255) - memcpy(palette + endCol * 3, _vm->screen()->getScreenPalette() + endCol * 3, (255-endCol)*3); + palette.copy(_vm->screen()->getPalette(0), 0, startCol); + if (endCol < palette.getNumColors()) + palette.copy(_vm->screen()->getPalette(0), endCol); _vm->screen()->setScreenPalette(palette); _vm->screen()->updateScreen(); diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp index faea2c9a72..85d974f675 100644 --- a/engines/kyra/gui.cpp +++ b/engines/kyra/gui.cpp @@ -83,17 +83,21 @@ void GUI::initMenu(Menu &menu) { int menu_y2 = menu.height + menu.y - 1; _screen->fillRect(menu.x + 2, menu.y + 2, menu_x2 - 2, menu_y2 - 2, menu.bkgdColor); - _screen->drawShadedBox(menu.x, menu.y, menu_x2, menu_y2, menu.color1, menu.color2); + _screen->drawShadedBox(menu.x, menu.y, menu_x2, menu_y2, menu.color1, menu.color2, _vm->gameFlags().gameID == GI_LOL ? Screen::kShadeTypeLol : Screen::kShadeTypeKyra); if (menu.titleX != -1) textX = menu.titleX; else - textX = _text->getCenterStringX(getMenuTitle(menu), menu.x, menu_x2); + textX = getMenuCenterStringX(getMenuTitle(menu), menu.x, menu_x2); textY = menu.y + menu.titleY; - _text->printText(getMenuTitle(menu), textX - 1, textY + 1, defaultColor1(), defaultColor2(), 0); - _text->printText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 0); + if (_vm->gameFlags().gameID == GI_LOL) { + printMenuText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 9); + } else { + printMenuText(getMenuTitle(menu), textX - 1, textY + 1, defaultColor1(), defaultColor2(), 0); + printMenuText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 0); + } int x1, y1, x2, y2; for (int i = 0; i < menu.numberOfItems; ++i) { @@ -114,35 +118,49 @@ void GUI::initMenu(Menu &menu) { menuButtonData->width = menu.item[i].width - 1; menuButtonData->height = menu.item[i].height - 1; menuButtonData->buttonCallback = menu.item[i].callback; - menuButtonData->keyCode = menu.item[i].unk1F; + menuButtonData->keyCode = menu.item[i].keyCode; menuButtonData->keyCode2 = 0; + menuButtonData->arg = menu.item[i].itemId; _menuButtonList = addButtonToList(_menuButtonList, menuButtonData); } _screen->fillRect(x1, y1, x2, y2, menu.item[i].bkgdColor); - _screen->drawShadedBox(x1, y1, x2, y2, menu.item[i].color1, menu.item[i].color2); + _screen->drawShadedBox(x1, y1, x2, y2, menu.item[i].color1, menu.item[i].color2, _vm->gameFlags().gameID == GI_LOL ? Screen::kShadeTypeLol : Screen::kShadeTypeKyra); if (getMenuItemTitle(menu.item[i])) { if (menu.item[i].titleX != -1) textX = x1 + menu.item[i].titleX + 3; else - textX = _text->getCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); + textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); textY = y1 + 2; - _text->printText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); - - if (i == menu.highlightedItem) - _text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0); - else - _text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0); + if (_vm->gameFlags().gameID == GI_LOL) { + textY++; + if (i == menu.highlightedItem) + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 8); + else + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 8); + } else { + printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); + if (i == menu.highlightedItem) + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0); + else + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0); + } } } for (int i = 0; i < menu.numberOfItems; ++i) { if (getMenuItemLabel(menu.item[i])) { - _text->printText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX - 1, menu.y + menu.item[i].labelY + 1, defaultColor1(), 0, 0); - _text->printText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 0); + if (_vm->gameFlags().gameID == GI_LOL) { + menu.item[i].labelX = menu.item[i].x - 1; + menu.item[i].labelY = menu.item[i].y + 3; + printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 10); + } else { + printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX - 1, menu.y + menu.item[i].labelY + 1, defaultColor1(), 0, 0); + printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 0); + } } } @@ -172,8 +190,22 @@ void GUI::initMenu(Menu &menu) { _screen->updateScreen(); } -void GUI::processHighlights(Menu &menu, int mouseX, int mouseY) { +void GUI::processHighlights(Menu &menu) { int x1, y1, x2, y2; + Common::Point p = _vm->getMousePos(); + int mouseX = p.x; + int mouseY = p.y; + + if (_vm->_flags.gameID == GI_LOL && menu.highlightedItem != 255) { + // LoL doesnt't have default highlighted items. + // We use a highlightedItem value of 255 for this. + + // With LoL no highlighting should take place unless the + // mouse cursor moves over a button. The highlighting should end + // when the mouse cursor leaves the button. + if (menu.item[menu.highlightedItem].enabled) + redrawText(menu); + } for (int i = 0; i < menu.numberOfItems; ++i) { if (!menu.item[i].enabled) @@ -188,9 +220,11 @@ void GUI::processHighlights(Menu &menu, int mouseX, int mouseY) { if (mouseX > x1 && mouseX < x2 && mouseY > y1 && mouseY < y2) { - if (menu.highlightedItem != i) { - if (menu.item[menu.highlightedItem].enabled) - redrawText(menu); + if (menu.highlightedItem != i || _vm->_flags.gameID == GI_LOL) { + if (_vm->_flags.gameID != GI_LOL) { + if (menu.item[menu.highlightedItem].enabled) + redrawText(menu); + } menu.highlightedItem = i; redrawHighlight(menu); @@ -212,11 +246,16 @@ void GUI::redrawText(const Menu &menu) { if (menu.item[i].titleX >= 0) textX = x1 + menu.item[i].titleX + 3; else - textX = _text->getCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); + textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); int textY = y1 + 2; - _text->printText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); - _text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0); + if (_vm->gameFlags().gameID == GI_LOL) { + textY++; + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 8); + } else { + printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0); + } } void GUI::redrawHighlight(const Menu &menu) { @@ -231,11 +270,17 @@ void GUI::redrawHighlight(const Menu &menu) { if (menu.item[i].titleX != -1) textX = x1 + menu.item[i].titleX + 3; else - textX = _text->getCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); + textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); int textY = y1 + 2; - _text->printText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); - _text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0); + + if (_vm->gameFlags().gameID == GI_LOL) { + textY++; + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 8); + } else { + printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0); + } } void GUI::updateAllMenuButtons() { @@ -296,7 +341,7 @@ int GUI::redrawShadedButtonCallback(Button *button) { return 0; } -void GUI::updateSaveList() { +void GUI::updateSaveList(bool excludeQuickSaves) { Common::String pattern = _vm->_targetName + ".???"; Common::StringList saveFileList = _vm->_saveFileMan->listSavefiles(pattern); _saveSlots.clear(); @@ -311,6 +356,8 @@ void GUI::updateSaveList() { s1 -= '0'; s2 -= '0'; s3 -= '0'; + if (excludeQuickSaves && s1 == 9 && s2 == 9) + continue; _saveSlots.push_back(s1*100+s2*10+s3); } @@ -383,6 +430,14 @@ void GUI::checkTextfieldInput() { _vm->_system->delayMillis(3); } +void GUI::printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2, Screen::FontId font) { + _text->printText(str, x, y, c0, c1, c2, font); +} + +int GUI::getMenuCenterStringX(const char *str, int x1, int x2) { + return _text->getCenterStringX(str, x1, x2); +} + #pragma mark - MainMenu::MainMenu(KyraEngine_v1 *vm) : _vm(vm), _screen(0) { @@ -404,7 +459,7 @@ void MainMenu::updateAnimation() { if (now > _nextUpdate) { _nextUpdate = now + _anim.delay * _vm->tickLength(); - _anim.anim->displayFrame(_animIntern.curFrame, 0, 0, 0); + _anim.anim->displayFrame(_animIntern.curFrame, 0, 0, 0, 0, 0, 0); _animIntern.curFrame += _animIntern.direction ; if (_animIntern.curFrame < _anim.startFrame) { _animIntern.curFrame = _anim.startFrame; @@ -421,8 +476,9 @@ void MainMenu::updateAnimation() { bool MainMenu::getInput() { Common::Event event; + Common::EventManager *eventMan = _vm->getEventManager(); - while (_system->getEventManager()->pollEvent(event)) { + while (eventMan->pollEvent(event)) { switch (event.type) { case Common::EVENT_LBUTTONUP: return true; diff --git a/engines/kyra/gui.h b/engines/kyra/gui.h index f83620c8f9..3989062506 100644 --- a/engines/kyra/gui.h +++ b/engines/kyra/gui.h @@ -114,7 +114,7 @@ struct MenuItem { uint16 labelId; int16 labelX, labelY; - uint16 unk1F; + uint16 keyCode; }; struct Menu { @@ -161,7 +161,7 @@ public: virtual void initMenuLayout(Menu &menu); void initMenu(Menu &menu); - void processHighlights(Menu &menu, int mouseX, int mouseY); + void processHighlights(Menu &menu); // utilities for thumbnail creation virtual void createScreenThumbnail(Graphics::Surface &dst) = 0; @@ -176,6 +176,9 @@ protected: bool _displaySubMenu; bool _cancelSubMenu; + virtual void printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2, Screen::FontId font=Screen::FID_8_FNT); + virtual int getMenuCenterStringX(const char *str, int x1, int x2); + Button::Callback _redrawShadedButtonFunctor; Button::Callback _redrawButtonFunctor; @@ -201,7 +204,7 @@ protected: void redrawHighlight(const Menu &menu); Common::Array<int> _saveSlots; - void updateSaveList(); + void updateSaveList(bool excludeQuickSaves = false); int getNextSavegameSlot(); uint32 _lastScreenUpdate; diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp index a37ac7b306..69e7419757 100644 --- a/engines/kyra/gui_hof.cpp +++ b/engines/kyra/gui_hof.cpp @@ -95,7 +95,11 @@ const char *GUI_HoF::getMenuItemTitle(const MenuItem &menuItem) { if (!menuItem.itemId) return 0; - return _vm->getTableString(menuItem.itemId, _vm->_optionsBuffer, 1); + // Strings 41-45 are menu labels, those must be handled uncompressed! + if (menuItem.itemId >= 41 && menuItem.itemId <= 45) + return _vm->getTableString(menuItem.itemId, _vm->_optionsBuffer, 0); + else + return _vm->getTableString(menuItem.itemId, _vm->_optionsBuffer, 1); } const char *GUI_HoF::getMenuItemLabel(const MenuItem &menuItem) { @@ -272,7 +276,7 @@ void KyraEngine_HoF::redrawInventory(int page) { } void KyraEngine_HoF::scrollInventoryWheel() { - WSAMovie_v2 movie(this, _screen); + WSAMovie_v2 movie(this); movie.open("INVWHEEL.WSA", 0, 0); int frames = movie.opened() ? movie.frames() : 6; memcpy(_screenBuffer, _screen->getCPagePtr(2), 64000); @@ -287,7 +291,7 @@ void KyraEngine_HoF::scrollInventoryWheel() { for (int i = 0; i <= 6 && !breakFlag; ++i) { if (movie.opened()) { _screen->hideMouse(); - movie.displayFrame(i % frames, 0, 0, 0, 0); + movie.displayFrame(i % frames, 0, 0, 0, 0, 0, 0); _screen->showMouse(); _screen->updateScreen(); } @@ -361,9 +365,9 @@ int KyraEngine_HoF::bookButton(Button *button) { _screen->showMouse(); } - memcpy(_screen->getPalette(2), _screen->getPalette(0), 768); + _screen->copyPalette(2, 0); _screen->fadeToBlack(7, &_updateFunctor); - _res->loadFileToBuf("_BOOK.COL", _screen->getPalette(0), 768); + _screen->loadPalette("_BOOK.COL", _screen->getPalette(0)); loadBookBkgd(); showBookPage(); _screen->copyRegion(0, 0, 0, 0, 0x140, 0xC8, 2, 0, Screen::CR_NO_P_CHECK); @@ -389,7 +393,7 @@ int KyraEngine_HoF::bookButton(Button *button) { } setHandItem(_itemInHand); - memcpy(_screen->getPalette(0), _screen->getPalette(2), 768); + _screen->copyPalette(0, 2); _screen->fadePalette(_screen->getPalette(0), 7, &_updateFunctor); _screen->showMouse(); @@ -700,7 +704,6 @@ int GUI_HoF::optionsButton(Button *button) { int oldHandItem = _vm->_itemInHand; _screen->setMouseCursor(0, 0, _vm->getShapePtr(0)); _vm->displayInvWsaLastFrame(); - //XXX _displayMenu = true; for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i) { @@ -763,7 +766,7 @@ int GUI_HoF::optionsButton(Button *button) { } while (_displayMenu) { - processHighlights(*_currentMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(*_currentMenu); getInput(); } @@ -796,16 +799,11 @@ void GUI_HoF::createScreenThumbnail(Graphics::Surface &dst) { } void GUI_HoF::setupPalette() { - memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); - - uint8 *palette = _screen->getPalette(0); - for (int i = 0; i < 768; ++i) - palette[i] >>= 1; - - static const uint8 guiPal[] = { 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFc, 0xFD, 0xFE }; + _screen->copyPalette(1, 0); - for (uint i = 0; i < ARRAYSIZE(guiPal); ++i) - memcpy(_screen->getPalette(0)+guiPal[i]*3, _screen->getPalette(1)+guiPal[i]*3, 3); + Palette &pal = _screen->getPalette(0); + for (int i = 0; i < 741; ++i) + pal[i] >>= 1; if (_isDeathMenu) _screen->fadePalette(_screen->getPalette(0), 0x64); @@ -814,7 +812,7 @@ void GUI_HoF::setupPalette() { } void GUI_HoF::restorePalette() { - memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); + _screen->copyPalette(0, 1); _screen->setScreenPalette(_screen->getPalette(0)); } @@ -851,8 +849,7 @@ void GUI_HoF::drawSliderBar(int slider, const uint8 *shape) { position = _vm->_configTextspeed; } - position = MAX(2, position); - position = MIN(97, position); + position = CLIP(position, 2, 97); _screen->drawShape(0, shape, x+position, y, 0, 0); } @@ -908,7 +905,7 @@ int GUI_HoF::audioOptions(Button *caller) { updateAllMenuButtons(); bool speechEnabled = _vm->speechEnabled(); while (_isOptionsMenu) { - processHighlights(_audioOptions, _vm->_mouseX, _vm->_mouseY); + processHighlights(_audioOptions); getInput(); } @@ -956,7 +953,7 @@ int GUI_HoF::gameOptions(Button *caller) { } while (_isOptionsMenu) { - processHighlights(_gameOptions, _vm->_mouseX, _vm->_mouseY); + processHighlights(_gameOptions); getInput(); } @@ -983,7 +980,7 @@ int GUI_HoF::gameOptionsTalkie(Button *caller) { _isOptionsMenu = true; while (_isOptionsMenu) { - processHighlights(_gameOptions, _vm->_mouseX, _vm->_mouseY); + processHighlights(_gameOptions); getInput(); } @@ -1094,8 +1091,7 @@ int GUI_HoF::sliderHandler(Button *caller) { else newVolume = _vm->_mouseX - caller->x - 7; - newVolume = MAX(2, newVolume); - newVolume = MIN(97, newVolume); + newVolume = CLIP(newVolume, 2, 97); if (newVolume == oldVolume) return 0; @@ -1175,7 +1171,7 @@ int GUI_HoF::loadMenu(Button *caller) { _screen->updateScreen(); while (_isLoadMenu) { - processHighlights(_loadMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(_loadMenu); getInput(); } diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp index 560bc6c2f2..9f42697ec7 100644 --- a/engines/kyra/gui_lok.cpp +++ b/engines/kyra/gui_lok.cpp @@ -31,6 +31,7 @@ #include "kyra/sound.h" #include "kyra/gui_lok.h" #include "kyra/timer.h" +#include "kyra/util.h" #include "common/config-manager.h" #include "common/savefile.h" @@ -86,7 +87,6 @@ int KyraEngine_LoK::buttonInventoryCallback(Button *caller) { } } _screen->updateScreen(); - // XXX clearKyrandiaButtonIO return 0; } @@ -182,7 +182,6 @@ int KyraEngine_LoK::buttonAmuletCallback(Button *caller) { break; } _unkAmuletVar = 0; - // XXX clearKyrandiaButtonIO (!used before every return in this function!) return 1; } @@ -479,7 +478,7 @@ int GUI_LoK::buttonMenuCallback(Button *caller) { } while (_displayMenu && !_vm->shouldQuit()) { - processHighlights(_menu[_toplevelMenu], _vm->_mouseX, _vm->_mouseY); + processHighlights(_menu[_toplevelMenu]); getInput(); } @@ -538,6 +537,9 @@ void GUI_LoK::setupSavegames(Menu &menu, int num) { if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header))) { strncpy(savenames[i], header.description.c_str(), ARRAYSIZE(savenames[0])); savenames[i][34] = 0; + + Util::convertISOToDOS(savenames[i]); + menu.item[i].itemString = savenames[i]; menu.item[i].enabled = 1; menu.item[i].saveSlot = _saveSlots[i + _savegameOffset]; @@ -570,7 +572,7 @@ int GUI_LoK::saveGameMenu(Button *button) { _cancelSubMenu = false; while (_displaySubMenu && !_vm->shouldQuit()) { - processHighlights(_menu[2], _vm->_mouseX, _vm->_mouseY); + processHighlights(_menu[2]); getInput(); } @@ -616,7 +618,7 @@ int GUI_LoK::loadGameMenu(Button *button) { _vm->_gameToLoad = -1; while (_displaySubMenu && !_vm->shouldQuit()) { - processHighlights(_menu[2], _vm->_mouseX, _vm->_mouseY); + processHighlights(_menu[2]); getInput(); } @@ -654,9 +656,12 @@ void GUI_LoK::updateSavegameString() { if (_keyPressed.keycode) { length = strlen(_savegameName); - if (_keyPressed.ascii > 31 && _keyPressed.ascii < 127) { + char inputKey = _keyPressed.ascii; + Util::convertISOToDOS(inputKey); + + if ((uint8)inputKey > 31 && (uint8)inputKey < 226) { if (length < ARRAYSIZE(_savegameName)-1) { - _savegameName[length] = _keyPressed.ascii; + _savegameName[length] = inputKey; _savegameName[length+1] = 0; redrawTextfield(); } @@ -703,7 +708,7 @@ int GUI_LoK::saveGame(Button *button) { while (_displaySubMenu && !_vm->shouldQuit()) { checkTextfieldInput(); updateSavegameString(); - processHighlights(_menu[3], _vm->_mouseX, _vm->_mouseY); + processHighlights(_menu[3]); } if (_cancelSubMenu) { @@ -715,6 +720,8 @@ int GUI_LoK::saveGame(Button *button) { if (_savegameOffset == 0 && _vm->_gameToLoad == 0) _vm->_gameToLoad = getNextSavegameSlot(); if (_vm->_gameToLoad > 0) { + Util::convertDOSToISO(_savegameName); + Graphics::Surface thumb; createScreenThumbnail(thumb); _vm->saveGameState(_vm->_gameToLoad, _savegameName, &thumb); @@ -773,7 +780,7 @@ bool GUI_LoK::quitConfirm(const char *str) { _cancelSubMenu = true; while (_displaySubMenu && !_vm->shouldQuit()) { - processHighlights(_menu[1], _vm->_mouseX, _vm->_mouseY); + processHighlights(_menu[1]); getInput(); } @@ -833,7 +840,7 @@ int GUI_LoK::gameControlsMenu(Button *button) { _cancelSubMenu = false; while (_displaySubMenu && !_vm->shouldQuit()) { - processHighlights(_menu[5], _vm->_mouseX, _vm->_mouseY); + processHighlights(_menu[5]); getInput(); } @@ -1015,25 +1022,25 @@ void GUI_LoK::fadePalette() { static const int16 menuPalIndexes[] = {248, 249, 250, 251, 252, 253, 254, -1}; int index = 0; - memcpy(_screen->getPalette(2), _screen->_currentPalette, 768); + _screen->copyPalette(2, 0); for (int i = 0; i < 768; i++) - _screen->_currentPalette[i] >>= 1; + _screen->getPalette(0)[i] >>= 1; while (menuPalIndexes[index] != -1) { - memcpy(&_screen->_currentPalette[menuPalIndexes[index]*3], &_screen->getPalette(2)[menuPalIndexes[index]*3], 3); - index++; + _screen->getPalette(0).copy(_screen->getPalette(2), menuPalIndexes[index], 1); + ++index; } - _screen->fadePalette(_screen->_currentPalette, 2); + _screen->fadePalette(_screen->getPalette(0), 2); } void GUI_LoK::restorePalette() { if (_vm->gameFlags().platform == Common::kPlatformAmiga) return; - memcpy(_screen->_currentPalette, _screen->getPalette(2), 768); - _screen->fadePalette(_screen->_currentPalette, 2); + _screen->copyPalette(0, 2); + _screen->fadePalette(_screen->getPalette(0), 2); } #pragma mark - diff --git a/engines/kyra/gui_lok.h b/engines/kyra/gui_lok.h index eec57f5546..5982ef1ce2 100644 --- a/engines/kyra/gui_lok.h +++ b/engines/kyra/gui_lok.h @@ -89,7 +89,7 @@ namespace Kyra { item.labelString = r; \ item.labelX = s; \ item.labelY = t; \ - item.unk1F = v; \ + item.keyCode = v; \ } while (0) class KyraEngine_LoK; diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp index af8bc6aa97..5e03f3d9bb 100644 --- a/engines/kyra/gui_lol.cpp +++ b/engines/kyra/gui_lol.cpp @@ -28,6 +28,14 @@ #include "kyra/lol.h" #include "kyra/screen_lol.h" #include "kyra/gui_lol.h" +#include "kyra/resource.h" +#include "kyra/util.h" + +#include "common/savefile.h" +#include "common/config-manager.h" +#include "graphics/scaler.h" + +#include "base/version.h" namespace Kyra { @@ -577,7 +585,7 @@ void LoLEngine::gui_drawCompass() { } int LoLEngine::gui_enableControls() { - _floatingMouseArrowControl = 0; + _floatingCursorControl = 0; if (!_currentControlMode) { for (int i = 76; i < 85; i++) @@ -592,7 +600,7 @@ int LoLEngine::gui_disableControls(int controlMode) { if (_currentControlMode) return 0; - _floatingMouseArrowControl = (controlMode & 2) ? 2 : 1; + _floatingCursorControl = (controlMode & 2) ? 2 : 1; gui_toggleFightButtons(true); @@ -1364,7 +1372,7 @@ int LoLEngine::clickedInventorySlot(Button *button) { (_itemsInPlay[hItem].itemPropertyIndex == 220 || _itemsInPlay[slotItem].itemPropertyIndex == 220)) { // merge ruby of truth - WSAMovie_v2 *wsa = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *wsa = new WSAMovie_v2(this); wsa->open("truth.wsa", 0, 0); _screen->hideMouse(); @@ -1377,7 +1385,7 @@ int LoLEngine::clickedInventorySlot(Button *button) { for (int i = 0; i < 25; i++) { uint32 delayTimer = _system->getMillis() + 7 * _tickLength; _screen->copyRegion(button->x, button->y - 3, 0, 0, 25, 27, 2, 2); - wsa->displayFrame(i, 2, 0, 0, 0x4000); + wsa->displayFrame(i, 2, 0, 0, 0x4000, 0, 0); _screen->copyRegion(0, 0, button->x, button->y - 3, 25, 27, 2, 0); _screen->updateScreen(); delayUntil(delayTimer); @@ -1536,10 +1544,43 @@ int LoLEngine::clickedSceneThrowItem(Button *button) { } int LoLEngine::clickedOptions(Button *button) { + removeInputTop(); gui_toggleButtonDisplayMode(76, 1); + _updateFlags |= 4; + + Button b; + b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xfe; + b.data0Val3 = b.data1Val3 = b.data2Val3 = 0x01; + + if (_weaponsDisabled) + clickedExitCharInventory(&b); + + initTextFading(0, 1); + updatePortraits(); + setLampMode(true); + setMouseCursorToIcon(0); + disableSysTimer(2); + gui_toggleButtonDisplayMode(76, 0); + bool speechWasEnabled = speechEnabled(); + _gui->runMenu(_gui->_mainMenu); + + _updateFlags &= 0xfffb; + setMouseCursorToItemInHand(); + resetLampStatus(); + gui_enableDefaultPlayfieldButtons(); + enableSysTimer(2); + updateDrawPage2(); + + gui_drawPlayField(); + + if (speechWasEnabled && !textEnabled() && (!speechEnabled() || getVolume(kVolumeSpeech) == 2)) + _configVoice = 0; + + writeSettings(); + return 1; } @@ -1773,7 +1814,7 @@ int LoLEngine::clickedAutomap(Button *button) { displayAutomap(); gui_drawPlayField(); - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); return 1; } @@ -1801,7 +1842,7 @@ int LoLEngine::clickedLamp(Button *button) { } if (_brightness) - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); return 1; } @@ -1826,9 +1867,13 @@ int LoLEngine::clickedStatusIcon(Button *button) { GUI_LoL::GUI_LoL(LoLEngine *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) { _scrollUpFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::scrollUp); _scrollDownFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::scrollDown); + _redrawButtonFunctor = BUTTON_FUNCTOR(GUI, this, &GUI::redrawButtonCallback); + _redrawShadedButtonFunctor = BUTTON_FUNCTOR(GUI, this, &GUI::redrawShadedButtonCallback); + _specialProcessButton = _backUpButtonList = 0; _flagsModifier = 0; _mouseClick = 0; + _sliderSfx = 11; _buttonListChanged = false; } @@ -2164,6 +2209,624 @@ int GUI_LoL::processButtonList(Button *buttonList, uint16 inputFlag, int8 mouseW return returnValue; } +int GUI_LoL::redrawButtonCallback(Button *button) { + if (!_displayMenu) + return 0; + + _screen->drawBox(button->x + 1, button->y + 1, button->x + button->width - 1, button->y + button->height - 1, 225); + return 0; +} + +int GUI_LoL::redrawShadedButtonCallback(Button *button) { + if (!_displayMenu) + return 0; + + _screen->drawShadedBox(button->x, button->y, button->x + button->width, button->y + button->height, 223, 227, Screen::kShadeTypeLol); + return 0; +} + +int GUI_LoL::runMenu(Menu &menu) { + _currentMenu = &menu; + _lastMenu = _currentMenu; + _newMenu = 0; + _displayMenu = true; + _menuResult = 1; + _savegameOffset = 0; + backupPage0(); + + const ScreenDim *d = _screen->getScreenDim(8); + uint32 textCursorTimer = 0; + uint8 textCursorStatus = 1; + int wW = _screen->getCharWidth('W'); + int fW = (d->w << 3) - wW; + int fC = 0; + + // LoL doesnt't have default higlighted items. No item should be + // highlighted when entering a new menu. + // Instead, the respevtive struct entry is used to determine whether + // a menu has scroll buttons or slider bars. + uint8 hasSpecialButtons = 0; + + while (_displayMenu) { + _vm->_mouseX = _vm->_mouseY = 0; + + if (_currentMenu == &_loadMenu || _currentMenu == &_saveMenu || _currentMenu == &_deleteMenu) { + updateSaveList(true); + Common::sort(_saveSlots.begin(), _saveSlots.end(), Common::Greater<int>()); + setupSavegameNames(*_currentMenu, 4); + } + + hasSpecialButtons = _currentMenu->highlightedItem; + _currentMenu->highlightedItem = 255; + + if (_currentMenu == &_gameOptions) { + char *s = (char *)_vm->_tempBuffer5120; + strncpy(s, _vm->getLangString(0x406f + _vm->_monsterDifficulty), 30); + s[29] = 0; + _currentMenu->item[0].itemString = s; + s += (strlen(s) + 1); + + strncpy(s, _vm->getLangString(_vm->_smoothScrollingEnabled ? 0x4068 : 0x4069), 30); + s[29] = 0; + _currentMenu->item[1].itemString = s; + s += (strlen(s) + 1); + + strncpy(s, _vm->getLangString(_vm->_floatingCursorsEnabled ? 0x4068 : 0x4069), 30); + s[29] = 0; + _currentMenu->item[2].itemString = s; + s += (strlen(s) + 1); + + strncpy(s, _vm->getLangString(0x42d6 + _vm->_lang), 30); + s[29] = 0; + _currentMenu->item[3].itemString = s; + s += (strlen(s) + 1); + + strncpy(s, _vm->getLangString(_vm->textEnabled() ? 0x4068 : 0x4069), 30); + s[29] = 0; + _currentMenu->item[4].itemString = s; + s += (strlen(s) + 1); + } + + if (hasSpecialButtons == 1) { + if (_savegameOffset == 0) { + _scrollUpButton.data0ShapePtr = _scrollUpButton.data1ShapePtr = _scrollUpButton.data2ShapePtr = 0; + } else { + _scrollUpButton.data0ShapePtr = _vm->_gameShapes[17]; + _scrollUpButton.data1ShapePtr = _scrollUpButton.data2ShapePtr = _vm->_gameShapes[19]; + } + if ((uint)_savegameOffset == _saveSlots.size() - 4) { + _scrollDownButton.data0ShapePtr = _scrollDownButton.data1ShapePtr = _scrollDownButton.data2ShapePtr = 0; + } else { + _scrollDownButton.data0ShapePtr = _vm->_gameShapes[18]; + _scrollDownButton.data1ShapePtr = _scrollDownButton.data2ShapePtr = _vm->_gameShapes[20]; + } + } + + for (uint i = 0; i < _currentMenu->numberOfItems; ++i) { + _menuButtons[i].data0Val1 = _menuButtons[i].data1Val1 = _menuButtons[i].data2Val1 = 4; + _menuButtons[i].data0Callback = _redrawShadedButtonFunctor; + _menuButtons[i].data1Callback = _menuButtons[i].data2Callback = _redrawButtonFunctor; + _menuButtons[i].flags = 0x4487; + _menuButtons[i].flags2 = 0; + } + + initMenu(*_currentMenu); + + if (hasSpecialButtons == 2) { + static const uint8 oX[] = { 0, 10, 124 }; + static const uint8 oW[] = { 10, 114, 10 }; + + for (int i = 1; i < 4; ++i) { + int tX = _currentMenu->x + _currentMenu->item[i].x; + int tY = _currentMenu->y + _currentMenu->item[i].y; + + for (int ii = 0; ii < 3; ++ii) { + Button *b = getButtonListData() + 1 + (i - 1) * 3 + ii; + b->nextButton = 0; + b->data0Val2 = b->data1Val2 = b->data2Val2 = 0xfe; + b->data0Val3 = b->data1Val3 = b->data2Val3 = 0x01; + + b->index = ii; + b->keyCode = b->keyCode2 = 0; + + b->x = tX + oX[ii]; + b->y = tY; + b->width = oW[ii]; + b->height = _currentMenu->item[i].height; + + b->data0Val1 = b->data1Val1 = b->data2Val1 = 0; + b->flags = (ii == 1) ? 0x6606 : 0x4406; + + b->dimTableIndex = 0; + + b->buttonCallback = _currentMenu->item[i].callback; + b->arg = _currentMenu->item[i].itemId; + + _menuButtonList = addButtonToList(_menuButtonList, b); + + processButton(b); + updateButton(b); + } + + _currentMenu->item[i].labelX = _currentMenu->item[i].x - 5; + _currentMenu->item[i].labelY = _currentMenu->item[i].y + 3; + + printMenuText(getMenuItemLabel(_currentMenu->item[i]), _currentMenu->x + _currentMenu->item[i].labelX, _currentMenu->y + _currentMenu->item[i].labelY, _currentMenu->item[i].textColor, 0, 10); + + int volume = _vm->getVolume((KyraEngine_v1::kVolumeEntry)(i - 1)); + _screen->drawShape(_screen->_curPage, _vm->_gameShapes[85], tX , tY, 0, 0x10); + _screen->drawShape(_screen->_curPage, _vm->_gameShapes[87], tX + 2 + oX[1], tY, 0, 0x10); + _screen->drawShape(_screen->_curPage, _vm->_gameShapes[86], tX + oX[1] + volume, tY, 0, 0x10); + } + + _screen->updateScreen(); + } + + if (_currentMenu == &_mainMenu) { + Screen::FontId f = _screen->setFont(Screen::FID_6_FNT); + _screen->fprintString("%s", menu.x + 8, menu.y + menu.height - 12, 204, 0, 8, gScummVMVersion); + _screen->setFont(f); + _screen->updateScreen(); + } + + if (_currentMenu == &_savenameMenu) { + int mx = (d->sx << 3) - 1; + int my = d->sy - 1; + int mw = (d->w << 3) + 1; + int mh = d->h + 1; + _screen->drawShadedBox(mx, my, mx + mw, my + mh, 227, 223, Screen::kShadeTypeLol); + int pg = _screen->setCurPage(0); + _vm->_txt->clearDim(8); + textCursorTimer = 0; + textCursorStatus = 0; + + fC = _screen->getTextWidth(_saveDescription); + while (fC >= fW) { + _saveDescription[strlen(_saveDescription) - 1] = 0; + fC = _screen->getTextWidth(_saveDescription); + } + + _screen->fprintString(_saveDescription, (d->sx << 3), d->sy + 2, d->unk8, d->unkA, 0); + _screen->fillRect((d->sx << 3) + fC, d->sy, (d->sx << 3) + fC + wW, d->sy + d->h - 1, d->unk8, 0); + _screen->setCurPage(pg); + } + + while (!_newMenu && _displayMenu) { + processHighlights(*_currentMenu); + + if (_currentMenu == &_savenameMenu) { + if (textCursorTimer <= _vm->_system->getMillis()) { + fC = _screen->getTextWidth(_saveDescription); + textCursorStatus ^= 1; + textCursorTimer = _vm->_system->getMillis() + 20 * _vm->_tickLength; + _screen->fillRect((d->sx << 3) + fC, d->sy, (d->sx << 3) + fC + wW, d->sy + d->h - 1, textCursorStatus ? d->unk8 : d->unkA, 0); + _screen->updateScreen(); + } + } + + if (getInput()) { + if (!_newMenu) + _newMenu = (_currentMenu != &_audioOptions) ? _currentMenu : 0; + else + _lastMenu = _menuResult == -1 ? _lastMenu : _currentMenu; + } + + if (!_menuResult) + _displayMenu = false; + } + + if (_newMenu != _currentMenu || !_displayMenu) + restorePage0(); + + _currentMenu->highlightedItem = hasSpecialButtons; + + if (_newMenu) + _currentMenu = _newMenu; + + _newMenu = 0; + } + + return _menuResult; +} + +void GUI_LoL::createScreenThumbnail(Graphics::Surface &dst) { + uint8 *screenPal = new uint8[768]; + _screen->getRealPalette(1, screenPal); + ::createThumbnail(&dst, _screen->getCPagePtr(7), Screen::SCREEN_W, Screen::SCREEN_H, screenPal); + delete[] screenPal; +} + +void GUI_LoL::backupPage0() { + _screen->copyPage(0, 7); +} + +void GUI_LoL::restorePage0() { + _screen->copyPage(7, 0); + _screen->updateScreen(); +} + +void GUI_LoL::setupSavegameNames(Menu &menu, int num) { + char *s = (char *)_vm->_tempBuffer5120; + + for (int i = 0; i < num; ++i) { + menu.item[i].saveSlot = -1; + menu.item[i].enabled = false; + } + + int startSlot = 0; + if (&menu == &_saveMenu && _savegameOffset == 0) + startSlot = 1; + + KyraEngine_v1::SaveHeader header; + Common::InSaveFile *in; + for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); ++i) { + if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset - startSlot]), header)) != 0) { + strncpy(s, header.description.c_str(), 80); + s[79] = 0; + + Util::convertISOToDOS(s); + + menu.item[i].itemString = s; + s += (strlen(s) + 1); + menu.item[i].saveSlot = _saveSlots[i + _savegameOffset]; + menu.item[i].enabled = true; + delete in; + } + } + + if (_savegameOffset == 0) { + if (&menu == &_saveMenu) { + strcpy(s, _vm->getLangString(0x4010)); + menu.item[0].itemString = s; + menu.item[0].saveSlot = -3; + menu.item[0].enabled = true; + } + } +} + +void GUI_LoL::printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 flags, Screen::FontId font) { + _screen->fprintString(str, x, y, c0, c1, flags); +} + +int GUI_LoL::getMenuCenterStringX(const char *str, int x1, int x2) { + if (!str) + return 0; + + int strWidth = _screen->getTextWidth(str); + int w = x2 - x1 + 1; + return x1 + (w - strWidth) / 2; +} + +int GUI_LoL::getInput() { + if (!_displayMenu) + return 0; + + Common::Point p = _vm->getMousePos(); + _vm->_mouseX = p.x; + _vm->_mouseY = p.y; + + if (_currentMenu == &_savenameMenu) { + _vm->updateInput(); + + for (Common::List<KyraEngine_v1::Event>::const_iterator evt = _vm->_eventList.begin(); evt != _vm->_eventList.end(); evt++) { + if (evt->event.type == Common::EVENT_KEYDOWN) + _keyPressed = evt->event.kbd; + } + } + + int inputFlag = _vm->checkInput(_menuButtonList); + + if (_currentMenu == &_savenameMenu && _keyPressed.ascii){ + char inputKey = _keyPressed.ascii; + Util::convertISOToDOS(inputKey); + + if ((uint8)inputKey > 31 && (uint8)inputKey < 226) { + _saveDescription[strlen(_saveDescription) + 1] = 0; + _saveDescription[strlen(_saveDescription)] = inputKey; + inputFlag |= 0x8000; + } else if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE && strlen(_saveDescription)) { + _saveDescription[strlen(_saveDescription) - 1] = 0; + inputFlag |= 0x8000; + } + } + + _vm->removeInputTop(); + _keyPressed.reset(); + + if (_vm->shouldQuit()) + _displayMenu = false; + + _vm->delay(8); + return inputFlag & 0x8000 ? 1 : 0; +} + +int GUI_LoL::clickedMainMenu(Button *button) { + updateMenuButton(button); + switch (button->arg) { + case 0x4001: + _savegameOffset = 0; + _newMenu = &_loadMenu; + break; + case 0x4002: + _savegameOffset = 0; + _newMenu = &_saveMenu; + break; + case 0x4003: + _savegameOffset = 0; + _newMenu = &_deleteMenu; + break; + case 0x4004: + _newMenu = &_gameOptions; + break; + case 0x42D9: + _newMenu = &_audioOptions; + break; + case 0x4006: + _choiceMenu.menuNameId = 0x400a; + _newMenu = &_choiceMenu; + break; + case 0x4005: + _displayMenu = false; + break; + } + return 1; +} + +int GUI_LoL::clickedLoadMenu(Button *button) { + updateMenuButton(button); + + if (button->arg == 0x4011) { + if (_currentMenu != _lastMenu) + _newMenu = _lastMenu; + else + _menuResult = 0; + return 1; + } + + int16 s = (int16)button->arg; + _vm->_gameToLoad = _loadMenu.item[-s - 2].saveSlot; + _displayMenu = false; + + return 1; +} + +int GUI_LoL::clickedSaveMenu(Button *button) { + updateMenuButton(button); + + if (button->arg == 0x4011) { + _newMenu = &_mainMenu; + return 1; + } + + _newMenu = &_savenameMenu; + int16 s = (int16)button->arg; + _menuResult = _saveMenu.item[-s - 2].saveSlot + 1; + _saveDescription = (char*)_vm->_tempBuffer5120 + 1000; + _saveDescription[0] = 0; + if (_saveMenu.item[-s - 2].saveSlot != -3) + strcpy(_saveDescription, _saveMenu.item[-s - 2].itemString); + + return 1; +} + +int GUI_LoL::clickedDeleteMenu(Button *button) { + updateMenuButton(button); + + if (button->arg == 0x4011) { + _newMenu = &_mainMenu; + return 1; + } + + _choiceMenu.menuNameId = 0x400b; + _newMenu = &_choiceMenu; + int16 s = (int16)button->arg; + _menuResult = _deleteMenu.item[-s - 2].saveSlot + 1; + + return 1; +} + +int GUI_LoL::clickedOptionsMenu(Button *button) { + updateMenuButton(button); + + switch (button->arg) { + case 0xfff7: + _vm->_monsterDifficulty = ++_vm->_monsterDifficulty % 3; + break; + case 0xfff6: + _vm->_smoothScrollingEnabled ^= true; + break; + case 0xfff5: + _vm->_floatingCursorsEnabled ^= true; + break; + case 0xfff4: + _vm->_lang = ++_vm->_lang % 3; + break; + case 0xfff3: + _vm->_configVoice ^= 1; + break; + case 0x4072: + char filename[13]; + snprintf(filename, sizeof(filename), "LEVEL%02d.%s", _vm->_currentLevel, _vm->_languageExt[_vm->_lang]); + if (_vm->_levelLangFile) + delete[] _vm->_levelLangFile; + _vm->_levelLangFile = _vm->resource()->fileData(filename, 0); + snprintf(filename, sizeof(filename), "LANDS.%s", _vm->_languageExt[_vm->_lang]); + if (_vm->_landsFile) + delete[] _vm->_landsFile; + _vm->_landsFile = _vm->resource()->fileData(filename, 0); + _newMenu = _lastMenu; + break; + } + + return 1; +} + +int GUI_LoL::clickedAudioMenu(Button *button) { + updateMenuButton(button); + + if (button->arg == 0x4072) { + _newMenu = _lastMenu; + return 1; + } + + int tX = button->x; + const int oldVolume = _vm->getVolume((KyraEngine_v1::kVolumeEntry)(button->arg - 3)); + int newVolume = oldVolume; + + if (button->index == 0) { + newVolume -= 10; + tX += 10; + } else if (button->index == 1) { + newVolume = _vm->_mouseX - (tX + 7); + } else if (button->index == 2) { + newVolume += 10; + tX -= 114; + } + + newVolume = CLIP(newVolume, 2, 102); + + if (newVolume == oldVolume) { + _screen->updateScreen(); + return 0; + } + + _screen->drawShape(0, _vm->_gameShapes[87], tX + oldVolume, button->y, 0, 0x10); + // Temporary HACK + const int volumeDrawX = _vm->convertVolumeFromMixer(_vm->convertVolumeToMixer(newVolume)); + _screen->drawShape(0, _vm->_gameShapes[86], tX + volumeDrawX, button->y, 0, 0x10); + _screen->updateScreen(); + + _vm->snd_stopSpeech(0); + + _vm->setVolume((KyraEngine_v1::kVolumeEntry)(button->arg - 3), newVolume); + + if (newVolume) { + if (button->arg == 4) { + _vm->snd_playSoundEffect(_sliderSfx, -1); + int16 vocIndex = (int16)READ_LE_UINT16(&_vm->_ingameSoundIndex[_sliderSfx * 2]); + do { + ++_sliderSfx; + if (_sliderSfx < 47) + _sliderSfx++; + if (vocIndex == 199) + _sliderSfx = 11; + vocIndex = (int16)READ_LE_UINT16(&_vm->_ingameSoundIndex[_sliderSfx * 2]); + if (vocIndex == -1) + continue; + if (!scumm_stricmp(_vm->_ingameSoundList[vocIndex], "EMPTY")) + continue; + break; + } while (1); + } else if (button->arg == 5) { + _vm->_lastSpeechId = -1; + _vm->snd_playCharacterSpeech(0x42e0, 0, 0); + } + } + + return 1; +} + +int GUI_LoL::clickedDeathMenu(Button *button) { + updateMenuButton(button); + if (button->arg == _deathMenu.item[0].itemId) { + _vm->quitGame(); + } else if (button->arg == _deathMenu.item[1].itemId) { + _newMenu = &_loadMenu; + } + return 1; +} + +int GUI_LoL::clickedSavenameMenu(Button *button) { + updateMenuButton(button); + if (button->arg == _savenameMenu.item[0].itemId) { + + Util::convertDOSToISO(_saveDescription); + + int slot = _menuResult == -2 ? getNextSavegameSlot() : _menuResult; + Graphics::Surface thumb; + createScreenThumbnail(thumb); + _vm->saveGameState(slot, _saveDescription, &thumb); + thumb.free(); + + _displayMenu = false; + + } else if (button->arg == _savenameMenu.item[1].itemId) { + _newMenu = &_saveMenu; + } + + return 1; +} + +int GUI_LoL::clickedChoiceMenu(Button *button) { + updateMenuButton(button); + if (button->arg == _choiceMenu.item[0].itemId) { + if (_lastMenu == &_mainMenu) { + _vm->quitGame(); + } else if (_lastMenu == &_deleteMenu) { + _vm->_saveFileMan->removeSavefile(_vm->getSavegameFilename(_menuResult - 1)); + Common::Array<int>::iterator i = Common::find(_saveSlots.begin(), _saveSlots.end(), _menuResult); + while (i != _saveSlots.end()) { + ++i; + if (i == _saveSlots.end()) + break; + // We are only renaming all savefiles until we get some slots missing + // Also not rename quicksave slot filenames + if (*(i-1) != *i || *i >= 990) + break; + Common::String oldName = _vm->getSavegameFilename(*i); + Common::String newName = _vm->getSavegameFilename(*i-1); + _vm->_saveFileMan->renameSavefile(oldName, newName); + } + _newMenu = &_mainMenu; + } + } else if (button->arg == _choiceMenu.item[1].itemId) { + _newMenu = &_mainMenu; + } + return 1; +} + +int GUI_LoL::scrollUp(Button *button) { + updateButton(button); + if (_savegameOffset > 0) { + _savegameOffset--; + _newMenu = _currentMenu; + _menuResult = -1; + } + return 1; +} + +int GUI_LoL::scrollDown(Button *button) { + updateButton(button); + if ((uint)_savegameOffset < _saveSlots.size() - 4) { + _savegameOffset++; + _newMenu = _currentMenu; + _menuResult = -1; + } + return 1; +} + +const char *GUI_LoL::getMenuTitle(const Menu &menu) { + if (!menu.menuNameId) + return 0; + return _vm->getLangString(menu.menuNameId); +} + +const char *GUI_LoL::getMenuItemTitle(const MenuItem &menuItem) { + if (menuItem.itemId & 0x8000 && menuItem.itemString) + return menuItem.itemString; + else if (menuItem.itemId & 0x8000 || !menuItem.itemId) + return 0; + return _vm->getLangString(menuItem.itemId); +} + +const char *GUI_LoL::getMenuItemLabel(const MenuItem &menuItem) { + if (menuItem.labelId & 0x8000 && menuItem.labelString) + return menuItem.labelString; + else if (menuItem.labelId & 0x8000 || !menuItem.labelId) + return 0; + return _vm->getLangString(menuItem.labelId); +} + } // end of namespace Kyra #endif // ENABLE_LOL diff --git a/engines/kyra/gui_lol.h b/engines/kyra/gui_lol.h index 631e29bd3b..832199f23e 100644 --- a/engines/kyra/gui_lol.h +++ b/engines/kyra/gui_lol.h @@ -31,6 +31,50 @@ #include "kyra/gui.h" namespace Kyra { +#define GUI_LOL_MENU(menu, a, b, c, d, e, f, g, i) \ + do { \ + const ScreenDim *dim = _screen->getScreenDim(a); \ + menu.x = (dim->sx << 3); \ + menu.y = (dim->sy); \ + menu.width = (dim->w << 3); \ + menu.height = (dim->h); \ + menu.bkgdColor = 225; \ + menu.color1 = 223; \ + menu.color2 = 227; \ + menu.menuNameId = b; \ + menu.highlightedItem = c; \ + menu.numberOfItems = d; \ + menu.titleX = (dim->sx << 3) + (dim->w << 2); \ + menu.titleY = 6; \ + menu.textColor = 254; \ + menu.scrollUpButtonX = e; \ + menu.scrollUpButtonY = f; \ + menu.scrollDownButtonX = g; \ + menu.scrollDownButtonY = i; \ + } while (0) + + #define GUI_LOL_MENU_ITEM(item, a, b, c, d, e, f, g) \ + do { \ + item.enabled = 1; \ + item.itemId = a; \ + item.itemString = 0; \ + item.x = b; \ + item.y = c; \ + item.width = d; \ + item.height = e; \ + item.textColor = 204; \ + item.highlightColor = 254; \ + item.titleX = -1; \ + item.bkgdColor = 225; \ + item.color1 = 223; \ + item.color2 = 227; \ + item.saveSlot = 0; \ + item.labelId = f; \ + item.labelString = 0; \ + item.labelX = 0; \ + item.labelY = 0; \ + item.keyCode = g; \ + } while (0) class LoLEngine; class Screen_LoL; @@ -40,14 +84,67 @@ class GUI_LoL : public GUI { public: GUI_LoL(LoLEngine *vm); + void initStaticData(); + // button specific void processButton(Button *button); int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel); + int redrawShadedButtonCallback(Button *button); + int redrawButtonCallback(Button *button); + + int runMenu(Menu &menu); + // utilities for thumbnail creation - void createScreenThumbnail(Graphics::Surface &dst) {} + void createScreenThumbnail(Graphics::Surface &dst); private: + void backupPage0(); + void restorePage0(); + + void setupSavegameNames(Menu &menu, int num); + + void printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 flags, Screen::FontId font=Screen::FID_9_FNT); + int getMenuCenterStringX(const char *str, int x1, int x2); + + int getInput(); + + int clickedMainMenu(Button *button); + int clickedLoadMenu(Button *button); + int clickedSaveMenu(Button *button); + int clickedDeleteMenu(Button *button); + int clickedOptionsMenu(Button *button); + int clickedAudioMenu(Button *button); + int clickedDeathMenu(Button *button); + int clickedSavenameMenu(Button *button); + int clickedChoiceMenu(Button *button); + + int scrollUp(Button *button); + int scrollDown(Button *button); + + Button *getButtonListData() { return _menuButtons; } + Button *getScrollUpButton() { return &_scrollUpButton; } + Button *getScrollDownButton() { return &_scrollDownButton; } + + + Button::Callback getScrollUpButtonHandler() const { return _scrollUpFunctor; } + Button::Callback getScrollDownButtonHandler() const { return _scrollDownFunctor; } + + uint8 defaultColor1() const { return 0xFE; } + uint8 defaultColor2() const { return 0x00; } + + const char *getMenuTitle(const Menu &menu); + const char *getMenuItemTitle(const MenuItem &menuItem); + const char *getMenuItemLabel(const MenuItem &menuItem); + + Button _menuButtons[10]; + Button _scrollUpButton; + Button _scrollDownButton; + Menu _mainMenu, _gameOptions, _audioOptions, _choiceMenu, _loadMenu, _saveMenu, _deleteMenu, _savenameMenu, _deathMenu; + Menu *_currentMenu, *_lastMenu, *_newMenu; + int _menuResult; + char *_saveDescription; + LoLEngine *_vm; Screen_LoL *_screen; @@ -59,24 +156,11 @@ private: uint16 _flagsModifier; uint8 _mouseClick; - int scrollUp(Button *button) { return 0; } - int scrollDown(Button *button) { return 0; } - - Button *getButtonListData() { return 0; } - Button *getScrollUpButton() { return 0; } - Button *getScrollDownButton() { return 0; } + int _savegameOffset; + int _sliderSfx; Button::Callback _scrollUpFunctor; Button::Callback _scrollDownFunctor; - Button::Callback getScrollUpButtonHandler() const { return _scrollUpFunctor; } - Button::Callback getScrollDownButtonHandler() const { return _scrollDownFunctor; } - - uint8 defaultColor1() const { return 0; } - uint8 defaultColor2() const { return 0; } - - const char *getMenuTitle(const Menu &menu) { return 0; } - const char *getMenuItemTitle(const MenuItem &menuItem) { return 0; } - const char *getMenuItemLabel(const MenuItem &menuItem) { return 0; } }; } // end of namespace Kyra diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp index c4d804c14d..e7001ed31f 100644 --- a/engines/kyra/gui_mr.cpp +++ b/engines/kyra/gui_mr.cpp @@ -352,10 +352,10 @@ void KyraEngine_MR::drawMalcolmsMoodPointer(int frame, int page) { frame = 13; if (page == 0) { - _invWsa->displayFrame(frame, 0, 0, 0, 0); + _invWsa->displayFrame(frame, 0, 0, 0, 0, 0, 0); _screen->updateScreen(); } else if (page == 30) { - _invWsa->displayFrame(frame, 2, 0, -144, 0); + _invWsa->displayFrame(frame, 2, 0, -144, 0, 0, 0); } _invWsaFrame = frame; @@ -674,21 +674,21 @@ void KyraEngine_MR::showAlbum() { _screen->copyRegionToBuffer(0, 0, 0, 320, 200, _screenBuffer); _screen->copyRegionToBuffer(4, 0, 0, 320, 200, _album.backUpPage); - memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); + _screen->copyPalette(1, 0); _screen->fadeToBlack(9); int itemInHand = _itemInHand; removeHandItem(); - _res->loadFileToBuf("ALBUM.COL", _screen->getPalette(0), 768); + _screen->loadPalette("ALBUM.COL", _screen->getPalette(0)); loadAlbumPage(); loadAlbumPageWSA(); if (_album.leftPage.wsa->opened()) - _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000); + _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000, 0, 0); if (_album.rightPage.wsa->opened()) - _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000); + _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000, 0, 0); printAlbumPageText(); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); @@ -707,7 +707,7 @@ void KyraEngine_MR::showAlbum() { _screen->copyBlockToPage(0, 0, 0, 320, 200, _screenBuffer); _screen->copyBlockToPage(4, 0, 0, 320, 200, _album.backUpPage); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); + _screen->copyPalette(0, 1); _screen->fadePalette(_screen->getPalette(0), 9); delete[] _album.backUpRect; @@ -843,10 +843,10 @@ void KyraEngine_MR::processAlbum() { loadAlbumPageWSA(); if (_album.leftPage.wsa->opened()) - _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000); + _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000, 0, 0); if (_album.rightPage.wsa->opened()) - _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000); + _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000, 0, 0); printAlbumPageText(); @@ -899,7 +899,7 @@ void KyraEngine_MR::albumUpdateAnims() { nextRun = _album.leftPage.timer + 5 * _tickLength; if (nextRun < _system->getMillis() && _album.leftPage.wsa->opened()) { - _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000); + _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000, 0, 0); _screen->copyRegion(40, 17, 40, 17, 87, 73, 2, 0, Screen::CR_NO_P_CHECK); ++_album.leftPage.curFrame; @@ -918,7 +918,7 @@ void KyraEngine_MR::albumUpdateAnims() { nextRun = _album.rightPage.timer + 5 * _tickLength; if (nextRun < _system->getMillis() && _album.rightPage.wsa->opened()) { - _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000); + _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000, 0, 0); _screen->copyRegion(194, 20, 194, 20, 85, 69, 2, 0, Screen::CR_NO_P_CHECK); ++_album.rightPage.curFrame; @@ -936,13 +936,13 @@ void KyraEngine_MR::albumUpdateAnims() { void KyraEngine_MR::albumAnim1() { for (int i = 6; i >= 3; --i) { albumRestoreRect(); - _album.wsa->displayFrame(i, 2, -100, 90, 0x4000); + _album.wsa->displayFrame(i, 2, -100, 90, 0x4000, 0, 0); albumUpdateRect(); delayWithTicks(1); } albumRestoreRect(); - _album.wsa->displayFrame(14, 2, -100, 90, 0x4000); + _album.wsa->displayFrame(14, 2, -100, 90, 0x4000, 0, 0); albumUpdateRect(); delayWithTicks(1); } @@ -950,7 +950,7 @@ void KyraEngine_MR::albumAnim1() { void KyraEngine_MR::albumAnim2() { for (int i = 3; i <= 6; ++i) { albumRestoreRect(); - _album.wsa->displayFrame(i, 2, -100, 90, 0x4000); + _album.wsa->displayFrame(i, 2, -100, 90, 0x4000, 0, 0); albumUpdateRect(); delayWithTicks(1); } @@ -1269,7 +1269,7 @@ int GUI_MR::optionsButton(Button *button) { } while (_displayMenu) { - processHighlights(*_currentMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(*_currentMenu); getInput(); } @@ -1312,7 +1312,7 @@ int GUI_MR::loadMenu(Button *caller) { _screen->updateScreen(); while (_isLoadMenu) { - processHighlights(_loadMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(_loadMenu); getInput(); } @@ -1362,7 +1362,7 @@ int GUI_MR::gameOptions(Button *caller) { _isOptionsMenu = true; while (_isOptionsMenu) { - processHighlights(_gameOptions, _vm->_mouseX, _vm->_mouseY); + processHighlights(_gameOptions); getInput(); } @@ -1525,7 +1525,7 @@ int GUI_MR::audioOptions(Button *caller) { updateAllMenuButtons(); bool speechEnabled = _vm->speechEnabled(); while (_isOptionsMenu) { - processHighlights(_audioOptions, _vm->_mouseX, _vm->_mouseY); + processHighlights(_audioOptions); getInput(); } @@ -1554,7 +1554,7 @@ int GUI_MR::sliderHandler(Button *caller) { assert(button >= 0 && button <= 3); - int oldVolume = _vm->getVolume(KyraEngine_v1::kVolumeEntry(button)); + const int oldVolume = _vm->getVolume(KyraEngine_v1::kVolumeEntry(button)); int newVolume = oldVolume; if (caller->index >= 24 && caller->index <= 27) @@ -1564,8 +1564,7 @@ int GUI_MR::sliderHandler(Button *caller) { else newVolume = _vm->_mouseX - caller->x - 7; - newVolume = MAX(2, newVolume); - newVolume = MIN(97, newVolume); + newVolume = CLIP(newVolume, 2, 97); if (newVolume == oldVolume) return 0; @@ -1621,8 +1620,7 @@ void GUI_MR::drawSliderBar(int slider, const uint8 *shape) { int position = _vm->getVolume(KyraEngine_v1::kVolumeEntry(slider)); - position = MAX(2, position); - position = MIN(97, position); + position = CLIP(position, 2, 97); _screen->drawShape(0, shape, x+position, y, 0, 0); } diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp index 7e3d2b5afb..e5c8637fb5 100644 --- a/engines/kyra/gui_v2.cpp +++ b/engines/kyra/gui_v2.cpp @@ -27,6 +27,7 @@ #include "kyra/kyra_v2.h" #include "kyra/screen_v2.h" #include "kyra/text.h" +#include "kyra/util.h" #include "common/savefile.h" @@ -158,8 +159,9 @@ int GUI_v2::processButtonList(Button *buttonList, uint16 inputFlag, int8 mouseWh } } - int mouseX = _vm->_mouseX; - int mouseY = _vm->_mouseY; + Common::Point p = _vm->getMousePos(); + int mouseX = _vm->_mouseX = p.x; + int mouseY = _vm->_mouseY = p.y; uint16 flags = 0; @@ -454,8 +456,11 @@ void GUI_v2::setupSavegameNames(Menu &menu, int num) { Common::InSaveFile *in; for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); ++i) { if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header)) != 0) { - strncpy(getTableString(menu.item[i].itemId), header.description.c_str(), 80); - getTableString(menu.item[i].itemId)[79] = 0; + char *s = getTableString(menu.item[i].itemId); + strncpy(s, header.description.c_str(), 80); + s[79] = 0; + Util::convertISOToDOS(s); + menu.item[i].saveSlot = _saveSlots[i + _savegameOffset]; menu.item[i].enabled = true; delete in; @@ -601,7 +606,7 @@ int GUI_v2::saveMenu(Button *caller) { updateAllMenuButtons(); while (_isSaveMenu) { - processHighlights(_saveMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(_saveMenu); getInput(); } @@ -620,6 +625,7 @@ int GUI_v2::saveMenu(Button *caller) { Graphics::Surface thumb; createScreenThumbnail(thumb); + Util::convertDOSToISO(_saveDescription); _vm->saveGameState(_saveSlot, _saveDescription, &thumb); thumb.free(); @@ -697,7 +703,7 @@ int GUI_v2::deleteMenu(Button *caller) { updateAllMenuButtons(); while (_isDeleteMenu) { - processHighlights(_saveMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(_saveMenu); getInput(); } @@ -749,7 +755,11 @@ const char *GUI_v2::nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8 _cancelNameInput = _finishNameInput = false; while (running && !_vm->shouldQuit()) { checkTextfieldInput(); - processHighlights(_savenameMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(_savenameMenu); + + char inputKey = _keyPressed.ascii; + Util::convertISOToDOS(inputKey); + if (_keyPressed.keycode == Common::KEYCODE_RETURN || _keyPressed.keycode == Common::KEYCODE_KP_ENTER || _finishNameInput) { if (checkSavegameDescription(buffer, curPos)) { buffer[curPos] = 0; @@ -767,12 +777,12 @@ const char *GUI_v2::nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8 drawTextfieldBlock(x2, y2, c3); _screen->updateScreen(); _lastScreenUpdate = _vm->_system->getMillis(); - } else if (_keyPressed.ascii > 31 && _keyPressed.ascii < 127 && curPos < bufferSize) { - if (x2 + getCharWidth(_keyPressed.ascii) + 7 < 0x11F) { - buffer[curPos] = _keyPressed.ascii; + } else if ((uint8)inputKey > 31 && (uint8)inputKey < 226 && curPos < bufferSize) { + if (x2 + getCharWidth(inputKey) + 7 < 0x11F) { + buffer[curPos] = inputKey; const char text[2] = { buffer[curPos], 0 }; _text->printText(text, x2, y2, c1, c2, c2); - x2 += getCharWidth(_keyPressed.ascii); + x2 += getCharWidth(inputKey); drawTextfieldBlock(x2, y2, c3); ++curPos; _screen->updateScreen(); @@ -840,7 +850,7 @@ bool GUI_v2::choiceDialog(int name, bool type) { _choice = false; while (_isChoiceMenu) { - processHighlights(_choiceMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(_choiceMenu); getInput(); } diff --git a/engines/kyra/gui_v2.h b/engines/kyra/gui_v2.h index ec30640b88..9af4572e4d 100644 --- a/engines/kyra/gui_v2.h +++ b/engines/kyra/gui_v2.h @@ -96,7 +96,7 @@ namespace Kyra { item.labelId = n; \ item.labelX = o; \ item.labelY = p; \ - item.unk1F = q; \ + item.keyCode = q; \ } while (0) class KyraEngine_v2; diff --git a/engines/kyra/items_hof.cpp b/engines/kyra/items_hof.cpp index 9d18829252..13e269f363 100644 --- a/engines/kyra/items_hof.cpp +++ b/engines/kyra/items_hof.cpp @@ -238,9 +238,7 @@ void KyraEngine_HoF::itemDropDown(int startX, int startY, int dstX, int dstY, in _screen->drawShape(0, itemShape, curX, curY-16, 0, 0); _screen->updateScreen(); - // XXX: original doesn't update game state while delaying - // our implementation *could* do it, so maybe check this again - delayUntil(endDelay); + delayUntil(endDelay, false, true); } if (dstX != dstY || (dstY - startY > 16)) { @@ -275,9 +273,7 @@ void KyraEngine_HoF::itemDropDown(int startX, int startY, int dstX, int dstY, in _screen->drawShape(0, itemShape, x, y, 0, 0); _screen->updateScreen(); - // XXX: original doesn't update game state while delaying - // our implementation *could* do it, so maybe check this again - delayUntil(endDelay); + delayUntil(endDelay, false, true); } restoreGfxRect24x24(x, y); diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp index e75a13c870..c0ddd0c860 100644 --- a/engines/kyra/items_lol.cpp +++ b/engines/kyra/items_lol.cpp @@ -477,7 +477,7 @@ void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objec r = getNearestPartyMemberFromPos(x, y); runItemScript(t->attackerId, t->item, 0x8000, r, 0); } - } + } } void LoLEngine::updateFlyingObject(FlyingObject *t) { diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index c2c36dcc95..5c41989713 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -381,10 +381,10 @@ void KyraEngine_HoF::startup() { memset(_sceneAnims, 0, sizeof(_sceneAnims)); for (int i = 0; i < ARRAYSIZE(_sceneAnimMovie); ++i) - _sceneAnimMovie[i] = new WSAMovie_v2(this, _screen); + _sceneAnimMovie[i] = new WSAMovie_v2(this); memset(_wsaSlots, 0, sizeof(_wsaSlots)); for (int i = 0; i < ARRAYSIZE(_wsaSlots); ++i) - _wsaSlots[i] = new WSAMovie_v2(this, _screen); + _wsaSlots[i] = new WSAMovie_v2(this); _screen->_curPage = 0; @@ -415,7 +415,7 @@ void KyraEngine_HoF::startup() { setupLangButtonShapes(); loadInventoryShapes(); - _res->loadFileToBuf("PALETTE.COL", _screen->_currentPalette, 0x300); + _screen->loadPalette("PALETTE.COL", _screen->getPalette(0)); _screen->loadBitmap("_PLAYFLD.CPS", 3, 3, 0); _screen->copyPage(3, 0); _screen->showMouse(); @@ -451,7 +451,6 @@ void KyraEngine_HoF::startup() { (*_inventoryButtons[0].buttonCallback)(&_inventoryButtons[0]); setNextIdleAnimTimer(); - //XXX setWalkspeed(_configWalkspeed); } @@ -643,8 +642,6 @@ bool KyraEngine_HoF::handleInputUnkSub(int x, int y) { while (_emc->isValid(&_sceneScriptState)) _emc->run(&_sceneScriptState); - //XXXsys_unkKeyboad (flush? wait? whatever...) - if (queryGameFlag(0x1ED)) { _sound->beginFadeOut(); _screen->fadeToBlack(); @@ -919,9 +916,9 @@ void KyraEngine_HoF::showMessage(const char *string, int16 palIndex) { if (string) { if (palIndex != -1 || _fadeMessagePalette) { palIndex *= 3; - memcpy(_messagePal, _screen->_currentPalette + palIndex, 3); - memmove(_screen->_currentPalette + 765, _screen->_currentPalette + palIndex, 3); - _screen->setScreenPalette(_screen->_currentPalette); + memcpy(_messagePal, _screen->getPalette(0).getData() + palIndex, 3); + _screen->getPalette(0).copy(_screen->getPalette(0), palIndex / 3, 1, 255); + _screen->setScreenPalette(_screen->getPalette(0)); } int x = _text->getCenterStringX(string, 0, 320); @@ -978,7 +975,7 @@ void KyraEngine_HoF::fadeMessagePalette() { } if (updatePalette) { - memcpy(_screen->getPalette(0) + 765, _messagePal, 3); + _screen->getPalette(0).copy(_messagePal, 0, 1, 255); _screen->setScreenPalette(_screen->getPalette(0)); } else { _fadeMessagePalette = false; @@ -1139,7 +1136,7 @@ void KyraEngine_HoF::updateCharPal(int unk1) { if (palEntry != _charPalEntry && unk1) { const uint8 *src = &_scenePal[(palEntry << 4) * 3]; - uint8 *ptr = _screen->getPalette(0) + 336; + uint8 *ptr = _screen->getPalette(0).getData() + 336; for (int i = 0; i < 48; ++i) { *ptr -= (*ptr - *src) >> 1; ++ptr; @@ -1149,7 +1146,7 @@ void KyraEngine_HoF::updateCharPal(int unk1) { unkVar1 = true; _charPalEntry = palEntry; } else if (unkVar1 || !unk1) { - memcpy(_screen->getPalette(0) + 336, &_scenePal[(palEntry << 4) * 3], 48); + _screen->getPalette(0).copy(_scenePal, palEntry << 4, 16, 112); _screen->setScreenPalette(_screen->getPalette(0)); unkVar1 = false; } @@ -1550,7 +1547,7 @@ void KyraEngine_HoF::loadInvWsa(const char *filename, int run_, int delayTime, i wsaFlags |= 2; if (!_invWsa.wsa) - _invWsa.wsa = new WSAMovie_v2(this, _screen); + _invWsa.wsa = new WSAMovie_v2(this); if (!_invWsa.wsa->open(filename, wsaFlags, 0)) error("Couldn't open inventory WSA file '%s'", filename); @@ -1656,12 +1653,12 @@ void KyraEngine_HoF::displayInvWsaLastFrame() { #pragma mark - void KyraEngine_HoF::setCauldronState(uint8 state, bool paletteFade) { - memcpy(_screen->getPalette(2), _screen->getPalette(0), 768); + _screen->copyPalette(2, 0); Common::SeekableReadStream *file = _res->createReadStream("_POTIONS.PAL"); if (!file) error("Couldn't load cauldron palette"); file->seek(state*18, SEEK_SET); - file->read(_screen->getPalette(2)+723, 18); + _screen->getPalette(0).loadVGAPalette(*file, 241, 6); delete file; file = 0; @@ -1673,7 +1670,7 @@ void KyraEngine_HoF::setCauldronState(uint8 state, bool paletteFade) { _screen->updateScreen(); } - memcpy(_screen->getPalette(0)+723, _screen->getPalette(2)+723, 18); + _screen->getPalette(0).copy(_screen->getPalette(2), 241, 6); _cauldronState = state; _cauldronUseCount = 0; //if (state == 5) @@ -1833,11 +1830,11 @@ void KyraEngine_HoF::cauldronRndPaletteFade() { if (!file) error("Couldn't load cauldron palette"); file->seek(index*18, SEEK_SET); - file->read(_screen->getPalette(0)+723, 18); + _screen->getPalette(0).loadVGAPalette(*file, 241, 6); snd_playSoundEffect(0x6A); _screen->fadePalette(_screen->getPalette(0), 0x1E, &_updateFunctor); file->seek(0, SEEK_SET); - file->read(_screen->getPalette(0)+723, 18); + _screen->getPalette(0).loadVGAPalette(*file, 241, 6); delete file; _screen->fadePalette(_screen->getPalette(0), 0x1E, &_updateFunctor); } diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index fcd35e7282..e5ca52abcc 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -157,7 +157,10 @@ KyraEngine_LoK::~KyraEngine_LoK() { } Common::Error KyraEngine_LoK::init() { - _screen = new Screen_LoK(this, _system); + if (_flags.platform == Common::kPlatformPC98 && _flags.useHiResOverlay && ConfMan.getBool("16_color")) + _screen = new Screen_LoK_16(this, _system); + else + _screen = new Screen_LoK(this, _system); assert(_screen); _screen->setResolution(); @@ -358,7 +361,7 @@ void KyraEngine_LoK::startup() { loadButtonShapes(); initMainButtonList(); loadMainScreen(); - _screen->loadPalette("PALETTE.COL", _screen->_currentPalette); + _screen->loadPalette("PALETTE.COL", _screen->getPalette(0)); // XXX _animator->initAnimStateList(); @@ -906,6 +909,9 @@ void KyraEngine_LoK::registerDefaultSettings() { // Most settings already have sensible defaults. This one, however, is // specific to the Kyra engine. ConfMan.registerDefault("walkspeed", 2); + + if (_flags.platform == Common::kPlatformPC98 && _flags.useHiResOverlay) + ConfMan.registerDefault("16_color", false); } void KyraEngine_LoK::readSettings() { diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h index a0f38c3acc..a905c5521b 100644 --- a/engines/kyra/kyra_lok.h +++ b/engines/kyra/kyra_lok.h @@ -113,7 +113,6 @@ public: KyraEngine_LoK(OSystem *system, const GameFlags &flags); ~KyraEngine_LoK(); - //TODO: proper extended implementation of KyraEngine_v1::pauseEngineIntern. // _sprites and _seqplayer should be paused here too, to avoid some animation glitches, // also parts of the hardcoded Malcolm fight might need some special handling. diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index f2ea0c91df..871edd578d 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -230,7 +230,7 @@ Common::Error KyraEngine_MR::init() { _screen->setAnimBlockPtr(3500); _screen->setScreenDim(0); - _res->loadFileToBuf("PALETTE.COL", _screen->getPalette(0), 768); + _screen->loadPalette("PALETTE.COL", _screen->getPalette(0)); _screen->setScreenPalette(_screen->getPalette(0)); return Common::kNoError; @@ -269,19 +269,18 @@ Common::Error KyraEngine_MR::go() { _screen->setScreenPalette(_screen->getPalette(0)); - // XXX playMenuAudioFile(); for (int i = 0; i < 64 && !shouldQuit(); ++i) { uint32 nextRun = _system->getMillis() + 3 * _tickLength; - _menuAnim->displayFrame(i, 0, 0, 0, 0); + _menuAnim->displayFrame(i, 0, 0, 0, 0, 0, 0); _screen->updateScreen(); delayUntil(nextRun); } for (int i = 64; i > 29 && !shouldQuit(); --i) { uint32 nextRun = _system->getMillis() + 3 * _tickLength; - _menuAnim->displayFrame(i, 0, 0, 0, 0); + _menuAnim->displayFrame(i, 0, 0, 0, 0, 0, 0); _screen->updateScreen(); delayUntil(nextRun); } @@ -327,9 +326,9 @@ Common::Error KyraEngine_MR::go() { } void KyraEngine_MR::initMainMenu() { - _menuAnim = new WSAMovie_v2(this, _screen); - _menuAnim->open("REVENGE.WSA", 1, _screen->getPalette(0)); - memset(_screen->getPalette(0), 0, 3); + _menuAnim = new WSAMovie_v2(this); + _menuAnim->open("REVENGE.WSA", 1, &_screen->getPalette(0)); + _screen->getPalette(0).fill(0, 1, 0); _menu = new MainMenu(this); MainMenu::StaticData data = { @@ -378,7 +377,7 @@ void KyraEngine_MR::playVQA(const char *name) { } _screen->hideMouse(); - memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); + _screen->copyPalette(1, 0); fadeOutMusic(60); _screen->fadeToBlack(60); _screen->clearPage(0); @@ -390,12 +389,11 @@ void KyraEngine_MR::playVQA(const char *name) { _soundDigital->stopAllSounds(); _screen->showMouse(); - uint8 pal[768]; // Taken from original, it used '1' here too - memset(pal, 1, sizeof(pal)); - _screen->setScreenPalette(pal); + _screen->getPalette(0).fill(0, 256, 1); + _screen->setScreenPalette(_screen->getPalette(0)); _screen->clearPage(0); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); + _screen->copyPalette(0, 1); _wasPlayingVQA = true; } } @@ -541,11 +539,11 @@ void KyraEngine_MR::initMouseShapes() { } void KyraEngine_MR::startup() { - _album.wsa = new WSAMovie_v2(this, _screen); + _album.wsa = new WSAMovie_v2(this); assert(_album.wsa); - _album.leftPage.wsa = new WSAMovie_v2(this, _screen); + _album.leftPage.wsa = new WSAMovie_v2(this); assert(_album.leftPage.wsa); - _album.rightPage.wsa = new WSAMovie_v2(this, _screen); + _album.rightPage.wsa = new WSAMovie_v2(this); assert(_album.rightPage.wsa); musicUpdate(0); @@ -559,9 +557,7 @@ void KyraEngine_MR::startup() { _screen->setFont(Screen::FID_6_FNT); _stringBuffer = new char[500]; - //XXX musicUpdate(0); - //XXX allocAnimObjects(1, 16, 50); musicUpdate(0); @@ -586,19 +582,16 @@ void KyraEngine_MR::startup() { error("couldn't load _ACTOR"); musicUpdate(0); - //XXX - musicUpdate(0); openTalkFile(0); musicUpdate(0); _currentTalkFile = 0; openTalkFile(1); - //XXX loadCostPal(); musicUpdate(0); for (int i = 0; i < 16; ++i) { _sceneAnims[i].flags = 0; - _sceneAnimMovie[i] = new WSAMovie_v2(this, _screen); + _sceneAnimMovie[i] = new WSAMovie_v2(this); assert(_sceneAnimMovie[i]); } @@ -627,7 +620,7 @@ void KyraEngine_MR::startup() { loadInterfaceShapes(); musicUpdate(0); - _res->loadFileToBuf("PALETTE.COL", _screen->getPalette(0), 768); + _screen->loadPalette("PALETTE.COL", _screen->getPalette(0)); _paletteOverlay = new uint8[256]; _screen->generateOverlay(_screen->getPalette(0), _paletteOverlay, 0xF0, 0x19); @@ -655,7 +648,7 @@ void KyraEngine_MR::startup() { musicUpdate(0); runStartupScript(1, 0); _res->exists("MOODOMTR.WSA", true); - _invWsa = new WSAMovie_v2(this, _screen); + _invWsa = new WSAMovie_v2(this); assert(_invWsa); _invWsa->open("MOODOMTR.WSA", 1, 0); _invWsaFrame = 6; @@ -899,40 +892,30 @@ void KyraEngine_MR::updateCharAnimFrame(int character, int *table) { void KyraEngine_MR::updateCharPal(int unk1) { int layer = _screen->getLayer(_mainCharacter.x1, _mainCharacter.y1) - 1; const uint8 *src = _costPalBuffer + _characterShapeFile * 72; - uint8 *dst = _screen->getPalette(0) + 432; + Palette &dst = _screen->getPalette(0); const int8 *sceneDatPal = &_sceneDatPalette[layer * 3]; if (layer != _lastCharPalLayer && unk1) { - for (int i = 0, j = 0; i < 72; ++i) { - uint8 col = *dst; - int8 addCol = *src + *sceneDatPal; - addCol = MAX<int8>(0, MIN<int8>(addCol, 63)); - addCol = (col - addCol) >> 1; - *dst -= addCol; - ++dst; - ++src; - ++sceneDatPal; - ++j; - if (j > 3) { - sceneDatPal = &_sceneDatPalette[layer * 3]; - j = 0; + for (int i = 144; i < 168; ++i) { + for (int j = 0; j < 3; ++j) { + uint8 col = dst[i * 3 + j]; + int subCol = src[(i - 144) * 3 + j] + sceneDatPal[j]; + subCol = CLIP(subCol, 0, 63); + subCol = (col - subCol) / 2; + dst[i * 3 + j] -= subCol; } } + _charPalUpdate = true; _screen->setScreenPalette(_screen->getPalette(0)); _lastCharPalLayer = layer; } else if (_charPalUpdate || !unk1) { - memcpy(dst, src, 72); - - for (int i = 0, j = 0; i < 72; ++i) { - uint8 col = *dst + *sceneDatPal; - *dst = MAX<int8>(0, MIN<int8>(col, 63)); - ++dst; - ++sceneDatPal; - ++j; - if (j >= 3) { - sceneDatPal = &_sceneDatPalette[layer * 3]; - j = 0; + dst.copy(_costPalBuffer, _characterShapeFile * 24, 24, 144); + + for (int i = 144; i < 168; ++i) { + for (int j = 0; j < 3; ++j) { + int col = dst[i * 3 + j] + sceneDatPal[j]; + dst[i * 3 + j] = CLIP(col, 0, 63); } } diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h index 6c06a84433..88bfb8c89b 100644 --- a/engines/kyra/kyra_mr.h +++ b/engines/kyra/kyra_mr.h @@ -50,7 +50,6 @@ public: KyraEngine_MR(OSystem *system, const GameFlags &flags); ~KyraEngine_MR(); - //TODO: proper extended implementation of KyraEngine_v2::pauseEngineIntern. // Idle animation time, item animations and album animations should be taken // care of, but since those would just produce minor glitches it's not that // important. diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index d9fc8f9d66..80872877d5 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -81,7 +81,7 @@ KyraEngine_v1::KyraEngine_v1(OSystem *system, const GameFlags &flags) Common::addDebugChannel(kDebugLevelMovie, "Movie", "Movie debug level"); Common::addDebugChannel(kDebugLevelTimer, "Timer", "Timer debug level"); - system->getEventManager()->registerRandomSource(_rnd, "kyra"); + _eventMan->registerRandomSource(_rnd, "kyra"); } ::GUI::Debugger *KyraEngine_v1::getDebugger() { @@ -94,8 +94,6 @@ void KyraEngine_v1::pauseEngineIntern(bool pause) { } Common::Error KyraEngine_v1::init() { - registerDefaultSettings(); - // Setup mixer _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); @@ -278,10 +276,10 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop, int eventFlag) } else { switch(event.kbd.keycode) { case Common::KEYCODE_SPACE: - keys = 43; + keys = 61; break; case Common::KEYCODE_RETURN: - keys = 61; + keys = 43; break; case Common::KEYCODE_UP: case Common::KEYCODE_KP8: @@ -594,27 +592,27 @@ bool KyraEngine_v1::textEnabled() { return !_flags.isTalkie || (_configVoice == 0 || _configVoice == 2); } -inline int convertValueToMixer(int value) { +int KyraEngine_v1::convertVolumeToMixer(int value) { value -= 2; return (value * Audio::Mixer::kMaxMixerVolume) / 95; } -inline int convertValueFromMixer(int value) { +int KyraEngine_v1::convertVolumeFromMixer(int value) { return (value * 95) / Audio::Mixer::kMaxMixerVolume + 2; } void KyraEngine_v1::setVolume(kVolumeEntry vol, uint8 value) { switch (vol) { case kVolumeMusic: - ConfMan.setInt("music_volume", convertValueToMixer(value)); + ConfMan.setInt("music_volume", convertVolumeToMixer(value)); break; case kVolumeSfx: - ConfMan.setInt("sfx_volume", convertValueToMixer(value)); + ConfMan.setInt("sfx_volume", convertVolumeToMixer(value)); break; case kVolumeSpeech: - ConfMan.setInt("speech_volume", convertValueToMixer(value)); + ConfMan.setInt("speech_volume", convertVolumeToMixer(value)); break; } @@ -629,16 +627,16 @@ void KyraEngine_v1::setVolume(kVolumeEntry vol, uint8 value) { uint8 KyraEngine_v1::getVolume(kVolumeEntry vol) { switch (vol) { case kVolumeMusic: - return convertValueFromMixer(ConfMan.getInt("music_volume")); + return convertVolumeFromMixer(ConfMan.getInt("music_volume")); break; case kVolumeSfx: - return convertValueFromMixer(ConfMan.getInt("sfx_volume")); + return convertVolumeFromMixer(ConfMan.getInt("sfx_volume")); break; case kVolumeSpeech: if (speechEnabled()) - return convertValueFromMixer(ConfMan.getInt("speech_volume")); + return convertVolumeFromMixer(ConfMan.getInt("speech_volume")); else return 2; break; diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index b45f21dd89..5ece70e3f1 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -153,7 +153,7 @@ public: kVolumeSpeech = 2 }; - // volume reaches from 2 to 97 + // volume reaches per default from 2 to 97 void setVolume(kVolumeEntry vol, uint8 value); uint8 getVolume(kVolumeEntry vol); @@ -181,13 +181,16 @@ protected: // Engine APIs virtual Common::Error init(); virtual Common::Error go() = 0; + virtual Common::Error run() { Common::Error err; + registerDefaultSettings(); err = init(); if (err != Common::kNoError) return err; return go(); } + virtual ::GUI::Debugger *getDebugger(); virtual bool hasFeature(EngineFeature f) const; virtual void pauseEngineIntern(bool pause); @@ -289,6 +292,9 @@ protected: const int8 *_trackMap; int _trackMapSize; + virtual int convertVolumeToMixer(int value); + virtual int convertVolumeFromMixer(int value); + // pathfinder virtual int findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize); int findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end); diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 3461fa5da9..020e1ea3ea 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -82,7 +82,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _curTlkFile = -1; _lastSpeaker = _lastSpeechId = _nextSpeechId = _nextSpeaker = -1; - memset(_moneyColumnHeight, 0, 5); + memset(_moneyColumnHeight, 0, sizeof(_moneyColumnHeight)); _credits = 0; _itemsInPlay = 0; @@ -200,7 +200,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _partyPosX = _partyPosY = 0; _shpDmX = _shpDmY = _dmScaleW = _dmScaleH = 0; - _floatingMouseArrowControl = 0; + _floatingCursorControl = _currentFloatingCursor = 0; memset(_activeTim, 0, sizeof(_activeTim)); memset(_openDoorState, 0, sizeof(_openDoorState)); @@ -222,10 +222,6 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _preserveEvents = false; _buttonList1 = _buttonList2 = _buttonList3 = _buttonList4 = _buttonList5 = _buttonList6 = _buttonList7 = _buttonList8 = 0; - _monsterDifficulty = 1; - _smoothScrollingEnabled = true; - _floatingCursorsEnabled = false; - memset(_lvlTempData, 0, sizeof(_lvlTempData)); _mapOverlay = 0; @@ -436,6 +432,7 @@ Common::Error LoLEngine::init() { _gui = new GUI_LoL(this); assert(_gui); + _gui->initStaticData(); _txt = new TextDisplayer_LoL(this, _screen); @@ -456,8 +453,6 @@ Common::Error LoLEngine::init() { if (!_sound->init()) error("Couldn't init sound"); - _speechFlag = speechEnabled() ? 0x48 : 0; - _wllVmpMap = new uint8[80]; memset(_wllVmpMap, 0, 80); _wllShapeMap = new int8[80]; @@ -561,7 +556,7 @@ Common::Error LoLEngine::go() { // Usually fonts etc. would be setup by the prologue code, if we skip // the prologue code we need to setup them manually here. - if (_gameToLoad != -1) { + if (_gameToLoad != -1 && action != 3) { preInit(); _screen->setFont(Screen::FID_9_FNT); } @@ -591,8 +586,6 @@ Common::Error LoLEngine::go() { if (loadGameState(_gameToLoad) != Common::kNoError) error("Couldn't load game slot %d on startup", _gameToLoad); _gameToLoad = -1; - } else if (action == 3) { - // XXX } _screen->_fadeFlag = 3; @@ -639,6 +632,15 @@ void LoLEngine::loadItemIconShapes() { _itemIconShapes[i] = _screen->makeShapeCopy(shp, i); _screen->setMouseCursor(0, 0, _itemIconShapes[0]); + + if (!_gameShapes) { + _screen->loadBitmap("GAMESHP.SHP", 3, 3, 0); + shp = _screen->getCPagePtr(3); + _numGameShapes = READ_LE_UINT16(shp); + _gameShapes = new uint8*[_numGameShapes]; + for (int i = 0; i < _numGameShapes; i++) + _gameShapes[i] = _screen->makeShapeCopy(shp, i); + } } void LoLEngine::setMouseCursorToIcon(int icon) { @@ -661,6 +663,53 @@ bool LoLEngine::posWithinRect(int mouseX, int mouseY, int x1, int y1, int x2, in return true; } +void LoLEngine::checkFloatingPointerRegions() { + if (!_floatingCursorsEnabled) + return; + + int t = -1; + + Common::Point p = getMousePos(); + + if (!(_updateFlags & 4) & !_floatingCursorControl) { + if (posWithinRect(p.x, p.y, 96, 0, 303, 136)) { + if (!posWithinRect(p.x, p.y, 128, 16, 271, 119)) { + if (posWithinRect(p.x, p.y, 112, 0, 287, 15)) + t = 0; + if (posWithinRect(p.x, p.y, 272, 88, 303, 319)) + t = 1; + if (posWithinRect(p.x, p.y, 112, 110, 287, 135)) + t = 2; + if (posWithinRect(p.x, p.y, 96, 88, 127, 119)) + t = 3; + if (posWithinRect(p.x, p.y, 96, 16, 127, 87)) + t = 4; + if (posWithinRect(p.x, p.y, 272, 16, 303, 87)) + t = 5; + + if (t < 4) { + int d = (_currentDirection + t) & 3; + if (!checkBlockPassability(calcNewBlockPosition(_currentBlock, d), d)) + t = 6; + } + } + } + } + + if (t == _currentFloatingCursor) + return; + + if (t == -1) { + setMouseCursorToItemInHand(); + } else { + static const uint8 floatingPtrX[] = { 7, 13, 7, 0, 0, 15, 7 }; + static const uint8 floatingPtrY[] = { 0, 7, 12, 7, 6, 6, 7 }; + _screen->setMouseCursor(floatingPtrX[t], floatingPtrY[t], _gameShapes[10 + t]); + } + + _currentFloatingCursor = t; +} + uint8 *LoLEngine::getItemIconShapePtr(int index) { int ix = _itemProperties[_itemsInPlay[index].itemPropertyIndex].shpIndex; if (_itemProperties[_itemsInPlay[index].itemPropertyIndex].flags & 0x200) @@ -714,7 +763,7 @@ int LoLEngine::mainMenu() { assert(menu); menu->init(data[dataIndex], MainMenu::Animation()); - int selection = menu->handle(_flags.isTalkie ? (hasSave ? 17 : 6) : (hasSave ? 6 : 18)); + int selection = menu->handle(_flags.isTalkie ? (hasSave ? 19 : 6) : (hasSave ? 6 : 20)); delete menu; _screen->setScreenDim(0); @@ -729,20 +778,20 @@ int LoLEngine::mainMenu() { void LoLEngine::startup() { _screen->clearPage(0); - _screen->loadBitmap("PLAYFLD.CPS", 3, 3, _screen->_currentPalette); - uint8 *tmpPal = new uint8[0x300]; - memcpy(tmpPal, _screen->_currentPalette, 0x300); - memset(_screen->_currentPalette, 0x3f, 0x180); - memcpy(_screen->_currentPalette + 3, tmpPal + 3, 3); - memset(_screen->_currentPalette + 0x240, 0x3f, 12); - _screen->generateOverlay(_screen->_currentPalette, _screen->_paletteOverlay1, 1, 96); - _screen->generateOverlay(_screen->_currentPalette, _screen->_paletteOverlay2, 144, 65); - memcpy(_screen->_currentPalette, tmpPal, 0x300); - delete[] tmpPal; + Palette &pal = _screen->getPalette(0); + _screen->loadBitmap("PLAYFLD.CPS", 3, 3, &pal); - memset(_screen->getPalette(1), 0, 0x300); - memset(_screen->getPalette(2), 0, 0x300); + _screen->copyPalette(1, 0); + pal.fill(0, 1, 0x3F); + pal.fill(2, 126, 0x3F); + pal.fill(192, 4, 0x3F); + _screen->generateOverlay(pal, _screen->_paletteOverlay1, 1, 96); + _screen->generateOverlay(pal, _screen->_paletteOverlay2, 144, 65); + _screen->copyPalette(0, 1); + + _screen->getPalette(1).clear(); + _screen->getPalette(2).clear(); loadItemIconShapes(); _screen->setMouseCursor(0, 0, _itemIconShapes[0x85]); @@ -754,13 +803,6 @@ void LoLEngine::startup() { for (int i = 0; i < _numItemShapes; i++) _itemShapes[i] = _screen->makeShapeCopy(shp, i); - _screen->loadBitmap("GAMESHP.SHP", 3, 3, 0); - shp = _screen->getCPagePtr(3); - _numGameShapes = READ_LE_UINT16(shp); - _gameShapes = new uint8*[_numGameShapes]; - for (int i = 0; i < _numGameShapes; i++) - _gameShapes[i] = _screen->makeShapeCopy(shp, i); - _screen->loadBitmap("THROWN.SHP", 3, 3, 0); shp = _screen->getCPagePtr(3); _numThrownShapes = READ_LE_UINT16(shp); @@ -808,9 +850,6 @@ void LoLEngine::startup() { _loadSuppFilesFlag = 1; - _txt->setAnimParameters("<MORE>", 10, 31, 0); - _txt->setAnimFlag(true); - _sound->loadSfxFile("LORESFX"); setMouseCursorToItemInHand(); @@ -822,12 +861,6 @@ void LoLEngine::startupNew() { _compassDirection = _compassDirectionIndex = -1; _lastMouseRegion = -1; - - /* - _unk5 = 1; - _unk6 = 1; - _unk7 = 1 - _unk8 = 1*/ _currentLevel = 1; giveCredits(41, 0); @@ -858,6 +891,12 @@ void LoLEngine::runLoop() { _flagsTable[73] |= 0x08; while (!shouldQuit() && _runFlag) { + if (_gameToLoad != -1) { + if (loadGameState(_gameToLoad) != Common::kNoError) + error("Couldn't load game slot %d", _gameToLoad); + _gameToLoad = -1; + } + if (_nextScriptFunc) { runLevelScript(_nextScriptFunc, 2); _nextScriptFunc = 0; @@ -865,7 +904,7 @@ void LoLEngine::runLoop() { _timer->update(); - //checkFloatingPointerRegions(); + checkFloatingPointerRegions(); gui_updateInput(); update(); @@ -884,6 +923,55 @@ void LoLEngine::runLoop() { } } +void LoLEngine::registerDefaultSettings() { + KyraEngine_v1::registerDefaultSettings(); + + // Most settings already have sensible defaults. This one, however, is + // specific to the LoL engine. + ConfMan.registerDefault("floating_cursors", false); + ConfMan.registerDefault("smooth_scrolling", true); + ConfMan.registerDefault("monster_difficulty", 1); +} + +void LoLEngine::writeSettings() { + ConfMan.setInt("monster_difficulty", _monsterDifficulty); + ConfMan.setBool("floating_cursors", _floatingCursorsEnabled); + ConfMan.setBool("smooth_scrolling", _smoothScrollingEnabled); + + switch (_lang) { + case 1: + _flags.lang = Common::FR_FRA; + break; + + case 2: + _flags.lang = Common::DE_DEU; + break; + + case 3: + _flags.lang = Common::JA_JPN; + break; + + case 0: + default: + _flags.lang = Common::EN_ANY; + } + + if (_flags.lang == _flags.replacedLang && _flags.fanLang != Common::UNK_LANG) + _flags.lang = _flags.fanLang; + + ConfMan.set("language", Common::getLanguageCode(_flags.lang)); + + KyraEngine_v1::writeSettings(); +} + +void LoLEngine::readSettings() { + _monsterDifficulty = ConfMan.getInt("monster_difficulty"); + _smoothScrollingEnabled = ConfMan.getBool("smooth_scrolling"); + _floatingCursorsEnabled = ConfMan.getBool("floating_cursors"); + + KyraEngine_v1::readSettings(); +} + void LoLEngine::update() { updateSequenceBackgroundAnimations(); @@ -1095,7 +1183,7 @@ void LoLEngine::updatePortraitSpeechAnim() { f -= 5; f += 7; - if (_speechFlag) { + if (speechEnabled()) { if (snd_updateCharacterSpeech() == 2) _updatePortraitSpeechAnimDuration = 2; else @@ -1233,7 +1321,7 @@ void LoLEngine::setCharacterMagicOrHitPoints(int charNum, int type, int points, if (charNum > 3) return; - + LoLCharacter *c = &_characters[charNum]; if (!(c->flags & 1)) return; @@ -1421,7 +1509,7 @@ void LoLEngine::gui_specialSceneSuspendControls(int controlMode) { _specialSceneFlag = 1; _currentControlMode = controlMode; calcCharPortraitXpos(); - //checkMouseRegions(); + checkFloatingPointerRegions(); } void LoLEngine::gui_specialSceneRestoreControls(int restoreLamp) { @@ -1431,7 +1519,7 @@ void LoLEngine::gui_specialSceneRestoreControls(int restoreLamp) { } _updateFlags &= 0xfffe; _specialSceneFlag = 0; - //checkMouseRegions(); + checkFloatingPointerRegions(); } void LoLEngine::restoreAfterSceneWindowDialogue(int redraw) { @@ -1450,7 +1538,7 @@ void LoLEngine::restoreAfterSceneWindowDialogue(int redraw) { if (_screen->_fadeFlag != 2) _screen->fadeClearSceneWindow(10); gui_drawPlayField(); - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); _screen->_fadeFlag = 0; } @@ -1584,15 +1672,16 @@ void LoLEngine::transformRegion(int x1, int y1, int x2, int y2, int w, int h, in } } -void LoLEngine::setPaletteBrightness(uint8 *palette, int brightness, int modifier) { - generateBrightnessPalette(palette, _screen->getPalette(1), brightness, modifier); +void LoLEngine::setPaletteBrightness(const Palette &srcPal, int brightness, int modifier) { + generateBrightnessPalette(srcPal, _screen->getPalette(1), brightness, modifier); _screen->fadePalette(_screen->getPalette(1), 5, 0); _screen->_fadeFlag = 0; } -void LoLEngine::generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness, int modifier) { - memcpy(dst, src, 0x300); +void LoLEngine::generateBrightnessPalette(const Palette &src, Palette &dst, int brightness, int modifier) { + dst.copy(src); _screen->loadSpecialColors(dst); + brightness = (8 - brightness) << 5; if (modifier >= 0 && modifier < 8 && (_flagsTable[31] & 0x08)) { brightness = 256 - ((((modifier & 0xfffe) << 5) * (256 - brightness)) >> 8); @@ -1606,26 +1695,21 @@ void LoLEngine::generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness } } -void LoLEngine::generateFlashPalette(uint8 *src, uint8 *dst, int colorFlags) { - if (!src || !dst) - return; - - memcpy(dst, src, 6); - - uint8 *s = src + 6; - uint8 *d = dst + 6; +void LoLEngine::generateFlashPalette(const Palette &src, Palette &dst, int colorFlags) { + dst.copy(src, 0, 2); for (int i = 2; i < 128; i++) { for (int ii = 0; ii < 3; ii++) { - uint8 t = *s++ & 0x3f; + uint8 t = src[i * 3 + ii] & 0x3f; if (colorFlags & (1 << ii)) t += ((0x3f - t) >> 1); else t -= (t >> 1); - *d++ = t; + dst[i * 3 + ii] = t; } } - memcpy(d, s, 384); + + dst.copy(src, 128); } void LoLEngine::updateSequenceBackgroundAnimations() { @@ -1790,32 +1874,6 @@ void LoLEngine::delay(uint32 millis, bool doUpdate, bool) { } } -uint8 LoLEngine::getRandomNumberSpecial() { - uint8 a = _rndSpecial & 0xff; - uint8 b = (_rndSpecial >> 8) & 0xff; - uint8 c = (_rndSpecial >> 16) & 0xff; - - a >>= 1; - - uint as = a & 1; - uint bs = (b >> 7) ? 0 : 1; - uint cs = c >> 7; - - a >>= 1; - c = (c << 1) | as; - b = (b << 1) | cs; - - a -= ((_rndSpecial & 0xff) - bs); - as = a & 1; - a >>= 1; - - a = ((_rndSpecial & 0xff) >> 1) | (as << 7); - - _rndSpecial = (_rndSpecial & 0xff000000) | (c << 16) | (b << 8) | a; - - return a ^ b; -} - void LoLEngine::updateEnvironmentalSfx(int soundId) { snd_processEnvironmentalSoundEffect(soundId, _currentBlock); } @@ -1919,7 +1977,7 @@ int LoLEngine::castHealOnSingleCharacter(ActiveSpell *a) { } int LoLEngine::processMagicSpark(int charNum, int spellLevel) { - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); _screen->copyPage(0, 12); mov->open("spark1.wsa", 0, 0); @@ -2120,25 +2178,24 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { gui_drawScene(0); _screen->copyPage(0, 12); - uint8 *tpal = new uint8[768]; - uint8 *swampCol = new uint8[768]; + Palette tpal(768), swampCol(768); if (_currentLevel == 11 && !(_flagsTable[52] & 0x04)) { - uint8 *sc = _screen->_currentPalette; - uint8 *dc = _screen->getPalette(2); + uint8 *sc = _screen->getPalette(0).getData(); + uint8 *dc = _screen->getPalette(2).getData(); for (int i = 1; i < 768; i++) SWAP(sc[i], dc[i]); + _flagsTable[52] |= 0x04; static const uint8 freezeTimes[] = { 20, 28, 40, 60 }; setCharacterUpdateEvent(charNum, 8, freezeTimes[spellLevel], 1); } - uint8 *sc = _res->fileData("swampice.col", 0); - memcpy(swampCol, sc, 384); - uint8 *s = _screen->getPalette(1); - for (int i = 384; i < 768; i++) - swampCol[i] = tpal[i] = s[i] & 0x3f; + _screen->loadPalette("SWAMPICE.COL", swampCol); + tpal.copy(_screen->getPalette(1), 128); + swampCol.copy(_screen->getPalette(1), 128); + Palette &s = _screen->getPalette(1); for (int i = 1; i < 128; i++) { tpal[i * 3] = 0; uint16 v = (s[i * 3] + s[i * 3 + 1] + s[i * 3 + 2]) / 3; @@ -2148,24 +2205,25 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { if (tpal[i * 3 + 2] > 0x3f) tpal[i * 3 + 2] = 0x3f; } + generateBrightnessPalette(tpal, tpal, _brightness, _lampEffect); generateBrightnessPalette(swampCol, swampCol, _brightness, _lampEffect); swampCol[0] = swampCol[1] = swampCol[2] = tpal[0] = tpal[1] = tpal[2] = 0; - generateBrightnessPalette(_screen->_currentPalette, s, _brightness, _lampEffect); + generateBrightnessPalette(_screen->getPalette(0), s, _brightness, _lampEffect); int sX = 112; int sY = 0; - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); if (spellLevel == 0) { sX = 0; } if (spellLevel == 1 || spellLevel == 2) { - mov->open("snow.wsa", 1, 0); + mov->open("SNOW.WSA", 1, 0); if (!mov->opened()) error("Ice: Unable to load snow.wsa"); } if (spellLevel == 3) { - mov->open("ice.wsa", 1, 0); + mov->open("ICE.WSA", 1, 0); if (!mov->opened()) error("Ice: Unable to load ice.wsa"); sX = 136; @@ -2174,9 +2232,9 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { snd_playSoundEffect(71, -1); - playSpellAnimation(0, 0, 0, 2, 0, 0, 0, s, tpal, 40, false); + playSpellAnimation(0, 0, 0, 2, 0, 0, 0, s.getData(), tpal.getData(), 40, false); - _screen->fadePaletteStep(s, tpal, _system->getMillis(), _tickLength); + _screen->fadePaletteStep(s.getData(), tpal.getData(), _system->getMillis(), _tickLength); if (mov->opened()) { int r = true; if (spellLevel > 2) { @@ -2241,22 +2299,19 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { enableSysTimer(2); if (_currentLevel != 11) - generateBrightnessPalette(_screen->_currentPalette, swampCol, _brightness, _lampEffect); + generateBrightnessPalette(_screen->getPalette(0), swampCol, _brightness, _lampEffect); - playSpellAnimation(0, 0, 0, 2, 0, 0, 0, tpal, swampCol, 40, 0); + playSpellAnimation(0, 0, 0, 2, 0, 0, 0, tpal.getData(), swampCol.getData(), 40, 0); - _screen->fadePaletteStep(tpal, swampCol, _system->getMillis(), _tickLength); + _screen->fadePaletteStep(tpal.getData(), swampCol.getData(), _system->getMillis(), _tickLength); if (breakWall) - breakIceWall(tpal, swampCol); + breakIceWall(tpal.getData(), swampCol.getData()); static const uint8 freezeTime[] = { 20, 28, 40, 60 }; if (_currentLevel == 11) setCharacterUpdateEvent(charNum, 8, freezeTime[spellLevel], 1); - delete[] sc; - delete[] swampCol; - delete[] tpal; _screen->setCurPage(cp); return 1; } @@ -2417,7 +2472,7 @@ int LoLEngine::processMagicHandOfFate(int spellLevel) { int cp = _screen->setCurPage(2); _screen->copyPage(0, 12); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); mov->open("hand.wsa", 1, 0); if (!mov->opened()) error("Hand: Unable to load HAND.WSA"); @@ -2495,8 +2550,8 @@ int LoLEngine::processMagicHandOfFate(int spellLevel) { int LoLEngine::processMagicMistOfDoom(int charNum, int spellLevel) { static const uint8 mistDamage[] = { 30, 70, 110, 200 }; - - _envSfxUseQueue = true; + + _envSfxUseQueue = true; inflictMagicalDamageForBlock(calcNewBlockPosition(_currentBlock, _currentDirection), charNum, mistDamage[spellLevel], 0x80); _envSfxUseQueue = false; @@ -2509,7 +2564,7 @@ int LoLEngine::processMagicMistOfDoom(int charNum, int spellLevel) { char wsafile[13]; snprintf(wsafile, 13, "mists%0d.wsa", spellLevel + 1); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); mov->open(wsafile, 1, 0); if (!mov->opened()) error("Mist: Unable to load mists.wsa"); @@ -2541,7 +2596,7 @@ int LoLEngine::processMagicLightning(int charNum, int spellLevel) { char wsafile[13]; snprintf(wsafile, 13, "litning%d.wsa", spellLevel + 1); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); mov->open(wsafile, 1, 0); if (!mov->opened()) error("Litning: Unable to load litning.wsa"); @@ -2570,7 +2625,7 @@ int LoLEngine::processMagicFog() { int cp = _screen->setCurPage(2); _screen->copyPage(0, 12); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); int numFrames = mov->open("fog.wsa", 0, 0); if (!mov->opened()) error("Fog: Unable to load fog.wsa"); @@ -2646,7 +2701,7 @@ int LoLEngine::processMagicSwarm(int charNum, int damage) { _monsters[destIds[i]].fightCurTick = destTicks[i]; } - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); mov->open("swarm.wsa", 0, 0); if (!mov->opened()) @@ -2671,7 +2726,7 @@ int LoLEngine::processMagicSwarm(int charNum, int damage) { int LoLEngine::processMagicVaelansCube() { uint8 *tmpPal1 = new uint8[768]; uint8 *tmpPal2 = new uint8[768]; - uint8 *sp1 = _screen->getPalette(1); + uint8 *sp1 = _screen->getPalette(1).getData(); memcpy(tmpPal1, sp1, 768); memcpy(tmpPal2, sp1, 768); @@ -2734,7 +2789,7 @@ int LoLEngine::processMagicGuardian(int charNum) { _screen->copyPage(0, 2); _screen->copyPage(2, 12); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); mov->open("guardian.wsa", 0, 0); if (!mov->opened()) error("Guardian: Unable to load guardian.wsa"); @@ -2742,7 +2797,7 @@ int LoLEngine::processMagicGuardian(int charNum) { playSpellAnimation(mov, 0, 37, 2, 112, 0, 0, 0, 0, 0, false); _screen->copyPage(2, 12); - + uint16 bl = calcNewBlockPosition(_currentBlock, _currentDirection); int res = (_levelBlockProperties[bl].assignedObjects & 0x8000) ? 1 : 0; inflictMagicalDamageForBlock(bl, charNum, 200, 0x80); @@ -2754,7 +2809,7 @@ int LoLEngine::processMagicGuardian(int charNum) { _screen->copyPage(2, 12); snd_playSoundEffect(176, -1); playSpellAnimation(mov, 38, 48, 8, 112, 0, 0, 0, 0, 0, false); - + mov->close(); delete mov; @@ -2771,20 +2826,22 @@ void LoLEngine::callbackProcessMagicSwarm(WSAMovie_v2 *mov, int x, int y) { } void LoLEngine::callbackProcessMagicLightning(WSAMovie_v2 *mov, int x, int y) { - uint8 *tpal = new uint8[768]; if (_lightningDiv == 2) shakeScene(1, 2, 3, 0); - uint8 *p1 = _screen->getPalette(1); + const Palette &p1 = _screen->getPalette(1); if (_lightningSfxFrame % _lightningDiv) { _screen->setScreenPalette(p1); } else { - memcpy(tpal, p1, 768); + Palette tpal(p1.getNumColors()); + tpal.copy(p1); + for (int i = 6; i < 384; i++) { uint16 v = (tpal[i] * 120) / 64; tpal[i] = (v < 64) ? v : 63; } + _screen->setScreenPalette(tpal); } @@ -2799,7 +2856,55 @@ void LoLEngine::callbackProcessMagicLightning(WSAMovie_v2 *mov, int x, int y) { } _lightningSfxFrame++; - delete[] tpal; +} + +void LoLEngine::drinkBezelCup(int numUses, int charNum) { + int cp = _screen->setCurPage(2); + snd_playSoundEffect(73, -1); + + WSAMovie_v2 *mov = new WSAMovie_v2(this); + mov->open("bezel.wsa", 0, 0); + if (!mov->opened()) + error("Bezel: Unable to load bezel.wsa"); + + int x = _activeCharsXpos[charNum] - 11; + int y = 124; + int w = mov->width(); + int h = mov->height(); + + _screen->copyRegion(x, y, 0, 0, w, h, 0, 2, Screen::CR_NO_P_CHECK); + + static const uint8 bezelAnimData[] = { 0, 26, 20, 27, 61, 55, 62, 92, 86, 93, 131, 125 }; + int frm = bezelAnimData[numUses * 3]; + int hpDiff = _characters[charNum].hitPointsMax - _characters[charNum].hitPointsCur; + uint16 step = 0; + + do { + step = (step & 0xff) + (hpDiff * 256) / (bezelAnimData[numUses * 3 + 2]); + increaseCharacterHitpoints(charNum, step / 256, true); + gui_drawCharPortraitWithStats(charNum); + + uint32 etime = _system->getMillis() + 4 * _tickLength; + + _screen->copyRegion(0, 0, x, y, w, h, 2, 2, Screen::CR_NO_P_CHECK); + mov->displayFrame(frm, 2, x, y, 0x5000, _trueLightTable1, _trueLightTable2); + _screen->copyRegion(x, y, x, y, w, h, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + + delayUntil(etime); + } while (++frm < bezelAnimData[numUses * 3 + 1]); + + _characters[charNum].hitPointsCur = _characters[charNum].hitPointsMax; + _screen->copyRegion(0, 0, x, y, w, h, 2, 2, Screen::CR_NO_P_CHECK); + removeCharacterEffects(&_characters[charNum], 4, 4); + gui_drawCharPortraitWithStats(charNum); + _screen->copyRegion(x, y, x, y, w, h, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + + mov->close(); + delete mov; + + _screen->setCurPage(cp); } void LoLEngine::addSpellToScroll(int spell, int charNum) { @@ -2871,7 +2976,7 @@ void LoLEngine::transferSpellToScollAnimation(int charNum, int spell, int slot) snd_playSoundEffect(_updateSpellBookAnimData[(spell << 2) + 3], -1); snd_playSoundEffect(95, -1); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); mov->open("getspell.wsa", 0, 0); if (!mov->opened()) @@ -3282,6 +3387,52 @@ int LoLEngine::calcInflictableDamagePerItem(int16 attacker, int16 target, uint16 } void LoLEngine::checkForPartyDeath() { + Button b; + b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xfe; + b.data0Val3 = b.data1Val3 = b.data2Val3 = 0x01; + + for (int i = 0; i < 4; i++) { + if (!(_characters[i].flags & 1) || _characters[i].hitPointsCur <= 0) + continue; + return; + } + + if (_weaponsDisabled) + clickedExitCharInventory(&b); + + gui_drawAllCharPortraitsWithStats(); + + if (_partyDamageFlags & 0x40) { + _screen->fadeToBlack(40); + for (int i = 0; i < 4; i++) { + if (_characters[i].flags & 1) + increaseCharacterHitpoints(i, 1, true); + } + gui_drawAllCharPortraitsWithStats(); + _screen->fadeToPalette1(40); + + } else { + _screen->fadeClearSceneWindow(10); + restoreAfterSpecialScene(0, 1, 1, 0); + + snd_playTrack(325); + updatePortraits(); + initTextFading(0, 1); + setMouseCursorToIcon(0); + _updateFlags |= 4; + setLampMode(true); + disableSysTimer(2); + + _gui->runMenu(_gui->_deathMenu); + + setMouseCursorToItemInHand(); + _updateFlags &= 0xfffb; + resetLampStatus(); + + gui_enableDefaultPlayfieldButtons(); + enableSysTimer(2); + updateDrawPage2(); + } } void LoLEngine::applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, int16 damage) { @@ -3499,16 +3650,16 @@ void LoLEngine::restoreSwampPalette() { if (_currentLevel != 11) return; - uint8 *s = _screen->getPalette(2); - uint8 *d = _screen->_currentPalette; - uint8 *d2 = _screen->getPalette(1); + uint8 *s = _screen->getPalette(2).getData(); + uint8 *d = _screen->getPalette(0).getData(); + uint8 *d2 = _screen->getPalette(1).getData(); for (int i = 1; i < 768; i++) SWAP(s[i], d[i]); - generateBrightnessPalette(d, d2, _brightness, _lampEffect); - _screen->loadSpecialColors(s); - _screen->loadSpecialColors(d2); + generateBrightnessPalette(_screen->getPalette(0), _screen->getPalette(1), _brightness, _lampEffect); + _screen->loadSpecialColors(_screen->getPalette(2)); + _screen->loadSpecialColors(_screen->getPalette(1)); playSpellAnimation(0, 0, 0, 2, 0, 0, 0, s, d2, 40, 0); } @@ -3529,7 +3680,7 @@ void LoLEngine::launchMagicViper() { _screen->copyPage(0, 12); snd_playSoundEffect(148, -1); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); int numFrames = mov->open("viper.wsa", 1, 0); if (!mov->opened()) error("Viper: Unable to load viper.wsa"); @@ -3579,7 +3730,7 @@ void LoLEngine::breakIceWall(uint8 *pal1, uint8 *pal2) { gui_drawScene(2); _screen->copyPage(2, 10); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); int numFrames = mov->open("shatter.wsa", 1, 0); if (!mov->opened()) error("Shatter: Unable to load shatter.wsa"); @@ -3681,7 +3832,7 @@ void LoLEngine::displayAutomap() { uint8 *tmpWll = new uint8[80]; memcpy(tmpWll, _wllBuffer4, 80); - _screen->loadBitmap("parch.cps", 2, 2, _screen->getPalette(3)); + _screen->loadBitmap("parch.cps", 2, 2, &_screen->getPalette(3)); _screen->loadBitmap("autobut.shp", 3, 5, 0); const uint8 *shp = _screen->getCPagePtr(5); @@ -3848,12 +3999,17 @@ void LoLEngine::loadMapLegendData(int level) { } void LoLEngine::drawMapPage(int pageNum) { + // WORKAROUND for French version. The Text does not always properly fit the screen there. + int8 textOffset = (_lang == 1) ? -2 : 0; + for (int i = 0; i < 2; i++) { - _screen->loadBitmap("parch.cps", pageNum, pageNum, _screen->getPalette(3)); + _screen->loadBitmap("parch.cps", pageNum, pageNum, &_screen->getPalette(3)); + if (_lang == 1) + _screen->copyRegion(236, 16, 236 + textOffset, 16, -textOffset, 1, pageNum, pageNum, Screen::CR_NO_P_CHECK); int cp = _screen->setCurPage(pageNum); Screen::FontId of = _screen->setFont(Screen::FID_9_FNT); - _screen->printText(getLangString(_autoMapStrings[_currentMapLevel]), 236, 8, 1, 0); + _screen->printText(getLangString(_autoMapStrings[_currentMapLevel]), 236 + textOffset, 8, 1, 0); uint16 blX = mapGetStartPosX(); uint16 bl = (mapGetStartPosY() << 5) + blX; @@ -3932,7 +4088,7 @@ void LoLEngine::drawMapPage(int pageNum) { if (l[2] == 0xffff) continue; - printMapText(l[2], 244, (tY << 3) + 22); + printMapText(l[2], 244 + textOffset, (tY << 3) + 22); if (l[5] == 0xffff) { tY++; @@ -3942,7 +4098,7 @@ void LoLEngine::drawMapPage(int pageNum) { uint16 cbl2 = l[3] + (l[4] << 5); _levelBlockProperties[cbl2].flags |= 7; _screen->drawShape(2, _automapShapes[l[5] << 2], (l[3] - sx) * 7 + _automapTopLeftX - 3, (l[4] - sy) * 6 + _automapTopLeftY - 3, 0, 0); - _screen->drawShape(2, _automapShapes[l[5] << 2], 231, (tY << 3) + 19, 0, 0); + _screen->drawShape(2, _automapShapes[l[5] << 2], 231 + textOffset, (tY << 3) + 19, 0, 0); tY++; } @@ -3951,9 +4107,9 @@ void LoLEngine::drawMapPage(int pageNum) { for (int ii = 0; ii < 11; ii++) { if (!_defaultLegendData[ii].enable) continue; - _screen->copyBlockAndApplyOverlay(_screen->_curPage, 235, (tY << 3) + 21, _screen->_curPage, 235, (tY << 3) + 21, 7, 6, 0, _mapOverlay); - _screen->drawShape(_screen->_curPage, _automapShapes[_defaultLegendData[ii].shapeIndex << 2], 232, (tY << 3) + 18 + _defaultLegendData[ii].x, 0, 0); - printMapText(_defaultLegendData[ii].stringId, 244, (tY << 3) + 22); + _screen->copyBlockAndApplyOverlay(_screen->_curPage, 235, (tY << 3) + 21, _screen->_curPage, 235 + textOffset, (tY << 3) + 21, 7, 6, 0, _mapOverlay); + _screen->drawShape(_screen->_curPage, _automapShapes[_defaultLegendData[ii].shapeIndex << 2], 232 + textOffset, (tY << 3) + 18 + _defaultLegendData[ii].x, 0, 0); + printMapText(_defaultLegendData[ii].stringId, 244 + textOffset, (tY << 3) + 22); tY++; } diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index 45795a7cab..12000c31fa 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -307,6 +307,7 @@ public: Screen *screen(); GUI *gui() const; + private: Screen_LoL *_screen; GUI_LoL *_gui; @@ -326,6 +327,10 @@ private: void startup(); void startupNew(); + void registerDefaultSettings(); + void writeSettings(); + void readSettings(); + // options int _monsterDifficulty; bool _smoothScrollingEnabled; @@ -342,7 +347,9 @@ private: uint8 *getItemIconShapePtr(int index); bool posWithinRect(int mouseX, int mouseY, int x1, int y1, int x2, int y2); - int _floatingMouseArrowControl; + void checkFloatingPointerRegions(); + int _floatingCursorControl; + int _currentFloatingCursor; // intro + character selection int processPrologue(); @@ -441,6 +448,9 @@ private: int _timer3Para; // sound + int convertVolumeToMixer(int value); + int convertVolumeFromMixer(int value); + void loadTalkFile(int index); void snd_playVoiceFile(int track) {} bool snd_playCharacterSpeech(int id, int8 speaker, int); @@ -473,7 +483,6 @@ private: Common::List<Audio::AudioStream*> _speechList; int _curTlkFile; - int _speechFlag; char **_ingameSoundList; int _ingameSoundListSize; @@ -772,11 +781,12 @@ private: int olol_getNextActiveCharacter(EMCState *script); int olol_paralyzePoisonCharacter(EMCState *script); int olol_drawCharPortrait(EMCState *script); - int olol_removeInventoryItem(EMCState *script); + int olol_removeInventoryItem(EMCState *script); int olol_getAnimationLastPart(EMCState *script); int olol_assignSpecialGuiShape(EMCState *script); int olol_findInventoryItem(EMCState *script); int olol_restoreFadePalette(EMCState *script); + int olol_drinkBezelCup(EMCState *script); int olol_changeItemTypeOrFlag(EMCState *script); int olol_placeInventoryItemInHand(EMCState *script); int olol_castSpell(EMCState *script); @@ -862,9 +872,9 @@ private: void toggleSelectedCharacterFrame(bool mode); void fadeText(); void transformRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage); - void setPaletteBrightness(uint8 *palette, int brightness, int modifier); - void generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness, int modifier); - void generateFlashPalette(uint8 *src, uint8 *dst, int colorFlags); + void setPaletteBrightness(const Palette &srcPal, int brightness, int modifier); + void generateBrightnessPalette(const Palette &src, Palette &dst, int brightness, int modifier); + void generateFlashPalette(const Palette &src, Palette &dst, int colorFlags); void updateSequenceBackgroundAnimations(); bool _dialogueField; @@ -905,7 +915,7 @@ private: void setCharacterMagicOrHitPoints(int charNum, int type, int points, int mode); void increaseExperience(int charNum, int skill, uint32 points); - void increaseCharacterHitpoints(int charNum, int points, bool unk); + void increaseCharacterHitpoints(int charNum, int points, bool ignoreDeath); LoLCharacter *_characters; uint16 _activeCharsXpos[3]; @@ -1303,7 +1313,6 @@ private: // misc void delay(uint32 millis, bool doUpdate = false, bool isMainLoop = false); - uint8 getRandomNumberSpecial(); uint8 _compassBroken; uint8 _drainMagic; @@ -1349,6 +1358,8 @@ private: void callbackProcessMagicSwarm(WSAMovie_v2 *mov, int x, int y); void callbackProcessMagicLightning(WSAMovie_v2 *mov, int x, int y); + void drinkBezelCup(int a, int charNum); + void addSpellToScroll(int spell, int charNum); void transferSpellToScollAnimation(int charNum, int spell, int slot); diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index 79665068f6..ecd6bbe450 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -29,6 +29,7 @@ #include "graphics/thumbnail.h" #include "kyra/kyra_v1.h" +#include "kyra/util.h" #define CURRENT_SAVE_VERSION 16 @@ -65,6 +66,8 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab in->read(descriptionBuffer, descriptionSize[i]); descriptionBuffer[descriptionSize[i]] = 0; + Util::convertDOSToISO(descriptionBuffer); + type = in->readUint32BE(); header.version = in->readUint16LE(); if (type == MKID_BE('MBL3') && header.version == 100) { diff --git a/engines/kyra/scene_hof.cpp b/engines/kyra/scene_hof.cpp index fed7877c0b..2d15af92fd 100644 --- a/engines/kyra/scene_hof.cpp +++ b/engines/kyra/scene_hof.cpp @@ -330,9 +330,6 @@ int KyraEngine_HoF::trySceneChange(int *moveTable, int unk1, int updateChar) { updateCharacterAnim(0); refreshAnimObjectsIfNeed(); - if (!changedScene && !_unk4) { - //XXX - } return changedScene; } @@ -396,14 +393,14 @@ void KyraEngine_HoF::unloadScene() { void KyraEngine_HoF::loadScenePal() { uint16 sceneId = _mainCharacter.sceneId; - memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); + _screen->copyPalette(1, 0); char filename[14]; strcpy(filename, _sceneList[sceneId].filename1); strcat(filename, ".COL"); _screen->loadBitmap(filename, 3, 3, 0); - memcpy(_screen->getPalette(1), _screen->getCPagePtr(3), 384); - memset(_screen->getPalette(1), 0, 3); + _screen->getPalette(1).copy(_screen->getCPagePtr(3), 0, 128); + _screen->getPalette(1).fill(0, 1, 0); memcpy(_scenePal, _screen->getCPagePtr(3)+336, 432); } @@ -669,7 +666,7 @@ void KyraEngine_HoF::initSceneScreen(int unk1) { } if (_noScriptEnter) { - memset(_screen->getPalette(0), 0, 384); + _screen->getPalette(0).fill(0, 128, 0); _screen->setScreenPalette(_screen->getPalette(0)); } @@ -677,7 +674,7 @@ void KyraEngine_HoF::initSceneScreen(int unk1) { if (_noScriptEnter) { _screen->setScreenPalette(_screen->getPalette(1)); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 384); + _screen->getPalette(0).copy(_screen->getPalette(1), 0, 128); } updateCharPal(0); @@ -695,10 +692,7 @@ void KyraEngine_HoF::freeSceneShapePtrs() { } void KyraEngine_HoF::fadeScenePal(int srcIndex, int delayTime) { - uint8 *dst = _screen->getPalette(0) + 336; - const uint8 *src = _scenePal + (srcIndex << 4)*3; - memcpy(dst, src, 48); - + _screen->getPalette(0).copy(_scenePal, srcIndex << 4, 16, 112); _screen->fadePalette(_screen->getPalette(0), delayTime, &_updateFunctor); } diff --git a/engines/kyra/scene_lok.cpp b/engines/kyra/scene_lok.cpp index 345998e40e..fc1ca41189 100644 --- a/engines/kyra/scene_lok.cpp +++ b/engines/kyra/scene_lok.cpp @@ -406,7 +406,7 @@ void KyraEngine_LoK::startSceneScript(int brandonAlive) { _screen->clearPage(3); _res->exists(fileNameBuffer, true); // FIXME: check this hack for amiga version - _screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? _screen->getPalette(0) : 0)); + _screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? &_screen->getPalette(0) : 0)); _sprites->loadSceneShapes(); _exitListPtr = 0; @@ -770,7 +770,7 @@ void KyraEngine_LoK::initSceneObjectList(int brandonAlive) { void KyraEngine_LoK::initSceneScreen(int brandonAlive) { if (_flags.platform == Common::kPlatformAmiga) { if (_unkScreenVar1 && !queryGameFlag(0xF0)) { - memset(_screen->getPalette(2), 0, 32*3); + _screen->getPalette(2).clear(); if (_currentCharacter->sceneId != 117 || !queryGameFlag(0xB3)) _screen->setScreenPalette(_screen->getPalette(2)); } @@ -782,10 +782,10 @@ void KyraEngine_LoK::initSceneScreen(int brandonAlive) { if (_unkScreenVar1 && !queryGameFlag(0xA0)) { if (_currentCharacter->sceneId == 45 && _paletteChanged) - memcpy(_screen->getPalette(0) + 12*3, _screen->getPalette(4) + 12*3, 2); + _screen->getPalette(0).copy(_screen->getPalette(4), 12, 1); if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245 && (_brandonStatusBit & 1)) - memcpy(_screen->getPalette(0), _screen->getPalette(0) + 320*3, 64); + _screen->copyPalette(0, 10); _screen->setScreenPalette(_screen->getPalette(0)); } @@ -807,10 +807,10 @@ void KyraEngine_LoK::initSceneScreen(int brandonAlive) { if (_unkScreenVar1 && _paletteChanged) { if (!queryGameFlag(0xA0)) { - memcpy(_screen->getPalette(0) + 684, _screen->getPalette(1) + 684, 60); + _screen->getPalette(0).copy(_screen->getPalette(1), 228, 20); _screen->setScreenPalette(_screen->getPalette(0)); } else { - memset(_screen->getPalette(0), 0, 768); + _screen->getPalette(0).clear(); } } } diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index 0236e4fa7d..945495517f 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -86,7 +86,7 @@ void LoLEngine::loadLevel(int index) { addLevelItems(); deleteMonstersFromBlock(_currentBlock); - _screen->generateGrayOverlay(_screen->_currentPalette, _screen->_grayOverlay, 32, 16, 0, 0, 128, true); + _screen->generateGrayOverlay(_screen->getPalette(0), _screen->_grayOverlay, 32, 16, 0, 0, 128, true); _sceneDefaultUpdate = 0; if (_screen->_fadeFlag == 3) @@ -94,7 +94,7 @@ void LoLEngine::loadLevel(int index) { gui_drawPlayField(); - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); setMouseCursorToItemInHand(); snd_playTrack(_curMusicTheme); @@ -379,28 +379,24 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight v += 128; if (_lastOverridePalFilePtr) { - uint8 *tpal = _res->fileData(_lastOverridePalFilePtr, 0); - memcpy(_screen->_currentPalette, tpal, 384); - delete[] tpal; + _res->loadFileToBuf(_lastOverridePalFilePtr, _screen->getPalette(0).getData(), 384); } else { - memcpy(_screen->_currentPalette, v, 384); + _screen->getPalette(0).copy(v, 0, 128); } v += 384; /*uint8 tmpPal = new uint8[384]; - memcpy(tmpPal, _screen->_currentPalette + 384, 384); - memset(_screen->_currentPalette + 384, 0xff, 384); - memcpy(_screen->_currentPalette + 384, tmpPal, 384);*/ + memcpy(tmpPal, _screen->getPalette(0) + 384, 384); + memset(_screen->getPalette(0) + 384, 0xff, 384); + memcpy(_screen->getPalette(0) + 384, tmpPal, 384);*/ if (_currentLevel == 11) { - uint8 *swampPal = _res->fileData("SWAMPICE.COL", 0); - memcpy(_screen->getPalette(2), swampPal, 384); - memcpy(_screen->getPalette(2) + 384, _screen->_currentPalette + 384, 384); - delete[] swampPal; + _screen->loadPalette("SWAMPICE.COL", _screen->getPalette(2)); + _screen->getPalette(2).copy(_screen->getPalette(0), 128); if (_flagsTable[52] & 0x04) { - uint8 *pal0 = _screen->_currentPalette; - uint8 *pal2 = _screen->getPalette(2); + uint8 *pal0 = _screen->getPalette(0).getData(); + uint8 *pal2 = _screen->getPalette(2).getData(); for (int i = 1; i < 768; i++) SWAP(pal0[i], pal2[i]); } @@ -427,7 +423,7 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight for (int i = 0; i < 7; i++) { weight = 100 - (i * _lastSpecialColorWeight); weight = (weight > 0) ? (weight * 255) / 100 : 0; - _screen->generateLevelOverlay(_screen->_currentPalette, _screen->getLevelOverlay(i), _lastSpecialColor, weight); + _screen->generateLevelOverlay(_screen->getPalette(0), _screen->getLevelOverlay(i), _lastSpecialColor, weight); for (int ii = 0; ii < 128; ii++) { if (_screen->getLevelOverlay(i)[ii] == 255) @@ -442,7 +438,7 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight _screen->getLevelOverlay(7)[i] = i & 0xff; _loadSuppFilesFlag = 0; - generateBrightnessPalette(_screen->_currentPalette, _screen->getPalette(1), _brightness, _lampEffect); + generateBrightnessPalette(_screen->getPalette(0), _screen->getPalette(1), _brightness, _lampEffect); char tname[13]; snprintf(tname, sizeof(tname), "LEVEL%.02d.TLC", _currentLevel); @@ -548,14 +544,14 @@ void LoLEngine::updateLampStatus() { if (!_brightness || !_lampOilStatus) { newLampEffect = 8; if (newLampEffect != _lampEffect && _screen->_fadeFlag == 0) - setPaletteBrightness(_screen->_currentPalette, _brightness, newLampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, newLampEffect); } else { tmpOilStatus = (_lampOilStatus < 100) ? _lampOilStatus : 100; newLampEffect = (3 - ((tmpOilStatus - 1) / 25)) << 1; if (_lampEffect == -1) { if (_screen->_fadeFlag == 0) - setPaletteBrightness(_screen->_currentPalette, _brightness, newLampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, newLampEffect); _lampStatusTimer = _system->getMillis() + (10 + _rnd.getRandomNumberRng(1, 30)) * _tickLength; } else { if ((_lampEffect & 0xfe) == (newLampEffect & 0xfe)) { @@ -567,7 +563,7 @@ void LoLEngine::updateLampStatus() { } } else { if (_screen->_fadeFlag == 0) - setPaletteBrightness(_screen->_currentPalette, _lampEffect, newLampEffect); + setPaletteBrightness(_screen->getPalette(0), _lampEffect, newLampEffect); } } } @@ -604,7 +600,7 @@ void LoLEngine::updateCompass() { if (_compassStep) _compassStep -= (((ABS(_compassStep) >> 4) + 2) * dir); - int16 d = _compassBroken ? ((int8)getRandomNumberSpecial() - _compassDirection) : (_currentDirection << 6) - _compassDirection; + int16 d = _compassBroken ? (int8(_rnd.getRandomNumber(255)) - _compassDirection) : (_currentDirection << 6) - _compassDirection; if (d <= -128) d += 256; if (d >= 128) @@ -1261,8 +1257,8 @@ void LoLEngine::shakeScene(int duration, int width, int height, int restore) { while (endTime > _system->getMillis()) { uint32 delayTimer = _system->getMillis() + 2 * _tickLength; - int s1 = width ? (getRandomNumberSpecial() % (width << 1)) - width : 0; - int s2 = height ? (getRandomNumberSpecial() % (height << 1)) - height : 0; + int s1 = width ? (_rnd.getRandomNumber(255) % (width << 1)) - width : 0; + int s2 = height ? (_rnd.getRandomNumber(255) % (height << 1)) - height : 0; int x1, y1, x2, y2, w, h; if (s1 >= 0) { @@ -1308,11 +1304,11 @@ void LoLEngine::processGasExplosion(int soundId) { uint16 targetBlock = 0; int dist = getSpellTargetBlock(_currentBlock, _currentDirection, 3, targetBlock); - uint8 *p1 = _screen->getPalette(1); - uint8 *p2 = _screen->getPalette(3); + uint8 *p1 = _screen->getPalette(1).getData(); + uint8 *p2 = _screen->getPalette(3).getData(); if (dist) { - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); char file[13]; snprintf(file, 13, "gasexp%0d.wsa", dist); mov->open(file, 1, 0); @@ -1331,11 +1327,11 @@ void LoLEngine::processGasExplosion(int soundId) { p2[i * 3] = 0x3f; uint32 ctime = _system->getMillis(); - while (_screen->fadePaletteStep(_screen->_currentPalette, p2, _system->getMillis() - ctime, 10)) + while (_screen->fadePaletteStep(_screen->getPalette(0).getData(), p2, _system->getMillis() - ctime, 10)) updateInput(); ctime = _system->getMillis(); - while (_screen->fadePaletteStep(p2, _screen->_currentPalette, _system->getMillis() - ctime, 50)) + while (_screen->fadePaletteStep(p2, _screen->getPalette(0).getData(), _system->getMillis() - ctime, 50)) updateInput(); } @@ -1437,7 +1433,7 @@ void LoLEngine::prepareSpecialScene(int fieldType, int hasDialogue, int suspendG gui_disableControls(controlMode); if (fadeFlag) { - memcpy(_screen->getPalette(3) + 384, _screen->_currentPalette + 384, 384); + _screen->getPalette(3).copy(_screen->getPalette(0), 128); _screen->loadSpecialColors(_screen->getPalette(3)); _screen->fadePalette(_screen->getPalette(3), 10); _screen->_fadeFlag = 0; @@ -1495,7 +1491,7 @@ int LoLEngine::restoreAfterSpecialScene(int fadeFlag, int redrawPlayField, int r if (redrawPlayField) gui_drawPlayField(); - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); } else { _currentControlMode = 0; @@ -1517,6 +1513,7 @@ void LoLEngine::setSequenceButtons(int x, int y, int w, int h, int enableFlags) _seqWindowY2 = y + h; int offs = _itemInHand ? 10 : 0; _screen->setMouseCursor(offs, offs, getItemIconShapePtr(_itemInHand)); + _currentFloatingCursor = -1; if (w == 320) { setLampMode(0); _lampStatusSuspended = true; diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp index 07a7aa0d07..a68dcfb394 100644 --- a/engines/kyra/scene_mr.cpp +++ b/engines/kyra/scene_mr.cpp @@ -48,10 +48,8 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 } musicUpdate(0); - if (!unk3) { - //XXX + if (!unk3) musicUpdate(0); - } if (unk1) { int x = _mainCharacter.x1; @@ -88,7 +86,7 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 newSoundFile = true; } - //XXX + _chatAltFlag = false; if (!unk3) { _emc->init(&_sceneScriptState, &_sceneScriptData); @@ -328,25 +326,23 @@ void KyraEngine_MR::freeSceneShapes() { void KyraEngine_MR::loadScenePal() { char filename[16]; - memcpy(_screen->getPalette(2), _screen->getPalette(0), 768); + _screen->copyPalette(2, 0); strcpy(filename, _sceneList[_mainCharacter.sceneId].filename1); strcat(filename, ".COL"); _screen->loadBitmap(filename, 3, 3, 0); - memcpy(_screen->getPalette(2), _screen->getCPagePtr(3), 432); - memset(_screen->getPalette(2), 0, 3); + _screen->getPalette(2).copy(_screen->getCPagePtr(3), 0, 144); + _screen->getPalette(2).fill(0, 1, 0); for (int i = 144; i <= 167; ++i) { - uint8 *palette = _screen->getPalette(2) + i * 3; + uint8 *palette = _screen->getPalette(2).getData() + i * 3; palette[0] = palette[2] = 63; palette[1] = 0; } _screen->generateOverlay(_screen->getPalette(2), _paletteOverlay, 0xF0, 0x19); - uint8 *palette = _screen->getPalette(2) + 432; - const uint8 *costPal = _costPalBuffer + _characterShapeFile * 72; - memcpy(palette, costPal, 24*3); + _screen->getPalette(2).copy(_costPalBuffer, _characterShapeFile * 24, 24, 144); } void KyraEngine_MR::loadSceneMsc() { @@ -609,7 +605,7 @@ void KyraEngine_MR::initSceneScreen(int unk1) { } if (_noScriptEnter) { - memset(_screen->getPalette(0), 0, 432); + _screen->getPalette(0).fill(0, 144, 0); if (!_wasPlayingVQA) _screen->setScreenPalette(_screen->getPalette(0)); } @@ -619,7 +615,7 @@ void KyraEngine_MR::initSceneScreen(int unk1) { if (_noScriptEnter) { if (!_wasPlayingVQA) _screen->setScreenPalette(_screen->getPalette(2)); - memcpy(_screen->getPalette(0), _screen->getPalette(2), 432); + _screen->getPalette(0).copy(_screen->getPalette(2), 0, 144); if (_wasPlayingVQA) { _screen->fadeFromBlack(0x3C); _wasPlayingVQA = false; diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 2b3a9366e6..fa54bffa98 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -34,9 +34,15 @@ namespace Kyra { Screen::Screen(KyraEngine_v1 *vm, OSystem *system) - : _system(system), _vm(vm), _sjisInvisibleColor(0) { + : _system(system), _vm(vm), _sjisInvisibleColor(0), + _cursorColorKey((vm->gameFlags().gameID == GI_KYRA1) ? 0xFF : 0x00) { _debugEnabled = false; _maskMinY = _maskMaxY = -1; + + _drawShapeVar1 = 0; + _drawShapeVar3 = 1; + _drawShapeVar4 = 0; + _drawShapeVar5 = 0; } Screen::~Screen() { @@ -52,15 +58,13 @@ Screen::~Screen() { delete[] _sjisFontData; delete[] _sjisTempPage; - delete[] _currentPalette; - delete[] _screenPalette; + delete _screenPalette; + delete _internFadePalette; delete[] _decodeShapeBuffer; delete[] _animBlockPtr; - if (_vm->gameFlags().platform != Common::kPlatformAmiga) { - for (int i = 0; i < ARRAYSIZE(_palettes); ++i) - delete[] _palettes[i]; - } + for (uint i = 0; i < _palettes.size(); ++i) + delete _palettes[i]; CursorMan.popAllCursors(); } @@ -123,30 +127,38 @@ bool Screen::init() { memset(_shapePages, 0, sizeof(_shapePages)); - memset(_palettes, 0, sizeof(_palettes)); - _screenPalette = new uint8[768]; + const int paletteCount = (_vm->gameFlags().platform == Common::kPlatformAmiga) ? 12 : 4; + const int numColors = _use16ColorMode ? 16 : ((_vm->gameFlags().platform == Common::kPlatformAmiga) ? 32 : 256); + + _screenPalette = new Palette(numColors); assert(_screenPalette); - memset(_screenPalette, 0, 768); - if (_vm->gameFlags().platform == Common::kPlatformAmiga) { - _currentPalette = new uint8[1248]; - assert(_currentPalette); - memset(_currentPalette, 0, 1248); + _palettes.resize(paletteCount); + for (int i = 0; i < paletteCount; ++i) { + _palettes[i] = new Palette(numColors); + assert(_palettes[i]); + } - for (int i = 0; i < 6; ++i) - _palettes[i] = _currentPalette + (i+1)*96; - } else { - _currentPalette = new uint8[768]; - assert(_currentPalette); - memset(_currentPalette, 0, 768); - for (int i = 0; i < 3; ++i) { - _palettes[i] = new uint8[768]; - assert(_palettes[i]); - memset(_palettes[i], 0, 768); + _internFadePalette = new Palette(numColors); + assert(_internFadePalette); + + setScreenPalette(getPalette(0)); + + // We setup the PC98 text mode palette at [16, 24], since that will be used + // for KANJI characters in Lands of Lore. + if (_use16ColorMode && _vm->gameFlags().platform == Common::kPlatformPC98) { + uint8 palette[8 * 4]; + + for (int i = 0; i < 8; ++i) { + palette[i * 4 + 0] = ((i >> 1) & 1) * 0xFF; + palette[i * 4 + 1] = ((i >> 2) & 1) * 0xFF; + palette[i * 4 + 2] = ((i >> 0) & 1) * 0xFF; + palette[i * 4 + 3] = 0; + + _system->setPalette(palette, 16, 8); } } - setScreenPalette(_currentPalette); _curDim = 0; _charWidth = 0; _charOffset = 0; @@ -339,6 +351,148 @@ void Screen::clearCurPage() { clearOverlayPage(_curPage); } +void Screen::copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src, + int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2) { + uint8 *dstPtr = getPagePtr(_curPage); + uint8 *origDst = dstPtr; + + const ScreenDim *dim = getScreenDim(dimState); + int dimX1 = dim->sx << 3; + int dimX2 = dim->w << 3; + dimX2 += dimX1; + + int dimY1 = dim->sy; + int dimY2 = dim->h; + dimY2 += dimY1; + + int temp = y - dimY1; + if (temp < 0) { + if ((temp += h) <= 0) + return; + else { + SWAP(temp, h); + y += temp - h; + src += (temp - h) * w; + } + } + + temp = dimY2 - y; + if (temp <= 0) + return; + + if (temp < h) + h = temp; + + int srcOffset = 0; + temp = x - dimX1; + if (temp < 0) { + temp = -temp; + srcOffset = temp; + x += temp; + w -= temp; + } + + int srcAdd = 0; + + temp = dimX2 - x; + if (temp <= 0) + return; + + if (temp < w) { + SWAP(w, temp); + temp -= w; + srcAdd = temp; + } + + dstPtr += y * SCREEN_W + x; + uint8 *dst = dstPtr; + + if (_curPage == 0 || _curPage == 1) + addDirtyRect(x, y, w, h); + + clearOverlayRect(_curPage, x, y, w, h); + + temp = h; + int curY = y; + while (h--) { + src += srcOffset; + ++curY; + int cW = w; + + switch (plotFunc) { + case 0: + memcpy(dst, src, cW); + dst += cW; src += cW; + break; + + case 1: + while (cW--) { + uint8 d = *src++; + uint8 t = unkPtr1[d]; + if (t != 0xFF) + d = unkPtr2[*dst + (t << 8)]; + *dst++ = d; + } + break; + + case 4: + while (cW--) { + uint8 d = *src++; + if (d) + *dst = d; + ++dst; + } + break; + + case 5: + while (cW--) { + uint8 d = *src++; + if (d) { + uint8 t = unkPtr1[d]; + if (t != 0xFF) + d = unkPtr2[*dst + (t << 8)]; + *dst = d; + } + ++dst; + } + break; + + case 8: + case 9: + while (cW--) { + uint8 d = *src++; + uint8 t = _shapePages[0][dst - origDst] & 7; + if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY)) + d = _shapePages[1][dst - origDst]; + *dst++ = d; + } + break; + + case 12: + case 13: + while (cW--) { + uint8 d = *src++; + if (d) { + uint8 t = _shapePages[0][dst - origDst] & 7; + if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY)) + d = _shapePages[1][dst - origDst]; + *dst++ = d; + } else { + d = _shapePages[1][dst - origDst]; + *dst++ = d; + } + } + break; + + default: + break; + } + + dst = (dstPtr += SCREEN_W); + src += srcAdd; + } +} + uint8 Screen::getPagePixel(int pageNum, int x, int y) { assert(pageNum < SCREEN_PAGE_NUM); assert(x >= 0 && x < SCREEN_W && y >= 0 && y < SCREEN_H); @@ -354,26 +508,25 @@ void Screen::setPagePixel(int pageNum, int x, int y, uint8 color) { } void Screen::fadeFromBlack(int delay, const UpdateFunctor *upFunc) { - fadePalette(_currentPalette, delay, upFunc); + fadePalette(getPalette(0), delay, upFunc); } void Screen::fadeToBlack(int delay, const UpdateFunctor *upFunc) { - uint8 blackPal[768]; - memset(blackPal, 0, 768); - fadePalette(blackPal, delay, upFunc); + Palette pal(getPalette(0).getNumColors()); + fadePalette(pal, delay, upFunc); } -void Screen::fadePalette(const uint8 *palData, int delay, const UpdateFunctor *upFunc) { +void Screen::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc) { updateScreen(); int diff = 0, delayInc = 0; - getFadeParams(palData, delay, delayInc, diff); + getFadeParams(pal, delay, delayInc, diff); int delayAcc = 0; while (!_vm->shouldQuit()) { delayAcc += delayInc; - int refreshed = fadePalStep(palData, diff); + int refreshed = fadePalStep(pal, diff); if (upFunc && upFunc->isValid()) (*upFunc)(); @@ -388,7 +541,7 @@ void Screen::fadePalette(const uint8 *palData, int delay, const UpdateFunctor *u } if (_vm->shouldQuit()) { - setScreenPalette(palData); + setScreenPalette(pal); if (upFunc && upFunc->isValid()) (*upFunc)(); else @@ -396,12 +549,11 @@ void Screen::fadePalette(const uint8 *palData, int delay, const UpdateFunctor *u } } -void Screen::getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff) { +void Screen::getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff) { uint8 maxDiff = 0; - const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256) * 3; - for (int i = 0; i < colors; ++i) { - diff = ABS(palette[i] - _screenPalette[i]); + for (int i = 0; i < pal.getNumColors() * 3; ++i) { + diff = ABS(pal[i] - (*_screenPalette)[i]); maxDiff = MAX<uint8>(maxDiff, diff); } @@ -417,17 +569,14 @@ void Screen::getFadeParams(const uint8 *palette, int delay, int &delayInc, int & } } -int Screen::fadePalStep(const uint8 *palette, int diff) { - const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : (_use16ColorMode ? 16 : 256)) * 3; - - uint8 fadePal[768]; - memcpy(fadePal, _screenPalette, colors); +int Screen::fadePalStep(const Palette &pal, int diff) { + _internFadePalette->copy(*_screenPalette); bool needRefresh = false; - for (int i = 0; i < colors; ++i) { - int c1 = palette[i]; - int c2 = fadePal[i]; + for (int i = 0; i < pal.getNumColors() * 3; ++i) { + int c1 = pal[i]; + int c2 = (*_internFadePalette)[i]; if (c1 != c2) { needRefresh = true; if (c1 > c2) { @@ -442,26 +591,26 @@ int Screen::fadePalStep(const uint8 *palette, int diff) { c2 = c1; } - fadePal[i] = (uint8)c2; + (*_internFadePalette)[i] = (uint8)c2; } } if (needRefresh) - setScreenPalette(fadePal); + setScreenPalette(*_internFadePalette); return needRefresh ? 1 : 0; } void Screen::setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue) { - _currentPalette[index * 3 + 0] = red; - _currentPalette[index * 3 + 1] = green; - _currentPalette[index * 3 + 2] = blue; - setScreenPalette(_currentPalette); + getPalette(0)[index * 3 + 0] = red; + getPalette(0)[index * 3 + 1] = green; + getPalette(0)[index * 3 + 2] = blue; + setScreenPalette(getPalette(0)); } void Screen::getRealPalette(int num, uint8 *dst) { const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256); - const uint8 *palData = getPalette(num); + const uint8 *palData = getPalette(num).getData(); if (!palData) { memset(dst, 0, colors * 3); @@ -469,46 +618,26 @@ void Screen::getRealPalette(int num, uint8 *dst) { } for (int i = 0; i < colors; ++i) { - dst[0] = (palData[0] << 2) | (palData[0] & 3); - dst[1] = (palData[1] << 2) | (palData[1] & 3); - dst[2] = (palData[2] << 2) | (palData[2] & 3); + dst[0] = (palData[0] * 0xFF) / 0x3F; + dst[1] = (palData[1] * 0xFF) / 0x3F; + dst[2] = (palData[2] * 0xFF) / 0x3F; dst += 3; palData += 3; } } -void Screen::setScreenPalette(const uint8 *palData) { - const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256); - +void Screen::setScreenPalette(const Palette &pal) { uint8 screenPal[256 * 4]; - if (palData != _screenPalette) - memcpy(_screenPalette, palData, colors*3); + _screenPalette->copy(pal); - if (_use16ColorMode && _vm->gameFlags().platform == Common::kPlatformPC98) { - for (int l = 0; l < 1024; l += 64) { - const uint8 *tp = palData; - for (int i = 0; i < 16; ++i) { - screenPal[l + 4 * i + 0] = palData[1]; - screenPal[l + 4 * i + 1] = palData[0]; - screenPal[l + 4 * i + 2] = palData[2]; - screenPal[l + 4 * i + 3] = 0; - palData += 3; - } - palData = tp; - } - } else { - if (palData != _screenPalette) - memcpy(_screenPalette, palData, colors*3); - for (int i = 0; i < colors; ++i) { - screenPal[4 * i + 0] = (palData[0] << 2) | (palData[0] & 3); - screenPal[4 * i + 1] = (palData[1] << 2) | (palData[1] & 3); - screenPal[4 * i + 2] = (palData[2] << 2) | (palData[2] & 3); - screenPal[4 * i + 3] = 0; - palData += 3; - } + for (int i = 0; i < pal.getNumColors(); ++i) { + screenPal[4 * i + 0] = (pal[i * 3 + 0] * 0xFF) / 0x3F; + screenPal[4 * i + 1] = (pal[i * 3 + 1] * 0xFF) / 0x3F; + screenPal[4 * i + 2] = (pal[i * 3 + 2] * 0xFF) / 0x3F; + screenPal[4 * i + 3] = 0; } - _system->setPalette(screenPal, 0, colors); + _system->setPalette(screenPal, 0, pal.getNumColors()); } void Screen::copyToPage0(int y, int h, uint8 page, uint8 *seqBuf) { @@ -656,63 +785,6 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint } } -void Screen::copyFromCurPageBlock(int x, int y, int w, int h, const uint8 *src) { - if (x < 0) - x = 0; - else if (x >= 40) - return; - - if (x + w > 40) - w = 40 - x; - - if (y < 0) - y = 0; - else if (y >= 200) - return; - - if (y + h > 200) - h = 200 - y; - - uint8 *dst = getPagePtr(_curPage) + y * SCREEN_W + x * 8; - - if (_curPage == 0 || _curPage == 1) - addDirtyRect(x*8, y, w*8, h); - - clearOverlayRect(_curPage, x*8, y, w*8, h); - - while (h--) { - memcpy(dst, src, w*8); - dst += SCREEN_W; - src += w*8; - } -} - -void Screen::copyCurPageBlock(int x, int y, int w, int h, uint8 *dst) { - assert(dst); - if (x < 0) - x = 0; - else if (x >= 40) - return; - - if (x + w > 40) - w = 40 - x; - - if (y < 0) - y = 0; - else if (y >= 200) - return; - - if (y + h > 200) - h = 200 - y; - - const uint8 *src = getPagePtr(_curPage) + y * SCREEN_W + x * 8; - while (h--) { - memcpy(dst, src, w*8); - dst += w*8; - src += SCREEN_W; - } -} - void Screen::shuffleScreen(int sx, int sy, int w, int h, int srcPage, int dstPage, int ticks, bool transparent) { assert(sx >= 0 && w <= SCREEN_W); int x; @@ -802,17 +874,26 @@ void Screen::drawBox(int x1, int y1, int x2, int y2, int color) { drawClippedLine(x1, y2, x2, y2, color); } -void Screen::drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2) { +void Screen::drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2, ShadeType shadeType) { assert(x1 >= 0 && y1 >= 0); hideMouse(); fillRect(x1, y1, x2, y1 + 1, color1); - fillRect(x2 - 1, y1, x2, y2, color1); + if (shadeType == kShadeTypeLol) + fillRect(x1, y1, x1 + 1, y2, color1); + else + fillRect(x2 - 1, y1, x2, y2, color1); - drawClippedLine(x1, y1, x1, y2, color2); - drawClippedLine(x1 + 1, y1 + 1, x1 + 1, y2 - 1, color2); + if (shadeType == kShadeTypeLol) { + drawClippedLine(x2, y1, x2, y2, color2); + drawClippedLine(x2 - 1, y1 + 1, x2 - 1, y2 - 1, color2); + drawClippedLine(x1 + 1, y2 - 1, x2, y2 - 1, color2); + } else { + drawClippedLine(x1, y1, x1, y2, color2); + drawClippedLine(x1 + 1, y1 + 1, x1 + 1, y2 - 1, color2); + drawClippedLine(x1, y2 - 1, x2 - 1, y2 - 1, color2); + } drawClippedLine(x1, y2, x2, y2, color2); - drawClippedLine(x1, y2 - 1, x2 - 1, y2 - 1, color2); showMouse(); } @@ -909,11 +990,13 @@ bool Screen::loadFont(FontId fontId, const char *filename) { error("Invalid font data (file '%s', fontSig: %.04X)", filename, fontSig); fnt->charWidthTable = fontData + READ_LE_UINT16(fontData + 8); - fnt->charSizeOffset = READ_LE_UINT16(fontData + 4); + fnt->fontDescOffset = READ_LE_UINT16(fontData + 4); fnt->charBitmapOffset = READ_LE_UINT16(fontData + 6); fnt->charWidthTableOffset = READ_LE_UINT16(fontData + 8); fnt->charHeightTableOffset = READ_LE_UINT16(fontData + 0xC); + fnt->lastGlyph = *(fnt->fontData + fnt->fontDescOffset + 3); + return true; } @@ -927,23 +1010,30 @@ int Screen::getFontHeight() const { // FIXME: add font support for amiga version if (_vm->gameFlags().platform == Common::kPlatformAmiga) return 0; - return *(_fonts[_currentFont].fontData + _fonts[_currentFont].charSizeOffset + 4); + + return *(_fonts[_currentFont].fontData + _fonts[_currentFont].fontDescOffset + 4); } int Screen::getFontWidth() const { // FIXME: add font support for amiga version if (_vm->gameFlags().platform == Common::kPlatformAmiga) return 0; - return *(_fonts[_currentFont].fontData + _fonts[_currentFont].charSizeOffset + 5); + + return *(_fonts[_currentFont].fontData + _fonts[_currentFont].fontDescOffset + 5); } int Screen::getCharWidth(uint16 c) const { // FIXME: add font support for amiga version if (_vm->gameFlags().platform == Common::kPlatformAmiga) return 0; + if (c & 0xFF00) return SJIS_CHARSIZE >> 1; - return (int)_fonts[_currentFont].charWidthTable[c] + _charWidth; + + if (_fonts[_currentFont].lastGlyph < c) + return 0; + else + return (int)_fonts[_currentFont].charWidthTable[c] + _charWidth; } int Screen::getTextWidth(const char *str) const { @@ -986,8 +1076,7 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2 cmap[1] = color1; setTextColor(cmap, 0, 1); - Font *fnt = &_fonts[_currentFont]; - const uint8 charHeightFnt = *(fnt->fontData + fnt->charSizeOffset + 4); + const uint8 charHeightFnt = getFontHeight(); uint8 charHeight = 0; if (x < 0) @@ -1037,6 +1126,10 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2 void Screen::drawCharANSI(uint8 c, int x, int y) { Font *fnt = &_fonts[_currentFont]; + + if (c > fnt->lastGlyph) + return; + uint8 *dst = getPagePtr(_curPage) + y * SCREEN_W + x; uint16 bitmapOffset = READ_LE_UINT16(fnt->fontData + fnt->charBitmapOffset + c * 2); @@ -1044,15 +1137,16 @@ void Screen::drawCharANSI(uint8 c, int x, int y) { return; uint8 charWidth = *(fnt->fontData + fnt->charWidthTableOffset + c); - if (charWidth + x > SCREEN_W) + if (!charWidth || charWidth + x > SCREEN_W) return; - uint8 charH0 = *(fnt->fontData + fnt->charSizeOffset + 4); - if (charH0 + y > SCREEN_H) + uint8 charH0 = getFontHeight(); + if (!charH0 || charH0 + y > SCREEN_H) return; uint8 charH1 = *(fnt->fontData + fnt->charHeightTableOffset + c * 2); uint8 charH2 = *(fnt->fontData + fnt->charHeightTableOffset + c * 2 + 1); + charH0 -= charH1 + charH2; const uint8 *src = fnt->fontData + bitmapOffset; @@ -1097,15 +1191,17 @@ void Screen::drawCharANSI(uint8 c, int x, int y) { } if (_curPage == 0 || _curPage == 1) - addDirtyRect(x, y, charWidth, *(fnt->fontData + fnt->charSizeOffset + 4)); + addDirtyRect(x, y, charWidth, getFontHeight()); } void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...) { if (!shapeData) return; - int f = _vm->gameFlags().useAltShapeHeader ? 2 : 0; - if (shapeData[f] & 1) + if (_vm->gameFlags().useAltShapeHeader) + shapeData += 2; + + if (*shapeData & 1) flags |= 0x400; va_list args; @@ -1115,11 +1211,6 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int 1, 3, 2, 5, 4, 3, 2, 1 }; - _drawShapeVar1 = 0; - _drawShapeVar3 = 1; - _drawShapeVar4 = 0; - _drawShapeVar5 = 0; - _dsTable = 0; _dsTableLoopCount = 0; _dsTable2 = 0; @@ -1145,8 +1236,8 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } if (flags & 0x200) { - _drawShapeVar1 += 1; - _drawShapeVar1 &= 7; + ++_drawShapeVar1; + _drawShapeVar1 &= (_vm->gameFlags().gameID == GI_KYRA1) ? 0x7 : 0xF; _drawShapeVar3 = drawShapeVar2[_drawShapeVar1]; _drawShapeVar4 = 0; _drawShapeVar5 = 256; @@ -1237,12 +1328,12 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int int scaleCounterV = 0; - f = flags & 0x0f; - _dsProcessMargin = dsMarginFunc[f]; - _dsScaleSkip = dsSkipFunc[f]; - _dsProcessLine = dsLineFunc[f]; + const int drawFunc = flags & 0x0f; + _dsProcessMargin = dsMarginFunc[drawFunc]; + _dsScaleSkip = dsSkipFunc[drawFunc]; + _dsProcessLine = dsLineFunc[drawFunc]; - int ppc = (flags >> 8) & 0x3F; + const int ppc = (flags >> 8) & 0x3F; _dsPlot = dsPlotFunc[ppc]; DsPlotFunc dsPlot2 = dsPlotFunc[ppc], dsPlot3 = dsPlotFunc[ppc]; if (flags & 0x800) @@ -1274,8 +1365,6 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int int y2 = y1 + dsDim->h; - if (_vm->gameFlags().useAltShapeHeader) - src += 2; uint16 shapeFlags = READ_LE_UINT16(src); src += 2; int shapeHeight = *src++; @@ -1318,8 +1407,6 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int int t = (flags & 2) ? y2 - y - shapeHeight : y - y1; - const uint8 *s = src; - if (t < 0) { shapeHeight += t; if (shapeHeight <= 0) { @@ -1328,23 +1415,29 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } t *= -1; - uint8 *tmp = dst; + const uint8 *srcBackUp = 0; do { _dsOffscreenScaleVal1 = 0; + srcBackUp = src; _dsTmpWidth = shapeWidth; + int cnt = shapeWidth; - (this->*_dsScaleSkip)(tmp, s, cnt); + (this->*_dsScaleSkip)(dst, src, cnt); + scaleCounterV += _dsScaleH; - if (!(scaleCounterV & 0xff00)) - continue; - uint8 r = scaleCounterV >> 8; - scaleCounterV &= 0xff; - t -= r; - } while (t > 0); - - if (t < 0) + + if (scaleCounterV & 0xFF00) { + uint8 r = scaleCounterV >> 8; + scaleCounterV &= 0xFF; + t -= r; + } + } while (!(scaleCounterV & 0xFF00) && (t > 0)); + + if (t < 0) { + src = srcBackUp; scaleCounterV += (-t << 8); + } if (!(flags & 2)) y = y1; @@ -1409,6 +1502,9 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int _dsOffscreenLeft /= _dsScaleW; } + if (shapeHeight <= 0 || shpWidthScaled1 <= 0) + return; + if (pageNum == 0 || pageNum == 1) addDirtyRect(x, y, shpWidthScaled1, shapeHeight); clearOverlayRect(pageNum, x, y, shpWidthScaled1, shapeHeight); @@ -1422,28 +1518,28 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int if (!(scaleCounterV & 0xFF00)) { _dsTmpWidth = shapeWidth; int cnt = shapeWidth; - (this->*_dsScaleSkip)(d, s, cnt); + (this->*_dsScaleSkip)(d, src, cnt); } } - const uint8 *b_src = s; + const uint8 *b_src = src; do { - s = b_src; + src = b_src; _dsTmpWidth = shapeWidth; int cnt = _dsOffscreenLeft; - int scaleState = (this->*_dsProcessMargin)(d, s, cnt); + int scaleState = (this->*_dsProcessMargin)(d, src, cnt); if (_dsTmpWidth) { cnt += shpWidthScaled1; if (cnt > 0) { if (flags & 0x800) normalPlot = (curY > _maskMinY && curY < _maskMaxY); _dsPlot = normalPlot ? dsPlot2 : dsPlot3; - (this->*_dsProcessLine)(d, s, cnt, scaleState); + (this->*_dsProcessLine)(d, src, cnt, scaleState); } cnt += _dsOffscreenRight; if (cnt) - (this->*_dsScaleSkip)(d, s, cnt); + (this->*_dsScaleSkip)(d, src, cnt); } dst += dsPitch; d = dst; @@ -2492,9 +2588,14 @@ void Screen::hideMouse() { } void Screen::showMouse() { - if (_mouseLockCount == 1) + if (_mouseLockCount == 1) { CursorMan.showMouse(true); + // We need to call OSystem::updateScreen here, else the mouse cursor + // will only be visible on mouse movment. + _system->updateScreen(); + } + if (_mouseLockCount > 0) _mouseLockCount--; } @@ -2531,12 +2632,11 @@ void Screen::setMouseCursor(int x, int y, const byte *shape) { y <<= 1; mouseWidth <<= 1; mouseHeight <<= 1; - fillRect(mouseWidth, 0, mouseWidth, mouseHeight, 0, 8); } uint8 *cursor = new uint8[mouseHeight * mouseWidth]; - fillRect(0, 0, mouseWidth, mouseHeight, 0, 8); + fillRect(0, 0, mouseWidth, mouseHeight, _cursorColorKey, 8); drawShape(8, shape, 0, 0, 0, 0); int xOffset = 0; @@ -2544,11 +2644,14 @@ void Screen::setMouseCursor(int x, int y, const byte *shape) { if (_vm->gameFlags().useHiResOverlay) { xOffset = mouseWidth; scale2x(getPagePtr(8) + mouseWidth, SCREEN_W, getPagePtr(8), SCREEN_W, mouseWidth, mouseHeight); + postProcessCursor(getPagePtr(8) + mouseWidth, mouseWidth, mouseHeight, SCREEN_W); + } else { + postProcessCursor(getPagePtr(8), mouseWidth, mouseHeight, SCREEN_W); } CursorMan.showMouse(false); copyRegionToBuffer(8, xOffset, 0, mouseWidth, mouseHeight, cursor); - CursorMan.replaceCursor(cursor, mouseWidth, mouseHeight, x, y, 0); + CursorMan.replaceCursor(cursor, mouseWidth, mouseHeight, x, y, _cursorColorKey); if (isMouseVisible()) CursorMan.showMouse(true); delete[] cursor; @@ -2560,12 +2663,13 @@ void Screen::setMouseCursor(int x, int y, const byte *shape) { _system->updateScreen(); } -uint8 *Screen::getPalette(int num) { - assert(num >= 0 && num < (_vm->gameFlags().platform == Common::kPlatformAmiga ? 6 : 4)); - if (num == 0) - return _currentPalette; +Palette &Screen::getPalette(int num) { + assert(num >= 0 && (uint)num < _palettes.size()); + return *_palettes[num]; +} - return _palettes[num-1]; +void Screen::copyPalette(const int dst, const int src) { + getPalette(dst).copy(getPalette(src)); } byte Screen::getShapeFlag1(int x, int y) { @@ -2685,7 +2789,7 @@ void Screen::shakeScreen(int times) { } } -void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *palData, bool skip) { +void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip) { uint32 fileSize; uint8 *srcData = _vm->resource()->fileData(filename, &fileSize); @@ -2702,9 +2806,8 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 * uint32 imgSize = scumm_stricmp(ext, "CMP") ? READ_LE_UINT32(srcData + 4) : READ_LE_UINT16(srcData); uint16 palSize = READ_LE_UINT16(srcData + 8); - if (palData && palSize) { - loadPalette(srcData + 10, palData, palSize); - } + if (pal && palSize) + loadPalette(srcData + 10, *pal, palSize); uint8 *srcPtr = srcData + 10 + palSize; uint8 *dstData = getPagePtr(dstPage); @@ -2738,38 +2841,62 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 * delete[] srcData; } -bool Screen::loadPalette(const char *filename, uint8 *palData) { - uint32 fileSize = 0; - uint8 *srcData = _vm->resource()->fileData(filename, &fileSize); - if (!srcData) +bool Screen::loadPalette(const char *filename, Palette &pal) { + Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename); + + if (!stream) return false; - if (palData && fileSize) { - loadPalette(srcData, palData, fileSize); - } - delete[] srcData; + debugC(3, kDebugLevelScreen, "Screen::loadPalette('%s', %p)", filename, (const void *)&pal); + + if (_vm->gameFlags().platform == Common::kPlatformAmiga) + pal.loadAmigaPalette(*stream, 0, stream->size() / Palette::kAmigaBytesPerColor); + else if (_vm->gameFlags().platform == Common::kPlatformPC98 && _use16ColorMode) + pal.loadPC98Palette(*stream, 0, stream->size() / Palette::kPC98BytesPerColor); + else + pal.loadVGAPalette(*stream, 0, stream->size() / Palette::kVGABytesPerColor); + + delete stream; return true; } -void Screen::loadPalette(const byte *data, uint8 *palData, int bytes) { +bool Screen::loadPaletteTable(const char *filename, int firstPalette) { + Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename); + + if (!stream) + return false; + + debugC(3, kDebugLevelScreen, "Screen::loadPaletteTable('%s', %d)", filename, firstPalette); + if (_vm->gameFlags().platform == Common::kPlatformAmiga) { - assert(bytes % 2 == 0); - assert(bytes / 2 <= 256); - bytes >>= 1; - const uint16 *src = (const uint16 *)data; - for (int i = 0; i < bytes; ++i) { - uint16 col = READ_BE_UINT16(src); ++src; - palData[2] = (col & 0xF) << 2; col >>= 4; - palData[1] = (col & 0xF) << 2; col >>= 4; - palData[0] = (col & 0xF) << 2; col >>= 4; - palData += 3; - } - } else if (_use16ColorMode) { - for (int i = 0; i < bytes; ++i) - palData[i] = ((data[i] & 0xF) << 4) | (data[i] & 0xF0); + const int numColors = getPalette(firstPalette).getNumColors(); + const int palSize = getPalette(firstPalette).getNumColors() * Palette::kAmigaBytesPerColor; + const int numPals = stream->size() / palSize; + + for (int i = 0; i < numPals; ++i) + getPalette(i + firstPalette).loadAmigaPalette(*stream, 0, numColors); } else { - memcpy(palData, data, bytes); + const int numColors = getPalette(firstPalette).getNumColors(); + const int palSize = getPalette(firstPalette).getNumColors() * Palette::kVGABytesPerColor; + const int numPals = stream->size() / palSize; + + for (int i = 0; i < numPals; ++i) + getPalette(i + firstPalette).loadVGAPalette(*stream, 0, numColors); } + + delete stream; + return true; +} + +void Screen::loadPalette(const byte *data, Palette &pal, int bytes) { + Common::MemoryReadStream stream(data, bytes, false); + + if (_vm->gameFlags().platform == Common::kPlatformAmiga) + pal.loadAmigaPalette(stream, 0, stream.size() / Palette::kAmigaBytesPerColor); + else if (_vm->gameFlags().platform == Common::kPlatformPC98 && _use16ColorMode) + pal.loadPC98Palette(stream, 0, stream.size() / Palette::kPC98BytesPerColor); + else + pal.loadVGAPalette(stream, 0, stream.size() / Palette::kVGABytesPerColor); } // dirty rect handling @@ -2967,8 +3094,17 @@ int SJIStoFMTChunk(int f, int s) { // copied from scumm\charset.cpp } // end of anonymous namespace void Screen::drawCharSJIS(uint16 c, int x, int y) { - int color1 = _textColorsMap[1]; - int color2 = _textColorsMap[0]; + int color1, color2; + + if (_use16ColorMode) { + // PC98 16 color games specify a color value which is for the + // PC98 text mode palette, thus we need to remap it. + color1 = ((_textColorsMap[1] >> 5) & 0x7) + 16; + color2 = ((_textColorsMap[0] >> 5) & 0x7) + 16; + } else { + color1 = _textColorsMap[1]; + color2 = _textColorsMap[0]; + } memset(_sjisTempPage2, _sjisInvisibleColor, 324); memset(_sjisSourceChar, 0, 36); @@ -3139,5 +3275,102 @@ void Screen::drawCharSJIS(uint16 c, int x, int y) { #pragma mark - +Palette::Palette(const int numColors) : _palData(0), _numColors(numColors) { + _palData = new uint8[numColors * 3]; + assert(_palData); + + memset(_palData, 0, numColors * 3); +} + +Palette::~Palette() { + delete[] _palData; + _palData = 0; +} + +void Palette::loadVGAPalette(Common::ReadStream &stream, int startIndex, int colors) { + assert(startIndex + colors <= _numColors); + + stream.read(_palData + startIndex * 3, colors * 3); +} + +void Palette::loadAmigaPalette(Common::ReadStream &stream, int startIndex, int colors) { + assert(startIndex + colors <= _numColors); + + for (int i = 0; i < colors; ++i) { + uint16 col = stream.readUint16BE(); + _palData[(i + startIndex) * 3 + 2] = ((col & 0xF) * 0xFF) / 0x3F; col >>= 4; + _palData[(i + startIndex) * 3 + 1] = ((col & 0xF) * 0xFF) / 0x3F; col >>= 4; + _palData[(i + startIndex) * 3 + 0] = ((col & 0xF) * 0xFF) / 0x3F; col >>= 4; + } +} + +void Palette::loadPC98Palette(Common::ReadStream &stream, int startIndex, int colors) { + assert(startIndex + colors <= _numColors); + + for (int i = 0; i < colors; ++i) { + const byte g = stream.readByte(), r = stream.readByte(), b = stream.readByte(); + + _palData[(i + startIndex) * 3 + 0] = ((r & 0x0F) * 0x3F) / 0x0F; + _palData[(i + startIndex) * 3 + 1] = ((g & 0x0F) * 0x3F) / 0x0F; + _palData[(i + startIndex) * 3 + 2] = ((b & 0x0F) * 0x3F) / 0x0F; + } +} + +void Palette::clear() { + memset(_palData, 0, _numColors * 3); +} + +void Palette::fill(int firstCol, int numCols, uint8 value) { + assert(firstCol >= 0 && firstCol + numCols <= _numColors); + + memset(_palData + firstCol * 3, CLIP<int>(value, 0, 63), numCols * 3); +} + +void Palette::copy(const Palette &source, int firstCol, int numCols, int dstStart) { + if (numCols == -1) + numCols = MIN(source.getNumColors(), _numColors) - firstCol; + if (dstStart == -1) + dstStart = firstCol; + + assert(numCols >= 0 && numCols <= _numColors); + assert(firstCol >= 0 && firstCol <= source.getNumColors()); + assert(dstStart >= 0 && dstStart + numCols <= _numColors); + + memcpy(_palData + dstStart * 3, source._palData + firstCol * 3, numCols * 3); +} + +void Palette::copy(const uint8 *source, int firstCol, int numCols, int dstStart) { + if (source == _palData) + return; + + if (dstStart == -1) + dstStart = firstCol; + + assert(numCols >= 0 && numCols <= _numColors); + assert(firstCol >= 0); + assert(dstStart >= 0 && dstStart + numCols <= _numColors); + + memcpy(_palData + dstStart * 3, source + firstCol * 3, numCols * 3); +} + +uint8 *Palette::fetchRealPalette() const { + uint8 *buffer = new uint8[_numColors * 3]; + assert(buffer); + + uint8 *dst = buffer; + const uint8 *palData = _palData; + + for (int i = 0; i < _numColors; ++i) { + dst[0] = (palData[0] << 2) | (palData[0] & 3); + dst[1] = (palData[1] << 2) | (palData[1] & 3); + dst[2] = (palData[2] << 2) | (palData[2] & 3); + + dst += 3; + palData += 3; + } + + return buffer; +} + } // End of namespace Kyra diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index 1691c73a90..390d058bb8 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -29,7 +29,9 @@ #include "common/util.h" #include "common/func.h" #include "common/list.h" +#include "common/array.h" #include "common/rect.h" +#include "common/stream.h" class OSystem; @@ -53,10 +55,112 @@ struct ScreenDim { struct Font { uint8 *fontData; uint8 *charWidthTable; - uint16 charSizeOffset; + uint16 fontDescOffset; uint16 charBitmapOffset; uint16 charWidthTableOffset; uint16 charHeightTableOffset; + + uint8 lastGlyph; +}; + +/** + * A class that manages KYRA palettes. + * + * This class stores the palette data as VGA RGB internally. + */ +class Palette { +public: + Palette(const int numColors); + ~Palette(); + + enum { + kVGABytesPerColor = 3, + kPC98BytesPerColor = 3, + kAmigaBytesPerColor = 2 + }; + + /** + * Load a VGA palette from the given stream. + */ + void loadVGAPalette(Common::ReadStream &stream, int startIndex, int colors); + + /** + * Load a AMIGA palette from the given stream. + */ + void loadAmigaPalette(Common::ReadStream &stream, int startIndex, int colors); + + /** + * Load a PC98 16 color palette from the given stream. + */ + void loadPC98Palette(Common::ReadStream &stream, int startIndex, int colors); + + /** + * Return the number of colors this palette manages. + */ + int getNumColors() const { return _numColors; } + + /** + * Set all palette colors to black. + */ + void clear(); + + /** + * Fill the given indexes with the given component value. + * + * @param firstCol the first color, which should be overwritten. + * @param numCols number of colors, which schould be overwritten. + * @param value color component value, which should be stored. + */ + void fill(int firstCol, int numCols, uint8 value); + + /** + * Copy data from another palette. + * + * @param source palette to copy data from. + * @param firstCol the first color of the source which should be copied. + * @param numCols number of colors, which should be copied. -1 all remaining colors. + * @param dstStart the first color, which should be ovewritten. If -1 firstCol will be used as start. + */ + void copy(const Palette &source, int firstCol = 0, int numCols = -1, int dstStart = -1); + + /** + * Copy data from a raw VGA palette. + * + * @param source source buffer + * @param firstCol the first color of the source which should be copied. + * @param numCols number of colors, which should be copied. + * @param dstStart the first color, which should be ovewritten. If -1 firstCol will be used as start. + */ + void copy(const uint8 *source, int firstCol, int numCols, int dstStart = -1); + + /** + * Fetch a RGB palette. + * + * @return a pointer to the RGB palette data, the client must delete[] it. + */ + uint8 *fetchRealPalette() const; + + //XXX + uint8 &operator[](const int index) { + assert(index >= 0 && index <= _numColors * 3); + return _palData[index]; + } + + const uint8 &operator[](const int index) const { + assert(index >= 0 && index <= _numColors * 3); + return _palData[index]; + } + + /** + * Gets raw access to the palette. + * + * TODO: Get rid of this. + */ + uint8 *getData() { return _palData; } + const uint8 *getData() const { return _palData; } +private: + uint8 *_palData; + const int _numColors; }; class Screen { @@ -110,12 +214,11 @@ public: // page cur. functions int setCurPage(int pageNum); - - void copyFromCurPageBlock(int x, int y, int w, int h, const uint8 *src); - void copyCurPageBlock(int x, int y, int w, int h, uint8 *dst); - void clearCurPage(); + void copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src, + int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2); + // page 0 functions void copyToPage0(int y, int h, uint8 page, uint8 *seqBuf); void shakeScreen(int times); @@ -142,21 +245,25 @@ public: void fadeFromBlack(int delay=0x54, const UpdateFunctor *upFunc = 0); void fadeToBlack(int delay=0x54, const UpdateFunctor *upFunc = 0); - void fadePalette(const uint8 *palData, int delay, const UpdateFunctor *upFunc = 0); - virtual void getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff); - int fadePalStep(const uint8 *palette, int diff); + virtual void fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc = 0); + virtual void getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff); + virtual int fadePalStep(const Palette &pal, int diff); void setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue); - void setScreenPalette(const uint8 *palData); - const uint8 *getScreenPalette() const { return _screenPalette; } + virtual void setScreenPalette(const Palette &pal); void getRealPalette(int num, uint8 *dst); - uint8 *getPalette(int num); + Palette &getPalette(int num); + void copyPalette(const int dst, const int src); // gui specific (processing on _curPage) + enum ShadeType { + kShadeTypeKyra, + kShadeTypeLol + }; void drawLine(bool vertical, int x, int y, int length, int color); void drawClippedLine(int x1, int y1, int x2, int y2, int color); - void drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2); + void drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2, ShadeType shadeType = kShadeTypeKyra); void drawBox(int x1, int y1, int x2, int y2, int color); // font/text handling @@ -199,10 +306,11 @@ public: void rectClip(int &x, int &y, int w, int h); // misc - void loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *palData, bool skip=false); + void loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip=false); - bool loadPalette(const char *filename, uint8 *palData); - void loadPalette(const byte *data, uint8 *palData, int bytes); + bool loadPalette(const char *filename, Palette &pal); + bool loadPaletteTable(const char *filename, int firstPalette); + void loadPalette(const byte *data, Palette &pal, int bytes); void setAnimBlockPtr(int size); @@ -220,7 +328,6 @@ public: int _charWidth; int _charOffset; int _curPage; - uint8 *_currentPalette; uint8 *_shapePages[2]; int _maskMinY, _maskMaxY; FontId _currentFont; @@ -231,6 +338,7 @@ public: static uint decodeFrame4(const uint8 *src, uint8 *dst, uint32 dstSize); static void decodeFrameDelta(uint8 *dst, const uint8 *src, bool noXor = false); static void decodeFrameDeltaPage(uint8 *dst, const uint8 *src, const int pitch, bool noXor); + static void convertAmigaGfx(uint8 *data, int w, int h, bool offscreen = true); static void convertAmigaMsc(uint8 *data); @@ -240,7 +348,7 @@ protected: void updateDirtyRectsOvl(); void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h); - void mergeOverlay(int x, int y, int w, int h); + virtual void mergeOverlay(int x, int y, int w, int h); // overlay specific byte *getOverlayPtr(int pageNum); @@ -275,8 +383,9 @@ protected: uint8 *_sjisSourceChar; uint8 _sjisInvisibleColor; - uint8 *_screenPalette; - uint8 *_palettes[6]; + Palette *_screenPalette; + Common::Array<Palette *> _palettes; + Palette *_internFadePalette; Font _fonts[FID_NUM]; uint8 _textColorsMap[16]; @@ -287,7 +396,11 @@ protected: uint8 *_animBlockPtr; int _animBlockSize; + // mouse handling int _mouseLockCount; + const uint8 _cursorColorKey; + + virtual void postProcessCursor(uint8 *data, int w, int h, int pitch) {}; enum { kMaxDirtyRects = 50 diff --git a/engines/kyra/screen_hof.cpp b/engines/kyra/screen_hof.cpp index 206f8beb87..516cb5bc41 100644 --- a/engines/kyra/screen_hof.cpp +++ b/engines/kyra/screen_hof.cpp @@ -44,8 +44,8 @@ const ScreenDim *Screen_HoF::getScreenDim(int dim) { return &_screenDimTable[dim]; } -void Screen_HoF::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag) { - uint8 tmpPal[768]; +void Screen_HoF::generateGrayOverlay(const Palette &srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag) { + Palette tmpPal(lastColor); for (int i = 0; i != lastColor; i++) { if (flag) { @@ -63,7 +63,7 @@ void Screen_HoF::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, in } for (int i = 0; i < lastColor; i++) - grayOverlay[i] = findLeastDifferentColor(tmpPal + 3 * i, srcPal, lastColor); + grayOverlay[i] = findLeastDifferentColor(tmpPal.getData() + 3 * i, srcPal, 0, lastColor); } void Screen_HoF::cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int srcY, int dstPage, int dstW, diff --git a/engines/kyra/screen_hof.h b/engines/kyra/screen_hof.h index 088e8b7f55..1c17a424b3 100644 --- a/engines/kyra/screen_hof.h +++ b/engines/kyra/screen_hof.h @@ -41,7 +41,7 @@ public: const ScreenDim *getScreenDim(int dim); // sequence player - void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag); + void generateGrayOverlay(const Palette &pal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag); void cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int srcY, int dstPage, int dstW, int dstH, int dstX, int dstY, int cmpW, int cmpH, int cmpPage); void copyPageMemory(int srcPage, int srcPos, int dstPage, int dstPos, int numBytes); void copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int dstX,int dstY, int dstW, int dstH, const ScreenDim *d, bool flag = false); diff --git a/engines/kyra/screen_lok.cpp b/engines/kyra/screen_lok.cpp index 6d97db2f28..9fdeae1398 100644 --- a/engines/kyra/screen_lok.cpp +++ b/engines/kyra/screen_lok.cpp @@ -26,8 +26,9 @@ #include "kyra/kyra_lok.h" #include "kyra/screen_lok.h" -namespace Kyra { +#include "graphics/cursorman.h" +namespace Kyra { Screen_LoK::Screen_LoK(KyraEngine_LoK *vm, OSystem *system) : Screen(vm, system) { @@ -80,13 +81,15 @@ const ScreenDim *Screen_LoK::getScreenDim(int dim) { void Screen_LoK::fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime) { assert(_vm->palTable1()[palIndex]); - assert(_currentPalette); - uint8 tempPal[768]; - memcpy(tempPal, _currentPalette, 768); - memcpy(&tempPal[startIndex*3], _vm->palTable1()[palIndex], size*3); + + Palette tempPal(getPalette(0).getNumColors()); + tempPal.copy(getPalette(0)); + tempPal.copy(_vm->palTable1()[palIndex], 0, size, startIndex); + fadePalette(tempPal, fadeTime*18); - memcpy(&_currentPalette[startIndex*3], &tempPal[startIndex*3], size*3); - setScreenPalette(_currentPalette); + + getPalette(0).copy(tempPal, startIndex, size); + setScreenPalette(getPalette(0)); _system->updateScreen(); } @@ -237,4 +240,200 @@ int Screen_LoK::getRectSize(int x, int y) { return ((x*y) << 3); } +#pragma mark - + +Screen_LoK_16::Screen_LoK_16(KyraEngine_LoK *vm, OSystem *system) : Screen_LoK(vm, system) { + memset(_paletteDither, 0, sizeof(_paletteDither)); +} + +void Screen_LoK_16::setScreenPalette(const Palette &pal) { + _screenPalette->copy(pal); + + for (int i = 0; i < 256; ++i) + paletteMap(i, pal[i * 3 + 0] << 2, pal[i * 3 + 1] << 2, pal[i * 3 + 2] << 2); + + set16ColorPalette(_palette16); +} + +void Screen_LoK_16::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc) { + uint8 notBlackFlag = 0; + for (int i = 0; i < 768; ++i) { + if ((*_screenPalette)[i]) + notBlackFlag |= 1; + if (pal[i]) + notBlackFlag |= 2; + } + + if (notBlackFlag == 1 || notBlackFlag == 2) { + bool upFade = false; + + for (int i = 0; i < 768; ++i) { + if ((*_screenPalette)[i] < pal[i]) { + upFade = true; + break; + } + } + + if (upFade) { + for (int i = 0; i < 256; ++i) + paletteMap(i, pal[i * 3 + 0] << 2, pal[i * 3 + 1] << 2, pal[i * 3 + 2] << 2); + _forceFullUpdate = true; + } + + uint8 color16Palette[16 * 3]; + + if (upFade) + memset(color16Palette, 0, sizeof(color16Palette)); + else + memcpy(color16Palette, _palette16, sizeof(color16Palette)); + + set16ColorPalette(color16Palette); + updateScreen(); + + for (int i = 0; i < 16; ++i) { + set16ColorPalette(color16Palette); + + for (int k = 0; k < 48; ++k) { + if (upFade) { + if (color16Palette[k] < _palette16[k]) + ++color16Palette[k]; + } else { + if (color16Palette[k] > 0) + --color16Palette[k]; + } + } + + if (upFunc && upFunc->isValid()) + (*upFunc)(); + else + _system->updateScreen(); + + _vm->delay((delay >> 5) * _vm->tickLength()); + } + } + + setScreenPalette(pal); +} + +void Screen_LoK_16::getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff) { + error("Screen_LoK_16::getFadeParams called"); +} + +int Screen_LoK_16::fadePalStep(const Palette &pal, int diff) { + error("Screen_LoK_16::fadePalStep called"); + return 0; +} + +void Screen_LoK_16::paletteMap(uint8 idx, int r, int g, int b) { + const int red = r; + const int green = g; + const int blue = b; + + uint16 rgbDiff = 1000; + int rDiff = 0, gDiff = 0, bDiff = 0; + + int index1 = -1; + + for (int i = 0; i < 16; ++i) { + const int realR = _palette16[i * 3 + 0] << 4; + const int realG = _palette16[i * 3 + 1] << 4; + const int realB = _palette16[i * 3 + 2] << 4; + + uint16 diff = ABS(r - realR) + ABS(g - realG) + ABS(b - realB); + + if (diff < rgbDiff) { + rgbDiff = diff; + index1 = i; + + rDiff = r - realR; + gDiff = g - realG; + bDiff = b - realB; + } + } + + r = rDiff / 4 + red; + g = gDiff / 4 + green; + b = bDiff / 4 + blue; + + rgbDiff = 1000; + int index2 = -1; + + for (int i = 0; i < 16; ++i) { + const int realR = _palette16[i * 3 + 0] << 4; + const int realG = _palette16[i * 3 + 1] << 4; + const int realB = _palette16[i * 3 + 2] << 4; + + uint16 diff = ABS(r - realR) + ABS(g - realG) + ABS(b - realB); + + if (diff < rgbDiff) { + rgbDiff = diff; + index2 = i; + } + } + + _paletteDither[idx].bestMatch = index1; + _paletteDither[idx].invertMatch = index2; +} + +void Screen_LoK_16::convertTo16Colors(uint8 *page, int w, int h, int pitch, int keyColor) { + const int rowAdd = pitch * 2 - w; + + uint8 *row1 = page; + uint8 *row2 = page + pitch; + + for (int i = 0; i < h; i += 2) { + for (int k = 0; k < w; k += 2) { + if (keyColor == -1 || keyColor != *row1) { + const PaletteDither &dither = _paletteDither[*row1]; + + *row1++ = dither.bestMatch; + *row1++ = dither.invertMatch; + *row2++ = dither.invertMatch; + *row2++ = dither.bestMatch; + } else { + row1 += 2; + row2 += 2; + } + } + + row1 += rowAdd; + row2 += rowAdd; + } +} + +void Screen_LoK_16::mergeOverlay(int x, int y, int w, int h) { + byte *dst = _sjisOverlayPtrs[0] + y * 640 + x; + + // We do a game screen rect to 16 color dithering here. It is + // important that we do not dither the overlay, since else the + // japanese fonts will look wrong. + convertTo16Colors(dst, w, h, 640); + + const byte *src = _sjisOverlayPtrs[1] + y * 640 + x; + + int add = 640 - w; + + while (h--) { + for (x = 0; x < w; ++x, ++dst) { + byte col = *src++; + if (col != _sjisInvisibleColor) + *dst = _paletteDither[col].bestMatch; + } + dst += add; + src += add; + } +} + +void Screen_LoK_16::set16ColorPalette(const uint8 *pal) { + uint8 palette[16 * 4]; + for (int i = 0; i < 16; ++i) { + palette[i * 4 + 0] = (pal[i * 3 + 0] * 0xFF) / 0x0F; + palette[i * 4 + 1] = (pal[i * 3 + 1] * 0xFF) / 0x0F; + palette[i * 4 + 2] = (pal[i * 3 + 2] * 0xFF) / 0x0F; + palette[i * 4 + 3] = 0; + } + + _system->setPalette(palette, 0, 16); +} + } // end of namespace Kyra diff --git a/engines/kyra/screen_lok.h b/engines/kyra/screen_lok.h index d74da66df5..4eb22df374 100644 --- a/engines/kyra/screen_lok.h +++ b/engines/kyra/screen_lok.h @@ -77,6 +77,38 @@ protected: uint8 *_saveLoadPageOvl[8]; }; +class Screen_LoK_16 : public Screen_LoK { +public: + Screen_LoK_16(KyraEngine_LoK *vm, OSystem *system); + + void setScreenPalette(const Palette &pal); + + void fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc = 0); + void getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff); + int fadePalStep(const Palette &pal, int diff); +private: + void updateDirtyRectsOvl(); + + void convertTo16Colors(uint8 *page, int w, int h, int pitch, int keyColor = -1); + void postProcessCursor(uint8 *data, int width, int height, int pitch) { + convertTo16Colors(data, width, height, pitch, _cursorColorKey); + } + void mergeOverlay(int x, int y, int w, int h); + + void set16ColorPalette(const uint8 *pal); + + void paletteMap(uint8 idx, int r, int g, int b); + + struct PaletteDither { + uint8 bestMatch; + uint8 invertMatch; + }; + + PaletteDither _paletteDither[256]; + + static const uint8 _palette16[48]; +}; + } // end of namespace Kyra #endif diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp index 3f3aef72fe..b9bf9961c5 100644 --- a/engines/kyra/screen_lol.cpp +++ b/engines/kyra/screen_lol.cpp @@ -105,7 +105,7 @@ void Screen_LoL::fprintString(const char *format, int x, int y, uint8 col1, uint va_end(vaList); if (flags & 1) - x -= getTextWidth(string) >> 1; + x -= (getTextWidth(string) >> 1); if (flags & 2) x -= getTextWidth(string); @@ -144,8 +144,8 @@ void Screen_LoL::fprintStringIntro(const char *format, int x, int y, uint8 c1, u printText(buffer, x, y, c1, c2); } -void Screen_LoL::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors) { - uint8 tmpPal[768]; +void Screen_LoL::generateGrayOverlay(const Palette &srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors) { + Palette tmpPal(lastColor); for (int i = 0; i != lastColor; i++) { int v = (((srcPal[3 * i] & 0x3f) * factor) / 0x40) + addR; @@ -157,11 +157,11 @@ void Screen_LoL::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, in } for (int i = 0; i < lastColor; i++) - grayOverlay[i] = findLeastDifferentColor(tmpPal + 3 * i, srcPal, lastColor, skipSpecialColors); + grayOverlay[i] = findLeastDifferentColor(tmpPal.getData() + 3 * i, srcPal, 0, lastColor, skipSpecialColors); } -uint8 *Screen_LoL::generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight) { - if (!srcPal || !ovl) +uint8 *Screen_LoL::generateLevelOverlay(const Palette &srcPal, uint8 *ovl, int opColor, int weight) { + if (!ovl) return ovl; if (weight > 255) @@ -186,7 +186,7 @@ uint8 *Screen_LoL::generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opC int m = 0x7fff; int ii = 127; int x = 1; - const uint8 *s = srcPal + 3; + const uint8 *s = srcPal.getData() + 3; do { if (i == x) { @@ -282,14 +282,13 @@ void Screen_LoL::fadeClearSceneWindow(int delay) { if (_fadeFlag == 1) return; - uint8 *tpal = new uint8[768]; + Palette tpal(getPalette(0).getNumColors()); + tpal.copy(getPalette(0), 128); - memcpy(tpal, _currentPalette, 768); - memset(tpal, 0, 384); loadSpecialColors(tpal); fadePalette(tpal, delay); + fillRect(112, 0, 288, 120, 0); - delete[] tpal; _fadeFlag = 1; } @@ -838,18 +837,18 @@ void Screen_LoL::fadeToBlack(int delay, const UpdateFunctor *upFunc) { } void Screen_LoL::fadeToPalette1(int delay) { - loadSpecialColors(_palettes[0]); - fadePalette(_palettes[0], delay); + loadSpecialColors(getPalette(1)); + fadePalette(getPalette(1), delay); _fadeFlag = 0; } -void Screen_LoL::loadSpecialColors(uint8 *destPalette) { - memcpy(destPalette + 0x240, _screenPalette + 0x240, 12); +void Screen_LoL::loadSpecialColors(Palette &dst) { + dst.copy(*_screenPalette, 192, 4); } void Screen_LoL::copyColor(int dstColorIndex, int srcColorIndex) { - uint8 *s = _screenPalette + srcColorIndex * 3; - uint8 *d = _screenPalette + dstColorIndex * 3; + uint8 *s = _screenPalette->getData() + srcColorIndex * 3; + uint8 *d = _screenPalette->getData() + dstColorIndex * 3; memcpy(d, s, 3); uint8 ci[4]; @@ -862,9 +861,9 @@ void Screen_LoL::copyColor(int dstColorIndex, int srcColorIndex) { } bool Screen_LoL::fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedTime, uint32 targetTime) { - uint8 *dst = _screenPalette + 3 * dstColorIndex; - uint8 *src = _screenPalette + 3 * srcColorIndex; - uint8 *p = getPalette(1) + 3 * dstColorIndex; + const uint8 *dst = _screenPalette->getData() + 3 * dstColorIndex; + const uint8 *src = _screenPalette->getData() + 3 * srcColorIndex; + uint8 *p = getPalette(1).getData() + 3 * dstColorIndex; bool res = false; @@ -897,22 +896,21 @@ bool Screen_LoL::fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedT p++; } - uint8 tpal[768]; - memcpy(tpal, _screenPalette, 768); - memcpy(tpal + dstColorIndex * 3, tmpPalEntry, 3); - setScreenPalette(tpal); + _internFadePalette->copy(*_screenPalette); + _internFadePalette->copy(tmpPalEntry, 0, 1, dstColorIndex); + setScreenPalette(*_internFadePalette); updateScreen(); return res; } bool Screen_LoL::fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime) { - uint8 tpal[768]; - uint8 *p1 = _palettes[0]; + Palette &p1 = getPalette(1); bool res = false; for (int i = 0; i < 768; i++) { uint8 out = 0; + if (elapsedTime < targetTime) { int32 d = ((pal2[i] & 0x3f) - (pal1[i] & 0x3f)); if (d) @@ -925,10 +923,10 @@ bool Screen_LoL::fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, u res = false; } - tpal[i] = out; + (*_internFadePalette)[i] = out; } - setScreenPalette(tpal); + setScreenPalette(*_internFadePalette); updateScreen(); return res; @@ -936,7 +934,7 @@ bool Screen_LoL::fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, u uint8 *Screen_LoL::generateFadeTable(uint8 *dst, uint8 *src1, uint8 *src2, int numTabs) { if (!src1) - src1 = _screenPalette; + src1 = _screenPalette->getData(); uint8 *p1 = dst; uint8 *p2 = src1; @@ -949,14 +947,14 @@ uint8 *Screen_LoL::generateFadeTable(uint8 *dst, uint8 *src1, uint8 *src2, int n int16 t = 0; int16 d = 256 / numTabs; - + for (int i = 1; i < numTabs - 1; i++) { p2 = src1; p3 = p1; t += d; for (int ii = 0; ii < 768; ii++) { - int val = (((int8)*p3++ * t) >> 8) + (int8)*p2++; + int16 val = (((int8)*p3++ * t) >> 8) + (int8)*p2++; *dst++ = (uint8)val; } } @@ -972,6 +970,45 @@ uint8 Screen_LoL::getShapePaletteSize(const uint8 *shp) { return shp[10]; } +void Screen_LoL::mergeOverlay(int x, int y, int w, int h) { + // For now we convert to 16 colors on overlay merging. If that gives + // any problems, like Screen functionallity not prepared for the + // format PC98 16 color uses, we'll need to think of a better way. + // + // We must do this before merging the overlay, else the font colors + // will be wrong. + if (_use16ColorMode) + convertPC98Gfx(_sjisOverlayPtrs[0] + y * 640 + x, w, h, 640); + + Screen_v2::mergeOverlay(x, y, w, h); +} + +void Screen_LoL::convertPC98Gfx(uint8 *data, int w, int h, int pitch) { + while (h--) { + for (int i = 0; i < w; ++i) { + *data = _paletteConvTable[*data]; + ++data; + } + + data += pitch - w; + } +} + +void Screen_LoL::postProcessCursor(uint8 *data, int w, int h, int pitch) { + if (!_use16ColorMode) + return; + + while (h--) { + for (int i = 0; i < w; ++i) { + if (*data != _cursorColorKey) + *data = _paletteConvTable[*data]; + ++data; + } + + data += pitch - w; + } +} + } // end of namespace Kyra #endif // ENABLE_LOL diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h index 017af4ba48..db355977f8 100644 --- a/engines/kyra/screen_lol.h +++ b/engines/kyra/screen_lol.h @@ -70,14 +70,14 @@ public: // palette stuff void fadeToBlack(int delay=0x54, const UpdateFunctor *upFunc = 0); void fadeToPalette1(int delay); - void loadSpecialColors(uint8 *destPalette); + void loadSpecialColors(Palette &dst); void copyColor(int dstColorIndex, int srcColorIndex); bool fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedTime, uint32 targetTime); bool fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime); uint8 *generateFadeTable(uint8 *dst, uint8 *src1, uint8 *src2, int numTabs); - void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors); - uint8 *generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight); + void generateGrayOverlay(const Palette &Pal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors); + uint8 *generateLevelOverlay(const Palette &Pal, uint8 *ovl, int opColor, int weight); uint8 *getLevelOverlay(int index) { return _levelOverlays[index]; } void copyBlockAndApplyOverlay(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl); @@ -92,6 +92,9 @@ public: uint8 *_grayOverlay; int _fadeFlag; + // PC98 specific + static void convertPC98Gfx(uint8 *data, int w, int h, int pitch); + private: LoLEngine *_vm; @@ -106,6 +109,10 @@ private: uint8 *_levelOverlays[8]; + static const uint8 _paletteConvTable[256]; + void mergeOverlay(int x, int y, int w, int h); + void postProcessCursor(uint8 *data, int width, int height, int pitch); + // magic atlas void calcBoundariesIntern(int dstX, int dstY, int c, int d); diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp index a4e014e8c1..177d7d66dd 100644 --- a/engines/kyra/screen_v2.cpp +++ b/engines/kyra/screen_v2.cpp @@ -38,39 +38,38 @@ Screen_v2::~Screen_v2() { delete[] _wsaFrameAnimBuffer; } -uint8 *Screen_v2::generateOverlay(const uint8 *palette, uint8 *buffer, int startColor, uint16 factor) { - if (!palette || !buffer) +uint8 *Screen_v2::generateOverlay(const Palette &pal, uint8 *buffer, int startColor, uint16 factor) { + if (!buffer) return buffer; factor = MIN<uint16>(255, factor); factor >>= 1; factor &= 0xFF; - const byte col1 = palette[startColor * 3 + 0]; - const byte col2 = palette[startColor * 3 + 1]; - const byte col3 = palette[startColor * 3 + 2]; + const byte col1 = pal[startColor * 3 + 0]; + const byte col2 = pal[startColor * 3 + 1]; + const byte col3 = pal[startColor * 3 + 2]; uint8 *dst = buffer; *dst++ = 0; for (int i = 1; i != 255; ++i) { uint8 processedPalette[3]; - const uint8 *src = palette + i*3; byte col; - col = *src++; + col = pal[i * 3 + 0]; col -= ((((col - col1) * factor) << 1) >> 8) & 0xFF; processedPalette[0] = col; - col = *src++; + col = pal[i * 3 + 1]; col -= ((((col - col2) * factor) << 1) >> 8) & 0xFF; processedPalette[1] = col; - col = *src++; + col = pal[i * 3 + 2]; col -= ((((col - col3) * factor) << 1) >> 8) & 0xFF; processedPalette[2] = col; - *dst++ = findLeastDifferentColor(processedPalette, palette+3, 255)+1; + *dst++ = findLeastDifferentColor(processedPalette, pal, 1, 255) + 1; } return buffer; @@ -90,7 +89,7 @@ void Screen_v2::applyOverlay(int x, int y, int w, int h, int pageNum, const uint } } -int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColors) { +int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const Palette &pal, uint8 firstColor, uint16 numColors, bool skipSpecialColors) { int m = 0x7fff; int r = 0x101; @@ -98,11 +97,11 @@ int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *p if (skipSpecialColors && i >= 0xc0 && i <= 0xc3) continue; - int v = paletteEntry[0] - *palette++; + int v = paletteEntry[0] - pal[(i + firstColor) * 3 + 0]; int c = v * v; - v = paletteEntry[1] - *palette++; + v = paletteEntry[1] - pal[(i + firstColor) * 3 + 1]; c += (v * v); - v = paletteEntry[2] - *palette++; + v = paletteEntry[2] - pal[(i + firstColor) * 3 + 2]; c += (v * v); if (c <= m) { @@ -114,12 +113,11 @@ int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *p return r; } -void Screen_v2::getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff) { +void Screen_v2::getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff) { int maxDiff = 0; diff = 0; - int len = _use16ColorMode ? 48 : 768; - for (int i = 0; i < len; ++i) { - diff = ABS(palette[i] - _screenPalette[i]); + for (int i = 0; i < pal.getNumColors() * 3; ++i) { + diff = ABS(pal[i] - (*_screenPalette)[i]); maxDiff = MAX(maxDiff, diff); } @@ -137,148 +135,6 @@ void Screen_v2::getFadeParams(const uint8 *palette, int delay, int &delayInc, in } } -void Screen_v2::copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src, - int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2) { - uint8 *dstPtr = getPagePtr(_curPage); - uint8 *origDst = dstPtr; - - const ScreenDim *dim = getScreenDim(dimState); - int dimX1 = dim->sx << 3; - int dimX2 = dim->w << 3; - dimX2 += dimX1; - - int dimY1 = dim->sy; - int dimY2 = dim->h; - dimY2 += dimY1; - - int temp = y - dimY1; - if (temp < 0) { - if ((temp += h) <= 0) - return; - else { - SWAP(temp, h); - y += temp - h; - src += (temp - h) * w; - } - } - - temp = dimY2 - y; - if (temp <= 0) - return; - - if (temp < h) - h = temp; - - int srcOffset = 0; - temp = x - dimX1; - if (temp < 0) { - temp = -temp; - srcOffset = temp; - x += temp; - w -= temp; - } - - int srcAdd = 0; - - temp = dimX2 - x; - if (temp <= 0) - return; - - if (temp < w) { - SWAP(w, temp); - temp -= w; - srcAdd = temp; - } - - dstPtr += y * SCREEN_W + x; - uint8 *dst = dstPtr; - - if (_curPage == 0 || _curPage == 1) - addDirtyRect(x, y, w, h); - - clearOverlayRect(_curPage, x, y, w, h); - - temp = h; - int curY = y; - while (h--) { - src += srcOffset; - ++curY; - int cW = w; - - switch (plotFunc) { - case 0: - memcpy(dst, src, cW); - dst += cW; src += cW; - break; - - case 1: - while (cW--) { - uint8 d = *src++; - uint8 t = unkPtr1[d]; - if (t != 0xFF) - d = unkPtr2[*dst + (t << 8)]; - *dst++ = d; - } - break; - - case 4: - while (cW--) { - uint8 d = *src++; - if (d) - *dst = d; - ++dst; - } - break; - - case 5: - while (cW--) { - uint8 d = *src++; - if (d) { - uint8 t = unkPtr1[d]; - if (t != 0xFF) - d = unkPtr2[*dst + (t << 8)]; - *dst = d; - } - ++dst; - } - break; - - case 8: - case 9: - while (cW--) { - uint8 d = *src++; - uint8 t = _shapePages[0][dst - origDst] & 7; - if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY)) - d = _shapePages[1][dst - origDst]; - *dst++ = d; - } - break; - - case 12: - case 13: - while (cW--) { - uint8 d = *src++; - if (d) { - uint8 t = _shapePages[0][dst - origDst] & 7; - if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY)) - d = _shapePages[1][dst - origDst]; - *dst++ = d; - } else { - d = _shapePages[1][dst - origDst]; - *dst++ = d; - } - } - break; - - default: - break; - } - - dst = (dstPtr += SCREEN_W); - src += srcAdd; - } -} - const uint8 *Screen_v2::getPtrToShape(const uint8 *shpFile, int shape) { uint16 shapes = READ_LE_UINT16(shpFile); diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h index 18bac764ec..3aa726334c 100644 --- a/engines/kyra/screen_v2.h +++ b/engines/kyra/screen_v2.h @@ -37,17 +37,14 @@ public: ~Screen_v2(); // screen page handling - void copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src, - int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2); - void checkedPageUpdate(int srcPage, int dstPage); // palette handling - uint8 *generateOverlay(const uint8 *palette, uint8 *buffer, int color, uint16 factor); + uint8 *generateOverlay(const Palette &pal, uint8 *buffer, int color, uint16 factor); void applyOverlay(int x, int y, int w, int h, int pageNum, const uint8 *overlay); - int findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColors = false); + int findLeastDifferentColor(const uint8 *paletteEntry, const Palette &pal, uint8 firstColor, uint16 numColors, bool skipSpecialColors = false); - virtual void getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff); + virtual void getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff); // shape handling uint8 *getPtrToShape(uint8 *shpFile, int shape); diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp index 9035708f5e..0473f03591 100644 --- a/engines/kyra/script.cpp +++ b/engines/kyra/script.cpp @@ -66,6 +66,42 @@ EMCInterpreter::EMCInterpreter(KyraEngine_v1 *vm) : _vm(vm) { #undef OPCODE } +bool EMCInterpreter::callback(Common::IFFChunk &chunk) { + switch (chunk._type) { + case MKID_BE('TEXT'): + _scriptData->text = new byte[chunk._size]; + assert(_scriptData->text); + if (chunk._stream->read(_scriptData->text, chunk._size) != chunk._size) + error("Couldn't read TEXT chunk from file '%s'", _filename); + break; + + case MKID_BE('ORDR'): + _scriptData->ordr = new uint16[chunk._size >> 1]; + assert(_scriptData->ordr); + if (chunk._stream->read(_scriptData->ordr, chunk._size) != chunk._size) + error("Couldn't read ORDR chunk from file '%s'", _filename); + + for (int i = (chunk._size >> 1) - 1; i >= 0; --i) + _scriptData->ordr[i] = READ_BE_UINT16(&_scriptData->ordr[i]); + break; + + case MKID_BE('DATA'): + _scriptData->data = new uint16[chunk._size >> 1]; + assert(_scriptData->data); + if (chunk._stream->read(_scriptData->data, chunk._size) != chunk._size) + error("Couldn't read DATA chunk from file '%s'", _filename); + + for (int i = (chunk._size >> 1) - 1; i >= 0; --i) + _scriptData->data[i] = READ_BE_UINT16(&_scriptData->data[i]); + break; + + default: + warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk._type), chunk._size, _filename); + } + + return false; +} + bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Common::Array<const Opcode*> *opcodes) { Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename); if (!stream) { @@ -75,47 +111,17 @@ bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Commo memset(scriptData, 0, sizeof(EMCData)); + _scriptData = scriptData; + _filename = filename; + IFFParser iff(*stream); - Common::IFFChunk *chunk = 0; - - while ((chunk = iff.nextChunk()) != 0) { - switch (chunk->id) { - case MKID_BE('TEXT'): - scriptData->text = new byte[chunk->size]; - assert(scriptData->text); - if (chunk->read(scriptData->text, chunk->size) != chunk->size) - error("Couldn't read TEXT chunk from file '%s'", filename); - break; - - case MKID_BE('ORDR'): - scriptData->ordr = new uint16[chunk->size >> 1]; - assert(scriptData->ordr); - if (chunk->read(scriptData->ordr, chunk->size) != chunk->size) - error("Couldn't read ORDR chunk from file '%s'", filename); - - for (int i = (chunk->size >> 1) - 1; i >= 0; --i) - scriptData->ordr[i] = READ_BE_UINT16(&scriptData->ordr[i]); - break; - - case MKID_BE('DATA'): - scriptData->data = new uint16[chunk->size >> 1]; - assert(scriptData->data); - if (chunk->read(scriptData->data, chunk->size) != chunk->size) - error("Couldn't read DATA chunk from file '%s'", filename); - - for (int i = (chunk->size >> 1) - 1; i >= 0; --i) - scriptData->data[i] = READ_BE_UINT16(&scriptData->data[i]); - break; - - default: - warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk->id), chunk->size, filename); - } - } + Common::Functor1Mem< Common::IFFChunk &, bool, EMCInterpreter > c(this, &EMCInterpreter::callback); + iff.parse(c); - if (!scriptData->ordr) + if (!_scriptData->ordr) error("No ORDR chunk found in file: '%s'", filename); - if (!scriptData->data) + if (!_scriptData->data) error("No DATA chunk found in file: '%s'", filename); if (stream->err()) @@ -123,10 +129,10 @@ bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Commo delete stream; - scriptData->sysFuncs = opcodes; + _scriptData->sysFuncs = opcodes; - strncpy(scriptData->filename, filename, 13); - scriptData->filename[12] = 0; + strncpy(_scriptData->filename, filename, 13); + _scriptData->filename[12] = 0; return true; } diff --git a/engines/kyra/script.h b/engines/kyra/script.h index 88bbe86c4d..862cfb7d97 100644 --- a/engines/kyra/script.h +++ b/engines/kyra/script.h @@ -70,7 +70,7 @@ class KyraEngine_v1; class IFFParser : public Common::IFFParser { public: - IFFParser(Common::SeekableReadStream &input) : Common::IFFParser(input) { + IFFParser(Common::ReadStream &input) : Common::IFFParser(&input) { // It seems Westwood missunderstood the 'size' field of the FORM chunk. // // For EMC scripts (type EMC2) it's filesize instead of filesize - 8, @@ -84,9 +84,9 @@ public: // Both lead to some problems in our IFF parser, either reading after the end // of file or producing a "Chunk overread" error message. To work around this // we need to adjust the size field properly. - if (_typeId == MKID_BE('EMC2')) + if (_formType == MKID_BE('EMC2')) _formChunk.size -= 8; - else if (_typeId == MKID_BE('AVFS')) + else if (_formType == MKID_BE('AVFS')) _formChunk.size += 4; } }; @@ -108,6 +108,11 @@ protected: KyraEngine_v1 *_vm; int16 _parameter; + const char *_filename; + EMCData *_scriptData; + + bool callback(Common::IFFChunk &chunk); + typedef void (EMCInterpreter::*OpcodeProc)(EMCState *); struct OpcodeEntry { OpcodeProc proc; diff --git a/engines/kyra/script_hof.cpp b/engines/kyra/script_hof.cpp index b2a581cece..1b8c1d32b3 100644 --- a/engines/kyra/script_hof.cpp +++ b/engines/kyra/script_hof.cpp @@ -146,7 +146,7 @@ int KyraEngine_HoF::o2_meanWhileScene(EMCState *script) { const char *palfile = stackPosString(1); _screen->loadBitmap(cpsfile, 3, 3, 0); - memcpy(_screen->getPalette(2), _screen->_currentPalette, 768); + _screen->copyPalette(2, 0); _screen->loadPalette(palfile, _screen->getPalette(2)); _screen->fillRect(0, 0, 319, 199, 207); _screen->setScreenPalette(_screen->getPalette(2)); @@ -559,14 +559,14 @@ int KyraEngine_HoF::o2_enableAnimObject(EMCState *script) { int KyraEngine_HoF::o2_loadPalette384(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_loadPalette384(%p) ('%s')", (const void *)script, stackPosString(0)); - memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); - _res->loadFileToBuf(stackPosString(0), _screen->getPalette(1), 384); + _screen->copyPalette(1, 0); + _res->loadFileToBuf(stackPosString(0), _screen->getPalette(1).getData(), 384); return 0; } int KyraEngine_HoF::o2_setPalette384(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_setPalette384(%p) ()", (const void *)script); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 384); + _screen->getPalette(0).copy(_screen->getPalette(1), 0, 128); _screen->setScreenPalette(_screen->getPalette(0)); return 0; } @@ -774,13 +774,13 @@ int KyraEngine_HoF::o2_showLetter(EMCState *script) { displayInvWsaLastFrame(); backUpPage0(); - memcpy(_screen->getPalette(2), _screen->getPalette(0), 768); + _screen->copyPalette(2, 0); _screen->clearPage(3); _screen->loadBitmap("_NOTE.CPS", 3, 3, 0); sprintf(filename, "_NTEPAL%.1d.COL", letter+1); - _res->loadFileToBuf(filename, _screen->getPalette(0), 768); + _screen->loadPalette(filename, _screen->getPalette(0)); _screen->fadeToBlack(0x14); @@ -819,7 +819,7 @@ int KyraEngine_HoF::o2_showLetter(EMCState *script) { _screen->hideMouse(); _screen->fadeToBlack(0x14); restorePage0(); - memcpy(_screen->getPalette(0), _screen->getPalette(2), 768); + _screen->copyPalette(0, 2); _screen->fadePalette(_screen->getPalette(0), 0x14); setHandItem(_itemInHand); _screen->showMouse(); @@ -1125,25 +1125,25 @@ int KyraEngine_HoF::o2_resetInputColorCode(EMCState *script) { int KyraEngine_HoF::o2_mushroomEffect(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_mushroomEffect(%p)", (const void *)script); - memcpy(_screen->getPalette(2), _screen->_currentPalette, 768); + _screen->copyPalette(2, 0); for (int i = 1; i < 768; i += 3) - _screen->_currentPalette[i] = 0; + _screen->getPalette(0)[i] = 0; snd_playSoundEffect(106); - _screen->fadePalette(_screen->_currentPalette, 90, &_updateFunctor); - memcpy(_screen->_currentPalette, _screen->getPalette(2), 768); + _screen->fadePalette(_screen->getPalette(0), 90, &_updateFunctor); + _screen->copyPalette(0, 2); for (int i = 0; i < 768; i += 3) { - _screen->_currentPalette[i] = _screen->_currentPalette[i + 1] = 0; - _screen->_currentPalette[i + 2] += (((int8)_screen->_currentPalette[i + 2]) >> 1); - if (_screen->_currentPalette[i + 2] > 63) - _screen->_currentPalette[i + 2] = 63; + _screen->getPalette(0)[i] = _screen->getPalette(0)[i + 1] = 0; + _screen->getPalette(0)[i + 2] += (((int8)_screen->getPalette(0)[i + 2]) >> 1); + if (_screen->getPalette(0)[i + 2] > 63) + _screen->getPalette(0)[i + 2] = 63; } snd_playSoundEffect(106); - _screen->fadePalette(_screen->_currentPalette, 90, &_updateFunctor); + _screen->fadePalette(_screen->getPalette(0), 90, &_updateFunctor); - memcpy(_screen->_currentPalette, _screen->getPalette(2), 768); - _screen->fadePalette(_screen->_currentPalette, 30, &_updateFunctor); + _screen->copyPalette(0, 2); + _screen->fadePalette(_screen->getPalette(0), 30, &_updateFunctor); return 0; } @@ -1262,19 +1262,23 @@ int KyraEngine_HoF::o2_stopSceneAnimation(EMCState *script) { int KyraEngine_HoF::o2_processPaletteIndex(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_processPaletteIndex(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); - uint8 *palette = _screen->getPalette(0); + Palette &palette = _screen->getPalette(0); + const int index = stackPos(0); const bool updatePalette = (stackPos(4) != 0); const int delayTime = stackPos(5); + palette[index*3+0] = (stackPos(1) * 0x3F) / 100; palette[index*3+1] = (stackPos(2) * 0x3F) / 100; palette[index*3+2] = (stackPos(3) * 0x3F) / 100; + if (updatePalette) { if (delayTime > 0) _screen->fadePalette(palette, delayTime, &_updateFunctor); else _screen->setScreenPalette(palette); } + return 0; } @@ -1396,7 +1400,7 @@ int KyraEngine_HoF::o2_demoFinale(EMCState *script) { assert(strings); _screen->clearPage(0); - _screen->loadPalette("THANKS.COL", _screen->_currentPalette); + _screen->loadPalette("THANKS.COL", _screen->getPalette(0)); _screen->loadBitmap("THANKS.CPS", 3, 3, 0); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); @@ -1406,7 +1410,7 @@ int KyraEngine_HoF::o2_demoFinale(EMCState *script) { for (int i = 0; i < 6; i++) _text->printText(strings[i], _text->getCenterStringX(strings[i], 1, 319), y + i * 10, 255, 207, 0); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->setScreenPalette(_screen->getPalette(0)); _screen->updateScreen(); _eventList.clear(); diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp index 03a5d4efc1..849c6b776d 100644 --- a/engines/kyra/script_lok.cpp +++ b/engines/kyra/script_lok.cpp @@ -231,7 +231,8 @@ int KyraEngine_LoK::o1_fadeSpecialPalette(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_fadeSpecialPalette(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); if (_currentCharacter->sceneId != 45) { if (stackPos(0) == 13) { - memcpy(_screen->getPalette(0), _screen->getPalette(0) + 384*3, 32*3); + // TODO: Check this! + _screen->copyPalette(0, 12); _screen->setScreenPalette(_screen->getPalette(0)); } } else { @@ -427,7 +428,7 @@ int KyraEngine_LoK::o1_runWSAFromBeginningToEnd(EMCState *script) { int wsaFrame = 0; while (running) { - _movieObjects[wsaIndex]->displayFrame(wsaFrame++, 0, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(wsaFrame++, 0, xpos, ypos, 0, 0, 0); _animator->_updateScreen = true; if (wsaFrame >= _movieObjects[wsaIndex]->frames()) running = false; @@ -458,7 +459,7 @@ int KyraEngine_LoK::o1_displayWSAFrame(EMCState *script) { int waitTime = stackPos(3); int wsaIndex = stackPos(4); _screen->hideMouse(); - _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos, 0, 0, 0); _animator->_updateScreen = true; uint32 continueTime = waitTime * _tickLength + _system->getMillis(); while (_system->getMillis() < continueTime) { @@ -500,7 +501,7 @@ int KyraEngine_LoK::o1_runWSAFrames(EMCState *script) { _screen->hideMouse(); for (; startFrame <= endFrame; ++startFrame) { uint32 nextRun = _system->getMillis() + delayTime * _tickLength; - _movieObjects[wsaIndex]->displayFrame(startFrame, 0, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(startFrame, 0, xpos, ypos, 0, 0, 0); _animator->_updateScreen = true; while (_system->getMillis() < nextRun) { _sprites->updateSceneAnims(); @@ -578,7 +579,7 @@ int KyraEngine_LoK::o1_restoreAllObjectBackgrounds(EMCState *script) { int KyraEngine_LoK::o1_setCustomPaletteRange(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setCustomPaletteRange(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); - memcpy(_screen->getPalette(1) + stackPos(1)*3, _specialPalettes[stackPos(0)], stackPos(2)*3); + _screen->getPalette(1).copy(_specialPalettes[stackPos(0)], 0, stackPos(2), stackPos(1)); return 0; } @@ -682,7 +683,7 @@ int KyraEngine_LoK::o1_displayWSAFrameOnHidPage(EMCState *script) { _screen->hideMouse(); uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - _movieObjects[wsaIndex]->displayFrame(frame, 2, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(frame, 2, xpos, ypos, 0, 0, 0); _animator->_updateScreen = true; while (_system->getMillis() < continueTime) { _sprites->updateSceneAnims(); @@ -753,7 +754,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { // what shouldn't happen. So we're not updating the screen for this special // case too. if (startFrame == 18 && endFrame == 18 && _currentRoom == 45) { - _movieObjects[wsaIndex]->displayFrame(18, 0, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(18, 0, xpos, ypos, 0, 0, 0); delay(waitTime * _tickLength); return 0; } @@ -765,7 +766,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { int frame = startFrame; while (endFrame >= frame) { uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos, 0, 0, 0); if (waitTime) _animator->_updateScreen = true; while (_system->getMillis() < continueTime) { @@ -783,7 +784,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { int frame = startFrame; while (endFrame <= frame) { uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos, 0, 0, 0); if (waitTime) _animator->_updateScreen = true; while (_system->getMillis() < continueTime) { @@ -912,8 +913,6 @@ int KyraEngine_LoK::o1_placeCharacterInOtherScene(EMCState *script) { int KyraEngine_LoK::o1_getKey(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getKey(%p) ()", (const void *)script); - // TODO: Check this implementation - while (true) { delay(10); @@ -1243,8 +1242,8 @@ int KyraEngine_LoK::o1_setFireberryGlowPalette(EMCState *script) { palIndex = 14; } } - const uint8 *palette = _specialPalettes[palIndex]; - memcpy(_screen->getPalette(1) + 684, palette, 44); + + _screen->getPalette(1).copy(_specialPalettes[palIndex], 0, 15, 228); return 0; } @@ -1276,7 +1275,7 @@ int KyraEngine_LoK::o1_makeAmuletAppear(EMCState *script) { if (code == 14) snd_playSoundEffect(0x73); - amulet.displayFrame(code, 0, 224, 152); + amulet.displayFrame(code, 0, 224, 152, 0, 0, 0); _animator->_updateScreen = true; while (_system->getMillis() < nextTime) { @@ -1501,40 +1500,38 @@ int KyraEngine_LoK::o1_setNoDrawShapesFlag(EMCState *script) { int KyraEngine_LoK::o1_fadeEntirePalette(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_fadeEntirePalette(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); int cmd = stackPos(0); - uint8 *fadePal = 0; + + int fadePal = 0; if (_flags.platform == Common::kPlatformAmiga) { if (cmd == 0) { - fadePal = _screen->getPalette(2); - memset(fadePal, 0, 32*3); - memcpy(_screen->getPalette(4), _screen->getPalette(0), 32*3); + _screen->getPalette(2).clear(); + fadePal = 2; + _screen->copyPalette(4, 0); } else if (cmd == 1) { - fadePal = _screen->getPalette(0); - memcpy(_screen->getPalette(0), _screen->getPalette(4), 32*3); + fadePal = 0; + _screen->copyPalette(0, 4); } else if (cmd == 2) { - fadePal = _screen->getPalette(0); - memset(_screen->getPalette(2), 0, 32*3); + fadePal = 0; + _screen->getPalette(2).clear(); } } else { if (cmd == 0) { - fadePal = _screen->getPalette(2); - uint8 *screenPal = _screen->getPalette(0); - uint8 *backUpPal = _screen->getPalette(3); - - memcpy(backUpPal, screenPal, sizeof(uint8)*768); - memset(fadePal, 0, sizeof(uint8)*768); + fadePal = 2; + _screen->getPalette(2).clear(); + _screen->copyPalette(3, 0); } else if (cmd == 1) { - //fadePal = _screen->getPalette(3); + //fadePal = 3; warning("unimplemented o1_fadeEntirePalette function"); return 0; } else if (cmd == 2) { - memset(_screen->getPalette(2), 0, 768); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); - fadePal = _screen->getPalette(0); + _screen->getPalette(2).clear(); + _screen->copyPalette(0, 1); + fadePal = 0; } } - _screen->fadePalette(fadePal, stackPos(1)); + _screen->fadePalette(_screen->getPalette(fadePal), stackPos(1)); return 0; } diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index 3d57b23181..a606419722 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -609,7 +609,7 @@ int LoLEngine::olol_fadePalette(EMCState *script) { int LoLEngine::olol_loadBitmap(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_clearDialogueField(%p) (%s, %d)", (const void *)script, stackPosString(0), stackPos(1)); - _screen->loadBitmap(stackPosString(0), 3, 3, _screen->getPalette(3)); + _screen->loadBitmap(stackPosString(0), 3, 3, &_screen->getPalette(3)); if (stackPos(1) != 2) _screen->copyPage(3, stackPos(1)); return 1; @@ -663,7 +663,7 @@ int LoLEngine::olol_getGlobalVar(EMCState *script) { case 12: return _drainMagic; case 13: - return _speechFlag; + return getVolume(kVolumeSpeech) - 2; default: break; } @@ -864,7 +864,7 @@ int LoLEngine::olol_fadeClearSceneWindow(EMCState *script) { int LoLEngine::olol_fadeSequencePalette(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_fadeSequencePalette(%p)", (const void *)script); - memcpy(_screen->getPalette(3) + 0x180, _screen->_currentPalette + 0x180, 0x180); + _screen->getPalette(3).copy(_screen->getPalette(0), 128); _screen->loadSpecialColors(_screen->getPalette(3)); _screen->fadePalette(_screen->getPalette(3), 10); _screen->_fadeFlag = 0; @@ -876,7 +876,7 @@ int LoLEngine::olol_redrawPlayfield(EMCState *script) { if (_screen->_fadeFlag != 2) _screen->fadeClearSceneWindow(10); gui_drawPlayField(); - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); _screen->_fadeFlag = 0; return 1; } @@ -1276,7 +1276,7 @@ int LoLEngine::olol_getMonsterStat(EMCState *script) { int LoLEngine::olol_releaseMonsterShapes(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_releaseMonsterShapes(%p)", (const void *)script); for (int i = 0; i < 3; i++) - releaseMonsterShapes(i); + releaseMonsterShapes(i); return 0; } @@ -1399,17 +1399,17 @@ int LoLEngine::olol_playEndSequence(EMCState *script){ if (_characters[0].id == -9) c = 1; else if (_characters[0].id == -5) - c = 3; + c = 3; else if (_characters[0].id == -1) c = 2; while (snd_updateCharacterSpeech()) delay(_tickLength); - + _eventList.clear(); _screen->hideMouse(); - memset(_screen->getPalette(1), 0, 768); - + _screen->getPalette(1).clear(); + showOutro(c, (_monsterDifficulty == 2)); quitGame(); @@ -1428,7 +1428,7 @@ int LoLEngine::olol_setPaletteBrightness(EMCState *script) { uint16 old = _brightness; _brightness = stackPos(0); if (stackPos(1) == 1) - setPaletteBrightness(_screen->_currentPalette, stackPos(0), _lampEffect); + setPaletteBrightness(_screen->getPalette(0), stackPos(0), _lampEffect); return old; } @@ -1994,10 +1994,16 @@ int LoLEngine::olol_findInventoryItem(EMCState *script) { return -1; } +int LoLEngine::olol_drinkBezelCup(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_drinkBezelCup(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + drinkBezelCup(3 - stackPos(0), stackPos(1)); + return 1; +} + int LoLEngine::olol_restoreFadePalette(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_restoreFadePalette(%p)", (const void *)script); - memcpy(_screen->_currentPalette, _screen->getPalette(1), 384); - _screen->fadePalette(_screen->_currentPalette, 10); + _screen->getPalette(0).copy(_screen->getPalette(1), 0, 128); + _screen->fadePalette(_screen->getPalette(0), 10); _screen->_fadeFlag = 0; return 1; } @@ -2095,27 +2101,29 @@ int LoLEngine::olol_increaseSkill(EMCState *script) { int LoLEngine::olol_paletteFlash(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_paletteFlash(%p) (%d)", (const void *)script, stackPos(0)); - uint8 *s = _screen->getPalette(1); - uint8 *d = _screen->getPalette(3); + Palette &p1 = _screen->getPalette(1); + Palette &p2 = _screen->getPalette(3); + uint8 ovl[256]; - generateFlashPalette(s, d, stackPos(0)); - _screen->loadSpecialColors(s); - _screen->loadSpecialColors(d); + generateFlashPalette(p1, p2, stackPos(0)); + _screen->loadSpecialColors(p1); + _screen->loadSpecialColors(p2); if (_smoothScrollModeNormal) { for (int i = 0; i < 256; i++) ovl[i] = i; ovl[1] = 6; + _screen->copyRegion(112, 0, 112, 0, 176, 120, 0, 2); _screen->applyOverlay(112, 0, 176, 120, 0, ovl); } - _screen->setScreenPalette(d); + _screen->setScreenPalette(p2); _screen->updateScreen(); delay(2 * _tickLength); - _screen->setScreenPalette(s); + _screen->setScreenPalette(p1); if (_smoothScrollModeNormal) _screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0); @@ -2126,55 +2134,65 @@ int LoLEngine::olol_paletteFlash(EMCState *script) { int LoLEngine::olol_restoreMagicShroud(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_restoreMagicShroud(%p)", (const void *)script); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); mov->open("DARKLITE.WSA", 2, 0); if (!mov->opened()) return 0; _screen->hideMouse(); + // TODO: This function could need some major cleanup to work with our + // new palette code without needless conversions. uint8 *fadeTab = new uint8[21504]; uint8 *tpal1 = fadeTab; uint8 *tpal2 = tpal1 + 768; uint8 *tpal3 = tpal2 + 768; uint8 *tpal4 = 0; - _screen->loadPalette("LITEPAL1.COL", tpal1); + _res->loadFileToBuf("LITEPAL1.COL", tpal1, 768); tpal2 = _screen->generateFadeTable(tpal3, 0, tpal1, 21); - _screen->loadPalette("LITEPAL2.COL", tpal2); + _res->loadFileToBuf("LITEPAL2.COL", tpal2, 768); tpal4 = tpal2; tpal2 += 768; - _screen->loadPalette("LITEPAL3.COL", tpal1); + _res->loadFileToBuf("LITEPAL3.COL", tpal1, 768); _screen->generateFadeTable(tpal2, tpal4, tpal1, 4); + Palette pal(768); + for (int i = 0; i < 21; i++) { uint32 etime = _system->getMillis() + 20 * _tickLength; - mov->displayFrame(i, 0, 0, 0, 0); + mov->displayFrame(i, 0, 0, 0, 0, 0, 0); _screen->updateScreen(); - _screen->setScreenPalette(tpal3); + + pal.copy(tpal3, 0, 256); + _screen->setScreenPalette(pal); tpal3 += 768; + if (i == 2 || i == 5 || i == 8 || i == 11 || i == 13 || i == 15 || i == 17 || i == 19) snd_playSoundEffect(95, -1); delayUntil(etime); } + pal.copy(tpal3, 0, 256); snd_playSoundEffect(91, -1); - _screen->fadePalette(tpal3, 300); + _screen->fadePalette(pal, 300); tpal3 += 768; for (int i = 22; i < 38; i++) { uint32 etime = _system->getMillis() + 12 * _tickLength; - mov->displayFrame(i, 0, 0, 0, 0); + mov->displayFrame(i, 0, 0, 0, 0, 0, 0); _screen->updateScreen(); if (i == 22 || i == 24 || i == 28 || i == 32) { snd_playSoundEffect(131, -1); - _screen->setScreenPalette(tpal3); + + pal.copy(tpal3, 0, 256); + _screen->setScreenPalette(pal); tpal3 += 768; } delayUntil(etime); } mov->close(); - delete mov; + delete mov; delete[] fadeTab; _screen->showMouse(); @@ -2297,7 +2315,7 @@ int LoLEngine::tlol_loadPalette(const TIM *tim, const uint16 *param) { int LoLEngine::tlol_setupPaletteFadeEx(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_setupPaletteFadeEx(%p, %p) (%d)", (const void *)tim, (const void *)param, param[0]); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); + _screen->copyPalette(0, 1); _screen->getFadeParams(_screen->getPalette(0), param[0], _tim->_palDelayInc, _tim->_palDiff); _tim->_palDelayAcc = 0; @@ -2375,7 +2393,6 @@ int LoLEngine::tlol_setPartyPosition(const TIM *tim, const uint16 *param) { int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_fadeClearWindow(%p, %p) (%d)", (const void *)tim, (const void *)param, param[0]); - uint8 *tmp = 0; switch (param[0]) { case 0: @@ -2383,10 +2400,9 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) { break; case 1: - tmp = _screen->getPalette(3); - memcpy(tmp + 0x180, _screen->_currentPalette + 0x180, 0x180); - _screen->loadSpecialColors(tmp); - _screen->fadePalette(tmp, 10); + _screen->getPalette(3).copy(_screen->getPalette(0), 128); + _screen->loadSpecialColors(_screen->getPalette(3)); + _screen->fadePalette(_screen->getPalette(3), 10); _screen->_fadeFlag = 0; break; @@ -2395,9 +2411,8 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) { break; case 3: - tmp = _screen->getPalette(3); - _screen->loadSpecialColors(tmp); - _screen->fadePalette(tmp, 10); + _screen->loadSpecialColors(_screen->getPalette(3)); + _screen->fadePalette(_screen->getPalette(3), 10); _screen->_fadeFlag = 0; break; @@ -2405,13 +2420,12 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) { if (_screen->_fadeFlag != 2) _screen->fadeClearSceneWindow(10); gui_drawPlayField(); - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); _screen->_fadeFlag = 0; break; case 5: - tmp = _screen->getPalette(3); - _screen->loadSpecialColors(tmp); + _screen->loadSpecialColors(_screen->getPalette(3)); _screen->fadePalette(_screen->getPalette(1), 10); _screen->_fadeFlag = 0; break; @@ -2511,7 +2525,7 @@ int LoLEngine::tlol_fadeInScene(const TIM *tim, const uint16 *param) { strcpy(filename, sceneFile); strcat(filename, ".CPS"); - _screen->loadBitmap(filename, 7, 5, _screen->getPalette(0)); + _screen->loadBitmap(filename, 7, 5, &_screen->getPalette(0)); filename[0] = 0; @@ -2547,9 +2561,11 @@ int LoLEngine::tlol_unusedResourceFunc(const TIM *tim, const uint16 *param) { int LoLEngine::tlol_fadeInPalette(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_fadeInPalette(%p, %p) (%d, %d)", (const void *)tim, (const void *)param, param[0], param[1]); const char *bitmap = (const char *)(tim->text + READ_LE_UINT16(tim->text + (param[0]<<1))); - uint8 palette[768]; - _screen->loadBitmap(bitmap, 3, 3, palette); - _screen->fadePalette(palette, param[1]); + + Palette pal(_screen->getPalette(0).getNumColors()); + _screen->loadBitmap(bitmap, 3, 3, &pal); + _screen->fadePalette(pal, param[1]); + return 1; } @@ -2566,7 +2582,7 @@ int LoLEngine::tlol_displayAnimFrame(const TIM *tim, const uint16 *param) { if (param[1] == 0xFFFF) { _screen->copyRegion(0, 0, 0, 0, 320, 200, 0, 2, Screen::CR_NO_P_CHECK); } else { - anim->wsa->displayFrame(param[1], 2, anim->x, anim->y, 0); + anim->wsa->displayFrame(param[1], 2, anim->x, anim->y, 0, 0, 0); _screen->copyRegion(anim->wsa->xAdd(), anim->wsa->yAdd(), anim->wsa->xAdd(), anim->wsa->yAdd(), anim->wsa->width(), anim->wsa->height(), 2, 0); } @@ -2852,7 +2868,7 @@ void LoLEngine::setupOpcodeTable() { // 0xA8 OpcodeUnImpl(); OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(olol_drinkBezelCup); Opcode(olol_changeItemTypeOrFlag); // 0xAC diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp index 558d703f15..1800bd1939 100644 --- a/engines/kyra/script_mr.cpp +++ b/engines/kyra/script_mr.cpp @@ -381,13 +381,10 @@ int KyraEngine_MR::o3_checkInRect(EMCState *script) { y += desc[1]; } - if (x >= x1 && x <= x2 && y >= y1 && y <= y2) { - //XXX + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) return 1; - } else { - //XXX + else return 0; - } } int KyraEngine_MR::o3_updateConversations(EMCState *script) { diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index e9ca23a4c9..424a62aaf8 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -116,6 +116,33 @@ TIMInterpreter::~TIMInterpreter() { delete[] _animations; } +bool TIMInterpreter::callback(Common::IFFChunk &chunk) { + switch (chunk._type) { + case MKID_BE('TEXT'): + _tim->text = new byte[chunk._size]; + assert(_tim->text); + if (chunk._stream->read(_tim->text, chunk._size) != chunk._size) + error("Couldn't read TEXT chunk from file '%s'", _filename); + break; + + case MKID_BE('AVTL'): + _avtlChunkSize = chunk._size >> 1; + _tim->avtl = new uint16[_avtlChunkSize]; + assert(_tim->avtl); + if (chunk._stream->read(_tim->avtl, chunk._size) != chunk._size) + error("Couldn't read AVTL chunk from file '%s'", _filename); + + for (int i = _avtlChunkSize - 1; i >= 0; --i) + _tim->avtl[i] = READ_LE_UINT16(&_tim->avtl[i]); + break; + + default: + warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk._type), chunk._size, _filename); + } + + return false; +} + TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpcode *> *opcodes) { if (!_vm->resource()->exists(filename)) return 0; @@ -124,44 +151,21 @@ TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpc if (!stream) error("Couldn't open TIM file '%s'", filename); - IFFParser iff(*stream); - Common::IFFChunk *chunk = 0; - - TIM *tim = new TIM; - assert(tim); - memset(tim, 0, sizeof(TIM)); + _avtlChunkSize = 0; + _filename = filename; - tim->procFunc = -1; - tim->opcodes = opcodes; + _tim = new TIM; + assert(_tim); + memset(_tim, 0, sizeof(TIM)); - int avtlChunkSize = 0; - - while ((chunk = iff.nextChunk()) != 0) { - switch (chunk->id) { - case MKID_BE('TEXT'): - tim->text = new byte[chunk->size]; - assert(tim->text); - if (chunk->read(tim->text, chunk->size) != chunk->size) - error("Couldn't read TEXT chunk from file '%s'", filename); - break; - - case MKID_BE('AVTL'): - avtlChunkSize = chunk->size >> 1; - tim->avtl = new uint16[avtlChunkSize]; - assert(tim->avtl); - if (chunk->read(tim->avtl, chunk->size) != chunk->size) - error("Couldn't read AVTL chunk from file '%s'", filename); - - for (int i = avtlChunkSize - 1; i >= 0; --i) - tim->avtl[i] = READ_LE_UINT16(&tim->avtl[i]); - break; + _tim->procFunc = -1; + _tim->opcodes = opcodes; - default: - warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk->id), chunk->size, filename); - } - } + IFFParser iff(*stream); + Common::Functor1Mem< Common::IFFChunk &, bool, TIMInterpreter > c(this, &TIMInterpreter::callback); + iff.parse(c); - if (!tim->avtl) + if (!_tim->avtl) error("No AVTL chunk found in file: '%s'", filename); if (stream->err()) @@ -169,17 +173,17 @@ TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpc delete stream; - int num = (avtlChunkSize < TIM::kCountFuncs) ? avtlChunkSize : (int)TIM::kCountFuncs; + int num = (_avtlChunkSize < TIM::kCountFuncs) ? _avtlChunkSize : (int)TIM::kCountFuncs; for (int i = 0; i < num; ++i) - tim->func[i].avtl = tim->avtl + tim->avtl[i]; + _tim->func[i].avtl = _tim->avtl + _tim->avtl[i]; - strncpy(tim->filename, filename, 13); - tim->filename[12] = 0; + strncpy(_tim->filename, filename, 13); + _tim->filename[12] = 0; - tim->isLoLOutro = (_vm->gameFlags().gameID == GI_LOL) && !scumm_stricmp(filename, "LOLFINAL.TIM"); - tim->lolCharacter = 0; + _tim->isLoLOutro = (_vm->gameFlags().gameID == GI_LOL) && !scumm_stricmp(filename, "LOLFINAL.TIM"); + _tim->lolCharacter = 0; - return tim; + return _tim; } void TIMInterpreter::unload(TIM *&tim) const { @@ -300,13 +304,15 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags) { memcpy(filename, text+1, end-1-text); } - if (filename[0]) + const bool isPC98 = (_vm->gameFlags().platform == Common::kPlatformPC98); + if (filename[0] && (_vm->speechEnabled() || isPC98)) _vm->sound()->voicePlay(filename); if (text[0] == '$') text = strchr(text + 1, '$') + 1; - setupTextPalette((flags < 0) ? 1 : flags, 0); + if (!isPC98) + setupTextPalette((flags < 0) ? 1 : flags, 0); if (flags < 0) { static const uint8 colorMap[] = { 0x00, 0xF0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -324,7 +330,7 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags) { char *str = text; int heightAdd = 0; - while (str[0]) { + while (str[0] && _vm->textEnabled()) { char *nextLine = strchr(str, '\r'); backupChar = 0; @@ -335,10 +341,16 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags) { int width = _screen->getTextWidth(str); - if (flags >= 0) - _screen->printText(str, (320 - width) >> 1, 160 + heightAdd, 0xF0, 0x00); - else + if (flags >= 0) { + if (isPC98) { + static const uint8 colorMap[] = { 0xE1, 0xE1, 0xC1, 0xA1, 0x81, 0x61 }; + _screen->printText(str, (320 - width) >> 1, 160 + heightAdd, colorMap[flags], 0x00); + } else { + _screen->printText(str, (320 - width) >> 1, 160 + heightAdd, 0xF0, 0x00); + } + } else { _screen->printText(str, (320 - width) >> 1, 188, 0xF0, 0x00); + } heightAdd += _screen->getFontHeight(); str += strlen(str); @@ -423,7 +435,7 @@ void TIMInterpreter::setupTextPalette(uint index, int fadePalette) { }; for (int i = 0; i < 15; ++i) { - uint8 *palette = _screen->getPalette(0) + (240 + i) * 3; + uint8 *palette = _screen->getPalette(0).getData() + (240 + i) * 3; uint8 c1 = (((15 - i) << 2) * palTable[index*3+0]) / 100; uint8 c2 = (((15 - i) << 2) * palTable[index*3+1]) / 100; @@ -471,10 +483,10 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char if (isLoLDemo) anim->wsa = new WSAMovie_v1(_vm); else - anim->wsa = new WSAMovie_v2(_vm, _screen); + anim->wsa = new WSAMovie_v2(_vm); assert(anim->wsa); - anim->wsa->open(file, wsaOpenFlags, (index == 1) ? _screen->getPalette(0) : 0); + anim->wsa->open(file, wsaOpenFlags, (index == 1) ? &_screen->getPalette(0) : 0); } if (anim->wsa && anim->wsa->opened()) { @@ -511,14 +523,14 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char snprintf(file, 32, "%s.CPS", filename); if (_vm->resource()->exists(file)) { - _screen->loadBitmap(file, 3, 3, _screen->getPalette(0)); + _screen->loadBitmap(file, 3, 3, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, _drawPage2, Screen::CR_NO_P_CHECK); if (_drawPage2) _screen->checkedPageUpdate(8, 4); _screen->updateScreen(); } - anim->wsa->displayFrame(0, 0, x, y, 0); + anim->wsa->displayFrame(0, 0, x, y, 0, 0, 0); } if (wsaFlags & 2) @@ -535,7 +547,7 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char snprintf(file, 32, "%s.CPS", filename); if (_vm->resource()->exists(file)) { - _screen->loadBitmap(file, 3, 3, _screen->getPalette(0)); + _screen->loadBitmap(file, 3, 3, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, _drawPage2, Screen::CR_NO_P_CHECK); if (_drawPage2) _screen->checkedPageUpdate(8, 4); @@ -941,21 +953,21 @@ TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const c snprintf(file, 32, "%s.WSA", filename); if (_vm->resource()->exists(file)) { - anim->wsa = new WSAMovie_v2(_vm, TIMInterpreter::_screen); + anim->wsa = new WSAMovie_v2(_vm); assert(anim->wsa); - anim->wsa->open(file, wsaOpenFlags, _screen->getPalette(3)); + anim->wsa->open(file, wsaOpenFlags, &_screen->getPalette(3)); } if (wsaFlags & 1) { if (_screen->_fadeFlag != 1) _screen->fadeClearSceneWindow(10); - memcpy(_screen->getPalette(3) + 384, _screen->_currentPalette + 384, 384); + _screen->getPalette(3).copy(_screen->getPalette(0), 128, 128); } else if (wsaFlags & 2) { _screen->fadeToBlack(10); } if (wsaFlags & 7) - anim->wsa->displayFrame(0, 0, x, y, 0); + anim->wsa->displayFrame(0, 0, x, y, 0, 0, 0); if (wsaFlags & 3) { _screen->loadSpecialColors(_screen->getPalette(3)); @@ -1000,7 +1012,7 @@ void TIMInterpreter_LoL::advanceToOpcode(int opcode) { void TIMInterpreter_LoL::drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3) { _screen->setScreenDim(5); - if (numStr == 1 && _vm->_speechFlag) { + if (numStr == 1 && _vm->speechEnabled()) { _dialogueNumButtons = 0; _dialogueButtonString[0] = _dialogueButtonString[1] = _dialogueButtonString[2] = 0; } else { @@ -1051,7 +1063,7 @@ void TIMInterpreter_LoL::startBackgroundAnimation(int animIndex, int part) { // WORKAROUND for some bugged scripts that will try to display frames of non-existent animations if (anim->wsa) - anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0); + anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0); } void TIMInterpreter_LoL::stopBackgroundAnimation(int animIndex) { @@ -1110,7 +1122,7 @@ void TIMInterpreter_LoL::updateBackgroundAnimation(int animIndex) { anim->nextFrame += (anim->frameDelay * _vm->_tickLength); - anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0); + anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0); anim->nextFrame += _system->getMillis(); } @@ -1126,10 +1138,12 @@ void TIMInterpreter_LoL::playAnimationPart(int animIndex, int firstFrame, int la _screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0); _screen->updateScreen(); } else { - anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0); + anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0, 0, 0); _screen->updateScreen(); } - _vm->delayUntil(next); + int32 del = (int32)(next - _system->getMillis()); + if (del > 0) + _vm->delay(del, true); } } @@ -1162,7 +1176,8 @@ uint16 TIMInterpreter_LoL::processDialogue() { int x = _dialogueButtonPosX; for (int i = 0; i < _dialogueNumButtons; i++) { - if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) { + Common::Point p = _vm->getMousePos(); + if (_vm->posWithinRect(p.x, p.y, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) { _dialogueHighlightedButton = i; break; } @@ -1222,7 +1237,8 @@ uint16 TIMInterpreter_LoL::processDialogue() { x = _dialogueButtonPosX; for (int i = 0; i < _dialogueNumButtons; i++) { - if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) { + Common::Point p = _vm->getMousePos(); + if (_vm->posWithinRect(p.x, p.y, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) { _dialogueHighlightedButton = i; res = _dialogueHighlightedButton + 1; break; diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h index 10337b4b09..40049c3dec 100644 --- a/engines/kyra/script_tim.h +++ b/engines/kyra/script_tim.h @@ -121,6 +121,8 @@ public: TIM *load(const char *filename, const Common::Array<const TIMOpcode*> *opcodes); void unload(TIM *&tim) const; + bool callback(Common::IFFChunk &chunk); + virtual Animation *initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags); virtual int freeAnimStruct(int index); @@ -169,6 +171,11 @@ protected: bool _finished; + // used when loading + int _avtlChunkSize; + const char *_filename; + TIM *_tim; + Common::String _vocFiles[120]; Animation *_animations; diff --git a/engines/kyra/seqplayer.cpp b/engines/kyra/seqplayer.cpp index 54d6f2cbe3..2145591c03 100644 --- a/engines/kyra/seqplayer.cpp +++ b/engines/kyra/seqplayer.cpp @@ -92,7 +92,7 @@ uint8 *SeqPlayer::setPanPages(int pageNum, int shape) { } void SeqPlayer::makeHandShapes() { - _screen->loadBitmap("WRITING.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("WRITING.CPS", 3, 3, &_screen->getPalette(0)); if (_vm->gameFlags().platform == Common::kPlatformMacintosh || _vm->gameFlags().platform == Common::kPlatformAmiga) { freeHandShapes(); @@ -148,7 +148,7 @@ void SeqPlayer::s1_wsaPlayFrame() { _seqMovies[wsaObj].pos.x = READ_LE_UINT16(_seqData); _seqData += 2; _seqMovies[wsaObj].pos.y = *_seqData++; assert(_seqMovies[wsaObj].movie); - _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y); + _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y, 0, 0, 0); _seqMovies[wsaObj].frame = frame; } @@ -160,7 +160,7 @@ void SeqPlayer::s1_wsaPlayNextFrame() { frame = 0; _seqMovies[wsaObj].frame = 0; } - _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y); + _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y, 0, 0, 0); } void SeqPlayer::s1_wsaPlayPrevFrame() { @@ -171,7 +171,7 @@ void SeqPlayer::s1_wsaPlayPrevFrame() { frame = _seqMovies[wsaObj].numFrames; _seqMovies[wsaObj].frame = frame; } else { - _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y); + _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y, 0, 0, 0); } } @@ -194,21 +194,18 @@ void SeqPlayer::s1_copyWaitTicks() { void SeqPlayer::s1_shuffleScreen() { _screen->shuffleScreen(0, 16, 320, 128, 2, 0, 0, false); - _screen->_curPage = 2; if (_specialBuffer) - _screen->copyCurPageBlock(0, 16, 40, 128, _specialBuffer); + _screen->copyRegionToBuffer(2, 0, 16, 320, 128, _specialBuffer); _screen->_curPage = 0; } void SeqPlayer::s1_copyView() { - int y = 128; - if (!_copyViewOffs) - y -= 8; + int h = !_copyViewOffs ? 120 : 128; if (_specialBuffer && !_copyViewOffs) - _screen->copyToPage0(16, y, 3, _specialBuffer); + _screen->copyToPage0(16, h, 3, _specialBuffer); else - _screen->copyRegion(0, 16, 0, 16, 320, y, 2, 0); + _screen->copyRegion(0, 16, 0, 16, 320, h, 2, 0); } void SeqPlayer::s1_loopInit() { @@ -244,25 +241,21 @@ void SeqPlayer::s1_loadPalette() { if (_vm->gameFlags().platform == Common::kPlatformAmiga) { if (!colNum) - memcpy(_screen->_currentPalette, _screen->_currentPalette + 576, 3*32); + _screen->copyPalette(0, 6); else if (colNum == 3) - memcpy(_screen->_currentPalette, _screen->_currentPalette + 672, 3*32); + _screen->copyPalette(0, 7); else if (colNum == 4) - memcpy(_screen->_currentPalette, _screen->_currentPalette + 288, 3*32); + _screen->copyPalette(0, 3); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->setScreenPalette(_screen->getPalette(0)); } else { - uint32 fileSize; - uint8 *srcData; - srcData = _res->fileData(_vm->seqCOLTable()[colNum], &fileSize); - memcpy(_screen->_currentPalette, srcData, fileSize); - delete[] srcData; + _screen->loadPalette(_vm->seqCOLTable()[colNum], _screen->getPalette(0)); } } void SeqPlayer::s1_loadBitmap() { uint8 cpsNum = *_seqData++; - _screen->loadBitmap(_vm->seqCPSTable()[cpsNum], 3, 3, _screen->_currentPalette); + _screen->loadBitmap(_vm->seqCPSTable()[cpsNum], 3, 3, &_screen->getPalette(0)); } void SeqPlayer::s1_fadeToBlack() { @@ -449,10 +442,7 @@ void SeqPlayer::s1_allocTempBuffer() { if (!_specialBuffer && !_copyViewOffs) { _specialBuffer = new uint8[40960]; assert(_specialBuffer); - int page = _screen->_curPage; - _screen->_curPage = 0; - _screen->copyCurPageBlock(0, 0, 320, 128, _specialBuffer); - _screen->_curPage = page; + _screen->copyRegionToBuffer(2, 0, 16, 320, 128, _specialBuffer); } } } diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index 4e53399fbf..90b2fdd580 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -62,7 +62,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { int oldPage = _screen->setCurPage(2); for (int i = 0; i < 4; ++i) - memset(_screen->getPalette(i), 0, 0x300); + _screen->getPalette(i).clear(); _screen->clearPage(10); _screen->clearPage(12); @@ -77,7 +77,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { for (int seqNum = startSeq; seqNum <= endSeq && !((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) { _screen->clearPage(0); _screen->clearPage(8); - memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300); + _screen->copyPalette(1, 0); _seqFrameCounter = 0; _seqStartTime = _system->getMillis(); @@ -87,7 +87,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { SeqProc cb = _callbackS[seqNum]; if (cseq.flags & 2) { - _screen->loadBitmap(cseq.cpsFile, 2, 2, _screen->getPalette(0)); + _screen->loadBitmap(cseq.cpsFile, 2, 2, &_screen->getPalette(0)); _screen->setScreenPalette(_screen->getPalette(0)); } else { _screen->setCurPage(2); @@ -100,9 +100,9 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { if (cseq.flags & 1) { _seqWsa->close(); - _seqWsa->open(cseq.wsaFile, 0, _screen->getPalette(0)); + _seqWsa->open(cseq.wsaFile, 0, &_screen->getPalette(0)); _screen->setScreenPalette(_screen->getPalette(0)); - _seqWsa->displayFrame(0, 2, cseq.xPos, cseq.yPos, 0); + _seqWsa->displayFrame(0, 2, cseq.xPos, cseq.yPos, 0, 0, 0); } if (cseq.flags & 4) { @@ -174,7 +174,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { if (_seqWsa) { int f = _seqWsaCurrentFrame % _seqWsa->frames(); - _seqWsa->displayFrame(f, 2, cseq.xPos, cseq.yPos, 0); + _seqWsa->displayFrame(f, 2, cseq.xPos, cseq.yPos, 0, 0, 0); } _screen->copyPage(2, 12); @@ -361,7 +361,7 @@ int KyraEngine_HoF::seq_introTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { } int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - uint8 *tmpPal = &(_screen->getPalette(3)[0x101]); + uint8 *tmpPal = _screen->getPalette(3).getData() + 0x101; memset(tmpPal, 0, 256); _seqSubFrameEndTimeInternal = 0; uint32 now = 0; @@ -372,9 +372,9 @@ int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm _sound->playTrack(4); _seqSubFrameEndTimeInternal = _system->getMillis() + 60 * _tickLength; - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; _screen->setTextColorMap(_seqTextColorMap); @@ -384,7 +384,7 @@ int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm break; case 1: - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x40, 0, 0, 0, 0x100, true); + _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x40, 0, 0, 0, 0x100, true); for (int i = 0; i < 256; i++) tmpPal[_screen->getPalette(3)[i]] = 1; @@ -417,7 +417,7 @@ int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm case 201: _screen->setScreenPalette(_screen->getPalette(2)); _screen->updateScreen(); - _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3)); + _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); _screen->copyPage(2, 12); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->setScreenPalette(_screen->getPalette(0)); @@ -465,10 +465,10 @@ int KyraEngine_HoF::seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm) _seqSubframePlaying = true; _sound->playTrack(5); - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x24, 0, 0, 0, 0x100, false); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; _screen->setTextColorMap(_seqTextColorMap); break; @@ -482,7 +482,7 @@ int KyraEngine_HoF::seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm) seq_waitForTextsTimeout(); _screen->copyPage(12, 2); - _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3)); + _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->updateScreen(); _screen->copyPage(2, 12); @@ -503,7 +503,7 @@ int KyraEngine_HoF::seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm) case 340: seq_resetActiveWSA(0); - _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3)); + _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); _screen->copyPage(2, 12); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->updateScreen(); @@ -539,10 +539,10 @@ int KyraEngine_HoF::seq_introHand(WSAMovie_v2 *wsaObj, int x, int y, int frm) { _seqSubframePlaying = true; _sound->playTrack(6); - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x24, 0, 0, 0, 0x100, false); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; _screen->setTextColorMap(_seqTextColorMap); break; @@ -556,7 +556,7 @@ int KyraEngine_HoF::seq_introHand(WSAMovie_v2 *wsaObj, int x, int y, int frm) { case 201: seq_waitForTextsTimeout(); - _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3)); + _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); _screen->copyPage(2, 12); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->updateScreen(); @@ -631,9 +631,9 @@ int KyraEngine_HoF::seq_introPoint(WSAMovie_v2 *wsaObj, int x, int y, int frm) { _seqTextColor[1] = 0xf7; memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; _screen->setTextColorMap(_seqTextColorMap); - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x24, 0, 0, 0, 0x100, false); + _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); break; case 1: @@ -661,7 +661,7 @@ int KyraEngine_HoF::seq_introZanfaun(WSAMovie_v2 *wsaObj, int x, int y, int frm) _seqTextColor[1] = 0xfd; memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; _screen->setTextColorMap(_seqTextColorMap); break; @@ -831,7 +831,7 @@ int KyraEngine_HoF::seq_finaleFunters(WSAMovie_v2 *wsaObj, int x, int y, int frm case 0: _sound->playTrack(3); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); _seqTextColor[0] = _seqTextColorMap[1] = 0xff; _screen->setTextColorMap(_seqTextColorMap); @@ -924,7 +924,7 @@ int KyraEngine_HoF::seq_finaleFerb(WSAMovie_v2 *wsaObj, int x, int y, int frm) { break; case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); _seqTextColor[0] = _seqTextColorMap[1] = 255; _screen->setTextColorMap(_seqTextColorMap); @@ -1006,7 +1006,7 @@ int KyraEngine_HoF::seq_finaleFish(WSAMovie_v2 *wsaObj, int x, int y, int frm) { break; case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); _seqTextColor[0] = _seqTextColorMap[1] = 0xff; _screen->setTextColorMap(_seqTextColorMap); @@ -1096,7 +1096,7 @@ int KyraEngine_HoF::seq_finaleFheep(WSAMovie_v2 *wsaObj, int x, int y, int frm) break; case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); _seqTextColor[0] = _seqTextColorMap[1] = 0xff; _screen->setTextColorMap(_seqTextColorMap); @@ -1172,9 +1172,9 @@ int KyraEngine_HoF::seq_finaleFarmer(WSAMovie_v2 *wsaObj, int x, int y, int frm) break; case 0: - _seqTextColor[1] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 254) & 0xff); + _seqTextColor[1] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 254) & 0xff); memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 254) & 0xff); + _seqTextColorMap[1] = _seqTextColor[0] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 254) & 0xff); _screen->setTextColorMap(_seqTextColorMap); seq_playTalkText(_flags.isTalkie ? 30 : 26); break; @@ -1339,7 +1339,7 @@ int KyraEngine_HoF::seq_finaleFirates(WSAMovie_v2 *wsaObj, int x, int y, int frm break; case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); _seqTextColor[0] = _seqTextColorMap[1] = 0xff; _screen->setTextColorMap(_seqTextColorMap); @@ -1426,7 +1426,7 @@ int KyraEngine_HoF::seq_finaleFrash(WSAMovie_v2 *wsaObj, int x, int y, int frm) case 0: if (_seqFrameCounter == 1) { _sound->playTrack(4); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); _seqTextColor[0] = _seqTextColorMap[1] = 0xff; _screen->setTextColorMap(_seqTextColorMap); @@ -1501,7 +1501,7 @@ void KyraEngine_HoF::seq_finaleActorScreen() { static const uint8 colormap[] = {0, 0, 102, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const ScreenDim d = { 0x00, 0x0C, 0x28, 0xB4, 0xFF, 0x00, 0x00, 0x00 }; - _screen->loadBitmap("finale.cps", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("finale.cps", 3, 3, &_screen->getPalette(0)); _screen->setFont(Screen::FID_GOLDFONT_FNT); int talkieCreditsSize, talkieCreditsSpecialSize; @@ -1781,19 +1781,21 @@ int KyraEngine_HoF::seq_demoDig(WSAMovie_v2 *wsaObj, int x, int y, int frm) { #ifdef ENABLE_LOL int KyraEngine_HoF::seq_lolDemoScene1(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - uint8 *tmpPal = _screen->getPalette(2); + Palette &tmpPal = _screen->getPalette(2); if (!(_seqFrameCounter % 100)) { if (_seqFrameCounter == 0) { _sound->haltTrack(); _sound->playTrack(6); } - memcpy(tmpPal, _screen->getPalette(0), 0x300); + tmpPal.copy(_screen->getPalette(0)); + for (int i = 3; i < 0x300; i++) { tmpPal[i] = ((int)tmpPal[i] * 120) / 64; if (tmpPal[i] > 0x3f) tmpPal[i] = 0x3f; } + seq_playTalkText(_rnd.getRandomBit()); _screen->setScreenPalette(tmpPal); _screen->updateScreen(); @@ -1926,13 +1928,15 @@ int KyraEngine_HoF::seq_lolDemoScene6(WSAMovie_v2 *wsaObj, int x, int y, int frm if (_seqFrameCounter % 175) { _screen->setScreenPalette(_screen->getPalette(0)); } else { - uint8 *tmpPal = _screen->getPalette(2); - memcpy(tmpPal, _screen->getPalette(0), 0x300); + Palette &tmpPal = _screen->getPalette(2); + tmpPal.copy(_screen->getPalette(0)); + for (int i = 3; i < 0x300; i++) { tmpPal[i] = ((int)tmpPal[i] * 120) / 64; if (tmpPal[i] > 0x3f) tmpPal[i] = 0x3f; } + seq_playTalkText(_rnd.getRandomBit()); _screen->setScreenPalette(tmpPal); _screen->updateScreen(); @@ -2045,37 +2049,35 @@ char *KyraEngine_HoF::seq_preprocessString(const char *srcStr, int width) { } void KyraEngine_HoF::seq_sequenceCommand(int command) { - uint8 pal[768]; - for (int i = 0; i < 8; i++) seq_resetActiveWSA(i); switch (command) { case 0: - memset(pal, 0, 0x300); - _screen->fadePalette(pal, 36); - memcpy(_screen->getPalette(0), pal, 0x300); - memcpy(_screen->getPalette(1), pal, 0x300); + _screen->fadeToBlack(36); + _screen->getPalette(0).clear(); + _screen->getPalette(1).clear(); break; case 1: - memset(pal, 0x3F, 0x300); seq_playTalkText(_rnd.getRandomBit()); - _screen->fadePalette(pal, 16); - memcpy(_screen->getPalette(0), pal, 0x300); - memcpy(_screen->getPalette(1), pal, 0x300); + + _screen->getPalette(0).fill(0, 256, 0x3F); + _screen->fadePalette(_screen->getPalette(0), 16); + + _screen->copyPalette(1, 0); break; case 3: _screen->copyPage(2, 0); _screen->fadePalette(_screen->getPalette(0), 16); - memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300); + _screen->copyPalette(1, 0); break; case 4: _screen->copyPage(2, 0); _screen->fadePalette(_screen->getPalette(0), 36); - memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300); + _screen->copyPalette(1, 0); break; case 5: @@ -2093,17 +2095,17 @@ void KyraEngine_HoF::seq_sequenceCommand(int command) { break; case 8: - memset(pal, 0, 0x300); - _screen->fadePalette(pal, 16); - memcpy(_screen->getPalette(0), pal, 0x300); - memcpy(_screen->getPalette(1), pal, 0x300); + _screen->fadeToBlack(16); + _screen->getPalette(0).clear(); + _screen->getPalette(1).clear(); delay(120 * _tickLength); break; - case 9: - for (int i = 0; i < 0x100; i++) { - int pv = (_screen->getPalette(0)[3 * i] + _screen->getPalette(0)[3 * i + 1] + _screen->getPalette(0)[3 * i + 2]) / 3; + case 9: { + Palette &pal = _screen->getPalette(0); + for (int i = 0; i < 256; i++) { + int pv = (pal[3 * i] + pal[3 * i + 1] + pal[3 * i + 2]) / 3; pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = pv & 0xff; } @@ -2112,9 +2114,8 @@ void KyraEngine_HoF::seq_sequenceCommand(int command) { //pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = 0x3f; _screen->fadePalette(pal, 64); - memcpy(_screen->getPalette(0), pal, 0x300); - memcpy(_screen->getPalette(1), pal, 0x300); - break; + _screen->copyPalette(1, 0); + } break; default: break; @@ -2201,7 +2202,7 @@ void KyraEngine_HoF::seq_loadNestedSequence(int wsaNum, int seqNum) { NestedSequence s = _sequences->seqn[seqNum]; if (!_activeWSA[wsaNum].movie) { - _activeWSA[wsaNum].movie = new WSAMovie_v2(this, _screen); + _activeWSA[wsaNum].movie = new WSAMovie_v2(this); assert(_activeWSA[wsaNum].movie); } @@ -2246,7 +2247,7 @@ void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) { case 0: xa = -_activeWSA[wsaNum].movie->xAdd(); ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0); + _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0, 0, 0); seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 2); break; @@ -2254,7 +2255,7 @@ void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) { case 1: xa = -_activeWSA[wsaNum].movie->xAdd(); ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0); + _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0, 0, 0); seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 1); break; @@ -2263,21 +2264,21 @@ void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) { seq_waitForTextsTimeout(); xa = -_activeWSA[wsaNum].movie->xAdd(); ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->displayFrame(0x15, 8, xa, ya, 0); + _activeWSA[wsaNum].movie->displayFrame(0x15, 8, xa, ya, 0, 0, 0); seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 0, 2); break; case 3: _screen->copyPage(2, 10); - _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0); + _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 12); seq_cmpFadeFrame("scene2.cmp"); break; case 4: _screen->copyPage(2, 10); - _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0); + _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 12); seq_cmpFadeFrame("scene3.cmp"); break; @@ -2364,10 +2365,10 @@ bool KyraEngine_HoF::seq_processNextSubFrame(int wsaNum) { if (_activeWSA[wsaNum].movie) { if (_activeWSA[wsaNum].flags & 0x20) { - _activeWSA[wsaNum].movie->displayFrame(_activeWSA[wsaNum].control[currentFrame].index, 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000); + _activeWSA[wsaNum].movie->displayFrame(_activeWSA[wsaNum].control[currentFrame].index, 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000, 0, 0); _activeWSA[wsaNum].frameDelay = _activeWSA[wsaNum].control[currentFrame].delay; } else { - _activeWSA[wsaNum].movie->displayFrame(currentFrame % _activeWSA[wsaNum].movie->frames(), 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000); + _activeWSA[wsaNum].movie->displayFrame(currentFrame % _activeWSA[wsaNum].movie->frames(), 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000, 0, 0); } } @@ -2477,7 +2478,7 @@ void KyraEngine_HoF::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, i _seqWsaChatFrameTimeout = _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; if (wsa) - wsa->displayFrame(curframe % wsa->frames(), 2, wsaXpos, wsaYpos, 0); + wsa->displayFrame(curframe % wsa->frames(), 2, wsaXpos, wsaYpos, 0, 0, 0); _screen->copyPage(2, 12); @@ -2663,9 +2664,9 @@ void KyraEngine_HoF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int if (palCycle) { for (int col = 133; col > 112; col--) - memcpy(_screen->_currentPalette + (col * 3), _screen->_currentPalette + ((col - 1) * 3), 3); - memcpy(_screen->_currentPalette + 336, _screen->_currentPalette + 399, 3); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->getPalette(0).copy(_screen->getPalette(0), col - 1, 1, col); + _screen->getPalette(0).copy(_screen->getPalette(0), 133, 1, 112); + _screen->setScreenPalette(_screen->getPalette(0)); } delayUntil(_seqSubFrameEndTimeInternal); @@ -2721,32 +2722,32 @@ void KyraEngine_HoF::seq_scrollPage(int bottom, int top) { } void KyraEngine_HoF::seq_showStarcraftLogo() { - WSAMovie_v2 *ci = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *ci = new WSAMovie_v2(this); assert(ci); _screen->clearPage(2); _res->loadPakFile("INTROGEN.PAK"); - int endframe = ci->open("ci.wsa", 0, _screen->_currentPalette); + int endframe = ci->open("ci.wsa", 0, &_screen->getPalette(0)); _res->unloadPakFile("INTROGEN.PAK"); if (!ci->opened()) { delete ci; return; } _screen->hideMouse(); - ci->displayFrame(0, 2, 0, 0, 0); + ci->displayFrame(0, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 0); _screen->fadeFromBlack(); for (int i = 1; i < endframe; i++) { _seqEndTime = _system->getMillis() + 50; if (skipFlag()) break; - ci->displayFrame(i, 2, 0, 0, 0); + ci->displayFrame(i, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 0); _screen->updateScreen(); delay(_seqEndTime - _system->getMillis()); } if (!skipFlag()) { _seqEndTime = _system->getMillis() + 50; - ci->displayFrame(0, 2, 0, 0, 0); + ci->displayFrame(0, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 0); _screen->updateScreen(); delay(_seqEndTime - _system->getMillis()); @@ -2760,7 +2761,7 @@ void KyraEngine_HoF::seq_showStarcraftLogo() { void KyraEngine_HoF::seq_init() { _seqProcessedString = new char[200]; - _seqWsa = new WSAMovie_v2(this, _screen); + _seqWsa = new WSAMovie_v2(this); _activeWSA = new ActiveWSA[8]; _activeText = new ActiveText[10]; diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index 12ede98ad4..d483409090 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -42,7 +42,7 @@ namespace Kyra { void KyraEngine_LoK::seq_demo() { snd_playTheme(0, 2); - _screen->loadBitmap("START.CPS", 7, 7, _screen->_currentPalette); + _screen->loadBitmap("START.CPS", 7, 7, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); _screen->fadeFromBlack(); @@ -50,8 +50,8 @@ void KyraEngine_LoK::seq_demo() { _screen->fadeToBlack(); _screen->clearPage(0); - _screen->loadBitmap("TOP.CPS", 7, 7, NULL); - _screen->loadBitmap("BOTTOM.CPS", 5, 5, _screen->_currentPalette); + _screen->loadBitmap("TOP.CPS", 7, 7, 0); + _screen->loadBitmap("BOTTOM.CPS", 5, 5, &_screen->getPalette(0)); _screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0); _screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0); _screen->updateScreen(); @@ -77,7 +77,7 @@ void KyraEngine_LoK::seq_demo() { _seq->playSequence(_seq_Demo4, true); _screen->clearPage(0); - _screen->loadBitmap("FINAL.CPS", 7, 7, _screen->_currentPalette); + _screen->loadBitmap("FINAL.CPS", 7, 7, &_screen->getPalette(0)); _screen->_curPage = 0; _screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0); _screen->updateScreen(); @@ -128,7 +128,7 @@ void KyraEngine_LoK::seq_intro() { void KyraEngine_LoK::seq_introLogos() { if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) { - _screen->loadBitmap("LOGO.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("LOGO.CPS", 3, 3, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->updateScreen(); _screen->fadeFromBlack(); @@ -141,7 +141,7 @@ void KyraEngine_LoK::seq_introLogos() { _screen->clearPage(0); if (_flags.platform == Common::kPlatformAmiga) { - _screen->loadPalette("INTRO.PAL", _screen->_currentPalette); + _screen->loadPaletteTable("INTRO.PAL", 0); _screen->loadBitmap("BOTTOM.CPS", 3, 5, 0); _screen->loadBitmap("TOP.CPS", 3, 3, 0); _screen->copyRegion(0, 0, 0, 111, 320, 64, 2, 0); @@ -149,7 +149,7 @@ void KyraEngine_LoK::seq_introLogos() { _screen->copyRegion(0, 0, 0, 0, 320, 190, 0, 2); } else { _screen->loadBitmap("TOP.CPS", 7, 7, 0); - _screen->loadBitmap("BOTTOM.CPS", 5, 5, _screen->_currentPalette); + _screen->loadBitmap("BOTTOM.CPS", 5, 5, &_screen->getPalette(0)); _screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0); _screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0); } @@ -166,8 +166,8 @@ void KyraEngine_LoK::seq_introLogos() { delay(60 * _tickLength); if (_flags.platform == Common::kPlatformAmiga) { - memcpy(_screen->_currentPalette, _screen->_currentPalette + 3*32, 3*32); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->copyPalette(0, 1); + _screen->setScreenPalette(_screen->getPalette(0)); } if ((_seq->playSequence(_seq_KyrandiaLogo, skipFlag()) && !seq_skipSequence()) || shouldQuit()) { @@ -181,7 +181,7 @@ void KyraEngine_LoK::seq_introLogos() { return; if (_flags.platform == Common::kPlatformAmiga) { - memcpy(_screen->_currentPalette, _screen->_currentPalette + 3*64, 3*32); + _screen->copyPalette(0, 2); _screen->fadeToBlack(); _screen->copyRegion(0, 0, 0, 0, 320, 200, 4, 0); _screen->fadeFromBlack(); @@ -236,22 +236,22 @@ void KyraEngine_LoK::seq_introStory() { return; if (_flags.lang == Common::EN_ANY && !_flags.isTalkie && (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformAmiga)) - _screen->loadBitmap("TEXT.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT.CPS", 3, 3, &_screen->getPalette(0)); else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN) - _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, &_screen->getPalette(0)); else if (_flags.lang == Common::DE_DEU) - _screen->loadBitmap("TEXT_GER.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT_GER.CPS", 3, 3, &_screen->getPalette(0)); else if (_flags.lang == Common::FR_FRA) - _screen->loadBitmap("TEXT_FRE.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT_FRE.CPS", 3, 3, &_screen->getPalette(0)); else if (_flags.lang == Common::ES_ESP) - _screen->loadBitmap("TEXT_SPA.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT_SPA.CPS", 3, 3, &_screen->getPalette(0)); else if (_flags.lang == Common::IT_ITA && !_flags.isTalkie) - _screen->loadBitmap("TEXT_ITA.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT_ITA.CPS", 3, 3, &_screen->getPalette(0)); else if (_flags.lang == Common::IT_ITA && _flags.isTalkie) - _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, &_screen->getPalette(0)); else warning("no story graphics file found"); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->setScreenPalette(_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 3, 0); if (_flags.lang == Common::JA_JPN) { @@ -569,12 +569,9 @@ void KyraEngine_LoK::seq_winterScroll1() { _sprites->_anims[i].play = false; _animator->sprites()[i].active = 0; } - uint8 tmpPal[768]; - memcpy(tmpPal, _screen->_currentPalette, 768); - memcpy(&tmpPal[684], palTable2()[0], 60); - _screen->fadePalette(tmpPal, 72); - memcpy(&_screen->_currentPalette[684], palTable2()[0], 60); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->getPalette(0).copy(palTable2()[0], 0, 20, 228); + _screen->fadePalette(_screen->getPalette(0), 72); + _screen->setScreenPalette(_screen->getPalette(0)); setGameFlag(0xB3); } else { delayWithTicks(120); @@ -950,8 +947,8 @@ int KyraEngine_LoK::seq_playEnd() { _screen->hideMouse(); _screen->fadeSpecialPalette(32, 228, 20, 60); delay(60 * _tickLength); - _screen->loadBitmap("GEMHEAL.CPS", 3, 3, _screen->_currentPalette); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->loadBitmap("GEMHEAL.CPS", 3, 3, &_screen->getPalette(0)); + _screen->setScreenPalette(_screen->getPalette(0)); _screen->shuffleScreen(8, 8, 304, 128, 2, 0, 1, 0); uint32 nextTime = _system->getMillis() + 120 * _tickLength; _finalA = new WSAMovie_v1(this); @@ -966,7 +963,7 @@ int KyraEngine_LoK::seq_playEnd() { else if (i == 20) snd_playSoundEffect(0x0E); nextTime = _system->getMillis() + 8 * _tickLength; - _finalA->displayFrame(i, 0, 8, 8); + _finalA->displayFrame(i, 0, 8, 8, 0, 0, 0); _screen->updateScreen(); } delete _finalA; @@ -1004,14 +1001,14 @@ void KyraEngine_LoK::seq_playEnding() { _screen->hideMouse(); _screen->_curPage = 0; _screen->fadeToBlack(); - _screen->loadBitmap("REUNION.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("REUNION.CPS", 3, 3, &_screen->getPalette(0)); _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); _screen->_curPage = 0; // XXX assert(_homeString); drawSentenceCommand(_homeString[0], 179); - memset(_screen->getPalette(2), 0, sizeof(uint8)*768); + _screen->getPalette(2).clear(); _screen->setScreenPalette(_screen->getPalette(2)); _seqPlayerFlag = true; @@ -1045,7 +1042,7 @@ void KyraEngine_LoK::seq_playCredits() { } else _screen->setFont(Screen::FID_8_FNT); - _screen->loadBitmap("CHALET.CPS", 4, 4, _screen->_currentPalette); + _screen->loadBitmap("CHALET.CPS", 4, 4, &_screen->getPalette(0)); _screen->setCurPage(0); _screen->clearCurPage(); @@ -1123,10 +1120,10 @@ void KyraEngine_LoK::seq_playCredits() { _screen->setCurPage(2); - memset(_screen->getPalette(2), 0, sizeof(uint8)*768); + _screen->getPalette(2).clear(); _screen->setScreenPalette(_screen->getPalette(2)); _screen->copyRegion(8, 32, 8, 32, 312, 128, 4, 0, Screen::CR_NO_P_CHECK); - _screen->fadePalette(_screen->_currentPalette, 0x5A); + _screen->fadePalette(_screen->getPalette(0), 0x5A); Common::Event event; bool finished = false; @@ -1198,7 +1195,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 2: if (_system->getMillis() >= timer2) { - _finalA->displayFrame(frame, 0, 8, 46); + _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1213,7 +1210,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { if (_system->getMillis() < timer1) { if (_system->getMillis() >= timer2) { frame = _rnd.getRandomNumberRng(14, 17); - _finalA->displayFrame(frame, 0, 8, 46); + _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; } @@ -1225,7 +1222,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 4: if (_system->getMillis() >= timer2) { - _finalA->displayFrame(frame, 0, 8, 46); + _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1239,7 +1236,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 5: if (_system->getMillis() >= timer2) { - _finalA->displayFrame(frame, 0, 8, 46); + _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1253,7 +1250,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 6: if (_unkEndSeqVar4) { if (frame <= 33 && _system->getMillis() >= timer2) { - _finalA->displayFrame(frame, 0, 8, 46); + _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1278,7 +1275,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 8: if (_system->getMillis() >= timer2) { - _finalA->displayFrame(frame, 0, 8, 46); + _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1295,7 +1292,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { snd_playSoundEffect(12); for (int i = 0; i < 18; ++i) { timer2 = _system->getMillis() + 4 * _tickLength; - _finalC->displayFrame(i, 0, 16, 50); + _finalC->displayFrame(i, 0, 16, 50, 0, 0, 0); _screen->updateScreen(); delayUntil(timer2); } @@ -1353,7 +1350,7 @@ int KyraEngine_LoK::handleBeadState() { switch (_beadStateVar) { case 0: if (beadState1.x != -1 && _endSequenceBackUpRect) { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); } @@ -1367,7 +1364,7 @@ int KyraEngine_LoK::handleBeadState() { case 1: if (beadState1.x != -1) { if (_endSequenceBackUpRect) { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); } beadState1.x = -1; @@ -1402,14 +1399,14 @@ int KyraEngine_LoK::handleBeadState() { beadState1.dstY = beadState1.y; return 0; } else { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); beadState1.x = x; beadState1.y = y; } } - _screen->copyCurPageBlock(x >> 3, y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyRegionToBuffer(_screen->_curPage, x, y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0); if (_lastDisplayedPanPage > 17) @@ -1422,12 +1419,12 @@ int KyraEngine_LoK::handleBeadState() { case 3: if (_system->getMillis() >= timer1) { timer1 = _system->getMillis() + 4 * _tickLength; - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); beadState1.x = beadState1.dstX + table1[beadState1.tableIndex]; beadState1.y = beadState1.dstY + table2[beadState1.tableIndex]; - _screen->copyCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], beadState1.x, beadState1.y, 0, 0); if (_lastDisplayedPanPage >= 17) @@ -1476,11 +1473,11 @@ int KyraEngine_LoK::handleBeadState() { _beadStateVar = 0; } } else { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); beadState1.x = x; beadState1.y = y; - _screen->copyCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0); if (_lastDisplayedPanPage > 17) { _lastDisplayedPanPage = 0; @@ -1496,24 +1493,24 @@ int KyraEngine_LoK::handleBeadState() { int x = 0, y = 0; if (processBead(beadState1.x, beadState1.y, x, y, &beadState2)) { if (beadState2.dstX == 290) { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); uint32 nextRun = 0; for (int i = 0; i < 8; ++i) { nextRun = _system->getMillis() + _tickLength; - _finalB->displayFrame(i, 0, 224, 8); + _finalB->displayFrame(i, 0, 224, 8, 0, 0, 0); _screen->updateScreen(); delayUntil(nextRun); } snd_playSoundEffect(0x0D); for (int i = 7; i >= 0; --i) { nextRun = _system->getMillis() + _tickLength; - _finalB->displayFrame(i, 0, 224, 8); + _finalB->displayFrame(i, 0, 224, 8, 0, 0, 0); _screen->updateScreen(); delayUntil(nextRun); } initBeadState(beadState1.x, beadState1.y, 63, 60, 12, &beadState2); } else { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); beadState1.x = -1; beadState1.tableIndex = 0; @@ -1521,11 +1518,11 @@ int KyraEngine_LoK::handleBeadState() { _malcolmFlag = 9; } } else { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); beadState1.x = x; beadState1.y = y; - _screen->copyCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0); if (_lastDisplayedPanPage > 17) _lastDisplayedPanPage = 0; @@ -1679,11 +1676,11 @@ void KyraEngine_LoK::updateKyragemFading() { _kyragemFadingState.timerCount = _system->getMillis() + 4 * _tickLength; int palPos = 684; for (int i = 0; i < 20; ++i) { - _screen->_currentPalette[palPos++] = kyraGemPalette[i + _kyragemFadingState.rOffset]; - _screen->_currentPalette[palPos++] = kyraGemPalette[i + _kyragemFadingState.gOffset]; - _screen->_currentPalette[palPos++] = kyraGemPalette[i + _kyragemFadingState.bOffset]; + _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.rOffset]; + _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.gOffset]; + _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.bOffset]; } - _screen->setScreenPalette(_screen->_currentPalette); + _screen->setScreenPalette(_screen->getPalette(0)); _animator->_updateScreen = true; switch (_kyragemFadingState.nextOperation) { case 0: diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp index 849a325560..beea129f66 100644 --- a/engines/kyra/sequences_lol.cpp +++ b/engines/kyra/sequences_lol.cpp @@ -43,7 +43,7 @@ int LoLEngine::processPrologue() { if (_flags.isDemo) { _screen->fadePalette(_screen->getPalette(1), 30, 0); - _screen->loadBitmap("FINAL.CPS", 2, 2, _screen->getPalette(0)); + _screen->loadBitmap("FINAL.CPS", 2, 2, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); _screen->fadePalette(_screen->getPalette(0), 30, 0); delayWithTicks(300); @@ -57,7 +57,7 @@ int LoLEngine::processPrologue() { int processSelection = -1; while (!shouldQuit() && processSelection == -1) { - _screen->loadBitmap("TITLE.CPS", 2, 2, _screen->getPalette(0)); + _screen->loadBitmap("TITLE.CPS", 2, 2, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); _screen->setFont(Screen::FID_6_FNT); @@ -71,11 +71,14 @@ int LoLEngine::processPrologue() { _eventList.clear(); int selection = mainMenu(); - _screen->hideMouse(); - // Unlike the original, we add a nice fade to black - memset(_screen->getPalette(0), 0, 768); - _screen->fadePalette(_screen->getPalette(0), 0x54); + if (selection != 3) { + _screen->hideMouse(); + + // Unlike the original, we add a nice fade to black + _screen->getPalette(0).clear(); + _screen->fadeToBlack(0x54); + } switch (selection) { case 0: // New game @@ -90,7 +93,8 @@ int LoLEngine::processPrologue() { break; case 3: // Load game - //processSelection = 3; + if (_gui->runMenu(_gui->_loadMenu)) + processSelection = 3; break; case 4: // Quit game @@ -100,7 +104,7 @@ int LoLEngine::processPrologue() { } } - if (processSelection == 0 || processSelection == 3) { + if (processSelection == 0) { _sound->loadSoundFile(0); _sound->playTrack(6); chooseCharacter(); @@ -131,7 +135,6 @@ void LoLEngine::setupPrologueData(bool load) { const char * const *fileList = _flags.isTalkie ? fileListCD : (_flags.useInstallerPackage ? fileListFloppy : fileListFloppyExtracted); - char filename[32]; for (uint i = 0; fileList[i]; ++i) { filename[0] = '\0'; @@ -155,7 +158,7 @@ void LoLEngine::setupPrologueData(bool load) { _screen->clearPage(3); if (load) { - _chargenWSA = new WSAMovie_v2(this, _screen); + _chargenWSA = new WSAMovie_v2(this); assert(_chargenWSA); //_charSelection = -1; @@ -165,7 +168,7 @@ void LoLEngine::setupPrologueData(bool load) { _selectionAnimFrames[1] = _selectionAnimFrames[3] = 1; memset(_selectionAnimTimers, 0, sizeof(_selectionAnimTimers)); - memset(_screen->getPalette(1), 0, 768); + _screen->getPalette(1).clear(); _sound->setSoundList(&_soundData[kMusicIntro]); @@ -181,9 +184,8 @@ void LoLEngine::setupPrologueData(bool load) { } else { delete _chargenWSA; _chargenWSA = 0; - uint8 *pal = _screen->getPalette(0); - memset(pal, 0, 768); - _screen->setScreenPalette(pal); + _screen->getPalette(0).clear(); + _screen->setScreenPalette(_screen->getPalette(0)); if (shouldQuit()) return; @@ -200,9 +202,8 @@ void LoLEngine::showIntro() { if (_flags.platform == Common::kPlatformPC98) showStarcraftLogo(); - uint8 *pal = _screen->getPalette(0); - memset(pal, 0, 768); - _screen->setScreenPalette(pal); + _screen->getPalette(0).clear(); + _screen->setScreenPalette(_screen->getPalette(0)); _screen->clearPage(0); _screen->clearPage(4); @@ -274,8 +275,8 @@ int LoLEngine::chooseCharacter() { while (!_screen->isMouseVisible()) _screen->showMouse(); - _screen->loadBitmap("CHAR.CPS", 2, 2, _screen->getPalette(0)); - _screen->loadBitmap("BACKGRND.CPS", 4, 4, _screen->getPalette(0)); + _screen->loadBitmap("CHAR.CPS", 2, 2, &_screen->getPalette(0)); + _screen->loadBitmap("BACKGRND.CPS", 4, 4, &_screen->getPalette(0)); if (!_chargenWSA->open("CHARGEN.WSA", 1, 0)) error("Couldn't load CHARGEN.WSA"); @@ -368,7 +369,7 @@ void LoLEngine::kingSelectionIntro() { _sound->voicePlay("KING01", &_speechHandle); int index = 4; - while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && !skipFlag()) { + while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && !skipFlag()) { index = MAX(index, 4); _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 113, 0, 0, 0, 0); @@ -384,7 +385,7 @@ void LoLEngine::kingSelectionIntro() { _system->delayMillis(10); } - if (_speechFlag) + if (speechEnabled()) index = (index + 1) % 22; else if (++index >= 27) break; @@ -407,7 +408,7 @@ void LoLEngine::kingSelectionReminder() { _sound->voicePlay("KING02", &_speechHandle); int index = 0; - while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && index < 15) { + while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && index < 15) { _chargenWSA->displayFrame(_chargenFrameTable[index+9], 0, 113, 0, 0, 0, 0); _screen->copyRegion(_selectionPosTable[_reminderChar1IdxTable[index]*2+0], _selectionPosTable[_reminderChar1IdxTable[index]*2+1], _charPreviews[0].x, _charPreviews[0].y, 32, 32, 4, 0); _screen->copyRegion(_selectionPosTable[_reminderChar2IdxTable[index]*2+0], _selectionPosTable[_reminderChar2IdxTable[index]*2+1], _charPreviews[1].x, _charPreviews[1].y, 32, 32, 4, 0); @@ -421,7 +422,7 @@ void LoLEngine::kingSelectionReminder() { _system->delayMillis(10); } - if (_speechFlag) + if (speechEnabled()) index = (index + 1) % 22; else if (++index >= 27) break; @@ -434,7 +435,7 @@ void LoLEngine::kingSelectionOutro() { _sound->voicePlay("KING03", &_speechHandle); int index = 0; - while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && !shouldQuit() && !skipFlag()) { + while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && !shouldQuit() && !skipFlag()) { index = MAX(index, 4); _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 113, 0, 0, 0, 0); @@ -446,7 +447,7 @@ void LoLEngine::kingSelectionOutro() { _system->delayMillis(10); } - if (_speechFlag) + if (speechEnabled()) index = (index + 1) % 22; else if (++index >= 27) break; @@ -581,13 +582,13 @@ void LoLEngine::selectionCharInfoIntro(char *file) { bool processAnim = true; while (_charSelectionInfoResult == -1 && !shouldQuit()) { - if (_speechFlag && !_sound->isVoicePresent(file)) + if (speechEnabled() && !_sound->isVoicePresent(file)) break; _sound->voicePlay(file, &_speechHandle); int i = 0; - while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && _charSelectionInfoResult == -1 && !shouldQuit()) { + while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && _charSelectionInfoResult == -1 && !shouldQuit()) { _screen->drawShape(0, _screen->getPtrToShape(_screen->getCPagePtr(9), _charInfoFrameTable[i]), 11, 130, 0, 0); _screen->updateScreen(); @@ -597,7 +598,7 @@ void LoLEngine::selectionCharInfoIntro(char *file) { _system->delayMillis(10); } - if (_speechFlag || processAnim) + if (speechEnabled() || processAnim) i = (i + 1) % 32; if (i == 0) processAnim = false; @@ -641,19 +642,19 @@ int LoLEngine::selectionCharAccept() { } void LoLEngine::showStarcraftLogo() { - WSAMovie_v2 *ci = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *ci = new WSAMovie_v2(this); assert(ci); _screen->clearPage(0); _screen->clearPage(2); - int endframe = ci->open("ci01.wsa", 0, _screen->_currentPalette); + int endframe = ci->open("ci01.wsa", 0, &_screen->getPalette(0)); if (!ci->opened()) { delete ci; return; } _screen->hideMouse(); - ci->displayFrame(0, 2, 32, 80, 0); + ci->displayFrame(0, 2, 32, 80, 0, 0, 0); _screen->copyPage(2, 0); _screen->fadeFromBlack(); int inputFlag = 0; @@ -661,7 +662,7 @@ void LoLEngine::showStarcraftLogo() { inputFlag = checkInput(0) & 0xff; if (shouldQuit() || inputFlag) break; - ci->displayFrame(i, 2, 32, 80, 0); + ci->displayFrame(i, 2, 32, 80, 0, 0, 0); _screen->copyPage(2, 0); _screen->updateScreen(); delay(4 * _tickLength); @@ -725,9 +726,8 @@ void LoLEngine::setupEpilogueData(bool load) { if (_flags.platform == Common::kPlatformPC98) _sound->loadSoundFile("SOUND.DAT"); } else { - uint8 *pal = _screen->getPalette(0); - memset(pal, 0, 768); - _screen->setScreenPalette(pal); + _screen->getPalette(0).clear(); + _screen->setScreenPalette(_screen->getPalette(0)); if (shouldQuit()) return; @@ -742,9 +742,8 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) { TIMInterpreter *timBackUp = _tim; _tim = new TIMInterpreter(this, _screen, _system); - uint8 *pal = _screen->getPalette(0); - memset(pal, 0, 768); - _screen->setScreenPalette(pal); + _screen->getPalette(0).clear(); + _screen->setScreenPalette(_screen->getPalette(0)); _screen->clearPage(0); _screen->clearPage(4); @@ -803,25 +802,24 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) { switch (character) { case 0: - _screen->loadBitmap("KIERAN.CPS", 3, 3, _screen->getPalette(0)); + _screen->loadBitmap("KIERAN.CPS", 3, 3, &_screen->getPalette(0)); break; case 1: - _screen->loadBitmap("AK'SHEL.CPS", 3, 3, _screen->getPalette(0)); + _screen->loadBitmap("AK'SHEL.CPS", 3, 3, &_screen->getPalette(0)); break; case 2: - _screen->loadBitmap("MICHAEL.CPS", 3, 3, _screen->getPalette(0)); + _screen->loadBitmap("MICHAEL.CPS", 3, 3, &_screen->getPalette(0)); break; case 3: - _screen->loadBitmap("CONRAD.CPS", 3, 3, _screen->getPalette(0)); + _screen->loadBitmap("CONRAD.CPS", 3, 3, &_screen->getPalette(0)); break; default: _screen->clearPage(3); - memset(_screen->getPalette(0), 0, 768); - break; + _screen->getPalette(0).clear(); } _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); @@ -856,8 +854,8 @@ void LoLEngine::showCredits() { _screen->setTextColorMap(colorMap); _screen->_charWidth = 0; - _screen->loadBitmap("ROOM.CPS", 2, 2, _screen->getPalette(0)); - memset(_screen->getPalette(0) + 764, 0, 3); + _screen->loadBitmap("ROOM.CPS", 2, 2, &_screen->getPalette(0)); + _screen->getPalette(0).fill(255, 1, 0); _screen->fadeToBlack(30); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); @@ -865,7 +863,7 @@ void LoLEngine::showCredits() { _screen->_charOffset = 0; char *credits = (char *)_res->fileData("CREDITS.TXT", 0); - processCredits(credits, 19, 4, 5); + processCredits(credits, 21, 4, 5); delete[] credits; uint32 endTime = _system->getMillis() + 120 * _tickLength; @@ -895,8 +893,8 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { uint8 *doorShape = _screen->makeShapeCopy(_screen->getCPagePtr(5), 0); assert(doorShape); - _screen->drawShape(0, doorShape, 0, 0, 20, 0x10); - _screen->drawShape(0, doorShape, 0, 0, 21, 0x11); + _screen->drawShape(0, doorShape, 0, 0, 22, 0x10); + _screen->drawShape(0, doorShape, 0, 0, 23, 0x11); int curShapeFile = 0; uint8 *shapes[12]; @@ -906,7 +904,7 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { uint8 *monsterPal = _res->fileData("MONSTERS.PAL", 0); assert(monsterPal); - memcpy(_screen->getPalette(0) + 88 * 3, monsterPal + 0 * 3, 40 * 3); + _screen->getPalette(0).copy(monsterPal, 0, 40, 88); _screen->fadePalette(_screen->getPalette(0), 30); uint32 waitTimer = _system->getMillis(); @@ -1042,8 +1040,8 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { } else { if (!monsterAnimFrame && doorRedraw) { _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, page, Screen::CR_NO_P_CHECK); - _screen->drawShape(page, doorShape, 0, 0, 20, 0x10); - _screen->drawShape(page, doorShape, 0, 0, 21, 0x11); + _screen->drawShape(page, doorShape, 0, 0, 22, 0x10); + _screen->drawShape(page, doorShape, 0, 0, 23, 0x11); --frameCounter; doorRedraw = false; @@ -1062,32 +1060,32 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { bool isRightMonster = ((curShapeFile - 1) & 1) != 0; if (isRightMonster) { - doorSD = 21; + doorSD = 23; doorX = _outroRightDoorPos[monsterAnimFrame * 2 + 0]; doorY = _outroRightDoorPos[monsterAnimFrame * 2 + 1]; monsterX = _outroRightMonsterPos[monsterAnimFrame * 2 + 0]; monsterY = _outroRightMonsterPos[monsterAnimFrame * 2 + 1]; - _screen->drawShape(page, doorShape, 0, 0, 20, 0x10); + _screen->drawShape(page, doorShape, 0, 0, 22, 0x10); } else { - doorSD = 20; + doorSD = 22; doorX = _outroLeftDoorPos[monsterAnimFrame * 2 + 0]; doorY = _outroLeftDoorPos[monsterAnimFrame * 2 + 1]; monsterX = _outroLeftMonsterPos[monsterAnimFrame * 2 + 0]; monsterY = _outroLeftMonsterPos[monsterAnimFrame * 2 + 1]; - _screen->drawShape(page, doorShape, 0, 0, 21, 0x11); + _screen->drawShape(page, doorShape, 0, 0, 23, 0x11); } if (monsterAnimFrame >= 8) - _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 20) ? 0 : 1); + _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 22) ? 0 : 1); _screen->drawShape(page, monsterShape, monsterX, monsterY, 0, 0x104 | ((!isRightMonster | (monsterAnimFrame < 20)) ? 0 : 1), _outroShapeTable, 1, _outroMonsterScaleTableX[monsterAnimFrame], _outroMonsterScaleTableY[monsterAnimFrame]); if (monsterAnimFrame < 8) - _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 20) ? 0 : 1); + _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 22) ? 0 : 1); _screen->copyRegion(0, 0, 0, 0, 320, 200, page, 6, Screen::CR_NO_P_CHECK); doorRedraw = true; @@ -1129,7 +1127,7 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { curShapeFile = curShapeFile % 28; loadOutroShapes(curShapeFile, shapes); - memcpy(_screen->getPalette(0) + 88 * 3, monsterPal + curShapeFile * 40 * 3, 40 * 3); + _screen->getPalette(0).copy(monsterPal, curShapeFile * 40, 40, 88); _screen->setScreenPalette(_screen->getPalette(0)); needNewShape = false; diff --git a/engines/kyra/sound_lol.cpp b/engines/kyra/sound_lol.cpp index 3f87036849..63a42837aa 100644 --- a/engines/kyra/sound_lol.cpp +++ b/engines/kyra/sound_lol.cpp @@ -34,7 +34,7 @@ namespace Kyra { bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) { - if (!_speechFlag) + if (!speechEnabled()) return false; if (speaker < 65) { @@ -304,6 +304,15 @@ int LoLEngine::snd_stopMusic() { return snd_playTrack(-1); } +int LoLEngine::convertVolumeToMixer(int value) { + value -= 2; + return (value * Audio::Mixer::kMaxMixerVolume) / 100; +} + +int LoLEngine::convertVolumeFromMixer(int value) { + return (value * 100) / Audio::Mixer::kMaxMixerVolume + 2; +} + } // end of namespace Kyra #endif // ENABLE_LOL diff --git a/engines/kyra/sound_midi.cpp b/engines/kyra/sound_midi.cpp index f798251525..451b77cec2 100644 --- a/engines/kyra/sound_midi.cpp +++ b/engines/kyra/sound_midi.cpp @@ -311,10 +311,8 @@ void MidiOutput::sendSysEx(const byte p1, const byte p2, const byte p3, const by } void MidiOutput::metaEvent(byte type, byte *data, uint16 length) { - if (type == 0x2F) { // End of Track + if (type == 0x2F) // End of Track deinitSource(_curSource); - //XXX - } _output->metaEvent(type, data, length); } diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 1980f62d7c..fe0a44c052 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1504,7 +1504,7 @@ public: private: void updatesRegs(); - uint8 _updateRequestBuf[32]; + uint8 _updateRequestBuf[64]; int _updateRequest; int _rand; @@ -2657,7 +2657,7 @@ void TownsPC98_OpnSquareSineSource::writeReg(uint8 address, uint8 value, bool fo } if (!force) { - if (_updateRequest == 31) { + if (_updateRequest >= 63) { warning("TownsPC98_OpnSquareSineSource: event buffer overflow"); _updateRequest = -1; } @@ -3420,6 +3420,8 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : To } TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { + reset(); + if (_channels) { for (int i = 0; i < _numChan; i++) delete _channels[i]; @@ -4120,7 +4122,7 @@ void SoundPC98::playSoundEffect(uint8 track) { // This has been disabled for now since I don't know // how to make up the correct track number. It probably // needs a map. - //_driver->loadSoundEffectData(_sfxTrackData, track); + _driver->loadSoundEffectData(_sfxTrackData, track); } diff --git a/engines/kyra/sprites.cpp b/engines/kyra/sprites.cpp index 147ded3cfd..3cc632a391 100644 --- a/engines/kyra/sprites.cpp +++ b/engines/kyra/sprites.cpp @@ -47,7 +47,7 @@ Sprites::Sprites(KyraEngine_LoK *vm, OSystem *system) { _spriteDefStart = 0; memset(_drawLayerTable, 0, sizeof(_drawLayerTable)); _sceneAnimatorBeaconFlag = 0; - system->getEventManager()->registerRandomSource(_rnd, "kyraSprites"); + _vm->getEventManager()->registerRandomSource(_rnd, "kyraSprites"); } Sprites::~Sprites() { @@ -420,16 +420,16 @@ void Sprites::loadDat(const char *filename, SceneExits &exits) { if (_vm->gameFlags().platform == Common::kPlatformAmiga) { if (_vm->queryGameFlag(0xA0)) - memcpy(_screen->getPalette(3), _screen->getPalette(4), 32*3); + _screen->copyPalette(3, 4); else - memcpy(_screen->getPalette(3), _screen->getPalette(0), 32*3); + _screen->copyPalette(3, 0); } else { if (_vm->queryGameFlag(0xA0)) - memcpy(_screen->getPalette(1), _screen->getPalette(3), 768); + _screen->copyPalette(1, 3); else - memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); + _screen->copyPalette(1, 0); - _screen->loadPalette(_dat + 0x17, _screen->getPalette(1) + 684, 60); + _screen->getPalette(1).copy(_dat + 0x17, 0, 20, 228); } uint8 *data = _dat + 0x6B; diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp index 732a8bb2ca..8cee1dc5fc 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -784,7 +784,7 @@ int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) { default: return m->damageReceived ? 5 : m->currentSubFrame; } - + break; default: break; @@ -1092,7 +1092,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) { setMonsterMode(monster, 7); if ((monster->mode != 11) && (monster->mode != 14)) { - if (!(getRandomNumberSpecial() & 3)) { + if (!(_rnd.getRandomNumber(255) & 3)) { monster->shiftStep = (++monster->shiftStep) & 0x0f; checkSceneUpdateNeed(monster->block); } diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 3f41768c3c..e8597c8326 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -1584,7 +1584,7 @@ void KyraEngine_LoK::loadMainScreen(int page) { _screen->clearPage(page); if (_flags.lang == Common::EN_ANY && !_flags.isTalkie && (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformAmiga)) - _screen->loadBitmap("MAIN15.CPS", page, page, _screen->getPalette(0)); + _screen->loadBitmap("MAIN15.CPS", page, page, &_screen->getPalette(0)); else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN || (_flags.isTalkie && _flags.lang == Common::IT_ITA)) _screen->loadBitmap("MAIN_ENG.CPS", page, page, 0); else if (_flags.lang == Common::FR_FRA) @@ -1599,7 +1599,7 @@ void KyraEngine_LoK::loadMainScreen(int page) { warning("no main graphics file found"); if (_flags.platform == Common::kPlatformAmiga) - memcpy(_screen->getPalette(1), _screen->getPalette(0), 32*3); + _screen->copyPalette(1, 0); _screen->copyRegion(0, 0, 0, 0, 320, 200, page, 0); } @@ -2011,9 +2011,108 @@ void LoLEngine::initStaticResource() { #undef cb } +void GUI_LoL::initStaticData() { + GUI_V2_BUTTON(_scrollUpButton, 20, 96, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0); + GUI_V2_BUTTON(_scrollDownButton, 21, 98, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0); + + for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i) + GUI_V2_BUTTON(_menuButtons[i], i, 0, 0, 0, 0, 0, 0x4487, 0, 0, 0, 0, 0, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0); + + GUI_LOL_MENU(_mainMenu, 9, 0x4000, 0, 7, -1, -1, -1, -1); + GUI_LOL_MENU_ITEM(_mainMenu.item[0], 0x4001, 16, 23, 176, 15, 0, 0); + GUI_LOL_MENU_ITEM(_mainMenu.item[1], 0x4002, 16, 40, 176, 15, 0, 0); + GUI_LOL_MENU_ITEM(_mainMenu.item[2], 0x4003, 16, 57, 176, 15, 0, 0); + GUI_LOL_MENU_ITEM(_mainMenu.item[3], 0x4004, 16, 74, 176, 15, 0, 0); + GUI_LOL_MENU_ITEM(_mainMenu.item[4], 0x42D9, 16, 91, 176, 15, 0, 0); + GUI_LOL_MENU_ITEM(_mainMenu.item[5], 0x4006, 16, 108, 176, 15, 0, 0); + GUI_LOL_MENU_ITEM(_mainMenu.item[6], 0x4005, 88, 127, 104, 15, 0, 110); + Button::Callback mainMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedMainMenu); + for (int i = 0; i < 7; ++i) + _mainMenu.item[i].callback = mainMenuFunctor; + + GUI_LOL_MENU(_loadMenu, 10, 0x400e, 1, 5, 128, 20, 128, 118); + GUI_LOL_MENU_ITEM(_loadMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_loadMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_loadMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_loadMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_loadMenu.item[4], 0x4011, 168, 118, 96, 15, 0, 110); + Button::Callback loadMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedLoadMenu); + for (int i = 0; i < 5; ++i) + _loadMenu.item[i].callback = loadMenuFunctor; + + GUI_LOL_MENU(_saveMenu, 10, 0x400d, 1, 5, 128, 20, 128, 118); + GUI_LOL_MENU_ITEM(_saveMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_saveMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_saveMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_saveMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_saveMenu.item[4], 0x4011, 168, 118, 96, 15, 0, 110); + Button::Callback saveMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedSaveMenu); + for (int i = 0; i < 5; ++i) + _saveMenu.item[i].callback = saveMenuFunctor; + + GUI_LOL_MENU(_deleteMenu, 10, 0x400f, 1, 5, 128, 20, 128, 118); + GUI_LOL_MENU_ITEM(_deleteMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_deleteMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_deleteMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_deleteMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_deleteMenu.item[4], 0x4011, 168, 118, 96, 15, 0, 110); + Button::Callback deleteMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedDeleteMenu); + for (int i = 0; i < 5; ++i) + _deleteMenu.item[i].callback = deleteMenuFunctor; + + GUI_LOL_MENU(_gameOptions, 17, 0x400c, 0, 6, -1, -1, -1, -1); + GUI_LOL_MENU_ITEM(_gameOptions.item[0], 0xfff7, 120, 22, 80, 15, 0x406e, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[1], 0xfff6, 120, 39, 80, 15, 0x406c, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[2], 0xfff5, 120, 56, 80, 15, 0x406d, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[3], 0xfff4, 120, 73, 80, 15, 0x42d5, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[4], 0xfff3, 120, 90, 80, 15, 0x42d2, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[5], 0x4072, 104, 110, 96, 15, 0, 110); + Button::Callback optionsMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedOptionsMenu); + for (int i = 0; i < 6; ++i) + _gameOptions.item[i].callback = optionsMenuFunctor; + + GUI_LOL_MENU(_audioOptions, 18, 0x42d9, 2, 1, -1, -1, -1, -1); + GUI_LOL_MENU_ITEM(_audioOptions.item[0], 0x4072, 152, 76, 96, 15, 0, 110); + GUI_LOL_MENU_ITEM(_audioOptions.item[1], 3, 128, 22, 114, 14, 0x42db, 0); + GUI_LOL_MENU_ITEM(_audioOptions.item[2], 4, 128, 39, 114, 14, 0x42da, 0); + GUI_LOL_MENU_ITEM(_audioOptions.item[3], 5, 128, 56, 114, 14, 0x42dc, 0); + Button::Callback audioMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedAudioMenu); + for (int i = 0; i < 4; ++i) + _audioOptions.item[i].callback = audioMenuFunctor; + + GUI_LOL_MENU(_deathMenu, 11, 0x4013, 0, 2, -1, -1, -1, -1); + GUI_LOL_MENU_ITEM(_deathMenu.item[0], 0x4006, 8, 30, 104, 15, 0, 0); + GUI_LOL_MENU_ITEM(_deathMenu.item[1], 0x4001, 176, 30, 104, 15, 0, 0); + Button::Callback deathMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedDeathMenu); + for (int i = 0; i < 2; ++i) + _deathMenu.item[i].callback = deathMenuFunctor; + + GUI_LOL_MENU(_savenameMenu, 7, 0x4053, 0, 2, -1, -1, -1, -1); + GUI_LOL_MENU_ITEM(_savenameMenu.item[0], 0x4012, 8, 38, 72, 15, 0, 43); + GUI_LOL_MENU_ITEM(_savenameMenu.item[1], 0x4011, 176, 38, 72, 15, 0, 110); + Button::Callback savenameMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedSavenameMenu); + for (int i = 0; i < 2; ++i) + _savenameMenu.item[i].callback = savenameMenuFunctor; + + GUI_LOL_MENU(_choiceMenu, 11, 0, 0, 2, -1, -1, -1, -1); + GUI_LOL_MENU_ITEM(_choiceMenu.item[0], 0x4007, 8, 30, 72, 15, 0, 0); + GUI_LOL_MENU_ITEM(_choiceMenu.item[1], 0x4008, 208, 30, 72, 15, 0, 0); + Button::Callback choiceMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedChoiceMenu); + for (int i = 0; i < 2; ++i) + _choiceMenu.item[i].callback = choiceMenuFunctor; +} #endif // ENABLE_LOL +const uint8 Screen_LoK_16::_palette16[48] = { + 0x00, 0x00, 0x00, 0x02, 0x07, 0x0B, 0x0C, 0x06, 0x04, + 0x0E, 0x09, 0x07, 0x00, 0x06, 0x03, 0x00, 0x0C, 0x07, + 0x0A, 0x0A, 0x0A, 0x08, 0x03, 0x03, 0x02, 0x02, 0x02, + 0x08, 0x0B, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x05, 0x05, 0x05, 0x00, 0x0F, 0x0F, 0x0F, 0x0D, 0x00, + 0x0F, 0x0F, 0x0F +}; + const ScreenDim Screen_LoK::_screenDimTable[] = { { 0x00, 0x00, 0x28, 0xC8, 0x0F, 0x0C, 0x00, 0x00 }, { 0x08, 0x48, 0x18, 0x38, 0x0F, 0x0C, 0x00, 0x00 }, @@ -3018,6 +3117,8 @@ const ScreenDim Screen_LoL::_screenDimTable256C[] = { { 0x0D, 0xA2, 0x18, 0x0C, 0xFE, 0x01, 0x00, 0x00 }, { 0x0F, 0x06, 0x14, 0x6E, 0x01, 0x00, 0x00, 0x00 }, { 0x1A, 0xBE, 0x0A, 0x07, 0xFE, 0x01, 0x00, 0x00 }, + { 0x07, 0x21, 0x1A, 0x85, 0x00, 0x00, 0x00, 0x00 }, + { 0x03, 0x32, 0x22, 0x62, 0x00, 0x00, 0x00, 0x00 }, { 0x0B, 0x8C, 0x10, 0x33, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (5 entries, CD version only) { 0x0B, 0x8C, 0x10, 0x23, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (3 entries, floppy version only) @@ -3045,6 +3146,8 @@ const ScreenDim Screen_LoL::_screenDimTable16C[] = { { 0x0D, 0xA2, 0x18, 0x0C, 0x33, 0x44, 0x00, 0x00 }, { 0x0F, 0x06, 0x14, 0x6E, 0x44, 0x00, 0x00, 0x00 }, { 0x1A, 0xBE, 0x0A, 0x07, 0x33, 0x44, 0x00, 0x00 }, + { 0x07, 0x21, 0x1A, 0x85, 0x00, 0x00, 0x00, 0x00 }, + { 0x03, 0x32, 0x22, 0x62, 0x00, 0x00, 0x00, 0x00 }, { 0x0B, 0x8C, 0x10, 0x33, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (5 entries, not used here) { 0x0B, 0x8C, 0x10, 0x23, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (3 entries) @@ -3056,6 +3159,42 @@ const ScreenDim Screen_LoL::_screenDimTable16C[] = { const int Screen_LoL::_screenDimTableCount = ARRAYSIZE(Screen_LoL::_screenDimTable256C); +// 256 -> 16 color conversion table +const uint8 Screen_LoL::_paletteConvTable[256] = { + 0x0, 0x1, 0x0, 0x3, 0x0, 0x5, 0x0, 0x7, + 0x0, 0x9, 0x0, 0xB, 0x0, 0xD, 0x0, 0xF, + 0x1, 0x1, 0x1, 0x3, 0x1, 0x5, 0x1, 0x7, + 0x1, 0x9, 0x1, 0xB, 0x1, 0xD, 0x1, 0xF, + 0x2, 0x1, 0x2, 0x3, 0x2, 0x5, 0x2, 0x7, + 0x2, 0x9, 0x2, 0xB, 0x2, 0xD, 0x2, 0xF, + 0x3, 0x1, 0x3, 0x3, 0x3, 0x5, 0x3, 0x7, + 0x3, 0x9, 0x3, 0xB, 0x3, 0xD, 0x3, 0xF, + 0x4, 0x1, 0x4, 0x3, 0x4, 0x5, 0x4, 0x7, + 0x4, 0x9, 0x4, 0xB, 0x4, 0xD, 0x4, 0xF, + 0x5, 0x1, 0x5, 0x3, 0x5, 0x5, 0x5, 0x7, + 0x5, 0x9, 0x5, 0xB, 0x5, 0xD, 0x5, 0xF, + 0x6, 0x1, 0x6, 0x3, 0x6, 0x5, 0x6, 0x7, + 0x6, 0x9, 0x6, 0xB, 0x6, 0xD, 0x6, 0xF, + 0x7, 0x1, 0x7, 0x3, 0x7, 0x5, 0x7, 0x7, + 0x7, 0x9, 0x7, 0xB, 0x7, 0xD, 0x7, 0xF, + 0x8, 0x1, 0x8, 0x3, 0x8, 0x5, 0x8, 0x7, + 0x8, 0x9, 0x8, 0xB, 0x8, 0xD, 0x8, 0xF, + 0x9, 0x1, 0x9, 0x3, 0x9, 0x5, 0x9, 0x7, + 0x9, 0x9, 0x9, 0xB, 0x9, 0xD, 0x9, 0xF, + 0xA, 0x1, 0xA, 0x3, 0xA, 0x5, 0xA, 0x7, + 0xA, 0x9, 0xA, 0xB, 0xA, 0xD, 0xA, 0xF, + 0xB, 0x1, 0xB, 0x3, 0xB, 0x5, 0xB, 0x7, + 0xB, 0x9, 0xB, 0xB, 0xB, 0xD, 0xB, 0xF, + 0xC, 0x1, 0xC, 0x3, 0xC, 0x5, 0xC, 0x7, + 0xC, 0x9, 0xC, 0xB, 0xC, 0xD, 0xC, 0xF, + 0xD, 0x1, 0xD, 0x3, 0xD, 0x5, 0xD, 0x7, + 0xD, 0x9, 0xD, 0xB, 0xD, 0xD, 0xD, 0xF, + 0xE, 0x1, 0xE, 0x3, 0xE, 0x5, 0xE, 0x7, + 0xE, 0x9, 0xE, 0xB, 0xE, 0xD, 0xE, 0xF, + 0xF, 0x1, 0xF, 0x3, 0xF, 0x5, 0xF, 0x7, + 0xF, 0x9, 0xF, 0xB, 0xF, 0xD, 0xF, 0xF +}; + const char * const LoLEngine::_languageExt[] = { "ENG", "FRE", @@ -3241,4 +3380,3 @@ const int LoLEngine::_outroMonsterScaleTableY[] = { #endif // ENABLE_LOL } // End of namespace Kyra - diff --git a/engines/kyra/text_lok.cpp b/engines/kyra/text_lok.cpp index 6b1cb4eca2..3f4bfb65ac 100644 --- a/engines/kyra/text_lok.cpp +++ b/engines/kyra/text_lok.cpp @@ -39,12 +39,9 @@ void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const uint8 currPage; Common::Event event; - //while (towns_isEscKeyPressed() ) - //towns_getKey(); - uint32 timeToEnd = strlen(chatStr) * 8 * _tickLength + _system->getMillis(); - if (_configVoice == 0 && chatDuration != -1) { + if (textEnabled() && !speechEnabled() && chatDuration != -1) { switch (_configTextspeed) { case 0: chatDuration *= 2; @@ -136,7 +133,6 @@ void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const _timer->enable(15); _timer->enable(18); _timer->enable(19); - //clearKyrandiaButtonIO(); } void KyraEngine_LoK::endCharacterChat(int8 charNum, int16 convoInitialized) { @@ -329,11 +325,11 @@ void KyraEngine_LoK::drawSentenceCommand(const char *sentence, int color) { _screen->fillRect(8, 143, 311, 152, 12); if (_startSentencePalIndex != color || _fadeText != false) { - _currSentenceColor[0] = _screen->_currentPalette[765] = _screen->_currentPalette[color*3]; - _currSentenceColor[1] = _screen->_currentPalette[766] = _screen->_currentPalette[color*3+1]; - _currSentenceColor[2] = _screen->_currentPalette[767] = _screen->_currentPalette[color*3+2]; + _currSentenceColor[0] = _screen->getPalette(0)[765] = _screen->getPalette(0)[color*3]; + _currSentenceColor[1] = _screen->getPalette(0)[766] = _screen->getPalette(0)[color*3+1]; + _currSentenceColor[2] = _screen->getPalette(0)[767] = _screen->getPalette(0)[color*3+2]; - _screen->setScreenPalette(_screen->_currentPalette); + _screen->setScreenPalette(_screen->getPalette(0)); _startSentencePalIndex = 0; } @@ -368,10 +364,10 @@ void KyraEngine_LoK::updateTextFade() { } } - _screen->_currentPalette[765] = _currSentenceColor[0]; - _screen->_currentPalette[766] = _currSentenceColor[1]; - _screen->_currentPalette[767] = _currSentenceColor[2]; - _screen->setScreenPalette(_screen->_currentPalette); + _screen->getPalette(0)[765] = _currSentenceColor[0]; + _screen->getPalette(0)[766] = _currSentenceColor[1]; + _screen->getPalette(0)[767] = _currSentenceColor[2]; + _screen->setScreenPalette(_screen->getPalette(0)); if (finished) { _fadeText = false; diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp index 7ce12f47c7..2174bcc441 100644 --- a/engines/kyra/text_lol.cpp +++ b/engines/kyra/text_lol.cpp @@ -33,8 +33,8 @@ namespace Kyra { TextDisplayer_LoL::TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen) : _vm(vm), _screen(screen), - _scriptParameter(0), _animWidth(0), _animColor1(0), _animColor2(0), _animFlag(true), _lineCount(0), - _printFlag(false), _lineWidth(0), _numCharsTotal(0), _numCharsLeft(0), _numCharsPrinted(0) { + _scriptParameter(0), _lineCount(0), _printFlag(false), _lineWidth(0), _numCharsTotal(0), + _numCharsLeft(0), _numCharsPrinted(0) { memset(_stringParameters, 0, 15 * sizeof(char *)); _buffer = new char[600]; @@ -138,7 +138,7 @@ void TextDisplayer_LoL::resetDimTextPositions(int dim) { _textDimData[dim].line = 0; } -void TextDisplayer_LoL::setAnimParameters(const char *str, int x, uint8 col1, uint8 col2) { +/*void TextDisplayer_LoL::setAnimParameters(const char *str, int x, uint8 col1, uint8 col2) { static const char defaultStr[] = "<MORE>"; if (str) { @@ -152,7 +152,7 @@ void TextDisplayer_LoL::setAnimParameters(const char *str, int x, uint8 col1, ui _animColor1 = 0; _animColor2 = 0; } -} +}*/ void TextDisplayer_LoL::printDialogueText(int dim, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex) { int oldDim = 0; @@ -496,7 +496,7 @@ void TextDisplayer_LoL::printLine(char *str) { int lines = (sd->h - _screen->_charOffset) / fh; while (_textDimData[sdx].line >= lines) { - if (lines <= _lineCount && _animFlag) { + if (lines <= _lineCount) { _lineCount = 0; textPageBreak(); _numCharsPrinted = 0; @@ -521,8 +521,8 @@ void TextDisplayer_LoL::printLine(char *str) { char c = 0; if ((lw + _textDimData[sdx].column) > w) { - if ((lines - 1) <= _lineCount && _animFlag) - w -= (_animWidth * (_screen->getFontWidth() + _screen->_charWidth)); + if ((lines - 1) <= _lineCount) + w -= (10 * (_screen->getFontWidth() + _screen->_charWidth)); w -= _textDimData[sdx].column; @@ -608,7 +608,7 @@ void TextDisplayer_LoL::textPageBreak() { } uint32 speechPartTime = 0; - if (_vm->_speechFlag && _vm->_activeVoiceFileTotalTime && _numCharsTotal) + if (_vm->speechEnabled() && _vm->_activeVoiceFileTotalTime && _numCharsTotal) speechPartTime = _vm->_system->getMillis() + ((_numCharsPrinted * _vm->_activeVoiceFileTotalTime) / _numCharsTotal); const ScreenDim *dim = _screen->getScreenDim(_screen->curDimIndex()); @@ -643,7 +643,7 @@ void TextDisplayer_LoL::textPageBreak() { while (!inputFlag) { _vm->update(); - if (_vm->_speechFlag) { + if (_vm->speechEnabled()) { if (((_vm->_system->getMillis() > speechPartTime) || (_vm->snd_updateCharacterSpeech() != 2)) && speechPartTime) { loop = false; inputFlag = 43; diff --git a/engines/kyra/text_lol.h b/engines/kyra/text_lol.h index fc707843aa..06c13e1fef 100644 --- a/engines/kyra/text_lol.h +++ b/engines/kyra/text_lol.h @@ -40,9 +40,6 @@ public: TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen); ~TextDisplayer_LoL(); - void setAnimParameters(const char *str, int x, uint8 col1, uint8 col2); - void setAnimFlag(bool flag) { _animFlag = flag; } - void setupField(bool mode); void expandField(); @@ -80,12 +77,6 @@ private: uint32 _numCharsLeft; uint32 _numCharsPrinted; - const char *_animString; - int16 _animWidth; - uint8 _animColor1; - uint8 _animColor2; - - bool _animFlag; bool _printFlag; LoLEngine *_vm; diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp index e28d97d154..40f651ab01 100644 --- a/engines/kyra/text_mr.cpp +++ b/engines/kyra/text_mr.cpp @@ -581,7 +581,7 @@ void KyraEngine_MR::albumChatWaitToFinish() { frame = 13; albumRestoreRect(); - _album.wsa->displayFrame(frame, 2, -100, 90, 0x4000); + _album.wsa->displayFrame(frame, 2, -100, 90, 0x4000, 0, 0); albumUpdateRect(); nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(4, 8) * _tickLength; diff --git a/engines/kyra/util.cpp b/engines/kyra/util.cpp index 794a1c78e3..fe02ba49ba 100644 --- a/engines/kyra/util.cpp +++ b/engines/kyra/util.cpp @@ -85,5 +85,68 @@ void Util::decodeString2(const char *src, char *dst) { *dst = 0; } +void Util::convertDOSToISO(char *str) { + uint8 *s = (uint8 *)str; + + for (; *s; ++s) { + if (*s >= 128) { + uint8 c = _charMapDOSToISO[*s - 128]; + + if (!c) + c = 0x20; + + *s = c; + } + } +} + +void Util::convertISOToDOS(char *str) { + while (*str) + convertISOToDOS(*str++); +} + +void Util::convertISOToDOS(char &c) { + uint8 code = (uint8)c; + if (code >= 128) { + code = _charMapISOToDOS[code - 128]; + if (!code) + code = 0x20; + } + + c = code; +} + +// CP850 to ISO-8859-1 (borrowed from engines/saga/font_map.cpp) +const uint8 Util::_charMapDOSToISO[128] = { + 199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, + 239, 238, 236, 196, 197, 201, 230, 198, 244, 246, 242, + 251, 249, 255, 214, 220, 248, 163, 216, 215, 0, 225, + 237, 243, 250, 241, 209, 170, 186, 191, 174, 172, 189, + 188, 161, 171, 187, 0, 0, 0, 0, 0, 193, 194, + 192, 169, 0, 0, 0, 0, 162, 165, 0, 0, 0, + 0, 0, 0, 0, 227, 195, 0, 0, 0, 0, 0, + 0, 0, 164, 240, 208, 202, 203, 200, 0, 205, 206, + 207, 0, 0, 0, 0, 166, 204, 0, 211, 223, 212, + 210, 245, 213, 181, 254, 222, 218, 219, 217, 253, 221, + 175, 180, 173, 177, 0, 190, 182, 167, 247, 184, 176, + 168, 183, 185, 179, 178, 0, 160 +}; + +// ISO-8859-1 to CP850 +const uint8 Util::_charMapISOToDOS[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, + 173, 189, 156, 207, 190, 221, 245, 249, 184, 166, 174, + 170, 240, 169, 238, 248, 241, 253, 252, 239, 230, 244, + 250, 247, 251, 167, 175, 172, 171, 243, 168, 183, 181, + 182, 199, 142, 143, 146, 128, 212, 144, 210, 211, 222, + 214, 215, 216, 209, 165, 227, 224, 226, 229, 153, 158, + 157, 235, 233, 234, 154, 237, 232, 225, 133, 160, 131, + 198, 132, 134, 145, 135, 138, 130, 136, 137, 141, 161, + 140, 139, 208, 164, 149, 162, 147, 228, 148, 246, 155, + 151, 163, 150, 129, 236, 231, 152 +}; + } // end of namespace Kyra diff --git a/engines/kyra/util.h b/engines/kyra/util.h index ee869d9c04..6850a4d757 100644 --- a/engines/kyra/util.h +++ b/engines/kyra/util.h @@ -34,6 +34,16 @@ class Util { public: static int decodeString1(const char *src, char *dst); static void decodeString2(const char *src, char *dst); + + // Since our current GUI font uses ISO-8859-1, this + // conversion functionallty uses that as a base. + static void convertDOSToISO(char *str); + static void convertISOToDOS(char *str); + static void convertISOToDOS(char &c); + +private: + static const uint8 _charMapDOSToISO[128]; + static const uint8 _charMapISOToDOS[128]; }; } // end of namespace Kyra diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp index 0b8f9c99a2..1225bc9976 100644 --- a/engines/kyra/vqa.cpp +++ b/engines/kyra/vqa.cpp @@ -32,12 +32,14 @@ // The jung2.vqa movie does work, but only thanks to a grotesque hack. +#include "kyra/vqa.h" + #include "common/system.h" #include "sound/audiostream.h" #include "sound/mixer.h" + #include "kyra/sound.h" #include "kyra/screen.h" -#include "kyra/vqa.h" #include "kyra/resource.h" namespace Kyra { @@ -45,6 +47,7 @@ namespace Kyra { VQAMovie::VQAMovie(KyraEngine_v1 *vm, OSystem *system) { _system = system; _vm = vm; + _screen = _vm->screen(); _opened = false; _x = _y = _drawPage = -1; } @@ -474,13 +477,13 @@ void VQAMovie::displayFrame(uint frameNum) { case MKID_BE('CPL0'): // Palette assert(size <= 3 * 256); - _file->read(_vm->screen()->_currentPalette, size); + _file->read(_screen->getPalette(0).getData(), size); break; case MKID_BE('CPLZ'): // Palette inbuf = (byte *)allocBuffer(0, size); _file->read(inbuf, size); - Screen::decodeFrame4(inbuf, _vm->screen()->_currentPalette, 768); + Screen::decodeFrame4(inbuf, _screen->getPalette(0).getData(), 768); break; case MKID_BE('VPT0'): // Frame data @@ -520,9 +523,8 @@ void VQAMovie::displayFrame(uint frameNum) { // The frame has been decoded - if (_frameInfo[frameNum] & 0x80000000) { - _vm->screen()->setScreenPalette(_vm->screen()->_currentPalette); - } + if (_frameInfo[frameNum] & 0x80000000) + _screen->setScreenPalette(_screen->getPalette(0)); int blockPitch = _header.width / _header.blockW; @@ -562,7 +564,7 @@ void VQAMovie::displayFrame(uint frameNum) { _partialCodeBookSize = 0; } - _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _header.width, _header.height, _frame); + _screen->copyBlockToPage(_drawPage, _x, _y, _header.width, _header.height, _frame); } void VQAMovie::play() { @@ -638,6 +640,7 @@ void VQAMovie::play() { } _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sound, _stream); + Common::EventManager *eventMan = _vm->getEventManager(); for (uint i = 0; i < _header.numFrames; i++) { displayFrame(i); @@ -656,17 +659,17 @@ void VQAMovie::play() { break; Common::Event event; - - Common::EventManager *eventMan = _system->getEventManager(); while (eventMan->pollEvent(event)) { switch (event.type) { case Common::EVENT_KEYDOWN: - if (event.kbd.ascii == 27) + if (event.kbd.keycode == Common::KEYCODE_ESCAPE) return; break; + case Common::EVENT_RTL: case Common::EVENT_QUIT: return; + default: break; } @@ -675,7 +678,7 @@ void VQAMovie::play() { _system->delayMillis(10); } - _vm->screen()->updateScreen(); + _screen->updateScreen(); } // TODO: Wait for the sound to finish? diff --git a/engines/kyra/vqa.h b/engines/kyra/vqa.h index 46d3bd48fb..98e279bd29 100644 --- a/engines/kyra/vqa.h +++ b/engines/kyra/vqa.h @@ -26,13 +26,24 @@ #ifndef KYRA_VQA_H #define KYRA_VQA_H -#include "common/stream.h" +#include "common/scummsys.h" + +#include "sound/mixer.h" class OSystem; +namespace Audio { +class AppendableAudioStream; +} // end of namespace Audio + +namespace Common { +class SeekableReadStream; +} // end of namespace Common + namespace Kyra { class KyraEngine_v1; +class Screen; class VQAMovie { public: @@ -57,6 +68,7 @@ public: protected: OSystem *_system; KyraEngine_v1 *_vm; + Screen *_screen; bool _opened; int _x, _y; diff --git a/engines/kyra/wsamovie.cpp b/engines/kyra/wsamovie.cpp index 26638b8172..ef3fd1a966 100644 --- a/engines/kyra/wsamovie.cpp +++ b/engines/kyra/wsamovie.cpp @@ -38,7 +38,7 @@ namespace Kyra { WSAMovie_v1::WSAMovie_v1(KyraEngine_v1 *vm) : Movie(vm) {} WSAMovie_v1::~WSAMovie_v1() { close(); } -int WSAMovie_v1::open(const char *filename, int offscreenDecode, uint8 *palBuf) { +int WSAMovie_v1::open(const char *filename, int offscreenDecode, Palette *palBuf) { close(); uint32 flags = 0; @@ -64,7 +64,7 @@ int WSAMovie_v1::open(const char *filename, int offscreenDecode, uint8 *palBuf) offsPal = 0x300; _flags |= WF_HAS_PALETTE; if (palBuf) - memcpy(palBuf, wsaData + 8 + (_numFrames << 2), 0x300); + _screen->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), *palBuf, 0x300); } if (offscreenDecode) { @@ -137,19 +137,19 @@ void WSAMovie_v1::close() { } } -void WSAMovie_v1::displayFrame(int frameNum, int pageNum, int x, int y, ...) { - if (frameNum >= _numFrames || !_opened) +void WSAMovie_v1::displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2) { + if (frameNum >= _numFrames || frameNum < 0 || !_opened) return; _x = x; _y = y; _drawPage = pageNum; - uint8 *dst; + uint8 *dst = 0; if (_flags & WF_OFFSCREEN_DECODE) dst = _offscreenBuffer; else - dst = _vm->screen()->getPageRect(_drawPage, _x, _y, _width, _height); + dst = _screen->getPageRect(_drawPage, _x, _y, _width, _height); if (_currentFrame == _numFrames) { if (!(_flags & WF_NO_FIRST_FRAME)) { @@ -200,8 +200,16 @@ void WSAMovie_v1::displayFrame(int frameNum, int pageNum, int x, int y, ...) { // display _currentFrame = frameNum; - if (_flags & WF_OFFSCREEN_DECODE) - _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _width, _height, _offscreenBuffer); + if (_flags & WF_OFFSCREEN_DECODE) { + int pageBackUp = _screen->setCurPage(_drawPage); + + int plotFunc = (flags & 0xFF00) >> 12; + int unk1 = flags & 0xFF; + + _screen->copyWsaRect(_x, _y, _width, _height, 0, plotFunc, _offscreenBuffer, unk1, table1, table2); + + _screen->_curPage = pageBackUp; + } } void WSAMovie_v1::processFrame(int frameNum, uint8 *dst) { @@ -220,7 +228,7 @@ void WSAMovie_v1::processFrame(int frameNum, uint8 *dst) { WSAMovieAmiga::WSAMovieAmiga(KyraEngine_v1 *vm) : WSAMovie_v1(vm), _buffer(0) {} -int WSAMovieAmiga::open(const char *filename, int offscreenDecode, uint8 *palBuf) { +int WSAMovieAmiga::open(const char *filename, int offscreenDecode, Palette *palBuf) { int res = WSAMovie_v1::open(filename, offscreenDecode, palBuf); if (!res) @@ -239,7 +247,7 @@ void WSAMovieAmiga::close() { WSAMovie_v1::close(); } -void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, ...) { +void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2) { if (frameNum >= _numFrames || frameNum < 0 || !_opened) return; @@ -266,7 +274,7 @@ void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, ...) { dst = _buffer; } else { - _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _width, _height, _buffer); + _screen->copyBlockToPage(_drawPage, _x, _y, _width, _height, _buffer); } } _currentFrame = 0; @@ -311,8 +319,16 @@ void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, ...) { // display _currentFrame = frameNum; - if (_flags & WF_OFFSCREEN_DECODE) - _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _width, _height, _offscreenBuffer); + if (_flags & WF_OFFSCREEN_DECODE) { + int pageBackUp = _screen->setCurPage(_drawPage); + + int plotFunc = (flags & 0xFF00) >> 12; + int unk1 = flags & 0xFF; + + _screen->copyWsaRect(_x, _y, _width, _height, 0, plotFunc, _offscreenBuffer, unk1, table1, table2); + + _screen->_curPage = pageBackUp; + } } void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) { @@ -334,7 +350,7 @@ void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) { dst = _offscreenBuffer; dstPitch = _width; } else { - dst = _vm->screen()->getPageRect(_drawPage, _x, _y, _width, _height); + dst = _screen->getPageRect(_drawPage, _x, _y, _width, _height); dstPitch = Screen::SCREEN_W; } @@ -347,9 +363,9 @@ void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) { #pragma mark - -WSAMovie_v2::WSAMovie_v2(KyraEngine_v1 *vm, Screen_v2 *screen) : WSAMovie_v1(vm), _screen(screen), _xAdd(0), _yAdd(0) {} +WSAMovie_v2::WSAMovie_v2(KyraEngine_v1 *vm) : WSAMovie_v1(vm), _xAdd(0), _yAdd(0) {} -int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) { +int WSAMovie_v2::open(const char *filename, int unk1, Palette *palBuf) { close(); uint32 flags = 0; @@ -376,7 +392,7 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) { offsPal = 0x300; _flags |= WF_HAS_PALETTE; if (palBuf) - _vm->screen()->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), palBuf, 0x300); + _screen->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), *palBuf, 0x300); } if (flags & 2) { @@ -384,7 +400,7 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) { offsPal = 0x30; _flags |= WF_HAS_PALETTE; if (palBuf) - _vm->screen()->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), palBuf, 0x30); + _screen->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), *palBuf, 0x30); } _flags |= WF_XOR; @@ -448,90 +464,6 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) { return _numFrames; } -void WSAMovie_v2::displayFrame(int frameNum, int pageNum, int x, int y, ...) { - if (frameNum >= _numFrames || frameNum < 0 || !_opened) - return; - - _x = x + _xAdd; - _y = y + _yAdd; - _drawPage = pageNum; - - uint8 *dst = 0; - if (_flags & WF_OFFSCREEN_DECODE) - dst = _offscreenBuffer; - else - dst = _screen->getPageRect(_drawPage, _x, _y, _width, _height); - - if (_currentFrame == _numFrames) { - if (!(_flags & WF_NO_FIRST_FRAME)) { - if (_flags & WF_OFFSCREEN_DECODE) - Screen::decodeFrameDelta(dst, _deltaBuffer); - else - Screen::decodeFrameDeltaPage(dst, _deltaBuffer, _width, (_flags & WF_XOR) == 0); - } - _currentFrame = 0; - } - - // try to reduce the number of needed frame operations - int diffCount = ABS(_currentFrame - frameNum); - int frameStep = 1; - int frameCount; - if (_currentFrame < frameNum) { - frameCount = _numFrames - frameNum + _currentFrame; - if (diffCount > frameCount && !(_flags & WF_NO_LAST_FRAME)) - frameStep = -1; - else - frameCount = diffCount; - } else { - frameCount = _numFrames - _currentFrame + frameNum; - if (frameCount >= diffCount || (_flags & WF_NO_LAST_FRAME)) { - frameStep = -1; - frameCount = diffCount; - } - } - - // process - if (frameStep > 0) { - uint16 cf = _currentFrame; - while (frameCount--) { - cf += frameStep; - processFrame(cf, dst); - if (cf == _numFrames) - cf = 0; - } - } else { - uint16 cf = _currentFrame; - while (frameCount--) { - if (cf == 0) - cf = _numFrames; - processFrame(cf, dst); - cf += frameStep; - } - } - - // display - _currentFrame = frameNum; - if (_flags & WF_OFFSCREEN_DECODE) { - int pageBackUp = _screen->_curPage; - _screen->_curPage = _drawPage; - - va_list args; - va_start(args, y); - - int copyParam = va_arg(args, int); - int plotFunc = (copyParam & 0xFF00) >> 12; - int unk1 = copyParam & 0xFF; - - const uint8 *unkPtr1 = va_arg(args, const uint8*); - const uint8 *unkPtr2 = va_arg(args, const uint8*); - va_end(args); - - _screen->copyWsaRect(_x, _y, _width, _height, 0, plotFunc, _offscreenBuffer, unk1, unkPtr1, unkPtr2); - - _screen->_curPage = pageBackUp; - } -} - } // end of namespace Kyra diff --git a/engines/kyra/wsamovie.h b/engines/kyra/wsamovie.h index fdceca1cd8..49ac5a28fe 100644 --- a/engines/kyra/wsamovie.h +++ b/engines/kyra/wsamovie.h @@ -26,6 +26,7 @@ #ifndef KYRA_WSAMOVIE_H #define KYRA_WSAMOVIE_H + namespace Audio { class AppendableAudioStream; class SoundHandle; @@ -34,10 +35,11 @@ class SoundHandle; namespace Kyra { class KyraEngine_v1; class Screen_v2; +class Palette; class Movie { public: - Movie(KyraEngine_v1 *vm) : _vm(vm), _opened(false), _x(-1), _y(-1), _drawPage(-1) {} + Movie(KyraEngine_v1 *vm) : _vm(vm), _screen(vm->screen()), _opened(false), _x(-1), _y(-1), _drawPage(-1) {} virtual ~Movie() {} virtual bool opened() { return _opened; } @@ -48,15 +50,16 @@ public: virtual int width() const = 0; virtual int height() const = 0; - virtual int open(const char *filename, int offscreen, uint8 *palette) = 0; + virtual int open(const char *filename, int offscreen, Palette *palette) = 0; virtual void close() = 0; virtual int frames() = 0; - virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...) = 0; + virtual void displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2) = 0; protected: KyraEngine_v1 *_vm; + Screen *_screen; bool _opened; int _x, _y; @@ -71,12 +74,12 @@ public: int width() const { return _width; } int height() const { return _height; } - virtual int open(const char *filename, int offscreen, uint8 *palette); + virtual int open(const char *filename, int offscreen, Palette *palette); virtual void close(); virtual int frames() { return _opened ? _numFrames : -1; } - virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...); + virtual void displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2); enum WSAFlags { WF_OFFSCREEN_DECODE = 0x10, @@ -104,10 +107,10 @@ protected: class WSAMovieAmiga : public WSAMovie_v1 { public: WSAMovieAmiga(KyraEngine_v1 *vm); - int open(const char *filename, int offscreen, uint8 *palette); + int open(const char *filename, int offscreen, Palette *palette); void close(); - void displayFrame(int frameNum, int pageNum, int x, int y, ...); + void displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2); private: void processFrame(int frameNum, uint8 *dst); @@ -116,11 +119,12 @@ private: class WSAMovie_v2 : public WSAMovie_v1 { public: - WSAMovie_v2(KyraEngine_v1 *vm, Screen_v2 *screen); - - int open(const char *filename, int unk1, uint8 *palette); + WSAMovie_v2(KyraEngine_v1 *vm); - virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...); + int open(const char *filename, int unk1, Palette *palette); + virtual void displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2) { + WSAMovie_v1::displayFrame(frameNum, pageNum, x + _xAdd, y + _yAdd, flags, table1, table2); + } int xAdd() const { return _xAdd; } int yAdd() const { return _yAdd; } @@ -128,8 +132,6 @@ public: void setWidth(int w) { _width = w; } void setHeight(int h) { _height = h; } protected: - Screen_v2 *_screen; - int16 _xAdd; int16 _yAdd; }; |