TWINE: started to refactor the main loop

This commit is contained in:
Martin Gerhardy 2020-10-22 16:32:52 +02:00 committed by Eugene Sandulenko
parent 3fbb55b76e
commit 60e7cbfe11
5 changed files with 128 additions and 144 deletions

View file

@ -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;

View file

@ -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() {

View file

@ -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();

View file

@ -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;

View file

@ -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);