scummvm/engines/agos/verb.cpp
athrxx be41ea3125 AGOS: (WW) - fix mouse cursor glitch
This one is pretty obvious when comparing ScummVM
with DOSBox behaviour. After the cursor changes to
one of the arrow cursors, it often stays that way when
it should actually switch back to the normal cursor. I have
fixed it to match the original code.
2024-03-27 21:55:11 +01:00

1048 lines
21 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
// Verb and hitarea handling
#include "common/system.h"
#include "graphics/surface.h"
#include "agos/agos.h"
#include "agos/intern.h"
namespace AGOS {
static const char *const russian_verb_names[] = {
"Ietj _",
"Qnotrft< pa",
"Nt_r[t<",
"Ecjdat<",
"Q=fst<",
"C^]t<",
"Ha_r[t<",
"Isqom<^ocat<",
"Docorjt<",
"Qp]t<",
"Neft<",
"Eat<"
};
static const char *const hebrew_verb_names[] = {
"LJ @L",
"DQZKL RL",
"TZG",
"DFF",
"@KEL",
"DXM",
"QBEX",
"DYZNY",
"CAX @L",
"DQX",
"LAY",
"ZO"
};
static const char *const spanish_verb_names[] = {
"Caminar",
"Mirar",
"Abrir",
"Mover",
"Consumir",
"Coger",
"Cerrar",
"Usar",
"Hablar",
"Quitar",
"Llevar",
"Dar"
};
static const char *const italian_verb_names[] = {
"Vai verso",
"Osserva",
"Apri",
"Sposta",
"Mangia",
"Raccogli",
"Chiudi",
"Usa",
"Parla a",
"Togli",
"Indossa",
"Dai"
};
static const char *const french_verb_names[] = {
"Aller vers",
"Regarder",
"Ouvrir",
"D/placer",
"Consommer",
"Prendre",
"Fermer",
"Utiliser",
"Parler ;",
"Enlever",
"Mettre",
"Donner"
};
static const char *const german_verb_names[] = {
"Gehe zu",
"Schau an",
";ffne",
"Bewege",
"Verzehre",
"Nimm",
"Schlie+e",
"Benutze",
"Rede mit",
"Entferne",
"Trage",
"Gib"
};
static const char *const english_verb_names[] = {
"Walk to",
"Look at",
"Open",
"Move",
"Consume",
"Pick up",
"Close",
"Use",
"Talk to",
"Remove",
"Wear",
"Give"
};
static const char *const czech_verb_names[] = {
"Jit",
"Podivat se",
"Otevrit",
"Pohnout s",
"Snist",
"Sebrat",
"Zavrit",
"Pouzit",
"Mluvit s",
"Odstranit",
"Oblect",
"Dat"
};
static const char *const russian_verb_prep_names[] = {
"", "", "", "",
"", "", "", "s yfn?",
"", "", "", "_onu ?"
};
static const char *const hebrew_verb_prep_names[] = {
"", "", "", "",
"", "", "", "RM ND ?",
"", "", "", "LNI ?"
};
static const char *const spanish_verb_prep_names[] = {
"", "", "", "",
"", "", "", "^con qu/?",
"", "", "", "^a qui/n?"
};
static const char *const italian_verb_prep_names[] = {
"", "", "", "",
"", "", "", "con cosa ?",
"", "", "", "a chi ?"
};
static const char *const french_verb_prep_names[] = {
"", "", "", "",
"", "", "", "avec quoi ?",
"", "", "", "; qui ?"
};
static const char *const german_verb_prep_names[] = {
"", "", "", "",
"", "", "", "mit was ?",
"", "", "", "zu wem ?"
};
static const char *const english_verb_prep_names[] = {
"", "", "", "",
"", "", "", "with what ?",
"", "", "", "to whom ?"
};
static const char *const czech_verb_prep_names[] = {
"", "", "", "",
"", "", "", "s cim ?",
"", "", "", "komu ?"
};
#ifdef ENABLE_AGOS2
void AGOSEngine_Feeble::clearName() {
stopAnimateSimon2(2, 6);
_lastNameOn = NULL;
_animatePointer = false;
_mouseAnim = 1;
return;
}
#endif
void AGOSEngine_Simon2::clearName() {
if (getBitFlag(79)) {
sendSync(202);
_lastNameOn = nullptr;
return;
}
if (_currentVerbBox == _lastVerbOn)
return;
resetNameWindow();
_lastVerbOn = _currentVerbBox;
if (_currentVerbBox != nullptr && !(_currentVerbBox->flags & kBFBoxDead))
printVerbOf(_currentVerbBox->id);
}
void AGOSEngine_Simon1::clearName() {
HitArea *ha;
if (_currentVerbBox == _lastVerbOn)
return;
resetNameWindow();
_lastVerbOn = _currentVerbBox;
if (_currentVerbBox != nullptr && (ha = findBox(200)) && (ha->flags & kBFBoxDead) && !(_currentVerbBox->flags & kBFBoxDead))
printVerbOf(_currentVerbBox->id);
}
void AGOSEngine::clearName() {
if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2)
return;
if (_nameLocked || !_lastNameOn)
return;
resetNameWindow();
}
static const byte convertVerbID[9] = {
0, 1, 5, 11, 8, 7, 10, 3, 2
};
void AGOSEngine::printVerbOf(uint hitarea_id) {
const char *txt;
const char * const *verb_names;
const char * const *verb_prep_names;
hitarea_id -= 101;
if (getGameType() == GType_SIMON2)
hitarea_id = convertVerbID[hitarea_id];
if (_showPreposition) {
switch (_language) {
case Common::RU_RUS:
verb_prep_names = russian_verb_prep_names;
break;
case Common::HE_ISR:
verb_prep_names = hebrew_verb_prep_names;
break;
case Common::ES_ESP:
verb_prep_names = spanish_verb_prep_names;
break;
case Common::IT_ITA:
verb_prep_names = italian_verb_prep_names;
break;
case Common::FR_FRA:
verb_prep_names = french_verb_prep_names;
break;
case Common::DE_DEU:
verb_prep_names = german_verb_prep_names;
break;
case Common::CS_CZE:
verb_prep_names = czech_verb_prep_names;
break;
default:
verb_prep_names = english_verb_prep_names;
break;
}
CHECK_BOUNDS(hitarea_id, english_verb_prep_names);
txt = verb_prep_names[hitarea_id];
} else {
switch (_language) {
case Common::RU_RUS:
verb_names = russian_verb_names;
break;
case Common::HE_ISR:
verb_names = hebrew_verb_names;
break;
case Common::ES_ESP:
verb_names = spanish_verb_names;
break;
case Common::IT_ITA:
verb_names = italian_verb_names;
break;
case Common::FR_FRA:
verb_names = french_verb_names;
break;
case Common::DE_DEU:
verb_names = german_verb_names;
break;
case Common::CS_CZE:
verb_names = czech_verb_names;
break;
default:
verb_names = english_verb_names;
break;
}
CHECK_BOUNDS(hitarea_id, english_verb_names);
txt = verb_names[hitarea_id];
}
showActionString((const byte *)txt);
}
void AGOSEngine::showActionString(const byte *string) {
WindowBlock *window;
uint x;
const uint len = (getGameType() == GType_WW) ? 29 : 53;
window = _windowArray[1];
if (window == nullptr || window->textColor == 0)
return;
// Arisme : hack for long strings in the French version
if ((strlen((const char*)string) - 1) <= len)
x = (len - (strlen((const char *)string) - 1)) * 3;
else
x = 0;
window->textColumn = x / 8;
window->textColumnOffset = x & 7;
if (_language == Common::HE_ISR && window->textColumnOffset != 0) {
window->textColumnOffset = 8 - window->textColumnOffset;
window->textColumn++;
}
for (; *string; string++)
windowPutChar(window, *string);
}
void AGOSEngine::handleVerbClicked(uint verb) {
Subroutine *sub;
int result;
if (shouldQuit())
return;
_objectItem = _hitAreaObjectItem;
if (_objectItem == _dummyItem2) {
_objectItem = me();
}
if (_objectItem == _dummyItem3) {
_objectItem = derefItem(me()->parent);
}
_subjectItem = _hitAreaSubjectItem;
if (_subjectItem == _dummyItem2) {
_subjectItem = me();
}
if (_subjectItem == _dummyItem3) {
_subjectItem = derefItem(me()->parent);
}
if (_subjectItem) {
_scriptNoun1 = _subjectItem->noun;
_scriptAdj1 = _subjectItem->adjective;
} else {
_scriptNoun1 = -1;
_scriptAdj1 = -1;
}
if (_objectItem) {
_scriptNoun2 = _objectItem->noun;
_scriptAdj2 = _objectItem->adjective;
} else {
_scriptNoun2 = -1;
_scriptAdj2 = -1;
}
_scriptVerb = _verbHitArea;
sub = getSubroutineByID(0);
if (sub == nullptr)
return;
result = startSubroutine(sub);
if (result == -1)
showMessageFormat("I don't understand");
_runScriptReturn1 = false;
sub = getSubroutineByID(100);
if (sub)
startSubroutine(sub);
if (getGameType() == GType_SIMON2 || getGameType() == GType_FF || getGameType() == GType_PP)
_runScriptReturn1 = false;
permitInput();
}
void AGOSEngine::resetNameWindow() {
WindowBlock *window;
if (getGameType() == GType_SIMON2 && getBitFlag(79))
return;
window = _windowArray[1];
if (window != nullptr && window->textColor != 0)
clearWindow(window);
_lastNameOn = nullptr;
_lastVerbOn = nullptr;
}
HitArea *AGOSEngine::findBox(uint hitarea_id) {
HitArea *ha = _hitAreas;
uint count = ARRAYSIZE(_hitAreas);
do {
if (getGameType() == GType_FF || getGameType() == GType_PP) {
if (ha->id == hitarea_id && ha->flags != 0)
return ha;
} else {
if (ha->id == hitarea_id)
return ha;
}
} while (ha++, --count);
return nullptr;
}
HitArea *AGOSEngine::findEmptyHitArea() {
HitArea *ha = _hitAreas;
uint count = ARRAYSIZE(_hitAreas) - 1;
do {
if (ha->flags == 0)
return ha;
} while (ha++, --count);
// The last box is overwritten, if too many boxes are allocated.
return ha;
}
void AGOSEngine::freeBox(uint index) {
CHECK_BOUNDS(index, _hitAreas);
_hitAreas[index].flags = 0;
}
void AGOSEngine::enableBox(uint hitarea) {
HitArea *ha = findBox(hitarea);
if (ha != nullptr)
ha->flags &= ~kBFBoxDead;
}
void AGOSEngine::disableBox(uint hitarea) {
HitArea *ha = findBox(hitarea);
if (ha != nullptr) {
ha->flags |= kBFBoxDead;
ha->flags &= ~kBFBoxSelected;
if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) &&
hitarea == 102) {
resetVerbs();
}
}
}
void AGOSEngine::moveBox(uint hitarea, int x, int y) {
HitArea *ha = findBox(hitarea);
if (ha != nullptr) {
if (getGameType() == GType_FF || getGameType() == GType_PP) {
ha->x += x;
ha->y += y;
} else {
ha->x = x;
ha->y = y;
}
}
}
void AGOSEngine::undefineBox(uint hitarea) {
HitArea *ha = findBox(hitarea);
if (ha != nullptr) {
ha->flags = 0;
if (ha == _lastNameOn)
clearName();
_needHitAreaRecalc++;
}
}
bool AGOSEngine::isBoxDead(uint hitarea) {
HitArea *ha = findBox(hitarea);
if (ha == nullptr)
return false;
return (ha->flags & kBFBoxDead) == 0;
}
void AGOSEngine::defineBox(uint16 id, uint16 x, uint16 y, uint16 height, uint16 width, uint16 msg1, uint16 msg2, uint16 flags) {
HitArea *ha = _hitAreaList + id;
ha->x = x;
ha->y = y;
ha->width = width;
ha->height = height;
ha->msg1 = msg1;
ha->msg2 = msg2;
ha->flags = flags;
ha->id = ha->priority = id;
}
void AGOSEngine::defineBox(int id, int x, int y, int width, int height, int flags, int verb, Item *itemPtr) {
HitArea *ha;
undefineBox(id);
ha = findEmptyHitArea();
ha->x = x;
ha->y = y;
ha->width = width;
ha->height = height;
ha->flags = flags | kBFBoxInUse;
ha->id = ha->priority = id;
ha->verb = verb;
ha->itemPtr = itemPtr;
if (getGameType() == GType_FF && (ha->flags & kBFHyperBox)) {
ha->data = _hyperLink;
ha->priority = 50;
}
_needHitAreaRecalc++;
}
#ifdef ENABLE_AGOS2
void AGOSEngine_PuzzlePack::resetVerbs() {
_verbHitArea = 300;
}
void AGOSEngine_Feeble::resetVerbs() {
_verbHitArea = 300;
int cursor = 0;
int animMax = 16;
if (getBitFlag(203)) {
cursor = 14;
animMax = 9;
} else if (getBitFlag(204)) {
cursor = 15;
animMax = 9;
} else if (getBitFlag(207)) {
cursor = 26;
animMax = 2;
}
_mouseCursor = cursor;
_mouseAnimMax = animMax;
_mouseAnim = 1;
_needHitAreaRecalc++;
if (getBitFlag(99)) {
setVerb(NULL);
}
}
#endif
void AGOSEngine::resetVerbs() {
if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2)
return;
uint id;
HitArea *ha;
if (getGameType() == GType_SIMON2) {
id = 2;
if (!getBitFlag(79))
id = (_mouse.y >= 136) ? 102 : 101;
} else {
id = (_mouse.y >= 136) ? 102 : 101;
}
_defaultVerb = id;
ha = findBox(id);
if (ha == nullptr)
return;
if (ha->flags & kBFBoxDead) {
_defaultVerb = 999;
_currentVerbBox = nullptr;
} else {
_verbHitArea = ha->verb;
setVerb(ha);
}
}
#ifdef ENABLE_AGOS2
void AGOSEngine_Feeble::setVerb(HitArea *ha) {
int cursor = _mouseCursor;
if (_noRightClick)
return;
if (cursor > 13)
cursor = 0;
cursor++;
if (cursor == 5)
cursor = 1;
if (cursor == 4) {
if (getBitFlag(72)) {
cursor = 1;
}
} else if (cursor == 2) {
if (getBitFlag(99)) {
cursor = 3;
}
}
_mouseCursor = cursor;
_mouseAnimMax = (cursor == 4) ? 14: 16;
_mouseAnim = 1;
_needHitAreaRecalc++;
_verbHitArea = cursor + 300;
}
#endif
void AGOSEngine::setVerb(HitArea *ha) {
HitArea *tmp = _currentVerbBox;
if (ha == tmp)
return;
if (getGameType() == GType_SIMON1) {
if (tmp != nullptr) {
tmp->flags |= kBFInvertTouch;
if (getFeatures() & GF_32COLOR)
invertBox(tmp, 212, 208, 212, 8);
else
invertBox(tmp, 213, 208, 213, 10);
}
if (ha->flags & kBFBoxSelected) {
if (getFeatures() & GF_32COLOR)
invertBox(ha, 216, 212, 212, 4);
else
invertBox(ha, 218, 213, 213, 5);
} else {
if (getFeatures() & GF_32COLOR)
invertBox(ha, 220, 216, 216, 8);
else
invertBox(ha, 223, 218, 218, 10);
}
ha->flags &= ~(kBFBoxSelected + kBFInvertTouch);
} else {
if (ha->id < 101)
return;
_mouseCursor = ha->id - 101;
_needHitAreaRecalc++;
}
_currentVerbBox = ha;
}
#ifdef ENABLE_AGOS2
void AGOSEngine_Feeble::hitarea_leave(HitArea *ha, bool state) {
invertBox(ha, state);
}
#endif
void AGOSEngine::hitarea_leave(HitArea *ha, bool state) {
if (getGameType() == GType_SIMON2) {
invertBox(ha, 231, 229, 230, 1);
} else {
if (getFeatures() & GF_32COLOR)
invertBox(ha, 220, 212, 216, 4);
else
invertBox(ha, 223, 213, 218, 5);
}
}
void AGOSEngine::leaveHitAreaById(uint hitarea_id) {
HitArea *ha = findBox(hitarea_id);
if (ha)
hitarea_leave(ha);
}
void AGOSEngine::inventoryUp(WindowBlock *window) {
if (window->iconPtr->line == 0)
return;
mouseOff();
uint index = getWindowNum(window);
drawIconArray(index, window->iconPtr->itemRef, window->iconPtr->line - 1, window->iconPtr->classMask);
mouseOn();
}
void AGOSEngine::inventoryDown(WindowBlock *window) {
mouseOff();
uint index = getWindowNum(window);
drawIconArray(index, window->iconPtr->itemRef, window->iconPtr->line + 1, window->iconPtr->classMask);
mouseOn();
}
void AGOSEngine::boxController(uint x, uint y, uint mode) {
HitArea *best_ha;
HitArea *ha = _hitAreas;
uint count = ARRAYSIZE(_hitAreas);
uint16 priority = 0;
best_ha = nullptr;
do {
if (ha->flags & kBFBoxInUse) {
if (!(ha->flags & kBFBoxDead)) {
if (x >= ha->x && y >= ha->y &&
x - ha->x < ha->width && y - ha->y < ha->height && priority <= ha->priority) {
priority = ha->priority;
best_ha = ha;
} else {
if (ha->flags & kBFBoxSelected) {
hitarea_leave(ha , true);
ha->flags &= ~kBFBoxSelected;
}
}
} else {
ha->flags &= ~kBFBoxSelected;
}
}
} while (ha++, --count);
_currentBoxNum = 0;
_currentBox = best_ha;
if (best_ha == nullptr)
return;
_currentBoxNum = best_ha->id;
if (mode != 0) {
if (mode == 3) {
if (best_ha->verb & 0x4000) {
if (getGameType() == GType_ELVIRA1 && _variableArray[500] == 0) {
_variableArray[500] = best_ha->verb & 0xBFFF;
}
if (_clickOnly && best_ha->id < 8) {
uint id = best_ha->id;
if (id >= 4)
id -= 4;
invertBox(findBox(id), 0, 0, 0, 0);
_clickOnly = false;
return;
}
}
if (best_ha->flags & kBFDragBox)
_lastClickRem = best_ha;
} else {
_lastHitArea = best_ha;
}
}
if (_clickOnly)
return;
if (best_ha->flags & kBFInvertTouch) {
if (!(best_ha->flags & kBFBoxSelected)) {
hitarea_leave(best_ha, false);
best_ha->flags |= kBFBoxSelected;
}
} else {
if (mode == 0)
return;
if (!(best_ha->flags & kBFInvertSelect))
return;
if (best_ha->flags & kBFToggleBox) {
hitarea_leave(best_ha, false);
best_ha->flags ^= kBFInvertSelect;
} else if (!(best_ha->flags & kBFBoxSelected)) {
hitarea_leave(best_ha, false);
best_ha->flags |= kBFBoxSelected;
}
}
}
void AGOSEngine_Waxworks::boxController(uint x, uint y, uint mode) {
HitArea *best_ha;
HitArea *ha = _hitAreas;
uint count = ARRAYSIZE(_hitAreas);
uint16 priority = 0;
uint16 x_ = x;
uint16 y_ = y;
if (getGameType() == GType_FF || getGameType() == GType_PP) {
x_ += _scrollX;
y_ += _scrollY;
} else if (getGameType() == GType_SIMON2) {
if (getBitFlag(79) || y < 134) {
x_ += _scrollX * 8;
}
}
best_ha = nullptr;
do {
if (ha->flags & kBFBoxInUse) {
if (!(ha->flags & kBFBoxDead)) {
if (x_ >= ha->x && y_ >= ha->y &&
x_ - ha->x < ha->width && y_ - ha->y < ha->height && priority <= ha->priority) {
priority = ha->priority;
best_ha = ha;
} else {
if (ha->flags & kBFBoxSelected) {
hitarea_leave(ha , true);
ha->flags &= ~kBFBoxSelected;
}
}
} else {
ha->flags &= ~kBFBoxSelected;
}
}
} while (ha++, --count);
_currentBoxNum = 0;
_currentBox = best_ha;
if (best_ha == nullptr) {
clearName();
if (getGameType() == GType_WW && _mouseCursor >= 4) {
_mouseCursor = 0;
_needHitAreaRecalc++;
}
return;
}
_currentBoxNum = best_ha->id;
if (mode != 0) {
if (mode == 3) {
if (best_ha->flags & kBFDragBox) {
_lastClickRem = best_ha;
}
} else {
_lastHitArea = best_ha;
if (getGameType() == GType_PP) {
_variableArray[400] = x;
_variableArray[401] = y;
} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2 ||
getGameType() == GType_FF) {
_variableArray[1] = x;
_variableArray[2] = y;
}
}
}
if ((getGameType() == GType_WW) && (_mouseCursor == 0 || _mouseCursor >= 4)) {
uint verb = best_ha->verb & 0x3FFF;
uint cursor = (verb >= 239 && verb <= 242) ? verb - 235 : 0;
if (_mouseCursor != cursor) {
_mouseCursor = cursor;
_needHitAreaRecalc++;
}
}
if (getGameType() != GType_WW || !_nameLocked) {
if (best_ha->flags & kBFNoTouchName) {
clearName();
} else if (best_ha != _lastNameOn) {
displayName(best_ha);
}
}
if (best_ha->flags & kBFInvertTouch && !(best_ha->flags & kBFBoxSelected)) {
hitarea_leave(best_ha, false);
best_ha->flags |= kBFBoxSelected;
}
}
void AGOSEngine::displayName(HitArea *ha) {
if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_PP)
return;
bool result;
int x = 0, y = 0;
if (getGameType() == GType_FF) {
if (ha->flags & kBFHyperBox) {
_lastNameOn = ha;
return;
}
if (findBox(50))
return;
if (getBitFlag(99))
_animatePointer = ((ha->flags & kBFTextBox) == 0);
else
_animatePointer = true;
if (!getBitFlag(73))
return;
y = ha->y;
if (getBitFlag(99) && y > 288)
y = 288;
y -= 17;
if (y < 0)
y = 0;
y += 2;
x = ha->width / 2 + ha->x;
} else {
resetNameWindow();
}
if (ha->flags & kBFTextBox) {
result = printTextOf(ha->flags / 256, x, y);
} else {
result = printNameOf(ha->itemPtr, x, y);
}
if (result)
_lastNameOn = ha;
}
#ifdef ENABLE_AGOS2
void AGOSEngine_Feeble::invertBox(HitArea *ha, bool state) {
if (getBitFlag(205) || getBitFlag(206)) {
if (state != 0) {
_mouseAnimMax = _oldMouseAnimMax;
_mouseCursor = _oldMouseCursor;
} else if (_mouseCursor != 18) {
_oldMouseCursor = _mouseCursor;
_animatePointer = false;
_oldMouseAnimMax = _mouseAnimMax;
_mouseAnimMax = 2;
_mouseCursor = 18;
}
} else {
if (getBitFlag(207)) {
if (state != 0) {
_noRightClick = 0;
resetVerbs();
} else {
int cursor = ha->id + 9;
if (cursor >= 23)
cursor = 21;
_mouseCursor = cursor;
_mouseAnimMax = 8;
_noRightClick = 1;
}
} else {
VgaSprite *vsp = _vgaSprites;
int id = ha->id - 43;
while (vsp->id) {
if (vsp->id == id && vsp->zoneNum == 2) {
if (state == 0)
vsp->flags |= kDFShaded;
else
vsp->flags &= ~kDFShaded;
break;
}
vsp++;
}
}
}
}
#endif
void AGOSEngine::invertBox(HitArea *ha, byte a, byte b, byte c, byte d) {
byte *src, color;
int w, h, i;
_videoLockOut |= 0x8000;
Graphics::Surface *screen = getBackendSurface();
src = (byte *)screen->getBasePtr(ha->x, ha->y);
// WORKAROUND: Hitareas for saved game names aren't adjusted for scrolling locations
if (getGameType() == GType_SIMON2 && ha->id >= 208 && ha->id <= 213) {
src -= _scrollX * 8;
}
_litBoxFlag = true;
w = ha->width;
h = ha->height;
do {
for (i = 0; i != w; ++i) {
color = src[i];
if (getGameType() == GType_WW) {
if (!(color & 0xF) || (color & 0xF) == 10) {
color ^= 10;
src[i] = color;
}
} else if (getGameType() == GType_ELVIRA2) {
if (!(color & 1)) {
color ^= 2;
src[i] = color;
}
} else if (getGameType() == GType_ELVIRA1) {
if (color & 1) {
color ^= 2;
src[i] = color;
}
} else if (getGameType() == GType_PN) {
if (getPlatform() == Common::kPlatformDOS) {
if (color != 15) {
color ^= 7;
src[i] = color;
}
} else {
if (color != 14) {
color ^= 15;
src[i] = color;
}
}
} else {
if (a >= color && b < color) {
if (c >= color)
color += d;
else
color -= d;
src[i] = color;
}
}
}
src += screen->pitch;
} while (--h);
Common::Rect dirtyRect(ha->x, ha->y, ha->x + w, ha->y + ha->height);
updateBackendSurface(&dirtyRect);
_videoLockOut &= ~0x8000;
}
} // End of namespace AGOS