scummvm/engines/sci/engine/selector.cpp

290 lines
7.7 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 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "sci/sci.h"
#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
namespace Sci {
#if 1
#define FIND_SELECTOR(_slc_) _selectorCache._slc_ = findSelector(#_slc_)
#define FIND_SELECTOR2(_slc_, _slcstr_) _selectorCache._slc_ = findSelector(_slcstr_)
#else
// The defines below can be used to construct static selector tables for games which don't have
// a vocab.997 resource, by dumping the selector table from other similar versions or games
#define FIND_SELECTOR(_slc_) _selectorCache._slc_ = findSelector(#_slc_); \
printf("\t{ \"%s\", %d },\n", #_slc_, _selectorCache._slc_)
#define FIND_SELECTOR2(_slc_, _slcstr_) _selectorCache._slc_ = findSelector(_slcstr_); \
printf("\t{ \"%s\", %d },\n", _slcstr_, _selectorCache._slc_)
#endif
void Kernel::mapSelectors() {
// species
// superClass
// -info-
FIND_SELECTOR(y);
FIND_SELECTOR(x);
FIND_SELECTOR(view);
FIND_SELECTOR(loop);
FIND_SELECTOR(cel);
FIND_SELECTOR(underBits);
FIND_SELECTOR(nsTop);
FIND_SELECTOR(nsLeft);
FIND_SELECTOR(nsBottom);
FIND_SELECTOR(lsTop);
FIND_SELECTOR(lsLeft);
FIND_SELECTOR(lsBottom);
FIND_SELECTOR(lsRight);
FIND_SELECTOR(nsRight);
FIND_SELECTOR(signal);
FIND_SELECTOR(illegalBits);
FIND_SELECTOR(brTop);
FIND_SELECTOR(brLeft);
FIND_SELECTOR(brBottom);
FIND_SELECTOR(brRight);
// name
// key
// time
FIND_SELECTOR(text);
FIND_SELECTOR(elements);
// color
// back
FIND_SELECTOR(mode);
// style
FIND_SELECTOR(state);
FIND_SELECTOR(font);
FIND_SELECTOR(type);
// window
FIND_SELECTOR(cursor);
FIND_SELECTOR(max);
// mark
// who
FIND_SELECTOR(message);
// edit
FIND_SELECTOR(play);
FIND_SELECTOR(number);
FIND_SELECTOR(handle); // nodePtr
FIND_SELECTOR(client);
FIND_SELECTOR(dx);
FIND_SELECTOR(dy);
FIND_SELECTOR2(b_movCnt, "b-moveCnt");
FIND_SELECTOR2(b_i1, "b-i1");
FIND_SELECTOR2(b_i2, "b-i2");
FIND_SELECTOR2(b_di, "b-di");
FIND_SELECTOR2(b_xAxis, "b-xAxis");
FIND_SELECTOR2(b_incr, "b-incr");
FIND_SELECTOR(xStep);
FIND_SELECTOR(yStep);
FIND_SELECTOR(xLast);
FIND_SELECTOR(yLast);
FIND_SELECTOR(moveSpeed);
FIND_SELECTOR(canBeHere); // cantBeHere
FIND_SELECTOR(heading);
FIND_SELECTOR(mover);
FIND_SELECTOR(doit);
FIND_SELECTOR(isBlocked);
FIND_SELECTOR(looper);
FIND_SELECTOR(priority);
FIND_SELECTOR(modifiers);
FIND_SELECTOR(replay);
// setPri
// at
// next
// done
// width
FIND_SELECTOR(wordFail);
FIND_SELECTOR(syntaxFail);
// semanticFail
// pragmaFail
// said
FIND_SELECTOR(claimed);
// value
// save
// restore
// title
// button
// icon
// draw
FIND_SELECTOR2(delete_, "delete");
FIND_SELECTOR(z);
// -----------------------------
FIND_SELECTOR(size);
FIND_SELECTOR(moveDone);
FIND_SELECTOR(vol);
FIND_SELECTOR(pri);
FIND_SELECTOR(min);
FIND_SELECTOR(sec);
FIND_SELECTOR(frame);
FIND_SELECTOR(dataInc);
FIND_SELECTOR(palette);
FIND_SELECTOR(cantBeHere);
FIND_SELECTOR(nodePtr);
FIND_SELECTOR(flags);
FIND_SELECTOR(points);
FIND_SELECTOR(syncCue);
FIND_SELECTOR(syncTime);
FIND_SELECTOR(printLang);
FIND_SELECTOR(subtitleLang);
FIND_SELECTOR(parseLang);
FIND_SELECTOR(overlay);
FIND_SELECTOR(topString);
FIND_SELECTOR(scaleSignal);
FIND_SELECTOR(scaleX);
FIND_SELECTOR(scaleY);
FIND_SELECTOR(maxScale);
FIND_SELECTOR(vanishingX);
FIND_SELECTOR(vanishingY);
FIND_SELECTOR(iconIndex);
#ifdef ENABLE_SCI32
FIND_SELECTOR(data);
FIND_SELECTOR(picture);
FIND_SELECTOR(plane);
FIND_SELECTOR(top);
FIND_SELECTOR(left);
FIND_SELECTOR(bottom);
FIND_SELECTOR(right);
FIND_SELECTOR(resY);
FIND_SELECTOR(resX);
FIND_SELECTOR(dimmed);
FIND_SELECTOR(fore);
FIND_SELECTOR(back);
#endif
}
reg_t readSelector(SegManager *segMan, reg_t object, Selector selectorId) {
ObjVarRef address;
if (lookupSelector(segMan, object, selectorId, &address, NULL) != kSelectorVariable)
return NULL_REG;
else
return *address.getPointer(segMan);
}
void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t value) {
ObjVarRef address;
if ((selectorId < 0) || (selectorId > (int)g_sci->getKernel()->getSelectorNamesSize())) {
error("Attempt to write to invalid selector %d of"
" object at %04x:%04x.", selectorId, PRINT_REG(object));
return;
}
if (lookupSelector(segMan, object, selectorId, &address, NULL) != kSelectorVariable)
error("Selector '%s' of object at %04x:%04x could not be"
" written to", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object));
else
*address.getPointer(segMan) = value;
}
void invokeSelector(EngineState *s, reg_t object, int selectorId,
int k_argc, StackPtr k_argp, int argc, const reg_t *argv) {
int i;
int framesize = 2 + 1 * argc;
int slc_type;
StackPtr stackframe = k_argp + k_argc;
stackframe[0] = make_reg(0, selectorId); // The selector we want to call
stackframe[1] = make_reg(0, argc); // Argument count
slc_type = lookupSelector(s->_segMan, object, selectorId, NULL, NULL);
if (slc_type == kSelectorNone) {
error("Selector '%s' of object at %04x:%04x could not be invoked",
g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object));
}
if (slc_type == kSelectorVariable) {
error("Attempting to invoke variable selector %s of object %04x:%04x",
g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object));
}
for (i = 0; i < argc; i++)
stackframe[2 + i] = argv[i]; // Write each argument
ExecStack *xstack;
// Now commit the actual function:
xstack = send_selector(s, object, object, stackframe, framesize, stackframe);
xstack->sp += argc + 2;
xstack->fp += argc + 2;
run_vm(s, false); // Start a new vm
}
SelectorType lookupSelector(SegManager *segMan, reg_t obj_location, Selector selectorId, ObjVarRef *varp, reg_t *fptr) {
const Object *obj = segMan->getObject(obj_location);
int index;
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
// Early SCI versions used the LSB in the selector ID as a read/write
// toggle, meaning that we must remove it for selector lookup.
if (oldScriptHeader)
selectorId &= ~1;
if (!obj) {
error("lookupSelector(): Attempt to send to non-object or invalid script. Address was %04x:%04x",
PRINT_REG(obj_location));
}
index = obj->locateVarSelector(segMan, selectorId);
if (index >= 0) {
// Found it as a variable
if (varp) {
varp->obj = obj_location;
varp->varindex = index;
}
return kSelectorVariable;
} else {
// Check if it's a method, with recursive lookup in superclasses
while (obj) {
index = obj->funcSelectorPosition(selectorId);
if (index >= 0) {
if (fptr)
*fptr = obj->getFunction(index);
return kSelectorMethod;
} else {
obj = segMan->getObject(obj->getSuperClassSelector());
}
}
return kSelectorNone;
}
// return _lookupSelector_function(segMan, obj, selectorId, fptr);
}
} // End of namespace Sci