SAGA: replace Script and Thread "::*alloc" & "::free" with Common::Array

svn-id: r53678
This commit is contained in:
Andrew Kurushin 2010-10-21 22:32:50 +00:00
parent c1505d6e51
commit 8b72f49460
7 changed files with 87 additions and 145 deletions

View File

@ -48,7 +48,7 @@ void Resource_RES::loadGlobalResources(int chapter, int actorsEntrance) {
if (chapter < 0)
chapter = !_vm->isIHNMDemo() ? 8 : 7;
_vm->_script->_globalVoiceLUT.freeMem();
_vm->_script->_globalVoiceLUT.clear();
// TODO: close chapter context, or rather reassign it in our case

View File

@ -240,9 +240,9 @@ void SagaEngine::save(const char *fileName, const char *saveName) {
_actor->saveState(out);
out->writeSint16LE(_script->_commonBufferSize);
out->writeSint16LE(_script->_commonBuffer.size());
out->write(_script->_commonBuffer, _script->_commonBufferSize);
out->write(&_script->_commonBuffer.front(), _script->_commonBuffer.size());
// ISO map x, y coordinates for ITE
if (getGameId() == GID_ITE) {
@ -351,7 +351,8 @@ void SagaEngine::load(const char *fileName) {
_actor->loadState(in);
commonBufferSize = in->readSint16LE();
in->read(_script->_commonBuffer, commonBufferSize);
_script->_commonBuffer.resize(commonBufferSize);
in->read(&_script->_commonBuffer.front(), commonBufferSize);
if (getGameId() == GID_ITE) {
mapx = in->readSint16LE();

View File

@ -624,7 +624,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) {
_vm->_interface->setLeftPortrait(0);
_vm->_anim->freeCutawayList();
_vm->_script->freeModules();
_vm->_script->clearModules();
// deleteAllScenes();

View File

@ -49,7 +49,8 @@ SAGA1Script::SAGA1Script(SagaEngine *vm) : Script(vm) {
byte *resourcePointer;
size_t resourceLength;
int prevTell;
int i, j;
uint ui;
int j;
byte *stringsPointer;
size_t stringsLength;
@ -67,9 +68,7 @@ SAGA1Script::SAGA1Script(SagaEngine *vm) : Script(vm) {
_pointerObject = ID_NOTHING;
_staticSize = 0;
_commonBufferSize = COMMON_BUFFER_SIZE;
_commonBuffer = (byte*)malloc(_commonBufferSize);
memset(_commonBuffer, 0, _commonBufferSize);
_commonBuffer.resize(COMMON_BUFFER_SIZE);
debug(8, "Initializing scripting subsystem");
// Load script resource file context
@ -98,30 +97,26 @@ SAGA1Script::SAGA1Script(SagaEngine *vm) : Script(vm) {
}
// Calculate number of entries
_modulesCount = resourceLength / _modulesLUTEntryLen;
int modulesCount = resourceLength / _modulesLUTEntryLen;
debug(3, "LUT has %i entries", _modulesCount);
debug(3, "LUT has %i entries", modulesCount);
// Allocate space for logical LUT
_modules = (ModuleData *)malloc(_modulesCount * sizeof(*_modules));
if (_modules == NULL) {
memoryError("Script::Script()");
}
_modules.resize(modulesCount);
// Convert LUT resource to logical LUT
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, resourceContext->isBigEndian());
for (i = 0; i < _modulesCount; i++) {
memset(&_modules[i], 0, sizeof(ModuleData));
for (ui = 0; ui < _modules.size(); ui++) {
prevTell = scriptS.pos();
_modules[i].scriptResourceId = scriptS.readUint16();
_modules[i].stringsResourceId = scriptS.readUint16();
_modules[i].voicesResourceId = scriptS.readUint16();
_modules[ui].scriptResourceId = scriptS.readUint16();
_modules[ui].stringsResourceId = scriptS.readUint16();
_modules[ui].voicesResourceId = scriptS.readUint16();
// Skip the unused portion of the structure
for (j = scriptS.pos(); j < prevTell + _modulesLUTEntryLen; j++) {
if (scriptS.readByte() != 0)
warning("Unused scriptLUT part isn't really unused for LUT %d (pos: %d)", i, j);
warning("Unused scriptLUT part isn't really unused for LUT %d (pos: %d)", ui, j);
}
}
@ -157,13 +152,6 @@ SAGA1Script::SAGA1Script(SagaEngine *vm) : Script(vm) {
SAGA1Script::~SAGA1Script() {
debug(8, "Shutting down scripting subsystem.");
_globalVoiceLUT.freeMem();
freeModules();
free(_modules);
free(_commonBuffer);
}
SAGA2Script::SAGA2Script(SagaEngine *vm) : Script(vm) {
@ -188,9 +176,9 @@ SAGA2Script::SAGA2Script(SagaEngine *vm) : Script(vm) {
_modulesLUTEntryLen = sizeof(uint32);
// Calculate number of entries
_modulesCount = resourceLength / _modulesLUTEntryLen + 1;
int modulesCount = resourceLength / _modulesLUTEntryLen + 1;
debug(3, "LUT has %i entries", _modulesCount);
debug(3, "LUT has %i entries", modulesCount);
// Script data segment
/*
@ -993,8 +981,8 @@ void Script::opSpeak(SCRIPTOP_PARAMS) {
}
} else {
#endif
if (thread->_voiceLUT->voicesCount > first)
sampleResourceId = thread->_voiceLUT->voices[first];
if (thread->_voiceLUT->size() > uint16(first))
sampleResourceId = (*thread->_voiceLUT)[uint16(first)];
#if 0
}
#endif
@ -1066,12 +1054,12 @@ void Script::opJmpSeedRandom(SCRIPTOP_PARAMS) {
warning("opJmpSeedRandom");
}
void Script::loadModule(int scriptModuleNumber) {
void Script::loadModule(uint scriptModuleNumber) {
byte *resourcePointer;
size_t resourceLength;
// Validate script number
if ((scriptModuleNumber < 0) || (scriptModuleNumber >= _modulesCount)) {
if ((scriptModuleNumber < 0) || (scriptModuleNumber >= _modules.size())) {
error("Script::loadScript() Invalid script module number");
}
@ -1101,60 +1089,56 @@ void Script::loadModule(int scriptModuleNumber) {
_modules[scriptModuleNumber].staticOffset = _staticSize;
_staticSize += _modules[scriptModuleNumber].staticSize;
if (_staticSize > _commonBufferSize) {
error("Script::loadModule() _staticSize > _commonBufferSize");
if (_staticSize > _commonBuffer.size()) {
error("Script::loadModule() _staticSize > _commonBuffer.size()");
}
_modules[scriptModuleNumber].loaded = true;
}
void Script::freeModules() {
int i;
for (i = 0; i < _modulesCount; i++) {
void Script::clearModules() {
uint i;
for (i = 0; i < _modules.size(); i++) {
if (_modules[i].loaded) {
_modules[i].freeMem();
_modules[i].loaded = false;
_modules[i].clear();
}
}
_staticSize = 0;
}
void Script::loadModuleBase(ModuleData &module, const byte *resourcePointer, size_t resourceLength) {
int i;
uint i;
debug(3, "Loading module base...");
module.moduleBase = (byte*)malloc(resourceLength);
module.moduleBaseSize = resourceLength;
module.moduleBase.resize(resourceLength);
memcpy(&module.moduleBase.front(), resourcePointer, resourceLength);
memcpy(module.moduleBase, resourcePointer, resourceLength);
MemoryReadStreamEndian scriptS(&module.moduleBase.front(), module.moduleBase.size(), _scriptContext->isBigEndian());
MemoryReadStreamEndian scriptS(module.moduleBase, module.moduleBaseSize, _scriptContext->isBigEndian());
module.entryPointsCount = scriptS.readUint16();
uint entryPointsCount = scriptS.readUint16();
scriptS.readUint16(); //skip
module.entryPointsTableOffset = scriptS.readUint16();
uint16 entryPointsTableOffset; // offset of entrypoint table in moduleBase
entryPointsTableOffset = scriptS.readUint16();
scriptS.readUint16(); //skip
if ((module.moduleBaseSize - module.entryPointsTableOffset) < (module.entryPointsCount * SCRIPT_TBLENTRY_LEN)) {
if ((module.moduleBase.size() - entryPointsTableOffset) < (entryPointsCount * SCRIPT_TBLENTRY_LEN)) {
error("Script::loadModuleBase() Invalid table offset");
}
if (module.entryPointsCount > SCRIPT_MAX) {
if (entryPointsCount > SCRIPT_MAX) {
error("Script::loadModuleBase()Script limit exceeded");
}
module.entryPoints = (EntryPoint *)malloc(module.entryPointsCount * sizeof(*module.entryPoints));
if (module.entryPoints == NULL) {
memoryError("Script::loadModuleBase");
}
module.entryPoints.resize(entryPointsCount);
// Read in the entrypoint table
module.staticSize = scriptS.readUint16();
while (scriptS.pos() < module.entryPointsTableOffset)
while (scriptS.pos() < entryPointsTableOffset)
scriptS.readByte();
for (i = 0; i < module.entryPointsCount; i++) {
for (i = 0; i < module.entryPoints.size(); i++) {
// First uint16 is the offset of the entrypoint name from the start
// of the bytecode resource, second uint16 is the offset of the
// bytecode itself for said entrypoint
@ -1162,7 +1146,7 @@ void Script::loadModuleBase(ModuleData &module, const byte *resourcePointer, siz
module.entryPoints[i].offset = scriptS.readUint16();
// Perform a simple range check on offset values
if ((module.entryPoints[i].nameOffset >= module.moduleBaseSize) || (module.entryPoints[i].offset >= module.moduleBaseSize)) {
if ((module.entryPoints[i].nameOffset >= module.moduleBase.size()) || (module.entryPoints[i].offset >= module.moduleBase.size())) {
error("Script::loadModuleBase() Invalid offset encountered in script entrypoint table");
}
}
@ -1171,17 +1155,12 @@ void Script::loadModuleBase(ModuleData &module, const byte *resourcePointer, siz
void Script::loadVoiceLUT(VoiceLUT &voiceLUT, const byte *resourcePointer, size_t resourceLength) {
uint16 i;
voiceLUT.voicesCount = resourceLength / 2;
voiceLUT.voices = (uint16 *)malloc(voiceLUT.voicesCount * sizeof(*voiceLUT.voices));
if (voiceLUT.voices == NULL) {
error("Script::loadVoiceLUT() not enough memory");
}
voiceLUT.resize(resourceLength / 2);
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, _scriptContext->isBigEndian());
for (i = 0; i < voiceLUT.voicesCount; i++) {
voiceLUT.voices[i] = scriptS.readUint16();
for (i = 0; i < voiceLUT.size(); i++) {
voiceLUT[i] = scriptS.readUint16();
}
}

View File

@ -129,16 +129,7 @@ struct EntryPoint {
uint16 offset;
};
struct VoiceLUT {
uint16 voicesCount;
uint16 *voices;
void freeMem() {
voicesCount = 0;
free(voices);
}
VoiceLUT() {
memset(this, 0, sizeof(*this));
}
class VoiceLUT : public Common::Array<uint16> {
};
struct ModuleData {
@ -147,28 +138,29 @@ struct ModuleData {
int stringsResourceId;
int voicesResourceId;
byte *moduleBase; // all base module
uint16 moduleBaseSize; // base module size
Common::Array<byte> moduleBase; // all base module
uint16 staticSize; // size of static data
uint staticOffset; // offset of static data begining in _commonBuffer
uint16 entryPointsTableOffset; // offset of entrypoint table in moduleBase
uint16 entryPointsCount;
EntryPoint *entryPoints;
Common::Array<EntryPoint> entryPoints;
StringsTable strings;
VoiceLUT voiceLUT;
void freeMem() {
void clear() {
loaded = false;
strings.clear();
voiceLUT.freeMem();
free(moduleBase);
free(entryPoints);
voiceLUT.clear();
moduleBase.clear();
entryPoints.clear();
}
ModuleData() : loaded(false), scriptResourceId(0), stringsResourceId(0), voicesResourceId(0), staticSize(0), staticOffset(0) {
}
};
class ScriptThread {
public:
int16 *_stackBuf;
Common::Array<int16> _stackBuf;
uint16 _stackTopIndex;
uint16 _frameIndex;
@ -264,41 +256,15 @@ public:
}
ScriptThread() {
memset(this, 0xFE, sizeof(*this));
memset(&_frameIndex, 0xFE, sizeof(_frameIndex));
memset(_threadVars, 0xFE, sizeof(_threadVars));
memset(&_waitType, 0xFE, sizeof(_waitType));
memset(&_sleepTime, 0xFE, sizeof(_sleepTime));
memset(&_threadObj, 0xFE, sizeof(_threadObj));
memset(&_returnValue, 0xFE, sizeof(_threadObj));
memset(&_frameWait, 0xFE, sizeof(_frameWait));
_flags = kTFlagNone;
_stackBuf = 0;
}
// copy constructor
ScriptThread(const ScriptThread& s) {
// Verify that s doesn't have a non-zero _stackBuf, for else
// we would have to clone that buffer, too, which we currently
// don't do. This case should never occur anyway, though (at
// least as long as the thread handling code does not change).
assert(!s._stackBuf);
memcpy(this, &s, sizeof(*this));
}
// assignment operator
ScriptThread& operator=(const ScriptThread &s) {
if (this == &s)
return *this;
// Verify that s doesn't have a non-zero _stackBuf, for else
// we would have to clone that buffer, too, which we currently
// don't do. This case should never occur anyway, though (at
// least as long as the thread handling code does not change).
assert(!s._stackBuf);
free(_stackBuf);
memcpy(this, &s, sizeof(*this));
return *this;
}
~ScriptThread() {
free(_stackBuf);
}
};
@ -315,8 +281,8 @@ public:
Script(SagaEngine *vm);
virtual ~Script();
void loadModule(int scriptModuleNumber);
void freeModules();
void loadModule(uint scriptModuleNumber);
void clearModules();
void doVerb();
void showVerb(int statusColor = -1);
@ -384,13 +350,11 @@ protected:
ResourceContext *_dataContext;
uint16 _modulesLUTEntryLen;
ModuleData *_modules;
int _modulesCount;
Common::Array<ModuleData> _modules;
TextListEntry *_placardTextEntry;
friend class SagaEngine;
byte *_commonBuffer;
uint _commonBufferSize;
Common::Array<byte> _commonBuffer;
uint _staticSize;
ScriptThreadList _threadList;

View File

@ -782,11 +782,11 @@ void Script::sfSimulSpeech(SCRIPTFUNC_PARAMS) {
for (i = 0; i < actorsCount; i++)
actorsIds[i] = thread->pop();
if (thread->_voiceLUT->voices) {
if (!thread->_voiceLUT->empty()) {
if (_vm->getGameId() == GID_IHNM && stringId >= 338) {
sampleResourceId = -1;
} else {
sampleResourceId = thread->_voiceLUT->voices[stringId];
sampleResourceId = (*thread->_voiceLUT)[stringId];
if (sampleResourceId <= 0 || sampleResourceId > 4000)
sampleResourceId = -1;
}
@ -1042,8 +1042,8 @@ void Script::sfSimulSpeech2(SCRIPTFUNC_PARAMS) {
for (i = 0; i < actorsCount; i++)
actorsIds[i] = thread->pop();
if (thread->_voiceLUT->voices) {
sampleResourceId = thread->_voiceLUT->voices[stringId];
if (!thread->_voiceLUT->empty()) {
sampleResourceId = (*thread->_voiceLUT)[stringId];
if (sampleResourceId <= 0 || sampleResourceId > 4000)
sampleResourceId = -1;
}
@ -1527,7 +1527,7 @@ void Script::finishDialog(int strID, int replyID, int flags, int bitOffset) {
const char *str = _conversingThread->_strings->getString(strID);
if (*str != '[') {
int sampleResourceId = -1;
sampleResourceId = _conversingThread->_voiceLUT->voices[strID];
sampleResourceId = (*_conversingThread->_voiceLUT)[strID];
if (sampleResourceId < 0 || sampleResourceId > 4000)
sampleResourceId = -1;

View File

@ -39,16 +39,18 @@ namespace Saga {
ScriptThread &Script::createThread(uint16 scriptModuleNumber, uint16 scriptEntryPointNumber) {
loadModule(scriptModuleNumber);
if (_modules[scriptModuleNumber].entryPointsCount <= scriptEntryPointNumber) {
if (_modules[scriptModuleNumber].entryPoints.size() <= scriptEntryPointNumber) {
error("Script::createThread wrong scriptEntryPointNumber");
}
ScriptThread newThread;
ScriptThread tmp;
_threadList.push_front(tmp);
ScriptThread &newThread = _threadList.front();
newThread._instructionOffset = _modules[scriptModuleNumber].entryPoints[scriptEntryPointNumber].offset;
newThread._commonBase = _commonBuffer;
newThread._staticBase = _commonBuffer + _modules[scriptModuleNumber].staticOffset;
newThread._moduleBase = _modules[scriptModuleNumber].moduleBase;
newThread._moduleBaseSize = _modules[scriptModuleNumber].moduleBaseSize;
newThread._commonBase = &_commonBuffer.front();
newThread._staticBase = &_commonBuffer.front() + _modules[scriptModuleNumber].staticOffset;
newThread._moduleBase = &_modules[scriptModuleNumber].moduleBase.front();
newThread._moduleBaseSize = _modules[scriptModuleNumber].moduleBase.size();
newThread._strings = &_modules[scriptModuleNumber].strings;
if (_vm->getGameId() == GID_IHNM)
@ -56,14 +58,10 @@ ScriptThread &Script::createThread(uint16 scriptModuleNumber, uint16 scriptEntry
else
newThread._voiceLUT = &_modules[scriptModuleNumber].voiceLUT;
_threadList.push_front(newThread);
newThread._stackBuf.resize(ScriptThread::THREAD_STACK_SIZE);
newThread._stackTopIndex = ScriptThread::THREAD_STACK_SIZE - 2;
debug(3, "createThread(). Total threads: %d", _threadList.size());
ScriptThread &tmp = *_threadList.begin();
tmp._stackBuf = (int16 *)malloc(ScriptThread::THREAD_STACK_SIZE * sizeof(int16));
tmp._stackTopIndex = ScriptThread::THREAD_STACK_SIZE - 2;
return tmp;
return newThread;
}
void Script::wakeUpActorThread(int waitType, void *threadObj) {