- Moved kernel_lookup_text inside the Kernel class

- Added a pointer to the segment manager from within the Kernel class, thus simplifying the calls to it

svn-id: r49076
This commit is contained in:
Filippos Karapetis 2010-05-18 12:16:48 +00:00
parent 75f4791a4a
commit 46af5a5162
7 changed files with 65 additions and 68 deletions

View file

@ -1834,7 +1834,7 @@ bool Console::cmdValueType(int argc, const char **argv) {
return true;
}
int t = g_sci->getKernel()->findRegType(_engine->_gamestate->_segMan, val);
int t = g_sci->getKernel()->findRegType(val);
switch (t) {
case KSIG_LIST:
@ -1903,7 +1903,7 @@ bool Console::cmdViewReference(int argc, const char **argv) {
}
}
int type_mask = g_sci->getKernel()->findRegType(_engine->_gamestate->_segMan, reg);
int type_mask = g_sci->getKernel()->findRegType(reg);
int filter;
int found = 0;

View file

@ -391,7 +391,7 @@ SciKernelFunction kfunct_mappers[] = {
{NULL, NULL, NULL} // Terminator
};
Kernel::Kernel(ResourceManager *resMan) : _resMan(resMan) {
Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) : _resMan(resMan), _segMan(segMan) {
loadSelectorNames();
mapSelectors(); // Map a few special selectors for later use
}
@ -642,13 +642,13 @@ void Kernel::mapFunctions() {
return;
}
int Kernel::findRegType(SegManager *segMan, reg_t reg) {
int Kernel::findRegType(reg_t reg) {
// No segment? Must be arithmetic
if (!reg.segment)
return reg.offset ? KSIG_ARITHMETIC : KSIG_ARITHMETIC | KSIG_NULL;
// Otherwise it's an object
SegmentObj *mobj = segMan->getSegmentObj(reg.segment);
SegmentObj *mobj = _segMan->getSegmentObj(reg.segment);
if (!mobj)
return 0; // Invalid
@ -684,14 +684,14 @@ int Kernel::findRegType(SegManager *segMan, reg_t reg) {
}
}
bool Kernel::signatureMatch(SegManager *segMan, const char *sig, int argc, const reg_t *argv) {
bool Kernel::signatureMatch(const char *sig, int argc, const reg_t *argv) {
// Always "match" if no signature is given
if (!sig)
return true;
while (*sig && argc) {
if ((*sig & KSIG_ANY) != KSIG_ANY) {
int type = findRegType(segMan, *argv);
int type = findRegType(*argv);
if (!type) {
warning("[KERN] Could not determine type of ref %04x:%04x; failing signature check", PRINT_REG(*argv));
@ -792,4 +792,37 @@ bool Kernel::loadKernelNames(Common::String gameId) {
return true;
}
Common::String Kernel::lookupText(reg_t address, int index) {
char *seeker;
Resource *textres;
if (address.segment)
return _segMan->getString(address);
else {
int textlen;
int _index = index;
textres = _resMan->findResource(ResourceId(kResourceTypeText, address.offset), 0);
if (!textres) {
error("text.%03d not found", address.offset);
return NULL; /* Will probably segfault */
}
textlen = textres->size;
seeker = (char *) textres->data;
while (index--)
while ((textlen--) && (*seeker++))
;
if (textlen)
return seeker;
else {
error("Index %d out of bounds in text.%03d", _index, address.offset);
return NULL;
}
}
}
} // End of namespace Sci

View file

@ -146,7 +146,7 @@ public:
/**
* Initializes the SCI kernel
*/
Kernel(ResourceManager *resMan);
Kernel(ResourceManager *resMan, SegManager *segMan);
~Kernel();
uint getSelectorNamesSize() const;
@ -193,17 +193,30 @@ public:
* @param argv argument list
* @return true if the signature was matched, false otherwise
*/
bool signatureMatch(SegManager *segMan, const char *sig, int argc, const reg_t *argv);
bool signatureMatch(const char *sig, int argc, const reg_t *argv);
/**
* Determines the type of the object indicated by reg.
* @param segMan the Segment manager
* @param reg register to check
* @return one of KSIG_* below KSIG_NULL.
* KSIG_INVALID set if the type of reg can be determined, but is invalid.
* 0 on error.
*/
int findRegType(SegManager *segMan, reg_t reg);
int findRegType(reg_t reg);
/******************** Text functionality ********************/
/**
* Looks up text referenced by scripts
* SCI uses two values to reference to text: An address, and an index. The address
* determines whether the text should be read from a resource file, or from the heap,
* while the index either refers to the number of the string in the specified source,
* or to a relative position inside the text.
*
* @param address The address to look up
* @param index The relative index
* @return The referenced text, or empty string on error.
*/
Common::String lookupText(reg_t address, int index);
private:
/**
@ -245,6 +258,7 @@ private:
void mapFunctions();
ResourceManager *_resMan;
SegManager *_segMan;
uint32 features;
// Kernel-related lists
@ -252,22 +266,6 @@ private:
Common::StringArray _kernelNames;
};
/******************** Text functionality ********************/
/**
* Looks up text referenced by scripts
* SCI uses two values to reference to text: An address, and an index. The address
* determines whether the text should be read from a resource file, or from the heap,
* while the index either refers to the number of the string in the specified source,
* or to a relative position inside the text.
*
* @param s The current state
* @param address The address to look up
* @param index The relative index
* @return The referenced text, or empty string on error.
*/
Common::String kernel_lookup_text(EngineState *s, reg_t address, int index);
#ifdef USE_OLD_MUSIC_FUNCTIONS
/******************** Misc functions ********************/

View file

@ -1071,7 +1071,7 @@ reg_t kDisplay(EngineState *s, int argc, reg_t *argv) {
text = s->_segMan->getString(textp);
} else {
argc--; argc--; argv++; argv++;
text = kernel_lookup_text(s, textp, index);
text = g_sci->getKernel()->lookupText(textp, index);
}
return g_sci->_gfxPaint16->kernelDisplay(g_sci->strSplit(text.c_str()).c_str(), argc, argv);

View file

@ -33,40 +33,6 @@
namespace Sci {
/* Returns the string the script intended to address */
Common::String kernel_lookup_text(EngineState *s, reg_t address, int index) {
char *seeker;
Resource *textres;
if (address.segment)
return s->_segMan->getString(address);
else {
int textlen;
int _index = index;
textres = g_sci->getResMan()->findResource(ResourceId(kResourceTypeText, address.offset), 0);
if (!textres) {
error("text.%03d not found", address.offset);
return NULL; /* Will probably segfault */
}
textlen = textres->size;
seeker = (char *) textres->data;
while (index--)
while ((textlen--) && (*seeker++))
;
if (textlen)
return seeker;
else {
error("Index %d out of bounds in text.%03d", _index, address.offset);
return 0;
}
}
}
reg_t kStrEnd(EngineState *s, int argc, reg_t *argv) {
reg_t address = argv[0];
address.offset += s->_segMan->strlen(address);
@ -211,7 +177,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
else
startarg = 3; /* First parameter to use for formatting */
Common::String source_str = kernel_lookup_text(s, position, index);
Common::String source_str = g_sci->getKernel()->lookupText(position, index);
const char* source = source_str.c_str();
debugC(2, kDebugLevelStrings, "Formatting \"%s\"", source);
@ -278,7 +244,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
reg = GET_SEL32(s->_segMan, reg, SELECTOR(data));
#endif
Common::String tempsource = (reg == NULL_REG) ? "" : kernel_lookup_text(s, reg,
Common::String tempsource = (reg == NULL_REG) ? "" : g_sci->getKernel()->lookupText(reg,
arguments[paramindex + 1]);
int slen = strlen(tempsource.c_str());
int extralen = str_leng - slen;

View file

@ -563,7 +563,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) {
const KernelFuncWithSignature &kernelFunc = g_sci->getKernel()->_kernelFuncs[kernelFuncNum];
if (kernelFunc.signature
&& !g_sci->getKernel()->signatureMatch(s->_segMan, kernelFunc.signature, argc, scriptState.xs->sp + 1)) {
&& !g_sci->getKernel()->signatureMatch(kernelFunc.signature, argc, scriptState.xs->sp + 1)) {
error("[VM] Invalid arguments to kernel call %x", kernelFuncNum);
}

View file

@ -140,6 +140,8 @@ Common::Error SciEngine::run() {
return Common::kNoGameDataFoundError;
}
SegManager *segMan = new SegManager(_resMan);
// Scale the screen, if needed
int upscaledHires = GFX_SCREEN_UPSCALED_DISABLED;
@ -175,13 +177,11 @@ Common::Error SciEngine::run() {
// Create debugger console. It requires GFX to be initialized
_console = new Console(this);
_kernel = new Kernel(_resMan);
_kernel = new Kernel(_resMan, segMan);
// Only SCI0 and SCI01 games used a parser
_vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan) : NULL;
_audio = new AudioPlayer(_resMan);
SegManager *segMan = new SegManager(_resMan);
_features = new GameFeatures(segMan, _kernel);
_gamestate = new EngineState(_vocabulary, segMan);