From 60e7cbfe11a01fb6b2d47e4846ac4cacb5e20a37 Mon Sep 17 00:00:00 2001 From: Martin Gerhardy Date: Thu, 22 Oct 2020 16:32:52 +0200 Subject: [PATCH] TWINE: started to refactor the main loop --- engines/twine/interface.cpp | 107 +++++++++++------------------- engines/twine/menu.cpp | 128 ++++++++++++++++++------------------ engines/twine/menu.h | 15 ++++- engines/twine/text.cpp | 5 +- engines/twine/twine.cpp | 17 +++-- 5 files changed, 128 insertions(+), 144 deletions(-) diff --git a/engines/twine/interface.cpp b/engines/twine/interface.cpp index 74177c96c2c..902b6b750d7 100644 --- a/engines/twine/interface.cpp +++ b/engines/twine/interface.cpp @@ -48,19 +48,12 @@ int32 Interface::checkClipping(int32 x, int32 y) { // TODO: check if Graphics::drawLine() works here void Interface::drawLine(int32 startWidth, int32 startHeight, int32 endWidth, int32 endHeight, int32 lineColor) { - int32 temp; - int32 flag2; - uint8 *out; - int16 color; - int16 var2; - int16 xchg; - int32 outcode0, outcode1; - int32 x, y, outcodeOut; int32 currentLineColor = lineColor; + uint8 *out; // draw line from left to right if (startWidth > endWidth) { - temp = endWidth; + int32 temp = endWidth; endWidth = startWidth; startWidth = temp; @@ -70,16 +63,18 @@ void Interface::drawLine(int32 startWidth, int32 startHeight, int32 endWidth, in } // Perform proper clipping (CohenSutherland algorithm) - outcode0 = checkClipping(startWidth, startHeight); - outcode1 = checkClipping(endWidth, endHeight); + int32 outcode0 = checkClipping(startWidth, startHeight); + int32 outcode1 = checkClipping(endWidth, endHeight); while ((outcode0 | outcode1) != 0) { if (((outcode0 & outcode1) != 0) && (outcode0 != INSIDE)) return; // Reject lines which are behind one clipping plane // At least one endpoint is outside the clip rectangle; pick it. - outcodeOut = outcode0 ? outcode0 : outcode1; + int32 outcodeOut = outcode0 ? outcode0 : outcode1; + int32 x = 0; + int32 y = 0; if (outcodeOut & TOP) { // point is above the clip rectangle x = startWidth + (int)((endWidth - startWidth) * (float)(textWindowTop - startHeight) / (float)(endHeight - startHeight)); y = textWindowTop; @@ -106,7 +101,7 @@ void Interface::drawLine(int32 startWidth, int32 startHeight, int32 endWidth, in } } - flag2 = 640; //SCREEN_WIDTH; + int32 flag2 = DEFAULT_SCREEN_WIDTH; endWidth -= startWidth; endHeight -= startHeight; if (endHeight < 0) { @@ -116,12 +111,12 @@ void Interface::drawLine(int32 startWidth, int32 startHeight, int32 endWidth, in out = (uint8*)_engine->frontVideoBuffer.getPixels() + _engine->screenLookupTable[startHeight] + startWidth; - color = currentLineColor; + int16 color = currentLineColor; if (endWidth < endHeight) { // significant slope - xchg = endWidth; + int16 xchg = endWidth; endWidth = endHeight; endHeight = xchg; - var2 = endWidth; + int16 var2 = endWidth; var2 <<= 1; startHeight = endWidth; endHeight <<= 1; @@ -137,7 +132,7 @@ void Interface::drawLine(int32 startWidth, int32 startHeight, int32 endWidth, in } } while (--endWidth); } else { // reduced slope - var2 = endWidth; + int16 var2 = endWidth; var2 <<= 1; startHeight = endWidth; endHeight <<= 1; @@ -155,29 +150,20 @@ void Interface::drawLine(int32 startWidth, int32 startHeight, int32 endWidth, in } void Interface::blitBox(int32 left, int32 top, int32 right, int32 bottom, const int8 *source, int32 leftDest, int32 topDest, int8 *dest) { - int32 width; - int32 height; - const int8 *s; - int8 *d; - int32 insideLine; - int32 temp3; - int32 i; - int32 j; + const int8 *s = _engine->screenLookupTable[top] + source + left; + int8 *d = _engine->screenLookupTable[topDest] + dest + leftDest; - s = _engine->screenLookupTable[top] + source + left; - d = _engine->screenLookupTable[topDest] + dest + leftDest; + int32 width = right - left + 1; + int32 height = bottom - top + 1; - width = right - left + 1; - height = bottom - top + 1; - - insideLine = SCREEN_WIDTH - width; - temp3 = left; + int32 insideLine = SCREEN_WIDTH - width; + int32 temp3 = left; left >>= 2; temp3 &= 3; - for (j = 0; j < height; j++) { - for (i = 0; i < width; i++) { + for (int32 j = 0; j < height; j++) { + for (int32 i = 0; i < width; i++) { *(d++) = *(s++); } @@ -187,16 +173,6 @@ void Interface::blitBox(int32 left, int32 top, int32 right, int32 bottom, const } void Interface::drawTransparentBox(int32 left, int32 top, int32 right, int32 bottom, int32 colorAdj) { - uint8 *pos; - int32 width; - int32 height; - int32 height2; - int32 temp; - int32 localMode; - int32 var1; - int8 color; - int8 color2; - if (left > SCREEN_TEXTLIMIT_RIGHT) return; if (right < SCREEN_TEXTLIMIT_LEFT) @@ -215,42 +191,33 @@ void Interface::drawTransparentBox(int32 left, int32 top, int32 right, int32 bot if (bottom > SCREEN_TEXTLIMIT_BOTTOM) bottom = SCREEN_TEXTLIMIT_BOTTOM; - pos = _engine->screenLookupTable[top] + (uint8*)_engine->frontVideoBuffer.getPixels() + left; - height2 = height = bottom - top; - height2++; - - width = right - left + 1; - - temp = 640 - width; // SCREEN_WIDTH - localMode = colorAdj; + uint8 *pos = (uint8*)_engine->frontVideoBuffer.getPixels() + _engine->screenLookupTable[top] + left; + int32 height = bottom - top; + int32 height2 = height + 1; + int32 width = right - left + 1; + int32 pitch = DEFAULT_SCREEN_WIDTH - width; + int32 localMode = colorAdj; do { - var1 = width; + int32 var1 = width; do { - color2 = color = *pos; - color2 &= 0xF0; - color &= 0x0F; + int8 color = *pos & 0x0F; + const int8 color2 = *pos & 0xF0; color -= localMode; - if (color < 0) + if (color < 0) { color = color2; - else + } else { color += color2; + } *pos++ = color; var1--; } while (var1 > 0); - pos += temp; + pos += pitch; height2--; } while (height2 > 0); } void Interface::drawSplittedBox(int32 left, int32 top, int32 right, int32 bottom, uint8 e) { // Box - uint8 *ptr; - - int32 offset; - - int32 x; - int32 y; - if (left > SCREEN_TEXTLIMIT_RIGHT) return; if (right < SCREEN_TEXTLIMIT_LEFT) @@ -261,12 +228,12 @@ void Interface::drawSplittedBox(int32 left, int32 top, int32 right, int32 bottom return; // cropping - offset = -((right - left) - SCREEN_WIDTH); + int32 offset = -((right - left) - SCREEN_WIDTH); - ptr = (uint8*)_engine->frontVideoBuffer.getPixels() + _engine->screenLookupTable[top] + left; + uint8 *ptr = (uint8*)_engine->frontVideoBuffer.getPixels() + _engine->screenLookupTable[top] + left; - for (x = top; x < bottom; x++) { - for (y = left; y < right; y++) { + for (int32 x = top; x < bottom; x++) { + for (int32 y = left; y < right; y++) { *(ptr++) = e; } ptr += offset; diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp index ffb9b568c53..3412edadf96 100644 --- a/engines/twine/menu.cpp +++ b/engines/twine/menu.cpp @@ -230,7 +230,7 @@ void Menu::plasmaEffectRenderFrame() { for (j = 1; j < PLASMA_HEIGHT - 1; j++) { for (i = 1; i < PLASMA_WIDTH - 1; i++) { - /*Here we calculate the average of all 8 neighbour pixel values*/ + /* Here we calculate the average of all 8 neighbour pixel values */ c = plasmaEffectPtr[(i - 1) + (j - 1) * PLASMA_WIDTH]; //top-left c += plasmaEffectPtr[(i + 0) + (j - 1) * PLASMA_WIDTH]; //top @@ -243,8 +243,9 @@ void Menu::plasmaEffectRenderFrame() { c += plasmaEffectPtr[(i + 0) + (j + 1) * PLASMA_WIDTH]; // bottom c += plasmaEffectPtr[(i + 1) + (j + 1) * PLASMA_WIDTH]; // bottom-right - c = (c >> 3) | ((c & 0x0003) << 13); /* And the 2 least significant bits are used as a - randomizing parameter for statistically fading the flames */ + /* And the 2 least significant bits are used as a + * randomizing parameter for statistically fading the flames */ + c = (c >> 3) | ((c & 0x0003) << 13); if (!(c & 0x6500) && (j >= (PLASMA_HEIGHT - 4) || c > 0)) { @@ -264,25 +265,21 @@ void Menu::plasmaEffectRenderFrame() { } void Menu::processPlasmaEffect(int32 top, int32 color) { - uint8 *in; - uint8 *out; - int32 i, j, target; - uint8 c; - uint8 max_value = color + 15; + const uint8 max_value = color + 15; plasmaEffectRenderFrame(); - in = plasmaEffectPtr + 5 * PLASMA_WIDTH; - out = (uint8 *)_engine->frontVideoBuffer.getPixels() + _engine->screenLookupTable[top]; + uint8 *in = plasmaEffectPtr + 5 * PLASMA_WIDTH; + uint8 *out = (uint8 *)_engine->frontVideoBuffer.getPixels() + _engine->screenLookupTable[top]; - for (i = 0; i < 25; i++) { - for (j = 0; j < kMainMenuButtonWidth; j++) { - c = in[i * kMainMenuButtonWidth + j] / 2 + color; + for (int32 i = 0; i < 25; i++) { + for (int32 j = 0; j < kMainMenuButtonWidth; j++) { + uint8 c = in[i * kMainMenuButtonWidth + j] / 2 + color; if (c > max_value) c = max_value; /* 2x2 squares sharing the same pixel color: */ - target = 2 * (i * SCREEN_W + j); + int32 target = 2 * (i * SCREEN_W + j); out[target] = c; out[target + 1] = c; out[target + SCREEN_W] = c; @@ -300,16 +297,19 @@ void Menu::drawBox(int32 left, int32 top, int32 right, int32 bottom) { void Menu::drawButtonGfx(int32 width, int32 topheight, int32 id, int32 value, int32 mode) { /* - * int CDvolumeRemaped; int musicVolumeRemaped; int masterVolumeRemaped; int lineVolumeRemaped; + * int CDvolumeRemaped; + * int musicVolumeRemaped; + * int masterVolumeRemaped; + * int lineVolumeRemaped; * int waveVolumeRemaped; */ int32 left = width - kMainMenuButtonSpan / 2; int32 right = width + kMainMenuButtonSpan / 2; - // topheigh is the center Y pos of the button + // topheight is the center Y pos of the button int32 top = topheight - 25; // this makes the button be 50 height - int32 bottom = topheight + 25; // || + int32 bottom = topheight + 25; int32 bottom2 = bottom; if (mode != 0) { @@ -423,12 +423,11 @@ void Menu::drawButton(const int16 *menuSettings, int32 mode) { } int32 Menu::processMenu(int16 *menuSettings) { - int16 *localData = menuSettings; - int16 currentButton = 0; // localData[0]; + int16 currentButton = menuSettings[MenuSettings_CurrentLoadedButton]; bool buttonReleased = true; bool buttonNeedRedraw = true; bool musicChanged = false; - int32 numEntry = localData[1]; + const int32 numEntry = menuSettings[MenuSettings_NumberOfButtons]; int32 localTime = _engine->lbaTime; int32 maxButton = numEntry - 1; @@ -436,7 +435,7 @@ int32 Menu::processMenu(int16 *menuSettings) { do { // if its on main menu - if (localData == MainMenuSettings) { + if (menuSettings == MainMenuSettings) { if (_engine->lbaTime - localTime > 11650) { return kBackground; } @@ -455,6 +454,7 @@ int32 Menu::processMenu(int16 *menuSettings) { _engine->_keyboard.key = _engine->_keyboard.pressedKey; if (((uint8)_engine->_keyboard.key & 2)) { // on arrow key down + debug("pressed down"); currentButton++; if (currentButton == numEntry) { // if current button is the last, than next button is the first currentButton = 0; @@ -464,6 +464,7 @@ int32 Menu::processMenu(int16 *menuSettings) { } if (((uint8)_engine->_keyboard.key & 1)) { // on arrow key up + debug("pressed up"); currentButton--; if (currentButton < 0) { // if current button is the first, than previous button is the last currentButton = maxButton; @@ -472,8 +473,9 @@ int32 Menu::processMenu(int16 *menuSettings) { buttonReleased = false; } - if (*(localData + 8) <= 5) { // if its a volume button - const int16 id = *(localData + currentButton * 2 + 4); // get button parameters from settings array + // if its a volume button + if ((menuSettings == OptionsMenuSettings || menuSettings == VolumeMenuSettings) && *(menuSettings + 8) <= 5) { + const int16 id = *(menuSettings + currentButton * 2 + MenuSettings_FirstButtonState); // get button parameters from settings array Audio::Mixer *mixer = _engine->_system->getMixer(); switch (id) { @@ -539,12 +541,12 @@ int32 Menu::processMenu(int16 *menuSettings) { } if (buttonNeedRedraw) { - *localData = currentButton; + menuSettings[MenuSettings_CurrentLoadedButton] = currentButton; - drawButton(localData, 0); // current button + drawButton(menuSettings, 0); // current button do { _engine->readKeys(); - drawButton(localData, 1); + drawButton(menuSettings, 1); } while (_engine->_keyboard.pressedKey == 0 && _engine->_keyboard.skippedKey == 0 && _engine->_keyboard.internalKeyCode == 0); buttonNeedRedraw = false; } else { @@ -552,14 +554,14 @@ int32 Menu::processMenu(int16 *menuSettings) { // TODO: update volume settings } - drawButton(localData, 1); + drawButton(menuSettings, 1); _engine->readKeys(); // WARNING: this is here to prevent a fade bug while quit the menu _engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer); } } while (!(_engine->_keyboard.skippedKey & 2) && !(_engine->_keyboard.skippedKey & 1)); - currentButton = *(localData + 5 + currentButton * 2); // get current browsed button + currentButton = *(menuSettings + MenuSettings_FirstButton + currentButton * 2); // get current browsed button _engine->readKeys(); @@ -679,50 +681,46 @@ int32 Menu::optionsMenu() { return 0; } -void Menu::mainMenu() { - _engine->_sound->stopSamples(); - - _engine->_screens->copyScreen(_engine->frontVideoBuffer, _engine->workVideoBuffer); - +bool Menu::init() { // load menu effect file only once plasmaEffectPtr = (uint8 *)malloc(kPlasmaEffectFilesize); memset(plasmaEffectPtr, 0, kPlasmaEffectFilesize); - _engine->_hqrdepack->hqrGetEntry(plasmaEffectPtr, Resources::HQR_RESS_FILE, RESSHQR_PLASMAEFFECT); + return _engine->_hqrdepack->hqrGetEntry(plasmaEffectPtr, Resources::HQR_RESS_FILE, RESSHQR_PLASMAEFFECT) > 0; +} - while (!_engine->shouldQuit()) { - _engine->_text->initTextBank(0); +void Menu::run() { + _engine->_text->initTextBank(0); - _engine->_music->playTrackMusic(9); // LBA's Theme - _engine->_sound->stopSamples(); + _engine->_music->playTrackMusic(9); // LBA's Theme + _engine->_sound->stopSamples(); - switch (processMenu(MainMenuSettings)) { - case kNewGame: { - _engine->_menuOptions->newGameMenu(); - break; - } - case kContinueGame: { - _engine->_menuOptions->continueGameMenu(); - break; - } - case kOptions: { - _engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer); - _engine->flip(); - OptionsMenuSettings[5] = kReturnMenu; - optionsMenu(); - break; - } - case kQuit: { - Common::Event event; - event.type = Common::EVENT_QUIT; - _engine->_system->getEventManager()->pushEvent(event); - break; - } - case kBackground: { - _engine->_screens->loadMenuImage(); - } - } - _engine->_system->delayMillis(1000 / _engine->cfgfile.Fps); + switch (processMenu(MainMenuSettings)) { + case kNewGame: { + _engine->_menuOptions->newGameMenu(); + break; } + case kContinueGame: { + _engine->_menuOptions->continueGameMenu(); + break; + } + case kOptions: { + _engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer); + _engine->flip(); + OptionsMenuSettings[5] = kReturnMenu; + optionsMenu(); + break; + } + case kQuit: { + Common::Event event; + event.type = Common::EVENT_QUIT; + _engine->_system->getEventManager()->pushEvent(event); + break; + } + case kBackground: { + _engine->_screens->loadMenuImage(); + } + } + _engine->_system->delayMillis(1000 / _engine->cfgfile.Fps); } int32 Menu::giveupMenu() { diff --git a/engines/twine/menu.h b/engines/twine/menu.h index 8c34f3d71a7..a764b93ec03 100644 --- a/engines/twine/menu.h +++ b/engines/twine/menu.h @@ -27,6 +27,17 @@ namespace TwinE { +enum MenuSettingsType { + // button number + MenuSettings_CurrentLoadedButton = 0, + // is used to calc the height where the first button will appear + MenuSettings_NumberOfButtons = 1, + MenuSettings_ButtonsBoxHeight = 2, + MenuSettings_HeaderEnd = 3, // TODO: unknown + MenuSettings_FirstButtonState = 4, + MenuSettings_FirstButton = 5 +}; + class Menu { private: TwinEEngine *_engine; @@ -124,8 +135,10 @@ public: */ int32 processMenu(int16 *menuSettings); + bool init(); + /** Used to run the main menu */ - void mainMenu(); + void run(); /** Used to run the in-game give-up menu */ int32 giveupMenu(); diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp index c9c9cccc7be..ae96deaa40b 100644 --- a/engines/twine/text.cpp +++ b/engines/twine/text.cpp @@ -257,10 +257,11 @@ void Text::drawText(int32 x, int32 y, const char *dialogue) { // Font return; do { - uint8 currChar = (uint8) *(dialogue++); // read the next char from the string + const uint8 currChar = (uint8) *(dialogue++); // read the next char from the string - if (currChar == 0) // if the char is 0x0, -> end of string + if (currChar == '\0') { break; + } if (currChar == ' ') { x += dialCharSpace; diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp index baf7b41fea6..26d94cb248a 100644 --- a/engines/twine/twine.cpp +++ b/engines/twine/twine.cpp @@ -142,6 +142,13 @@ Common::Error TwinEEngine::run() { allocVideoMemory(); initAll(); initEngine(); + _sound->stopSamples(); + _screens->copyScreen(frontVideoBuffer, workVideoBuffer); + + _menu->init(); + while (!shouldQuit()) { + _menu->run(); + } _music->stopTrackMusic(); _music->stopMidiMusic(); return Common::kNoError; @@ -258,8 +265,6 @@ void TwinEEngine::initEngine() { _flaMovies->playFlaMovie(FLA_DRAGON3); _screens->loadMenuImage(); - - _menu->mainMenu(); } void TwinEEngine::initMCGA() { @@ -358,7 +363,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration if (loopCurrentKey == twineactions[TwinEActionType::OptionsMenu].localKey) { freezeTime(); _sound->pauseSamples(); - _menu->OptionsMenuSettings[5] = 15; + _menu->OptionsMenuSettings[MenuSettings_FirstButton] = 15; _text->initTextBank(0); _menu->optionsMenu(); _text->initTextBank(_text->currentTextBank + 3); @@ -478,7 +483,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration _redraw->redrawEngineActions(1); } - // Process behaviour menu - Press CTRL and F1..F4 Keys + // Process behaviour menu if ((loopCurrentKey == twineactions[TwinEActionType::BehaviourMenu].localKey || loopCurrentKey == twineactions[TwinEActionType::QuickBehaviourNormal].localKey || loopCurrentKey == twineactions[TwinEActionType::QuickBehaviourAthletic].localKey || @@ -515,7 +520,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration } } - // Press Enter to Recenter Screen + // Recenter Screen if ((loopPressedKey & 2) && !disableScreenRecenter) { _grid->newCameraX = _scene->sceneActors[_scene->currentlyFollowedActor].x >> 9; _grid->newCameraY = _scene->sceneActors[_scene->currentlyFollowedActor].y >> 8; @@ -533,7 +538,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration _redraw->redrawEngineActions(1); } - // Process Pause - Press P + // Process Pause if (loopCurrentKey == twineactions[TwinEActionType::Pause].localKey) { freezeTime(); _text->setFontColor(15);