mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
problems solved:
- Allow more than one script work at once - Proper implementation of address methods some opcodes may be broken - cause work in progress todo: rewrite opcodes with new address functionality svn-id: r16604
This commit is contained in:
+7
-6
@@ -308,7 +308,7 @@ bool Actor::loadActorResources(ActorData *actor) {
|
||||
|
||||
framesPointer = (ActorFrameSequence *)malloc(sizeof(ActorFrameSequence) * framesCount);
|
||||
if (framesPointer == NULL) {
|
||||
error("Couldn't allocate memory for sprite frames");
|
||||
memoryError("Actor::loadActorResources");
|
||||
}
|
||||
|
||||
MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN);
|
||||
@@ -394,11 +394,12 @@ void Actor::stepZoneAction(ActorData *actor, const HitZone *hitZone, bool exit,
|
||||
event.code = SCRIPT_EVENT;
|
||||
event.op = EVENT_EXEC_NONBLOCKING;
|
||||
event.time = 0;
|
||||
event.param = hitZone->getScriptNumber();
|
||||
event.param2 = kVerbEnter; // Action
|
||||
event.param3 = ID_NOTHING; // Object
|
||||
event.param4 = ID_NOTHING; // With Object
|
||||
event.param5 = ID_PROTAG; // Actor
|
||||
event.param = _vm->_scene->getScriptModuleNumber(); // module number
|
||||
event.param2 = hitZone->getScriptNumber(); // script entry point number
|
||||
event.param3 = kVerbEnter; // Action
|
||||
event.param4 = ID_NOTHING; // Object
|
||||
event.param5 = ID_NOTHING; // With Object
|
||||
event.param6 = ID_PROTAG; // Actor
|
||||
|
||||
_vm->_events->queue(&event);
|
||||
}
|
||||
|
||||
+21
-31
@@ -395,20 +395,20 @@ int Events::handleOneShot(EVENT *event) {
|
||||
switch (event->op) {
|
||||
case EVENT_EXEC_BLOCKING:
|
||||
case EVENT_EXEC_NONBLOCKING:
|
||||
debug(0, "Starting start script #%d", event->param);
|
||||
debug(0, "Exec module number %d script entry number %d", event->param, event->param2);
|
||||
|
||||
sthread = _vm->_script->createThread();
|
||||
sthread = _vm->_script->createThread(event->param, event->param2);
|
||||
if (sthread == NULL) {
|
||||
_vm->_console->DebugPrintf("Thread creation failed.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
sthread->threadVars[kVarAction] = TO_LE_16(event->param2);
|
||||
sthread->threadVars[kVarObject] = TO_LE_16(event->param3);
|
||||
sthread->threadVars[kVarWithObject] = TO_LE_16(event->param4);
|
||||
sthread->threadVars[kVarActor] = TO_LE_16(event->param5);
|
||||
sthread->_threadVars[kThreadVarAction] = TO_LE_16(event->param3);
|
||||
sthread->_threadVars[kThreadVarObject] = TO_LE_16(event->param4);
|
||||
sthread->_threadVars[kThreadVarWithObject] = TO_LE_16(event->param5);
|
||||
sthread->_threadVars[kThreadVarActor] = TO_LE_16(event->param6);
|
||||
|
||||
_vm->_script->executeThread(sthread, event->param);
|
||||
// _vm->_script->executeThread(sthread, event->param);
|
||||
|
||||
if (event->op == EVENT_EXEC_BLOCKING)
|
||||
_vm->_script->completeThread();
|
||||
@@ -463,45 +463,35 @@ int Events::handleInterval(EVENT *event) {
|
||||
// Schedules an event in the event list; returns a pointer to the scheduled
|
||||
// event suitable for chaining if desired.
|
||||
EVENT *Events::queue(EVENT *event) {
|
||||
EVENT *queued_event;
|
||||
EVENT *queuedEvent;
|
||||
|
||||
event->chain = NULL;
|
||||
queued_event = _eventList.pushBack(*event).operator->();
|
||||
queuedEvent = _eventList.pushBack(*event).operator->();
|
||||
initializeEvent(queuedEvent);
|
||||
|
||||
initializeEvent(queued_event);
|
||||
|
||||
return queued_event;
|
||||
return queuedEvent;
|
||||
}
|
||||
|
||||
// Places a 'add_event' on the end of an event chain given by 'head_event'
|
||||
// (head_event may be in any position in the event chain)
|
||||
EVENT *Events::chain(EVENT *head_event, EVENT *add_event) {
|
||||
EVENT *walk_event;
|
||||
EVENT *new_event;
|
||||
|
||||
// Allocate space for new event
|
||||
new_event = (EVENT *)malloc(sizeof(*new_event));
|
||||
if (new_event == NULL) {
|
||||
return NULL;
|
||||
EVENT *Events::chain(EVENT *headEvent, EVENT *addEvent) {
|
||||
if (headEvent == NULL) {
|
||||
return queue(addEvent);
|
||||
}
|
||||
|
||||
// Copy event data to new event
|
||||
*new_event = *add_event;
|
||||
|
||||
// Walk to end of chain
|
||||
for (walk_event = head_event; walk_event->chain != NULL; walk_event = walk_event->chain) {
|
||||
EVENT *walkEvent;
|
||||
for (walkEvent = headEvent; walkEvent->chain != NULL; walkEvent = walkEvent->chain) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Place new event
|
||||
walk_event->chain = new_event;
|
||||
new_event->chain = NULL;
|
||||
initializeEvent(new_event);
|
||||
walkEvent->chain = (EVENT *)malloc(sizeof(*walkEvent->chain));
|
||||
*walkEvent->chain = *addEvent;
|
||||
initializeEvent(walkEvent->chain);
|
||||
|
||||
return new_event;
|
||||
return walkEvent->chain;
|
||||
}
|
||||
|
||||
int Events::initializeEvent(EVENT *event) {
|
||||
event->chain = NULL;
|
||||
switch (event->type) {
|
||||
case ONESHOT_EVENT:
|
||||
break;
|
||||
|
||||
+8
-5
@@ -30,7 +30,7 @@
|
||||
|
||||
namespace Saga {
|
||||
|
||||
enum EVENT_TYPES {
|
||||
enum EventTypes {
|
||||
ONESHOT_EVENT, // Event takes no time
|
||||
CONTINUOUS_EVENT, // Event takes time; next event starts immediately
|
||||
INTERVAL_EVENT, // Not yet implemented
|
||||
@@ -42,7 +42,7 @@ enum EVENT_FLAGS {
|
||||
NODESTROY = 0x4000
|
||||
};
|
||||
|
||||
enum EVENT_CODES {
|
||||
enum EventCodes {
|
||||
BG_EVENT = 1,
|
||||
ANIM_EVENT,
|
||||
MUSIC_EVENT,
|
||||
@@ -124,13 +124,16 @@ struct EVENT {
|
||||
long param3;
|
||||
long param4;
|
||||
long param5;
|
||||
long param6;
|
||||
void *data; // Optional event data
|
||||
long time; // Elapsed time until event
|
||||
long duration; // Duration of event
|
||||
long d_reserved;
|
||||
|
||||
EVENT *chain; // Event chain (For consecutive events)
|
||||
EVENT() { memset(this, 0, sizeof(*this)); }
|
||||
EVENT() {
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
};
|
||||
|
||||
typedef SortedList<EVENT> EventList;
|
||||
@@ -138,7 +141,7 @@ typedef SortedList<EVENT> EventList;
|
||||
#define EVENT_WARNINGCOUNT 1000
|
||||
#define EVENT_MASK 0x00FF
|
||||
|
||||
enum EVENT_STATUSCODE {
|
||||
enum EventStatusCode {
|
||||
EVENT_INVALIDCODE = 0,
|
||||
EVENT_DELETE,
|
||||
EVENT_CONTINUE,
|
||||
@@ -153,7 +156,7 @@ class Events {
|
||||
int clearList();
|
||||
int freeList();
|
||||
EVENT *queue(EVENT *event);
|
||||
EVENT *chain(EVENT *eead_event, EVENT *add_event);
|
||||
EVENT *chain(EVENT *headEvent, EVENT *addEvent);
|
||||
|
||||
private:
|
||||
int handleContinuous(EVENT * event);
|
||||
|
||||
+5
-5
@@ -47,7 +47,7 @@ Font::Font(SagaEngine *vm) : _vm(vm), _initialized(false) {
|
||||
|
||||
_fonts = (FONT **)malloc(_vm->getFontsCount() * sizeof(*_fonts));
|
||||
if (_fonts == NULL) {
|
||||
error("Font::Font(): Memory allocation failure.");
|
||||
memoryError("Font::Font");
|
||||
}
|
||||
|
||||
for (i = 0; i < _vm->getFontsCount(); i++) {
|
||||
@@ -104,7 +104,7 @@ int Font::loadFont(uint32 fontResourceId) {
|
||||
// Create new font structure
|
||||
font = (FONT *)malloc(sizeof(*font));
|
||||
if (font == NULL) {
|
||||
error("Font:loadFont(): Memory allocation error.");
|
||||
memoryError("Font::loadFont");
|
||||
}
|
||||
|
||||
// Read font header
|
||||
@@ -121,7 +121,7 @@ int Font::loadFont(uint32 fontResourceId) {
|
||||
// Create normal font style
|
||||
normal_font = (FONT_STYLE *)malloc(sizeof(*normal_font));
|
||||
if (normal_font == NULL) {
|
||||
error("Font::loadFont(): Memory allocation error.");
|
||||
memoryError("Font::loadFont");
|
||||
}
|
||||
|
||||
normal_font->font_free_p = fontres_p;
|
||||
@@ -207,7 +207,7 @@ FONT_STYLE *Font::createOutline(FONT_STYLE *src_font) {
|
||||
new_font = (FONT_STYLE *)malloc(sizeof(*new_font));
|
||||
|
||||
if (new_font == NULL) {
|
||||
error("Font::createOutline(): Memory allocation error.");
|
||||
memoryError("Font::createOutline");
|
||||
}
|
||||
|
||||
memset(new_font, 0, sizeof(*new_font));
|
||||
@@ -250,7 +250,7 @@ FONT_STYLE *Font::createOutline(FONT_STYLE *src_font) {
|
||||
new_font_data = (unsigned char *)malloc(new_font_data_len);
|
||||
|
||||
if (new_font_data == NULL) {
|
||||
error("Font::createOutline(): Memory allocation error.");
|
||||
memoryError("Font::createOutline");
|
||||
}
|
||||
|
||||
memset(new_font_data, 0, new_font_data_len);
|
||||
|
||||
+1
-1
@@ -854,7 +854,7 @@ int SagaEngine::loadGame(int gameNumber) {
|
||||
_gameFileContexts = (RSCFILE_CONTEXT **)realloc(_gameFileContexts, gameFileCount * sizeof(*_gameFileContexts));
|
||||
//TODO: on exit - FREE!
|
||||
if (_gameFileContexts == NULL) {
|
||||
error("SagaEngine::loadGame not enough memory");
|
||||
memoryError("SagaEngine::loadGame");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -67,11 +67,6 @@ Interface::Interface(SagaEngine *vm) : _vm(vm), _initialized(false) {
|
||||
return;
|
||||
}
|
||||
|
||||
_iThread = _vm->_script->createThread();
|
||||
if (_iThread == NULL) {
|
||||
error("Interface::Interface(): Error creating script thread for game interface module");
|
||||
}
|
||||
|
||||
// Load interface module resource file context
|
||||
_interfaceContext = _vm->getFileContext(GAME_RESOURCEFILE, 0);
|
||||
if (_interfaceContext == NULL) {
|
||||
|
||||
@@ -169,7 +169,6 @@ private:
|
||||
InterfacePanel _conversePanel;
|
||||
SpriteList _defPortraits;
|
||||
SpriteList _scenePortraits;
|
||||
ScriptThread *_iThread;
|
||||
PanelButton *_verbTypeToPanelButton[kVerbTypesMax];
|
||||
|
||||
bool _active;
|
||||
|
||||
+3
-3
@@ -51,7 +51,7 @@ HitZone::HitZone(MemoryReadStreamEndian *readStream, int index): _index(index) {
|
||||
_clickAreas = (HitZone::ClickArea *)malloc(_clickAreasCount * sizeof(*_clickAreas));
|
||||
|
||||
if (_clickAreas == NULL) {
|
||||
error("HitZone::HitZone Memory allocation failed");
|
||||
memoryError("HitZone::HitZone");
|
||||
}
|
||||
|
||||
for (i = 0; i < _clickAreasCount; i++) {
|
||||
@@ -62,7 +62,7 @@ HitZone::HitZone(MemoryReadStreamEndian *readStream, int index): _index(index) {
|
||||
|
||||
clickArea->points = (Point *)malloc(clickArea->pointsCount * sizeof(*(clickArea->points)));
|
||||
if (clickArea->points == NULL) {
|
||||
error("HitZone::HitZone Memory allocation failed");
|
||||
memoryError("HitZone::HitZone");
|
||||
}
|
||||
|
||||
for (j = 0; j < clickArea->pointsCount; j++) {
|
||||
@@ -169,7 +169,7 @@ void ObjectMap::load(const byte *resourcePointer, size_t resourceLength) {
|
||||
|
||||
_hitZoneList = (HitZone **) malloc(_hitZoneListCount * sizeof(HitZone *));
|
||||
if (_hitZoneList == NULL) {
|
||||
error("ObjectMap::load Memory allocation failure");
|
||||
memoryError("ObjectMap::load");
|
||||
}
|
||||
|
||||
for (i = 0; i < _hitZoneListCount; i++) {
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ Render::Render(SagaEngine *vm, OSystem *system) {
|
||||
_bg_buf = (byte *)calloc(_vm->getDisplayWidth(), _vm->getDisplayHeight());
|
||||
|
||||
if (_bg_buf == NULL) {
|
||||
error("Render::Render not enough memory");
|
||||
memoryError("Render::Render");
|
||||
}
|
||||
|
||||
// Allocate temp buffer for animation decoding,
|
||||
|
||||
+3
-1
@@ -75,6 +75,8 @@ class PalAnim;
|
||||
#define OBJECT_TYPE_SHIFT 13
|
||||
#define OBJECT_TYPE_MASK ((1 << OBJECT_TYPE_SHIFT) - 1)
|
||||
|
||||
#define memoryError(Place) error(Place##" Memory allocation error.")
|
||||
|
||||
struct RSCFILE_CONTEXT;
|
||||
struct StringList;
|
||||
|
||||
@@ -293,7 +295,7 @@ struct GameFontDescription {
|
||||
|
||||
struct GameResourceDescription {
|
||||
uint32 scene_lut_rn;
|
||||
uint32 script_lut_rn;
|
||||
uint32 moduleLUTResourceId;
|
||||
uint32 mainPanelResourceId;
|
||||
uint32 conversePanelResourceId;
|
||||
};
|
||||
|
||||
+33
-28
@@ -79,7 +79,7 @@ Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) {
|
||||
_sceneMax = _sceneCount - 1;
|
||||
_sceneLUT = (int *)malloc(_sceneMax * sizeof(*_sceneLUT));
|
||||
if (_sceneLUT == NULL) {
|
||||
error("Scene::Scene(): Memory allocation failed");
|
||||
memoryError("Scene::Scene()");
|
||||
}
|
||||
|
||||
MemoryReadStreamEndian readS(scene_lut_p, scene_lut_len, IS_BIG_ENDIAN);
|
||||
@@ -508,6 +508,9 @@ int Scene::loadScene(int scene_num, int load_flag, SCENE_PROC scene_proc, SceneD
|
||||
uint32 res_number = 0;
|
||||
int result;
|
||||
int i;
|
||||
EVENT event;
|
||||
EVENT *q_event;
|
||||
static PALENTRY current_pal[PAL_ENTRIES];
|
||||
|
||||
assert(_initialized);
|
||||
|
||||
@@ -578,20 +581,18 @@ int Scene::loadScene(int scene_num, int load_flag, SCENE_PROC scene_proc, SceneD
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// Load scene script data
|
||||
/* // Load scene script data
|
||||
if (_desc.scriptModuleNumber > 0) {
|
||||
if (_vm->_script->loadScript(_desc.scriptModuleNumber) != SUCCESS) {
|
||||
warning("Scene::loadScene(): Error loading scene script");
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
_sceneLoaded = true;
|
||||
|
||||
|
||||
q_event = NULL;
|
||||
if (fadeType == SCENE_FADE || fadeType == SCENE_FADE_NO_INTERFACE) {
|
||||
EVENT event;
|
||||
EVENT *q_event;
|
||||
static PALENTRY current_pal[PAL_ENTRIES];
|
||||
|
||||
_vm->_interface->rememberMode();
|
||||
_vm->_interface->setMode(kPanelFade, true);
|
||||
@@ -632,22 +633,25 @@ int Scene::loadScene(int scene_num, int load_flag, SCENE_PROC scene_proc, SceneD
|
||||
event.time = 0;
|
||||
event.duration = 0;
|
||||
q_event = _vm->_events->chain(q_event, &event);
|
||||
}
|
||||
|
||||
// Start the scene pre script, but stay with black palette
|
||||
if (_desc.startScriptEntrypointNumber > 0) {
|
||||
event.type = ONESHOT_EVENT;
|
||||
event.code = SCRIPT_EVENT;
|
||||
event.op = EVENT_EXEC_BLOCKING;
|
||||
event.time = 0;
|
||||
event.param = _desc.startScriptEntrypointNumber;
|
||||
event.param2 = 0; // Action
|
||||
event.param3 = _sceneNumber; // Object
|
||||
event.param4 = 0; // With Object - TODO: should be 'entrance'
|
||||
event.param5 = 0; // Actor
|
||||
// Start the scene pre script, but stay with black palette
|
||||
if (_desc.startScriptEntrypointNumber > 0) {
|
||||
event.type = ONESHOT_EVENT;
|
||||
event.code = SCRIPT_EVENT;
|
||||
event.op = EVENT_EXEC_BLOCKING;
|
||||
event.time = 0;
|
||||
event.param = _desc.scriptModuleNumber;
|
||||
event.param2 = _desc.startScriptEntrypointNumber;
|
||||
event.param3 = 0; // Action
|
||||
event.param4 = _sceneNumber; // Object
|
||||
event.param5 = 0; // With Object - TODO: should be 'entrance'
|
||||
event.param6 = 0; // Actor
|
||||
|
||||
q_event = _vm->_events->chain(q_event, &event);
|
||||
}
|
||||
q_event = _vm->_events->chain(q_event, &event);
|
||||
}
|
||||
|
||||
if (fadeType == SCENE_FADE || fadeType == SCENE_FADE_NO_INTERFACE) {
|
||||
// Fade in from black to the scene background palette
|
||||
event.type = IMMEDIATE_EVENT;
|
||||
event.code = PAL_EVENT;
|
||||
@@ -922,9 +926,9 @@ int Scene::endScene() {
|
||||
|
||||
_sceneProc(SCENE_END, &scene_info, this);
|
||||
|
||||
if (_desc.scriptModuleNumber > 0) {
|
||||
/* if (_desc.scriptModuleNumber > 0) {
|
||||
_vm->_script->freeScript();
|
||||
}
|
||||
}*/
|
||||
|
||||
// Free scene background
|
||||
if (_bg.loaded) {
|
||||
@@ -1082,11 +1086,12 @@ int Scene::defaultScene(int param, SCENE_INFO *scene_info) {
|
||||
event.code = SCRIPT_EVENT;
|
||||
event.op = EVENT_EXEC_NONBLOCKING;
|
||||
event.time = 0;
|
||||
event.param = _desc.sceneScriptEntrypointNumber;
|
||||
event.param2 = 0; // Action
|
||||
event.param3 = _sceneNumber; // Object
|
||||
event.param4 = 0; // With Object - TODO: should be 'entrance'
|
||||
event.param5 = 0; // Actor - TODO: should be VERB_ENTER
|
||||
event.param = _desc.scriptModuleNumber;
|
||||
event.param2 = _desc.sceneScriptEntrypointNumber;
|
||||
event.param3 = 0; // Action
|
||||
event.param4 = _sceneNumber; // Object
|
||||
event.param5 = 0; // With Object - TODO: should be 'entrance'
|
||||
event.param6 = 0; // Actor - TODO: should be VERB_ENTER
|
||||
|
||||
_vm->_events->queue(&event);
|
||||
}
|
||||
@@ -1116,7 +1121,7 @@ void Scene::loadSceneEntryList(const byte* resourcePointer, size_t resourceLengt
|
||||
|
||||
_entryList.entryList = (SceneEntry *) malloc(_entryList.entryListCount * sizeof(*_entryList.entryList));
|
||||
if (_entryList.entryList == NULL) {
|
||||
error("Scene::loadSceneEntryList Memory allocation failure");
|
||||
memoryError("Scene::loadSceneEntryList");
|
||||
}
|
||||
|
||||
for (i = 0; i < _entryList.entryListCount; i++) {
|
||||
|
||||
+134
-251
@@ -43,10 +43,9 @@ namespace Saga {
|
||||
// Initializes the scripting module.
|
||||
// Loads script resource look-up table, initializes script data system
|
||||
Script::Script() {
|
||||
RSCFILE_CONTEXT *s_lut_ctxt;
|
||||
RSCFILE_CONTEXT *resourceContext;
|
||||
byte *rsc_ptr;
|
||||
size_t rsc_len;
|
||||
byte *resourcePointer;
|
||||
size_t resourceLength;
|
||||
int prevTell;
|
||||
int result;
|
||||
int i, j;
|
||||
@@ -58,8 +57,7 @@ Script::Script() {
|
||||
_dbg_singlestep = 0;
|
||||
_scriptContext = 0;
|
||||
_voiceLUTPresent = false;
|
||||
_scriptLUTEntryLen = 0;
|
||||
_currentScript = 0;
|
||||
|
||||
_abortEnabled = true;
|
||||
_skipSpeeches = false;
|
||||
_conversingThread = NULL;
|
||||
@@ -73,84 +71,74 @@ Script::Script() {
|
||||
_rightButtonVerb = kVerbNone;
|
||||
_pointerObject = 0;
|
||||
|
||||
_dataBuf[0].data = _dataBuf[1].data = (ScriptDataWord *)calloc(SCRIPT_DATABUF_LEN, sizeof(ScriptDataWord));;
|
||||
_dataBuf[0].length = _dataBuf[1].length = SCRIPT_DATABUF_LEN;
|
||||
|
||||
for (i = 2; i < SCRIPT_DATABUF_NUM; i++) {
|
||||
_dataBuf[i].length = 0;
|
||||
_dataBuf[i].data = NULL;
|
||||
}
|
||||
|
||||
|
||||
_staticSize = 0;
|
||||
_commonBufferSize = COMMON_BUFFER_SIZE;
|
||||
_commonBuffer = (byte*)malloc(_commonBufferSize);
|
||||
memset(_commonBuffer, 0, _commonBufferSize);
|
||||
|
||||
debug(0, "Initializing scripting subsystem");
|
||||
// Load script resource file context
|
||||
_scriptContext = _vm->getFileContext(GAME_SCRIPTFILE, 0);
|
||||
if (_scriptContext == NULL) {
|
||||
error("Couldn't get script file context");
|
||||
error("Script::Script() Couldn't get script file context");
|
||||
}
|
||||
|
||||
// Load script LUT resource
|
||||
s_lut_ctxt = _vm->getFileContext(GAME_RESOURCEFILE, 0);
|
||||
if (s_lut_ctxt == NULL) {
|
||||
error("Couldn't get resource file context");
|
||||
resourceContext = _vm->getFileContext(GAME_RESOURCEFILE, 0);
|
||||
if (resourceContext == NULL) {
|
||||
error("Script::Script() Couldn't get resource file context");
|
||||
}
|
||||
|
||||
debug(0, "Loading script LUT from resource %u.", _vm->getResourceDescription()->script_lut_rn);
|
||||
result = RSC_LoadResource(s_lut_ctxt, _vm->getResourceDescription()->script_lut_rn, &rsc_ptr, &rsc_len);
|
||||
debug(0, "Loading module LUT from resource %u.", _vm->getResourceDescription()->moduleLUTResourceId);
|
||||
result = RSC_LoadResource(resourceContext, _vm->getResourceDescription()->moduleLUTResourceId, &resourcePointer, &resourceLength);
|
||||
if (result != SUCCESS) {
|
||||
error("Error: Couldn't load script resource look-up table");
|
||||
error("Script::Script() Couldn't load module LUT resource");
|
||||
}
|
||||
|
||||
// Create logical script LUT from resource
|
||||
if (rsc_len % S_LUT_ENTRYLEN_ITECD == 0) {
|
||||
_scriptLUTEntryLen = S_LUT_ENTRYLEN_ITECD;
|
||||
} else if (rsc_len % S_LUT_ENTRYLEN_ITEDISK == 0) {
|
||||
_scriptLUTEntryLen = S_LUT_ENTRYLEN_ITEDISK;
|
||||
if (resourceLength % S_LUT_ENTRYLEN_ITECD == 0) {
|
||||
_modulesLUTEntryLen = S_LUT_ENTRYLEN_ITECD;
|
||||
} else if (resourceLength % S_LUT_ENTRYLEN_ITEDISK == 0) {
|
||||
_modulesLUTEntryLen = S_LUT_ENTRYLEN_ITEDISK;
|
||||
} else {
|
||||
error("Error: Invalid script lookup table length (%d)", rsc_len);
|
||||
error("Script::Script() Invalid script lookup table length (%d)", resourceLength);
|
||||
}
|
||||
|
||||
// Calculate number of entries
|
||||
_scriptLUTMax = rsc_len / _scriptLUTEntryLen;
|
||||
_modulesCount = resourceLength / _modulesLUTEntryLen;
|
||||
|
||||
debug(0, "LUT has %d entries.", _scriptLUTMax);
|
||||
debug(0, "LUT has %d entries.", _modulesCount);
|
||||
|
||||
// Allocate space for logical LUT
|
||||
_scriptLUT = (SCRIPT_LUT_ENTRY *)malloc(_scriptLUTMax * sizeof(SCRIPT_LUT_ENTRY));
|
||||
if (_scriptLUT == NULL) {
|
||||
error("Error: Couldn't allocate memory for script resource look-up table");
|
||||
_modules = (ModuleData *)malloc(_modulesCount * sizeof(*_modules));
|
||||
if (_modules == NULL) {
|
||||
memoryError("Script::Script()");
|
||||
}
|
||||
|
||||
// Convert LUT resource to logical LUT
|
||||
MemoryReadStreamEndian scriptS(rsc_ptr, rsc_len, IS_BIG_ENDIAN);
|
||||
for (i = 0; i < _scriptLUTMax; i++) {
|
||||
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, IS_BIG_ENDIAN);
|
||||
for (i = 0; i < _modulesCount; i++) {
|
||||
memset(&_modules[i], 0, sizeof(ModuleData));
|
||||
|
||||
prevTell = scriptS.pos();
|
||||
_scriptLUT[i].script_rn = scriptS.readUint16();
|
||||
_scriptLUT[i].diag_list_rn = scriptS.readUint16();
|
||||
_scriptLUT[i].voice_lut_rn = scriptS.readUint16();
|
||||
_modules[i].scriptResourceId = scriptS.readUint16();
|
||||
_modules[i].stringsResourceId = scriptS.readUint16();
|
||||
_modules[i].voicesResourceId = scriptS.readUint16();
|
||||
|
||||
if (_modules[i].voicesResourceId > 0) {
|
||||
_voiceLUTPresent = true;
|
||||
}
|
||||
|
||||
|
||||
// Skip the unused portion of the structure
|
||||
for (j = scriptS.pos(); j < prevTell + _scriptLUTEntryLen; j++) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
RSC_FreeResource(rsc_ptr);
|
||||
|
||||
// Any voice lookup table resources present?
|
||||
for (i = 0; i < _scriptLUTMax; i++) {
|
||||
if (_scriptLUT[i].voice_lut_rn) {
|
||||
_voiceLUTPresent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setupScriptFuncList();
|
||||
|
||||
resourceContext = _vm->getFileContext(GAME_RESOURCEFILE, 0);
|
||||
|
||||
RSC_FreeResource(resourcePointer);
|
||||
|
||||
result = RSC_LoadResource(resourceContext, RID_ITE_MAIN_STRINGS, &stringsPointer, &stringsLength); // fixme: IHNM
|
||||
if ((result != SUCCESS) || (stringsLength == 0)) {
|
||||
error("Error loading strings list resource");
|
||||
@@ -159,6 +147,8 @@ Script::Script() {
|
||||
_vm->loadStrings(_mainStrings, stringsPointer, stringsLength);
|
||||
RSC_FreeResource(stringsPointer);
|
||||
|
||||
setupScriptFuncList();
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
@@ -173,14 +163,14 @@ Script::~Script() {
|
||||
|
||||
_mainStrings.freeMem();
|
||||
|
||||
// Free script lookup table
|
||||
free(_scriptLUT);
|
||||
freeModules();
|
||||
free(_modules);
|
||||
|
||||
free(_dataBuf[0].data);
|
||||
free(_commonBuffer);
|
||||
|
||||
_initialized = false;
|
||||
}
|
||||
|
||||
/*
|
||||
int Script::getWord(int bufNumber, int wordNumber, ScriptDataWord *data) {
|
||||
if ((bufNumber < 0) || (bufNumber >= SCRIPT_DATABUF_NUM)) {
|
||||
return FAILURE;
|
||||
@@ -265,242 +255,137 @@ int Script::getBit(int bufNumber, ScriptDataWord bitNumber, int *bitState) {
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
*/
|
||||
|
||||
// Loads a script; including script bytecode and dialogue list
|
||||
int Script::loadScript(int scriptModuleNumber) {
|
||||
ScriptData *script_data;
|
||||
byte *bytecode_p;
|
||||
size_t bytecode_len;
|
||||
uint32 scriptl_rn;
|
||||
byte *stringsPointer;
|
||||
size_t stringsLength;
|
||||
uint32 stringsResourceId;
|
||||
byte *voicelut_p;
|
||||
size_t voicelut_len;
|
||||
uint32 voicelut_rn;
|
||||
void Script::loadModule(int scriptModuleNumber) {
|
||||
byte *resourcePointer;
|
||||
size_t resourceLength;
|
||||
int result;
|
||||
|
||||
// Validate script number
|
||||
if ((scriptModuleNumber < 0) || (scriptModuleNumber > _scriptLUTMax)) {
|
||||
warning("Script::loadScript(): Invalid script module number");
|
||||
return FAILURE;
|
||||
if ((scriptModuleNumber < 0) || (scriptModuleNumber >= _modulesCount)) {
|
||||
error("Script::loadScript() Invalid script module number");
|
||||
}
|
||||
|
||||
// Release old script data if present
|
||||
freeScript();
|
||||
if (_modules[scriptModuleNumber].loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize script data structure
|
||||
debug(0, "Loading script data for script module #%d", scriptModuleNumber);
|
||||
debug(0, "Loading script module #%d", scriptModuleNumber);
|
||||
|
||||
script_data = (ScriptData *)malloc(sizeof(*script_data));
|
||||
if (script_data == NULL) {
|
||||
error("Memory allocation failed");
|
||||
}
|
||||
|
||||
script_data->loaded = 0;
|
||||
|
||||
// Initialize script pointers
|
||||
script_data->bytecode = NULL;
|
||||
script_data->voice = NULL;
|
||||
|
||||
// Load script bytecode
|
||||
scriptl_rn = _scriptLUT[scriptModuleNumber].script_rn;
|
||||
|
||||
result = RSC_LoadResource(_scriptContext, scriptl_rn, &bytecode_p, &bytecode_len);
|
||||
result = RSC_LoadResource(_scriptContext, _modules[scriptModuleNumber].scriptResourceId, &resourcePointer, &resourceLength);
|
||||
if (result != SUCCESS) {
|
||||
warning("Error loading script bytecode resource");
|
||||
free(script_data);
|
||||
return FAILURE;
|
||||
error("Script::loadModule() unable to load module base resource");
|
||||
}
|
||||
|
||||
script_data->bytecode = loadBytecode(bytecode_p, bytecode_len);
|
||||
loadModuleBase(_modules[scriptModuleNumber], resourcePointer, resourceLength);
|
||||
RSC_FreeResource(resourcePointer);
|
||||
|
||||
if (script_data->bytecode == NULL) {
|
||||
error("Error interpreting script bytecode resource");
|
||||
}
|
||||
|
||||
// Load script strings list
|
||||
stringsResourceId = _scriptLUT[scriptModuleNumber].diag_list_rn;
|
||||
|
||||
// Load strings list resource
|
||||
result = RSC_LoadResource(_scriptContext, stringsResourceId, &stringsPointer, &stringsLength);
|
||||
if ((result != SUCCESS) || (stringsLength == 0)) {
|
||||
error("Error loading strings list resource");
|
||||
result = RSC_LoadResource(_scriptContext, _modules[scriptModuleNumber].stringsResourceId, &resourcePointer, &resourceLength);
|
||||
if ((result != SUCCESS) || (resourceLength == 0)) {
|
||||
error("Script::loadModule() Error loading strings list resource");
|
||||
}
|
||||
|
||||
// Convert strings list resource to logical strings list
|
||||
_vm->loadStrings(script_data->strings, stringsPointer, stringsLength);
|
||||
RSC_FreeResource(stringsPointer);
|
||||
_vm->loadStrings(_modules[scriptModuleNumber].strings, resourcePointer, resourceLength);
|
||||
RSC_FreeResource(resourcePointer);
|
||||
|
||||
// Load voice resource lookup table
|
||||
if (_voiceLUTPresent) {
|
||||
voicelut_rn = _scriptLUT[scriptModuleNumber].voice_lut_rn;
|
||||
|
||||
// Load voice LUT resource
|
||||
result = RSC_LoadResource(_scriptContext, voicelut_rn, &voicelut_p, &voicelut_len);
|
||||
if (_modules[scriptModuleNumber].voicesResourceId > 0) {
|
||||
result = RSC_LoadResource(_scriptContext, _modules[scriptModuleNumber].voicesResourceId, &resourcePointer, &resourceLength);
|
||||
if (result != SUCCESS) {
|
||||
error("Error loading voice LUT resource");
|
||||
error("Script::loadModule() Error loading voice LUT resource");
|
||||
}
|
||||
|
||||
// Convert voice LUT resource to logical voice LUT
|
||||
script_data->voice = loadVoiceLUT(voicelut_p, voicelut_len, script_data);
|
||||
if (script_data->voice == NULL) {
|
||||
error("Error interpreting voice LUT resource");
|
||||
loadModuleVoiceLUT(_modules[scriptModuleNumber], resourcePointer, resourceLength);
|
||||
RSC_FreeResource(resourcePointer);
|
||||
}
|
||||
|
||||
_modules[scriptModuleNumber].staticOffset = _staticSize;
|
||||
_staticSize += _modules[scriptModuleNumber].staticSize;
|
||||
if (_staticSize > _commonBufferSize) {
|
||||
error("Script::loadModule() _staticSize > _commonBufferSize");
|
||||
}
|
||||
_modules[scriptModuleNumber].loaded = true;
|
||||
}
|
||||
|
||||
void Script::freeModules() {
|
||||
int i;
|
||||
for (i = 0; i < _modulesCount; i++) {
|
||||
if (_modules[i].loaded) {
|
||||
_modules[i].freeMem();
|
||||
}
|
||||
}
|
||||
|
||||
// Finish initialization
|
||||
script_data->loaded = 1;
|
||||
_currentScript = script_data;
|
||||
|
||||
return SUCCESS;
|
||||
_staticSize = 0;
|
||||
}
|
||||
|
||||
// Frees all resources associated with current script.
|
||||
int Script::freeScript() {
|
||||
if (_currentScript == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
void Script::loadModuleBase(ModuleData &module, const byte *resourcePointer, size_t resourceLength) {
|
||||
int i;
|
||||
|
||||
if (!_currentScript->loaded) {
|
||||
return FAILURE;
|
||||
}
|
||||
debug(0, "Loading module base...");
|
||||
|
||||
debug(0, "Releasing script data.");
|
||||
module.moduleBase = (byte*)malloc(resourceLength);
|
||||
module.moduleBaseSize = resourceLength;
|
||||
|
||||
// Finish initialization
|
||||
_currentScript->strings.freeMem();
|
||||
memcpy(module.moduleBase, resourcePointer, resourceLength);
|
||||
|
||||
if (_currentScript->bytecode != NULL) {
|
||||
free(_currentScript->bytecode->entrypoints);
|
||||
RSC_FreeResource(_currentScript->bytecode->bytecode_p);
|
||||
}
|
||||
MemoryReadStreamEndian scriptS(module.moduleBase, module.moduleBaseSize, IS_BIG_ENDIAN);
|
||||
|
||||
free(_currentScript->bytecode);
|
||||
|
||||
if (_voiceLUTPresent) {
|
||||
free(_currentScript->voice->voices);
|
||||
free(_currentScript->voice);
|
||||
}
|
||||
|
||||
free(_currentScript);
|
||||
|
||||
_currentScript = NULL;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// Reads the entrypoint table from a script bytecode resource in memory.
|
||||
// Returns NULL on failure.
|
||||
SCRIPT_BYTECODE *Script::loadBytecode(byte *bytecode_p, size_t bytecode_len) {
|
||||
PROC_TBLENTRY *bc_ep_tbl = NULL;
|
||||
SCRIPT_BYTECODE *bc_new_data = NULL;
|
||||
|
||||
unsigned long n_entrypoints; // Number of entrypoints
|
||||
size_t ep_tbl_offset; // Offset of bytecode entrypoint table
|
||||
unsigned long i;
|
||||
|
||||
debug(0, "Loading script bytecode...");
|
||||
|
||||
MemoryReadStreamEndian scriptS(bytecode_p, bytecode_len, IS_BIG_ENDIAN);
|
||||
|
||||
// The first two uint32 values are the number of entrypoints, and the
|
||||
// offset to the entrypoint table, respectively.
|
||||
n_entrypoints = scriptS.readUint16();
|
||||
module.entryPointsCount = scriptS.readUint16();
|
||||
scriptS.readUint16(); //skip
|
||||
ep_tbl_offset = scriptS.readUint16();
|
||||
module.entryPointsTableOffset = scriptS.readUint16();
|
||||
scriptS.readUint16(); //skip
|
||||
|
||||
// Check that the entrypoint table offset is valid.
|
||||
if ((bytecode_len - ep_tbl_offset) < (n_entrypoints * SCRIPT_TBLENTRY_LEN)) {
|
||||
warning("Invalid table offset");
|
||||
return NULL;
|
||||
if ((module.moduleBaseSize - module.entryPointsTableOffset) < (module.entryPointsCount * SCRIPT_TBLENTRY_LEN)) {
|
||||
error("Script::loadModuleBase() Invalid table offset");
|
||||
}
|
||||
|
||||
if (n_entrypoints > SCRIPT_MAX) {
|
||||
warning("Script limit exceeded");
|
||||
return NULL;
|
||||
if (module.entryPointsCount > SCRIPT_MAX) {
|
||||
error("Script::loadModuleBase()Script limit exceeded");
|
||||
}
|
||||
|
||||
// Allocate a new bytecode resource information structure and table of
|
||||
// entrypoints
|
||||
|
||||
bc_new_data = (SCRIPT_BYTECODE *)malloc(sizeof(*bc_new_data));
|
||||
if (bc_new_data == NULL) {
|
||||
warning("Memory allocation failure loading script bytecode");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bc_ep_tbl = (PROC_TBLENTRY *)malloc(n_entrypoints * sizeof(*bc_ep_tbl));
|
||||
if (bc_ep_tbl == NULL) {
|
||||
warning("Memory allocation failure creating script entrypoint table");
|
||||
free(bc_new_data);
|
||||
return NULL;
|
||||
|
||||
module.entryPoints = (EntryPoint *)malloc(module.entryPointsCount * sizeof(*module.entryPoints));
|
||||
if (module.entryPoints == NULL) {
|
||||
memoryError("Script::loadModuleBase");
|
||||
}
|
||||
|
||||
// Read in the entrypoint table
|
||||
|
||||
while (scriptS.pos() < ep_tbl_offset)
|
||||
|
||||
module.staticSize = scriptS.readUint16();
|
||||
while (scriptS.pos() < module.entryPointsTableOffset)
|
||||
scriptS.readByte();
|
||||
|
||||
for (i = 0; i < n_entrypoints; i++) {
|
||||
for (i = 0; i < module.entryPointsCount; 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
|
||||
bc_ep_tbl[i].name_offset = scriptS.readUint16();
|
||||
bc_ep_tbl[i].offset = scriptS.readUint16();
|
||||
module.entryPoints[i].nameOffset = scriptS.readUint16();
|
||||
module.entryPoints[i].offset = scriptS.readUint16();
|
||||
|
||||
// Perform a simple range check on offset values
|
||||
if ((bc_ep_tbl[i].name_offset > bytecode_len) || (bc_ep_tbl[i].offset > bytecode_len)) {
|
||||
warning("Invalid offset encountered in script entrypoint table");
|
||||
free(bc_new_data);
|
||||
free(bc_ep_tbl);
|
||||
return NULL;
|
||||
if ((module.entryPoints[i].nameOffset >= module.moduleBaseSize) || (module.entryPoints[i].offset >= module.moduleBaseSize)) {
|
||||
error("Script::loadModuleBase() Invalid offset encountered in script entrypoint table");
|
||||
}
|
||||
}
|
||||
|
||||
bc_new_data->bytecode_p = (byte *) bytecode_p;
|
||||
bc_new_data->bytecode_len = bytecode_len;
|
||||
|
||||
bc_new_data->n_entrypoints = n_entrypoints;
|
||||
bc_new_data->entrypoints = bc_ep_tbl;
|
||||
bc_new_data->ep_tbl_offset = ep_tbl_offset;
|
||||
|
||||
return bc_new_data;
|
||||
}
|
||||
|
||||
|
||||
// Reads a logical voice LUT from a voice LUT resource in memory.
|
||||
// Returns NULL on failure.
|
||||
VOICE_LUT *Script::loadVoiceLUT(const byte *voicelut_p, size_t voicelut_len, ScriptData *script) {
|
||||
VOICE_LUT *voice_lut;
|
||||
|
||||
void Script::loadModuleVoiceLUT(ModuleData &module, const byte *resourcePointer, size_t resourceLength) {
|
||||
uint16 i;
|
||||
|
||||
voice_lut = (VOICE_LUT *)malloc(sizeof(*voice_lut));
|
||||
if (voice_lut == NULL) {
|
||||
return NULL;
|
||||
module.voiceLUT.voicesCount = resourceLength / 2;
|
||||
if (module.voiceLUT.voicesCount != module.strings.stringsCount) {
|
||||
error("Script::loadModuleVoiceLUT() Voice LUT entries do not match strings entries");
|
||||
}
|
||||
|
||||
voice_lut->n_voices = voicelut_len / 2;
|
||||
if (voice_lut->n_voices != script->strings.stringsCount) {
|
||||
warning("Error: Voice LUT entries do not match dialogue entries");
|
||||
return NULL;
|
||||
module.voiceLUT.voices = (uint16 *)malloc(module.voiceLUT.voicesCount * sizeof(*module.voiceLUT.voices));
|
||||
if (module.voiceLUT.voices == NULL) {
|
||||
error("Script::loadModuleVoiceLUT() not enough memory");
|
||||
}
|
||||
|
||||
voice_lut->voices = (int *)malloc(voice_lut->n_voices * sizeof(*voice_lut->voices));
|
||||
if (voice_lut->voices == NULL) {
|
||||
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, IS_BIG_ENDIAN);
|
||||
|
||||
return NULL;
|
||||
for (i = 0; i < module.voiceLUT.voicesCount; i++) {
|
||||
module.voiceLUT.voices[i] = scriptS.readUint16();
|
||||
}
|
||||
|
||||
MemoryReadStreamEndian scriptS(voicelut_p, voicelut_len, IS_BIG_ENDIAN);
|
||||
|
||||
for (i = 0; i < voice_lut->n_voices; i++) {
|
||||
voice_lut->voices[i] = scriptS.readUint16();
|
||||
}
|
||||
|
||||
return voice_lut;
|
||||
}
|
||||
|
||||
void Script::scriptError(ScriptThread *thread, const char *format, ...) {
|
||||
@@ -511,13 +396,13 @@ void Script::scriptError(ScriptThread *thread, const char *format, ...) {
|
||||
vsprintf(buf, format, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
thread->flags |= kTFlagAborted;
|
||||
debug(0, "Script::scriptError %X: %s", thread->instructionOffset, buf);
|
||||
_vm->_console->DebugPrintf("Script::scriptError %X: %s", thread->instructionOffset, buf);
|
||||
thread->_flags |= kTFlagAborted;
|
||||
debug(0, "Script::scriptError %X: %s", thread->_instructionOffset, buf);
|
||||
_vm->_console->DebugPrintf("Script::scriptError %X: %s", thread->_instructionOffset, buf);
|
||||
}
|
||||
|
||||
void Script::scriptInfo() {
|
||||
uint32 n_entrypoints;
|
||||
/* uint32 n_entrypoints;
|
||||
uint32 i;
|
||||
char *name_ptr;
|
||||
|
||||
@@ -537,11 +422,11 @@ void Script::scriptInfo() {
|
||||
name_ptr = (char *)currentScript()->bytecode->bytecode_p +
|
||||
currentScript()->bytecode->entrypoints[i].name_offset;
|
||||
_vm->_console->DebugPrintf("%lu: %s\n", i, name_ptr);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void Script::scriptExec(int argc, const char **argv) {
|
||||
uint16 ep_num;
|
||||
/* uint16 ep_num;
|
||||
|
||||
ep_num = atoi(argv[1]);
|
||||
|
||||
@@ -559,7 +444,7 @@ void Script::scriptExec(int argc, const char **argv) {
|
||||
return;
|
||||
}
|
||||
|
||||
executeThread(_dbg_thread, ep_num);
|
||||
executeThread(_dbg_thread, ep_num);*/
|
||||
}
|
||||
|
||||
// verb
|
||||
@@ -699,19 +584,17 @@ void Script::doVerb() {
|
||||
}
|
||||
|
||||
if (scriptEntrypointNumber > 0) {
|
||||
if (scriptModuleNumber != _vm->_scene->getScriptModuleNumber()) {
|
||||
warning("scriptModuleNumber != _vm->_scene->getScriptModuleNumber()");
|
||||
}
|
||||
|
||||
event.type = ONESHOT_EVENT;
|
||||
event.code = SCRIPT_EVENT;
|
||||
event.op = EVENT_EXEC_NONBLOCKING;
|
||||
event.time = 0;
|
||||
event.param = scriptEntrypointNumber;
|
||||
event.param2 = _pendingVerb; // Action
|
||||
event.param3 = _pendingObject[0]; // Object
|
||||
event.param4 = _pendingObject[1]; // With Object
|
||||
event.param5 = (objectType == kGameObjectActor) ? _pendingObject[0] : ID_PROTAG; // Actor
|
||||
event.param = scriptModuleNumber;
|
||||
event.param2 = scriptEntrypointNumber;
|
||||
event.param3 = _pendingVerb; // Action
|
||||
event.param4 = _pendingObject[0]; // Object
|
||||
event.param5 = _pendingObject[1]; // With Object
|
||||
event.param6 = (objectType == kGameObjectActor) ? _pendingObject[0] : ID_PROTAG; // Actor
|
||||
|
||||
_vm->_events->queue(&event);
|
||||
|
||||
|
||||
+149
-103
@@ -31,8 +31,7 @@
|
||||
|
||||
namespace Saga {
|
||||
|
||||
#define SCRIPT_DATABUF_NUM 5
|
||||
#define SCRIPT_DATABUF_LEN 1024
|
||||
#define COMMON_BUFFER_SIZE 1024
|
||||
|
||||
#define S_LUT_ENTRYLEN_ITECD 22
|
||||
#define S_LUT_ENTRYLEN_ITEDISK 16
|
||||
@@ -48,8 +47,18 @@ namespace Saga {
|
||||
#define S_WARN_PREFIX "SWarning: "
|
||||
|
||||
#define SCRIPT_FUNCTION_MAX 78
|
||||
#define DEFAULT_THREAD_STACK_SIZE 256
|
||||
|
||||
typedef unsigned int ScriptDataWord;
|
||||
enum AddressTypes {
|
||||
kAddressCommon = 0, // offset from global variables
|
||||
kAddressStatic = 1, // offset from global variables
|
||||
kAddressModule = 2, // offset from start of module
|
||||
kAddressStack = 3, // offset from stack
|
||||
kAddressThread = 4, // offset from thread structure
|
||||
/* kAddressId = 5, // offset from const id object
|
||||
kAddressIdIndirect = 6, // offset from stack id object
|
||||
kAddressIndex = 7 // index from id*/
|
||||
};
|
||||
|
||||
enum VerbTypes {
|
||||
//todo: LUT for drawing
|
||||
@@ -74,11 +83,13 @@ enum VerbTypes {
|
||||
|
||||
#define STHREAD_TIMESLICE 8
|
||||
|
||||
enum {
|
||||
kVarObject = 0,
|
||||
kVarWithObject,
|
||||
kVarAction,
|
||||
kVarActor
|
||||
enum ThreadVarTypes {
|
||||
kThreadVarObject = 0,
|
||||
kThreadVarWithObject = 1,
|
||||
kThreadVarAction = 2,
|
||||
kThreadVarActor = 3,
|
||||
|
||||
kThreadVarMax = kThreadVarActor + 1
|
||||
};
|
||||
|
||||
enum ThreadFlags {
|
||||
@@ -136,104 +147,141 @@ enum ReplyFlags {
|
||||
kReplyCondition = 1 << 2
|
||||
};
|
||||
|
||||
struct ScriptThread {
|
||||
int flags; // ThreadFlags
|
||||
int waitType; // ThreadWaitTypes
|
||||
void *threadObj; // which object we're handling
|
||||
struct EntryPoint {
|
||||
uint16 nameOffset;
|
||||
uint16 offset;
|
||||
};
|
||||
|
||||
uint sleepTime;
|
||||
int entrypointNumber; // Entrypoint number
|
||||
unsigned long entrypointOffset; // Entrypoint offset
|
||||
unsigned long instructionOffset; // Instruction offset
|
||||
struct VoiceLUT {
|
||||
uint16 voicesCount;
|
||||
uint16 *voices;
|
||||
void freeMem() {
|
||||
free(voices);
|
||||
}
|
||||
};
|
||||
|
||||
// The scripts are allowed to access the stack like any other memory
|
||||
// area. It's therefore probably quite important that our stacks work
|
||||
// the same as in the original interpreter.
|
||||
struct ModuleData {
|
||||
bool loaded; // is it loaded or not?
|
||||
int scriptResourceId;
|
||||
int stringsResourceId;
|
||||
int voicesResourceId;
|
||||
|
||||
ScriptDataWord stackBuf[64];
|
||||
byte *moduleBase; // all base module
|
||||
uint16 moduleBaseSize; // base module size
|
||||
uint16 staticSize; // size of static data
|
||||
uint staticOffset; // offset of static data begining in _commonBuffer
|
||||
|
||||
int stackPtr;
|
||||
int framePtr;
|
||||
uint16 entryPointsTableOffset; // offset of entrypoint table in moduleBase
|
||||
uint16 entryPointsCount;
|
||||
EntryPoint *entryPoints;
|
||||
|
||||
ScriptDataWord threadVars[4];
|
||||
StringsTable strings;
|
||||
VoiceLUT voiceLUT;
|
||||
void freeMem() {
|
||||
strings.freeMem();
|
||||
voiceLUT.freeMem();
|
||||
free(moduleBase);
|
||||
free(entryPoints);
|
||||
memset(this, 0x0, sizeof(*this));
|
||||
}
|
||||
};
|
||||
|
||||
ScriptDataWord retVal;
|
||||
class ScriptThread {
|
||||
public:
|
||||
uint16 *_stackBuf;
|
||||
uint16 _stackSize; // stack size in uint16
|
||||
|
||||
uint16 _stackTopIndex;
|
||||
uint16 _frameIndex;
|
||||
|
||||
ScriptDataWord stackTop() {
|
||||
return stackBuf[stackPtr];
|
||||
uint16 _threadVars[kThreadVarMax];
|
||||
|
||||
byte *_moduleBase; //
|
||||
uint16 _moduleBaseSize;
|
||||
|
||||
byte *_commonBase; //
|
||||
byte *_staticBase; //
|
||||
VoiceLUT *_voiceLUT; //
|
||||
StringsTable *_strings; //
|
||||
|
||||
int _flags; // ThreadFlags
|
||||
int _waitType; // ThreadWaitTypes
|
||||
uint _sleepTime;
|
||||
void *_threadObj; // which object we're handling
|
||||
|
||||
uint16 _returnValue;
|
||||
|
||||
uint16 _instructionOffset; // Instruction offset
|
||||
|
||||
|
||||
public:
|
||||
byte *baseAddress(byte addrMode) {
|
||||
switch(addrMode) {
|
||||
case kAddressCommon:
|
||||
return _commonBase;
|
||||
case kAddressStatic:
|
||||
return _staticBase;
|
||||
case kAddressModule:
|
||||
return _moduleBase;
|
||||
/* case kAddressStack:
|
||||
return _stackBuf + framePtr;*/
|
||||
case kAddressThread:
|
||||
return (byte*)_threadVars;
|
||||
default:
|
||||
return _commonBase;
|
||||
}
|
||||
}
|
||||
|
||||
int stackSize() {
|
||||
return ARRAYSIZE(stackBuf) - stackPtr - 1;
|
||||
int16 stackTop() {
|
||||
return (int16)_stackBuf[_stackTopIndex];
|
||||
}
|
||||
|
||||
void push(ScriptDataWord n) {
|
||||
assert(stackPtr > 0);
|
||||
stackBuf[--stackPtr] = n;
|
||||
uint pushedSize() {
|
||||
return _stackSize - _stackTopIndex - 1;
|
||||
}
|
||||
|
||||
ScriptDataWord pop() {
|
||||
assert(stackPtr < ARRAYSIZE(stackBuf));
|
||||
return stackBuf[stackPtr++];
|
||||
void push(int16 value) {
|
||||
if (_stackTopIndex <= 0) {
|
||||
error("ScriptThread::push() stack overflow");
|
||||
}
|
||||
_stackBuf[--_stackTopIndex] = (uint16)value;
|
||||
}
|
||||
|
||||
int16 pop() {
|
||||
if (_stackTopIndex >= _stackSize) {
|
||||
error("ScriptThread::push() stack underflow");
|
||||
}
|
||||
return (int16)_stackBuf[_stackTopIndex++];
|
||||
}
|
||||
|
||||
void wait(int aWaitType) {
|
||||
waitType = aWaitType;
|
||||
flags |= kTFlagWaiting;
|
||||
|
||||
// wait stuff
|
||||
void wait(int waitType) {
|
||||
_waitType = waitType;
|
||||
_flags |= kTFlagWaiting;
|
||||
}
|
||||
|
||||
void waitWalk(void *aThreadObj) {
|
||||
void waitWalk(void *threadObj) {
|
||||
wait(kWaitTypeWalk);
|
||||
threadObj = aThreadObj;
|
||||
_threadObj = threadObj;
|
||||
}
|
||||
|
||||
void waitDelay(int aSleepTime) {
|
||||
void waitDelay(int sleepTime) {
|
||||
wait(kWaitTypeDelay);
|
||||
sleepTime = aSleepTime;
|
||||
_sleepTime = sleepTime;
|
||||
}
|
||||
|
||||
ScriptThread() {
|
||||
memset(this, 0, sizeof(*this));
|
||||
memset(this, 0xFE, sizeof(*this));
|
||||
_stackBuf = NULL;
|
||||
}
|
||||
~ScriptThread() {
|
||||
free(_stackBuf);
|
||||
}
|
||||
};
|
||||
|
||||
typedef SortedList<ScriptThread> ScriptThreadList;
|
||||
|
||||
struct PROC_TBLENTRY {
|
||||
size_t name_offset;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
struct SCRIPT_BYTECODE {
|
||||
unsigned char *bytecode_p;
|
||||
size_t bytecode_len;
|
||||
size_t ep_tbl_offset;
|
||||
unsigned long n_entrypoints;
|
||||
PROC_TBLENTRY *entrypoints;
|
||||
};
|
||||
|
||||
struct VOICE_LUT {
|
||||
int n_voices;
|
||||
int *voices;
|
||||
};
|
||||
|
||||
struct ScriptData {
|
||||
int loaded;
|
||||
SCRIPT_BYTECODE *bytecode;
|
||||
StringsTable strings;
|
||||
VOICE_LUT *voice;
|
||||
};
|
||||
|
||||
struct SCRIPT_LUT_ENTRY {
|
||||
int script_rn;
|
||||
int diag_list_rn;
|
||||
int voice_lut_rn;
|
||||
};
|
||||
|
||||
struct ScriptDataBuf {
|
||||
ScriptDataWord *data;
|
||||
int length;
|
||||
};
|
||||
|
||||
#define SCRIPTFUNC_PARAMS ScriptThread *thread, int nArgs
|
||||
|
||||
@@ -246,20 +294,17 @@ public:
|
||||
|
||||
void CF_script_togglestep();
|
||||
|
||||
int loadScript(int scriptNum);
|
||||
int freeScript();
|
||||
SCRIPT_BYTECODE *loadBytecode(byte *bytecode_p, size_t bytecode_len);
|
||||
VOICE_LUT *loadVoiceLUT(const byte *voicelut_p, size_t voicelut_len, ScriptData *script);
|
||||
void loadModule(int scriptModuleNumber);
|
||||
void freeModules();
|
||||
|
||||
bool isInitialized() const { return _initialized; }
|
||||
bool isVoiceLUTPresent() const { return _voiceLUTPresent; }
|
||||
ScriptData *currentScript() { return _currentScript; }
|
||||
ScriptDataBuf *dataBuffer(int idx) { return &_dataBuf[idx]; }
|
||||
/* ScriptData *currentScript() { return _currentScript; }
|
||||
int getWord(int bufNumber, int wordNumber, ScriptDataWord *data);
|
||||
int putWord(int bufNumber, int wordNumber, ScriptDataWord data);
|
||||
int setBit(int bufNumber, ScriptDataWord bitNumber, int bitState);
|
||||
int getBit(int bufNumber, ScriptDataWord bitNumber, int *bitState);
|
||||
const char * getScriptString(int index) const { return _currentScript->strings.getString(index); }
|
||||
int getBit(int bufNumber, ScriptDataWord bitNumber, int *bitState); */
|
||||
// const char * getScriptString(int index) const { return _currentScript->strings.getString(index); }
|
||||
|
||||
void doVerb();
|
||||
void showVerb(int statuscolor = -1);
|
||||
@@ -288,17 +333,22 @@ public:
|
||||
void scriptInfo();
|
||||
void scriptExec(int argc, const char **argv);
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool _initialized;
|
||||
bool _voiceLUTPresent;
|
||||
RSCFILE_CONTEXT *_scriptContext;
|
||||
SCRIPT_LUT_ENTRY *_scriptLUT;
|
||||
int _scriptLUTMax;
|
||||
uint16 _scriptLUTEntryLen;
|
||||
ScriptData *_currentScript;
|
||||
ScriptDataBuf _dataBuf[SCRIPT_DATABUF_NUM];
|
||||
|
||||
uint16 _modulesLUTEntryLen;
|
||||
ModuleData *_modules;
|
||||
int _modulesCount;
|
||||
|
||||
byte* _commonBuffer;
|
||||
uint _commonBufferSize;
|
||||
uint _staticSize;
|
||||
|
||||
ScriptThreadList _threadList;
|
||||
|
||||
ScriptThread *_conversingThread;
|
||||
|
||||
//verb
|
||||
bool _firstObjectSet;
|
||||
@@ -315,7 +365,6 @@ public:
|
||||
int _pendingVerb;
|
||||
uint16 _pointerObject;
|
||||
|
||||
public:
|
||||
bool _skipSpeeches;
|
||||
bool _abortEnabled;
|
||||
|
||||
@@ -325,7 +374,7 @@ public:
|
||||
TEXTLIST_ENTRY *_dbg_txtentry;
|
||||
|
||||
public:
|
||||
ScriptThread *createThread();
|
||||
ScriptThread *createThread(uint16 scriptModuleNumber, uint16 scriptEntryPointNumber);
|
||||
int executeThread(ScriptThread *thread, int entrypointNumber);
|
||||
int executeThreads(uint msec);
|
||||
int SThreadDebugStep();
|
||||
@@ -336,20 +385,17 @@ public:
|
||||
void wakeUpThreadsDelayed(int waitType, int sleepTime);
|
||||
|
||||
private:
|
||||
void setFramePtr(ScriptThread *thread, int newPtr);
|
||||
unsigned char *SThreadGetReadPtr(ScriptThread *thread);
|
||||
unsigned long SThreadGetReadOffset(const byte *read_p);
|
||||
size_t SThreadGetReadLen(ScriptThread *thread);
|
||||
void runThread(ScriptThread *thread, int instr_limit);
|
||||
void setThreadEntrypoint(ScriptThread *thread, int entrypointNumber);
|
||||
void loadModuleBase(ModuleData &module, const byte *resourcePointer, size_t resourceLength);
|
||||
void loadModuleVoiceLUT(ModuleData &module, const byte *resourcePointer, size_t resourceLength);
|
||||
|
||||
private:
|
||||
ScriptThread *_conversingThread;
|
||||
void runThread(ScriptThread *thread, uint instructionLimit);
|
||||
void setThreadEntrypoint(ScriptThread *thread, int entrypointNumber);
|
||||
|
||||
public:
|
||||
void finishDialog(int replyID, int flags, int bitOffset);
|
||||
|
||||
private:
|
||||
|
||||
typedef int (Script::*ScriptFunctionType)(SCRIPTFUNC_PARAMS);
|
||||
|
||||
struct ScriptFunctionDescription {
|
||||
@@ -442,7 +488,7 @@ private:
|
||||
int SF_playVoice(SCRIPTFUNC_PARAMS);
|
||||
};
|
||||
|
||||
inline int getSWord(ScriptDataWord word) {
|
||||
/*inline int getSWord(ScriptDataWord word) {
|
||||
uint16 uInt = word;
|
||||
int sInt;
|
||||
|
||||
@@ -458,7 +504,7 @@ inline int getSWord(ScriptDataWord word) {
|
||||
inline uint getUWord(ScriptDataWord word) {
|
||||
return (uint16) word;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
} // End of namespace Saga
|
||||
|
||||
|
||||
+5
-5
@@ -65,12 +65,12 @@ int Script::SDebugPrintInstr(ScriptThread *thread) {
|
||||
tl_e.string = disp_buf;
|
||||
tl_e.display = 1;
|
||||
|
||||
MemoryReadStream readS(currentScript()->bytecode->bytecode_p
|
||||
+ thread->instructionOffset,
|
||||
currentScript()->bytecode->bytecode_len
|
||||
- thread->instructionOffset);
|
||||
MemoryReadStream readS(thread->_moduleBase
|
||||
+ thread->_instructionOffset,
|
||||
thread->_moduleBaseSize
|
||||
- thread->_instructionOffset);
|
||||
in_char = readS.readByte();
|
||||
sprintf(tmp_buf, "%04lX | %02X | ", thread->instructionOffset, in_char);
|
||||
sprintf(tmp_buf, "%04lX | %02X | ", thread->_instructionOffset, in_char);
|
||||
strncat(disp_buf, tmp_buf, SD_DISPLAY_LEN);
|
||||
|
||||
switch (in_char) {
|
||||
|
||||
+147
-147
@@ -133,17 +133,17 @@ void Script::setupScriptFuncList(void) {
|
||||
// Script function #0 (0x00)
|
||||
// Print a debugging message
|
||||
int Script::SF_putString(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param = thread->pop();
|
||||
int16 stringIndex = thread->pop();
|
||||
|
||||
_vm->_console->DebugPrintf(getScriptString(param));
|
||||
_vm->_console->DebugPrintf(thread->_strings->getString(stringIndex));
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// Script function #1 (0x01) blocking
|
||||
// Param1: time in ticks
|
||||
int Script::sfWait(SCRIPTFUNC_PARAMS) {
|
||||
int time;
|
||||
time = getUWord(thread->pop());
|
||||
int16 time;
|
||||
time = thread->pop();
|
||||
|
||||
if (!_skipSpeeches) {
|
||||
thread->waitDelay(ticksToMSec(time)); // put thread to sleep
|
||||
@@ -176,7 +176,7 @@ int Script::SF_takeObject(SCRIPTFUNC_PARAMS) {
|
||||
int Script::SF_objectIsCarried(SCRIPTFUNC_PARAMS) {
|
||||
/*ScriptDataWord param =*/ thread->pop();
|
||||
warning("Not implemented");
|
||||
thread->retVal = 0;
|
||||
thread->_returnValue = 0;
|
||||
/*
|
||||
|
||||
int index = param & 0x1FFF;
|
||||
@@ -194,9 +194,9 @@ int Script::SF_objectIsCarried(SCRIPTFUNC_PARAMS) {
|
||||
// Set the command display to the specified text string
|
||||
// Param1: dialogue index of string
|
||||
int Script::sfStatusBar(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param = thread->pop();
|
||||
int16 stringIndex = thread->pop();
|
||||
|
||||
return _vm->_interface->setStatusText(getScriptString(param));
|
||||
return _vm->_interface->setStatusText(thread->_strings->getString(stringIndex));
|
||||
}
|
||||
|
||||
// Script function #5 (0x05)
|
||||
@@ -215,13 +215,13 @@ int Script::SF_mainMode(SCRIPTFUNC_PARAMS) {
|
||||
// Param2: actor x
|
||||
// Param3: actor y
|
||||
int Script::sfScriptWalkTo(SCRIPTFUNC_PARAMS) {
|
||||
uint16 actorId;
|
||||
int16 actorId;
|
||||
Location actorLocation;
|
||||
ActorData *actor;
|
||||
|
||||
actorId = getSWord(thread->pop());
|
||||
actorLocation.x = getSWord(thread->pop());
|
||||
actorLocation.y = getSWord(thread->pop());
|
||||
actorId = thread->pop();
|
||||
actorLocation.x = thread->pop();
|
||||
actorLocation.y = thread->pop();
|
||||
|
||||
actor = _vm->_actor->getActor(actorId);
|
||||
actorLocation.z = actor->location.z;
|
||||
@@ -236,14 +236,14 @@ int Script::sfScriptWalkTo(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #7 (0x07)
|
||||
int Script::SF_doAction(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord actor_parm = thread->pop();
|
||||
ScriptDataWord action_parm = thread->pop();
|
||||
ScriptDataWord obj_parm = thread->pop();
|
||||
ScriptDataWord withobj_parm = thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
|
||||
// The parameters correspond with the thread variables.
|
||||
|
||||
debug(1, "stub: SF_doAction(%d, %d, %d, %d)", actor_parm, action_parm, obj_parm, withobj_parm);
|
||||
//debug(1, "stub: SF_doAction(%d, %d, %d, %d)", actor_parm, action_parm, obj_parm, withobj_parm);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -251,12 +251,12 @@ int Script::SF_doAction(SCRIPTFUNC_PARAMS) {
|
||||
// Param1: actor id
|
||||
// Param2: actor orientation
|
||||
int Script::sfSetActorFacing(SCRIPTFUNC_PARAMS) {
|
||||
uint16 actorId;
|
||||
int16 actorId;
|
||||
int actorDirection;
|
||||
ActorData *actor;
|
||||
|
||||
actorId = getSWord(thread->pop());
|
||||
actorDirection = getSWord(thread->pop());
|
||||
actorId = thread->pop();
|
||||
actorDirection = thread->pop();
|
||||
|
||||
actor = _vm->_actor->getActor(actorId);
|
||||
actor->facingDirection = actor->actionDirection = actorDirection;
|
||||
@@ -267,8 +267,8 @@ int Script::sfSetActorFacing(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #9 (0x09)
|
||||
int Script::sfStartBgdAnim(SCRIPTFUNC_PARAMS) {
|
||||
int animId = getSWord(thread->pop());
|
||||
int cycles = getSWord(thread->pop());
|
||||
int16 animId = thread->pop();
|
||||
int16 cycles = thread->pop();
|
||||
|
||||
_vm->_anim->setCycles(animId, cycles);
|
||||
_vm->_anim->play(animId, kRepeatSpeed);
|
||||
@@ -279,7 +279,7 @@ int Script::sfStartBgdAnim(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #10 (0x0A)
|
||||
int Script::sfStopBgdAnim(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord animId = getSWord(thread->pop());
|
||||
int16 animId = thread->pop();
|
||||
|
||||
_vm->_anim->stop(animId);
|
||||
|
||||
@@ -293,11 +293,11 @@ int Script::sfStopBgdAnim(SCRIPTFUNC_PARAMS) {
|
||||
// reenabled.
|
||||
// Param1: boolean
|
||||
int Script::sfLockUser(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord b_param;
|
||||
int16 lock;
|
||||
|
||||
b_param = thread->pop();
|
||||
lock = thread->pop();
|
||||
|
||||
if (b_param) {
|
||||
if (lock) {
|
||||
_vm->_interface->deactivate();
|
||||
} else {
|
||||
_vm->_interface->activate();
|
||||
@@ -338,8 +338,8 @@ int Script::sfFaceTowards(SCRIPTFUNC_PARAMS) {
|
||||
int16 targetObject;
|
||||
ActorData *actor;
|
||||
|
||||
actorId = getSWord(thread->pop());
|
||||
targetObject = getSWord(thread->pop());
|
||||
actorId = thread->pop();
|
||||
targetObject = thread->pop();
|
||||
|
||||
actor = _vm->_actor->getActor(actorId);
|
||||
actor->targetObject = targetObject;
|
||||
@@ -356,8 +356,8 @@ int Script::sfSetFollower(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
ActorData *actor;
|
||||
|
||||
actorId = getSWord(thread->pop());
|
||||
targetObject = getSWord(thread->pop());
|
||||
actorId = thread->pop();
|
||||
targetObject = thread->pop();
|
||||
|
||||
debug(1, "sfSetFollower(%d, %d) [%d]", actorId, targetObject, _vm->_actor->actorIdToIndex(actorId));
|
||||
|
||||
@@ -429,8 +429,8 @@ static struct SceneSubstitutes {
|
||||
|
||||
// Script function #16 (0x10)
|
||||
int Script::SF_gotoScene(SCRIPTFUNC_PARAMS) {
|
||||
int16 sceneNum = getSWord(thread->pop());
|
||||
int16 entrance = getSWord(thread->pop());
|
||||
int16 sceneNum = thread->pop();
|
||||
int16 entrance = thread->pop();
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(sceneSubstitutes); i++)
|
||||
if (sceneSubstitutes[i].sceneId == sceneNum)
|
||||
@@ -504,8 +504,8 @@ int Script::SF_getNumber(SCRIPTFUNC_PARAMS) {
|
||||
// Script function #21 (0x15)
|
||||
// Param1: door #
|
||||
int Script::sfScriptOpenDoor(SCRIPTFUNC_PARAMS) {
|
||||
int doorNumber;
|
||||
doorNumber = getUWord(thread->pop());
|
||||
int16 doorNumber;
|
||||
doorNumber = thread->pop();
|
||||
|
||||
if (_vm->_scene->getFlags() & kSceneFlagISO) {
|
||||
//todo: it
|
||||
@@ -518,8 +518,8 @@ int Script::sfScriptOpenDoor(SCRIPTFUNC_PARAMS) {
|
||||
// Script function #22 (0x16)
|
||||
// Param1: door #
|
||||
int Script::sfScriptCloseDoor(SCRIPTFUNC_PARAMS) {
|
||||
int doorNumber;
|
||||
doorNumber = getUWord(thread->pop());
|
||||
int16 doorNumber;
|
||||
doorNumber = thread->pop();
|
||||
|
||||
if (_vm->_scene->getFlags() & kSceneFlagISO) {
|
||||
//todo: it
|
||||
@@ -531,8 +531,8 @@ int Script::sfScriptCloseDoor(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #23 (0x17)
|
||||
int Script::sfSetBgdAnimSpeed(SCRIPTFUNC_PARAMS) {
|
||||
int animId = getSWord(thread->pop());
|
||||
int speed = getSWord(thread->pop());
|
||||
int16 animId = thread->pop();
|
||||
int16 speed = thread->pop();
|
||||
|
||||
_vm->_anim->setFrameTime(animId, ticksToMSec(speed));
|
||||
debug(1, "sfSetBgdAnimSpeed(%d, %d)", animId, speed);
|
||||
@@ -552,8 +552,8 @@ int Script::SF_cycleColors(SCRIPTFUNC_PARAMS) {
|
||||
// Script function #25 (0x19)
|
||||
// Param1: actor id
|
||||
int Script::sfDoCenterActor(SCRIPTFUNC_PARAMS) {
|
||||
uint16 actorId;
|
||||
actorId = getSWord(thread->pop());
|
||||
int16 actorId;
|
||||
actorId = thread->pop();
|
||||
|
||||
_vm->_actor->_centerActor = _vm->_actor->getActor(actorId);
|
||||
return SUCCESS;
|
||||
@@ -562,9 +562,9 @@ int Script::sfDoCenterActor(SCRIPTFUNC_PARAMS) {
|
||||
// Script function #26 (0x1A) nonblocking
|
||||
// Starts the specified animation
|
||||
int Script::sfStartBgdAnimSpeed(SCRIPTFUNC_PARAMS) {
|
||||
int animId = getSWord(thread->pop());
|
||||
int cycles = getSWord(thread->pop());
|
||||
int speed = getSWord(thread->pop());
|
||||
int16 animId = thread->pop();
|
||||
int16 cycles = thread->pop();
|
||||
int16 speed = thread->pop();
|
||||
|
||||
_vm->_anim->setCycles(animId, cycles);
|
||||
_vm->_anim->play(animId, ticksToMSec(speed));
|
||||
@@ -578,13 +578,13 @@ int Script::sfStartBgdAnimSpeed(SCRIPTFUNC_PARAMS) {
|
||||
// Param2: actor x
|
||||
// Param3: actor y
|
||||
int Script::sfScriptWalkToAsync(SCRIPTFUNC_PARAMS) {
|
||||
uint16 actorId;
|
||||
int16 actorId;
|
||||
Location actorLocation;
|
||||
ActorData *actor;
|
||||
|
||||
actorId = getSWord(thread->pop());
|
||||
actorLocation.x = getSWord(thread->pop());
|
||||
actorLocation.y = getSWord(thread->pop());
|
||||
actorId = thread->pop();
|
||||
actorLocation.x = thread->pop();
|
||||
actorLocation.y = thread->pop();
|
||||
|
||||
actor = _vm->_actor->getActor(actorId);
|
||||
actorLocation.z = actor->location.z;
|
||||
@@ -608,12 +608,12 @@ int Script::SF_enableZone(SCRIPTFUNC_PARAMS) {
|
||||
// Param1: actor id
|
||||
// Param2: current action
|
||||
int Script::sfSetActorState(SCRIPTFUNC_PARAMS) {
|
||||
uint16 actorId;
|
||||
int16 actorId;
|
||||
int currentAction;
|
||||
ActorData *actor;
|
||||
|
||||
actorId = getSWord(thread->pop());
|
||||
currentAction = getSWord(thread->pop());
|
||||
actorId = thread->pop();
|
||||
currentAction = thread->pop();
|
||||
|
||||
actor = _vm->_actor->getActor(actorId);
|
||||
|
||||
@@ -631,13 +631,13 @@ int Script::sfSetActorState(SCRIPTFUNC_PARAMS) {
|
||||
// Param2: actor pos x
|
||||
// Param3: actor pos y
|
||||
int Script::scriptMoveTo(SCRIPTFUNC_PARAMS) {
|
||||
uint16 actorId;
|
||||
int16 actorId;
|
||||
Location actorLocation;
|
||||
ActorData *actor;
|
||||
|
||||
actorId = getSWord(thread->pop());
|
||||
actorLocation.x = getSWord(thread->pop());
|
||||
actorLocation.y = getSWord(thread->pop());
|
||||
actorId = thread->pop();
|
||||
actorLocation.x = thread->pop();
|
||||
actorLocation.y = thread->pop();
|
||||
|
||||
actor = _vm->_actor->getActor(actorId);
|
||||
|
||||
@@ -649,12 +649,12 @@ int Script::scriptMoveTo(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #31 (0x21)
|
||||
int Script::SF_sceneEq(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param = thread->pop();
|
||||
int16 param = thread->pop();
|
||||
|
||||
if (_vm->_scene->getSceneLUT(param) == _vm->_scene->currentSceneNumber())
|
||||
thread->retVal = 1;
|
||||
thread->_returnValue = 1;
|
||||
else
|
||||
thread->retVal = 0;
|
||||
thread->_returnValue = 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -687,7 +687,7 @@ int Script::SF_dropObject(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #33 (0x21)
|
||||
int Script::sfFinishBgdAnim(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord animId = getSWord(thread->pop());
|
||||
int16 animId = thread->pop();
|
||||
|
||||
_vm->_anim->finish(animId);
|
||||
|
||||
@@ -699,14 +699,14 @@ int Script::sfFinishBgdAnim(SCRIPTFUNC_PARAMS) {
|
||||
// Param1: actor id 1
|
||||
// Param2: actor id 2
|
||||
int Script::sfSwapActors(SCRIPTFUNC_PARAMS) {
|
||||
uint16 actorId1;
|
||||
uint16 actorId2;
|
||||
int16 actorId1;
|
||||
int16 actorId2;
|
||||
ActorData *actor1;
|
||||
ActorData *actor2;
|
||||
Location location;
|
||||
|
||||
actorId1 = getSWord(thread->pop());
|
||||
actorId2 = getSWord(thread->pop());
|
||||
actorId1 = thread->pop();
|
||||
actorId2 = thread->pop();
|
||||
|
||||
actor1 = _vm->_actor->getActor(actorId1);
|
||||
actor2 = _vm->_actor->getActor(actorId2);
|
||||
@@ -738,22 +738,22 @@ int Script::sfSwapActors(SCRIPTFUNC_PARAMS) {
|
||||
///....
|
||||
// Param3: actor idN
|
||||
int Script::sfSimulSpeech(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord stringId;
|
||||
int actorsCount;
|
||||
int16 stringId;
|
||||
int16 actorsCount;
|
||||
int i;
|
||||
uint16 actorsIds[ACTOR_SPEECH_ACTORS_MAX];
|
||||
const char *string;
|
||||
|
||||
stringId = thread->pop();
|
||||
actorsCount = getSWord(thread->pop());
|
||||
actorsCount = thread->pop();
|
||||
|
||||
if (actorsCount > ACTOR_SPEECH_ACTORS_MAX)
|
||||
error("sfSimulSpeech actorsCount=0x%X exceed ACTOR_SPEECH_ACTORS_MAX", actorsCount);
|
||||
|
||||
for (i = 0; i < actorsCount; i++)
|
||||
actorsIds[i] = getSWord(thread->pop());
|
||||
actorsIds[i] = thread->pop();
|
||||
|
||||
string = getScriptString(stringId);
|
||||
string = thread->_strings->getString(stringId);
|
||||
|
||||
_vm->_actor->simulSpeech(string, actorsIds, actorsCount, 0);
|
||||
return SUCCESS;
|
||||
@@ -765,15 +765,15 @@ int Script::sfSimulSpeech(SCRIPTFUNC_PARAMS) {
|
||||
// Param3: actor y
|
||||
// Param4: actor walk flag
|
||||
int Script::sfScriptWalk(SCRIPTFUNC_PARAMS) {
|
||||
uint16 actorId;
|
||||
int16 actorId;
|
||||
Location actorLocation;
|
||||
ActorData *actor;
|
||||
uint16 walkFlags;
|
||||
|
||||
actorId = getSWord(thread->pop());
|
||||
actorLocation.x = getSWord(thread->pop());
|
||||
actorLocation.y = getSWord(thread->pop());
|
||||
walkFlags = getUWord(thread->pop());
|
||||
actorId = thread->pop();
|
||||
actorLocation.x = thread->pop();
|
||||
actorLocation.y = thread->pop();
|
||||
walkFlags = thread->pop();
|
||||
|
||||
actor = _vm->_actor->getActor(actorId);
|
||||
actorLocation.z = actor->location.z;
|
||||
@@ -800,16 +800,16 @@ int Script::sfScriptWalk(SCRIPTFUNC_PARAMS) {
|
||||
// Param3: cycle frame number
|
||||
// Param4: cycle delay
|
||||
int Script::sfCycleFrames(SCRIPTFUNC_PARAMS) {
|
||||
uint16 actorId;
|
||||
int16 actorId;
|
||||
int flags;
|
||||
int cycleFrameSequence;
|
||||
int cycleDelay;
|
||||
ActorData *actor;
|
||||
|
||||
actorId = getSWord(thread->pop());
|
||||
flags = getUWord(thread->pop());
|
||||
cycleFrameSequence = getUWord(thread->pop());
|
||||
cycleDelay = getUWord(thread->pop());
|
||||
actorId = thread->pop();
|
||||
flags = thread->pop();
|
||||
cycleFrameSequence = thread->pop();
|
||||
cycleDelay = thread->pop();
|
||||
|
||||
actor = _vm->_actor->getActor(actorId);
|
||||
|
||||
@@ -844,15 +844,15 @@ int Script::sfCycleFrames(SCRIPTFUNC_PARAMS) {
|
||||
// Param2: frame type
|
||||
// Param3: frame offset
|
||||
int Script::sfSetFrame(SCRIPTFUNC_PARAMS) {
|
||||
uint16 actorId;
|
||||
int16 actorId;
|
||||
int frameType;
|
||||
int frameOffset;
|
||||
ActorData *actor;
|
||||
ActorFrameRange *frameRange;
|
||||
|
||||
actorId = getSWord(thread->pop());
|
||||
frameType = getSWord(thread->pop());
|
||||
frameOffset = getSWord(thread->pop());
|
||||
actorId = thread->pop();
|
||||
frameType = thread->pop();
|
||||
frameOffset = thread->pop();
|
||||
|
||||
actor = _vm->_actor->getActor(actorId);
|
||||
|
||||
@@ -875,7 +875,7 @@ int Script::sfSetFrame(SCRIPTFUNC_PARAMS) {
|
||||
// Script function #39 (0x27)
|
||||
// Sets the right-hand portrait
|
||||
int Script::sfSetPortrait(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param = thread->pop();
|
||||
int16 param = thread->pop();
|
||||
|
||||
return _vm->_interface->setRightPortrait(param);
|
||||
}
|
||||
@@ -883,7 +883,7 @@ int Script::sfSetPortrait(SCRIPTFUNC_PARAMS) {
|
||||
// Script function #40 (0x28)
|
||||
// Sets the left-hand portrait
|
||||
int Script::sfSetProtagPortrait(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param = thread->pop();
|
||||
int16 param = thread->pop();
|
||||
|
||||
return _vm->_interface->setLeftPortrait(param);
|
||||
}
|
||||
@@ -896,10 +896,10 @@ int Script::sfSetProtagPortrait(SCRIPTFUNC_PARAMS) {
|
||||
// Param3: animation id link target
|
||||
// Param4: animation id link source
|
||||
int Script::sfChainBgdAnim(SCRIPTFUNC_PARAMS) {
|
||||
int animId1 = getSWord(thread->pop());
|
||||
int animId = getSWord(thread->pop());
|
||||
int cycles = getSWord(thread->pop());
|
||||
int speed = getSWord(thread->pop());
|
||||
int16 animId1 = thread->pop();
|
||||
int16 animId = thread->pop();
|
||||
int16 cycles = thread->pop();
|
||||
int16 speed = thread->pop();
|
||||
|
||||
if (speed >= 0) {
|
||||
_vm->_anim->setCycles(animId, cycles);
|
||||
@@ -914,12 +914,12 @@ int Script::sfChainBgdAnim(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #42 (0x2A)
|
||||
int Script::SF_scriptSpecialWalk(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param1 = thread->pop();
|
||||
ScriptDataWord param2 = thread->pop();
|
||||
ScriptDataWord param3 = thread->pop();
|
||||
ScriptDataWord param4 = thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
|
||||
debug(1, "stub: SF_scriptSpecialWalk(%d, %d, %d, %d)", param1, param2, param3, param4);
|
||||
//debug(1, "stub: SF_scriptSpecialWalk(%d, %d, %d, %d)", param1, param2, param3, param4);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -931,7 +931,7 @@ int Script::SF_scriptSpecialWalk(SCRIPTFUNC_PARAMS) {
|
||||
// Param5: actor action
|
||||
// Param6: actor frame number
|
||||
int Script::sfPlaceActor(SCRIPTFUNC_PARAMS) {
|
||||
uint16 actorId;
|
||||
int16 actorId;
|
||||
Location actorLocation;
|
||||
int actorDirection;
|
||||
int frameType;
|
||||
@@ -939,12 +939,12 @@ int Script::sfPlaceActor(SCRIPTFUNC_PARAMS) {
|
||||
ActorData *actor;
|
||||
ActorFrameRange *frameRange;
|
||||
|
||||
actorId = getSWord(thread->pop());
|
||||
actorLocation.x = getSWord(thread->pop());
|
||||
actorLocation.y = getSWord(thread->pop());
|
||||
actorDirection = getSWord(thread->pop());
|
||||
frameType = getSWord(thread->pop());
|
||||
frameOffset = getSWord(thread->pop());
|
||||
actorId = thread->pop();
|
||||
actorLocation.x = thread->pop();
|
||||
actorLocation.y = thread->pop();
|
||||
actorDirection = thread->pop();
|
||||
frameType = thread->pop();
|
||||
frameOffset = thread->pop();
|
||||
|
||||
debug(1, "sfPlaceActor(%d, %d, %d, %d, %d, %d)", actorId, actorLocation.x,
|
||||
actorLocation.y, actorDirection, frameType, frameOffset);
|
||||
@@ -981,32 +981,32 @@ int Script::sfPlaceActor(SCRIPTFUNC_PARAMS) {
|
||||
// game cinematic. Pushes a zero or positive value if the game
|
||||
// has not been interrupted.
|
||||
int Script::SF_checkUserInterrupt(SCRIPTFUNC_PARAMS) {
|
||||
thread->retVal = (_skipSpeeches == true);
|
||||
thread->_returnValue = (_skipSpeeches == true);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// Script function #45 (0x2D)
|
||||
int Script::SF_walkRelative(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param1 = thread->pop();
|
||||
ScriptDataWord param2 = thread->pop();
|
||||
ScriptDataWord param3 = thread->pop();
|
||||
ScriptDataWord param4 = thread->pop();
|
||||
ScriptDataWord param5 = thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
|
||||
debug(1, "stub: SF_walkRelative(%d, %d, %d, %d, %d)", param1, param2, param3, param4, param5);
|
||||
//debug(1, "stub: SF_walkRelative(%d, %d, %d, %d, %d)", param1, param2, param3, param4, param5);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// Script function #46 (0x2E)
|
||||
int Script::SF_moveRelative(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param1 = thread->pop();
|
||||
ScriptDataWord param2 = thread->pop();
|
||||
ScriptDataWord param3 = thread->pop();
|
||||
ScriptDataWord param4 = thread->pop();
|
||||
ScriptDataWord param5 = thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
|
||||
debug(1, "stub: SF_moveRelative(%d, %d, %d, %d, %d)", param1, param2, param3, param4, param5);
|
||||
//debug(1, "stub: SF_moveRelative(%d, %d, %d, %d, %d)", param1, param2, param3, param4, param5);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1097,7 +1097,7 @@ int Script::sfPlacard(SCRIPTFUNC_PARAMS) {
|
||||
text_entry.text_y = (_vm->getSceneHeight() - _vm->_font->getHeight(MEDIUM_FONT_ID)) / 2;
|
||||
text_entry.font_id = MEDIUM_FONT_ID;
|
||||
text_entry.flags = FONT_OUTLINE | FONT_CENTERED;
|
||||
text_entry.string = getScriptString(stringId);
|
||||
text_entry.string = thread->_strings->getString(stringId);
|
||||
|
||||
placardTextEntry = _vm->textAddEntry(scene_info.text_list, &text_entry);
|
||||
|
||||
@@ -1203,8 +1203,8 @@ int Script::SF_setProtagState(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #51 (0x33)
|
||||
int Script::sfResumeBgdAnim(SCRIPTFUNC_PARAMS) {
|
||||
int animId = getSWord(thread->pop());
|
||||
int cycles = getSWord(thread->pop());
|
||||
int16 animId = thread->pop();
|
||||
int16 cycles = thread->pop();
|
||||
|
||||
_vm->_anim->resume(animId, cycles);
|
||||
debug(1, "sfResumeBgdAnimSpeed(%d, %d)", animId, cycles);
|
||||
@@ -1214,20 +1214,20 @@ int Script::sfResumeBgdAnim(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #52 (0x34)
|
||||
int Script::SF_throwActor(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param1 = thread->pop();
|
||||
ScriptDataWord param2 = thread->pop();
|
||||
ScriptDataWord param3 = thread->pop();
|
||||
ScriptDataWord param4 = thread->pop();
|
||||
ScriptDataWord param5 = thread->pop();
|
||||
ScriptDataWord param6 = thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
|
||||
debug(1, "stub: SF_throwActor(%d, %d, %d, %d, %d, %d)", param1, param2, param3, param4, param5, param6);
|
||||
//debug(1, "stub: SF_throwActor(%d, %d, %d, %d, %d, %d)", param1, param2, param3, param4, param5, param6);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// Script function #53 (0x35)
|
||||
int Script::SF_waitWalk(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param = thread->pop();
|
||||
int16 param = thread->pop();
|
||||
|
||||
debug(1, "stub: SF_waitWalk(%d)", param);
|
||||
return SUCCESS;
|
||||
@@ -1235,27 +1235,27 @@ int Script::SF_waitWalk(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #54 (0x36)
|
||||
int Script::SF_sceneID(SCRIPTFUNC_PARAMS) {
|
||||
thread->retVal = _vm->_scene->currentSceneNumber();
|
||||
thread->_returnValue = _vm->_scene->currentSceneNumber();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// Script function #55 (0x37)
|
||||
int Script::SF_changeActorScene(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param1 = thread->pop();
|
||||
ScriptDataWord param2 = thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
|
||||
debug(1, "stub: SF_changeActorScene(%d, %d)", param1, param2);
|
||||
//debug(1, "stub: SF_changeActorScene(%d, %d)", param1, param2);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// Script function #56 (0x38)
|
||||
int Script::SF_climb(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param1 = thread->pop();
|
||||
ScriptDataWord param2 = thread->pop();
|
||||
ScriptDataWord param3 = thread->pop();
|
||||
ScriptDataWord param4 = thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
|
||||
debug(1, "stub: SF_climb(%d, %d, %d, %d)", param1, param2, param3, param4);
|
||||
//debug(1, "stub: SF_climb(%d, %d, %d, %d)", param1, param2, param3, param4);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1263,10 +1263,10 @@ int Script::SF_climb(SCRIPTFUNC_PARAMS) {
|
||||
// Param1: door #
|
||||
// Param2: door state
|
||||
int Script::sfSetDoorState(SCRIPTFUNC_PARAMS) {
|
||||
int doorNumber;
|
||||
int doorState;
|
||||
doorNumber = getUWord(thread->pop());
|
||||
doorState = getUWord(thread->pop());
|
||||
int16 doorNumber;
|
||||
int16 doorState;
|
||||
doorNumber = thread->pop();
|
||||
doorState = thread->pop();
|
||||
|
||||
if (_vm->_scene->getFlags() & kSceneFlagISO) {
|
||||
//todo: it
|
||||
@@ -1278,10 +1278,10 @@ int Script::sfSetDoorState(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #58 (0x3A)
|
||||
int Script::SF_setActorZ(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param1 = thread->pop();
|
||||
ScriptDataWord param2 = thread->pop();
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
|
||||
debug(1, "stub: SF_setActorZ(%d, %d)", param1, param2);
|
||||
//debug(1, "stub: SF_setActorZ(%d, %d)", param1, param2);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1296,7 +1296,7 @@ int Script::SF_text(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #60 (0x3C)
|
||||
int Script::SF_getActorX(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param = thread->pop();
|
||||
int16 param = thread->pop();
|
||||
|
||||
debug(1, "stub: SF_getActorX(%d)", param);
|
||||
return SUCCESS;
|
||||
@@ -1304,7 +1304,7 @@ int Script::SF_getActorX(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #61 (0x3D)
|
||||
int Script::SF_getActorY(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param = thread->pop();
|
||||
int16 param = thread->pop();
|
||||
|
||||
debug(1, "stub: SF_getActorY(%d)", param);
|
||||
return SUCCESS;
|
||||
@@ -1322,15 +1322,15 @@ int Script::SF_eraseDelta(SCRIPTFUNC_PARAMS) {
|
||||
// Script function #63 (0x3F)
|
||||
int Script::sfPlayMusic(SCRIPTFUNC_PARAMS) {
|
||||
if (_vm->getGameType() == GType_ITE) {
|
||||
ScriptDataWord param = thread->pop() + 9;
|
||||
int16 param = thread->pop() + 9;
|
||||
|
||||
if (param >= 9 && param <= 34)
|
||||
_vm->_music->play(param);
|
||||
else
|
||||
_vm->_music->stop();
|
||||
} else {
|
||||
ScriptDataWord param1 = thread->pop();
|
||||
ScriptDataWord param2 = thread->pop();
|
||||
int16 param1 = thread->pop();
|
||||
int16 param2 = thread->pop();
|
||||
|
||||
debug(1, "Stub: sfPlayMusic(%d, %d)", param1, param2);
|
||||
}
|
||||
@@ -1468,7 +1468,7 @@ static struct {
|
||||
|
||||
// Script function #70 (0x46)
|
||||
int Script::sfPlaySound(SCRIPTFUNC_PARAMS) {
|
||||
int param = getSWord(thread->pop());
|
||||
int16 param = thread->pop();
|
||||
int res;
|
||||
|
||||
if (param < ARRAYSIZE(sfxTable)) {
|
||||
@@ -1522,9 +1522,9 @@ int Script::SF_protectResult(SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #75 (0x4d)
|
||||
int Script::sfRand(SCRIPTFUNC_PARAMS) {
|
||||
ScriptDataWord param = thread->pop();
|
||||
int16 param = thread->pop();
|
||||
|
||||
thread->retVal = (_vm->_rnd.getRandomNumber(param));
|
||||
thread->_returnValue = (_vm->_rnd.getRandomNumber(param));
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
@@ -1548,7 +1548,7 @@ void Script::finishDialog(int replyID, int flags, int bitOffset) {
|
||||
if (_conversingThread) {
|
||||
_vm->_interface->setMode(kPanelNull);
|
||||
|
||||
_conversingThread->flags &= ~kTFlagWaiting;
|
||||
_conversingThread->_flags &= ~kTFlagWaiting;
|
||||
|
||||
_conversingThread->push(replyID);
|
||||
|
||||
|
||||
+2
-2
@@ -99,7 +99,7 @@ int Sprite::loadList(int resourceId, SpriteList &spriteList) {
|
||||
|
||||
spriteList.infoList = (SpriteInfo *)realloc(spriteList.infoList, newSpriteCount * sizeof(*spriteList.infoList));
|
||||
if (spriteList.infoList == NULL) {
|
||||
error("Sprite::loadList Not enough memory");
|
||||
memoryError("Sprite::loadList");
|
||||
}
|
||||
|
||||
spriteList.spriteCount = newSpriteCount;
|
||||
@@ -138,7 +138,7 @@ int Sprite::loadList(int resourceId, SpriteList &spriteList) {
|
||||
decodeRLEBuffer(spriteDataPointer, 64000, outputLength); //todo: 64000 - should be replace by real input length
|
||||
spriteInfo->decodedBuffer = (byte *) malloc(outputLength);
|
||||
if (spriteInfo->decodedBuffer == NULL) {
|
||||
error("Sprite::loadList Not enough memory");
|
||||
memoryError("Sprite::loadList");
|
||||
}
|
||||
memcpy(spriteInfo->decodedBuffer, _decodeBuf, outputLength);
|
||||
}
|
||||
|
||||
+120
-176
@@ -37,29 +37,28 @@
|
||||
|
||||
namespace Saga {
|
||||
|
||||
void Script::setFramePtr(ScriptThread *thread, int newPtr) {
|
||||
thread->framePtr = newPtr;
|
||||
dataBuffer(3)->length = ARRAYSIZE(thread->stackBuf) - thread->framePtr;
|
||||
dataBuffer(3)->data = (ScriptDataWord *) &(thread->stackBuf[newPtr]);
|
||||
}
|
||||
|
||||
ScriptThread *Script::createThread() {
|
||||
ScriptThread *Script::createThread(uint16 scriptModuleNumber, uint16 scriptEntryPointNumber) {
|
||||
ScriptThread *newThread;
|
||||
|
||||
if (!isInitialized()) {
|
||||
return NULL;
|
||||
loadModule(scriptModuleNumber);
|
||||
if (_modules[scriptModuleNumber].entryPointsCount <= scriptEntryPointNumber) {
|
||||
error("Script::createThread wrong scriptEntryPointNumber");
|
||||
}
|
||||
|
||||
|
||||
newThread = _threadList.pushFront().operator->();
|
||||
newThread->_flags = kTFlagNone;
|
||||
newThread->_stackSize = DEFAULT_THREAD_STACK_SIZE;
|
||||
newThread->_stackBuf = (uint16 *)malloc(newThread->_stackSize * sizeof(*newThread->_stackBuf));
|
||||
newThread->_stackTopIndex = newThread->_stackSize - 1; // or 2 - as in original
|
||||
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->_strings = &_modules[scriptModuleNumber].strings;
|
||||
newThread->_voiceLUT = &_modules[scriptModuleNumber].voiceLUT;
|
||||
|
||||
newThread->stackPtr = ARRAYSIZE(newThread->stackBuf) - 1;
|
||||
setFramePtr(newThread, newThread->stackPtr);
|
||||
|
||||
newThread->flags = kTFlagWaiting;
|
||||
newThread->waitType = kWaitTypePause;
|
||||
|
||||
dataBuffer(4)->length = ARRAYSIZE(newThread->threadVars);
|
||||
dataBuffer(4)->data = newThread->threadVars;
|
||||
return newThread;
|
||||
}
|
||||
|
||||
@@ -69,8 +68,8 @@ void Script::wakeUpActorThread(int waitType, void *threadObj) {
|
||||
|
||||
for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) {
|
||||
thread = threadIterator.operator->();
|
||||
if ((thread->flags & kTFlagWaiting) && (thread->waitType == waitType) && (thread->threadObj == threadObj)) {
|
||||
thread->flags &= ~kTFlagWaiting;
|
||||
if ((thread->_flags & kTFlagWaiting) && (thread->_waitType == waitType) && (thread->_threadObj == threadObj)) {
|
||||
thread->_flags &= ~kTFlagWaiting;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,8 +80,8 @@ void Script::wakeUpThreads(int waitType) {
|
||||
|
||||
for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) {
|
||||
thread = threadIterator.operator->();
|
||||
if ((thread->flags & kTFlagWaiting) && (thread->waitType == waitType)) {
|
||||
thread->flags &= ~kTFlagWaiting;
|
||||
if ((thread->_flags & kTFlagWaiting) && (thread->_waitType == waitType)) {
|
||||
thread->_flags &= ~kTFlagWaiting;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,9 +92,9 @@ void Script::wakeUpThreadsDelayed(int waitType, int sleepTime) {
|
||||
|
||||
for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) {
|
||||
thread = threadIterator.operator->();
|
||||
if ((thread->flags & kTFlagWaiting) && (thread->waitType == waitType)) {
|
||||
thread->waitType = kWaitTypeDelay;
|
||||
thread->sleepTime = sleepTime;
|
||||
if ((thread->_flags & kTFlagWaiting) && (thread->_waitType == waitType)) {
|
||||
thread->_waitType = kWaitTypeDelay;
|
||||
thread->_sleepTime = sleepTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,37 +112,37 @@ int Script::executeThreads(uint msec) {
|
||||
while (threadIterator != _threadList.end()) {
|
||||
thread = threadIterator.operator->();
|
||||
|
||||
if (thread->flags & (kTFlagFinished | kTFlagAborted)) {
|
||||
if (thread->flags & kTFlagFinished)
|
||||
if (thread->_flags & (kTFlagFinished | kTFlagAborted)) {
|
||||
if (thread->_flags & kTFlagFinished)
|
||||
setPointerVerb();
|
||||
|
||||
threadIterator = _threadList.erase(threadIterator);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (thread->flags & kTFlagWaiting) {
|
||||
if (thread->_flags & kTFlagWaiting) {
|
||||
|
||||
if (thread->waitType == kWaitTypeDelay) {
|
||||
if (thread->sleepTime < msec) {
|
||||
thread->sleepTime = 0;
|
||||
if (thread->_waitType == kWaitTypeDelay) {
|
||||
if (thread->_sleepTime < msec) {
|
||||
thread->_sleepTime = 0;
|
||||
} else {
|
||||
thread->sleepTime -= msec;
|
||||
thread->_sleepTime -= msec;
|
||||
}
|
||||
|
||||
if (thread->sleepTime == 0)
|
||||
thread->flags &= ~kTFlagWaiting;
|
||||
if (thread->_sleepTime == 0)
|
||||
thread->_flags &= ~kTFlagWaiting;
|
||||
} else {
|
||||
if (thread->waitType == kWaitTypeWalk) {
|
||||
if (thread->_waitType == kWaitTypeWalk) {
|
||||
ActorData *actor;
|
||||
actor = (ActorData *)thread->threadObj;
|
||||
actor = (ActorData *)thread->_threadObj;
|
||||
if (actor->currentAction == kActionWait) {
|
||||
thread->flags &= ~kTFlagWaiting;
|
||||
thread->_flags &= ~kTFlagWaiting;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(thread->flags & kTFlagWaiting))
|
||||
if (!(thread->_flags & kTFlagWaiting))
|
||||
runThread(thread, STHREAD_TIMESLICE);
|
||||
|
||||
++threadIterator;
|
||||
@@ -157,55 +156,6 @@ void Script::completeThread(void) {
|
||||
executeThreads(0);
|
||||
}
|
||||
|
||||
void Script::setThreadEntrypoint(ScriptThread *thread, int entrypointNumber) {
|
||||
SCRIPT_BYTECODE *bytecode;
|
||||
int max_entrypoint;
|
||||
|
||||
assert(isInitialized());
|
||||
|
||||
bytecode = currentScript()->bytecode;
|
||||
max_entrypoint = bytecode->n_entrypoints;
|
||||
|
||||
if ((entrypointNumber < 0) || (entrypointNumber >= max_entrypoint)) {
|
||||
error("Script::setThreadEntrypoint wrong entrypointNumber");
|
||||
}
|
||||
|
||||
thread->entrypointNumber = entrypointNumber;
|
||||
thread->entrypointOffset = bytecode->entrypoints[entrypointNumber].offset;
|
||||
}
|
||||
|
||||
int Script::executeThread(ScriptThread *thread, int entrypointNumber) {
|
||||
assert(isInitialized());
|
||||
|
||||
if ((currentScript() == NULL) || (!currentScript()->loaded)) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
setThreadEntrypoint(thread, entrypointNumber);
|
||||
|
||||
thread->instructionOffset = thread->entrypointOffset;
|
||||
thread->flags = kTFlagNone;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned char *Script::SThreadGetReadPtr(ScriptThread *thread) {
|
||||
return currentScript()->bytecode->bytecode_p + thread->instructionOffset;
|
||||
}
|
||||
|
||||
unsigned long Script::SThreadGetReadOffset(const byte *read_p) {
|
||||
return (unsigned long)(read_p - (unsigned char *)currentScript()->bytecode->bytecode_p);
|
||||
}
|
||||
|
||||
size_t Script::SThreadGetReadLen(ScriptThread *thread) {
|
||||
return currentScript()->bytecode->bytecode_len - thread->instructionOffset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int Script::SThreadDebugStep() {
|
||||
if (_dbg_singlestep) {
|
||||
_dbg_dostep = 1;
|
||||
@@ -214,20 +164,20 @@ int Script::SThreadDebugStep() {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
int instr_count;
|
||||
void Script::runThread(ScriptThread *thread, uint instructionLimit) {
|
||||
uint instructionCount;
|
||||
uint32 saved_offset;
|
||||
ScriptDataWord param1;
|
||||
ScriptDataWord param2;
|
||||
uint16 param1;
|
||||
uint16 param2;
|
||||
long iparam1;
|
||||
long iparam2;
|
||||
long iresult;
|
||||
|
||||
ScriptDataWord data;
|
||||
ScriptDataWord scriptRetVal = 0;
|
||||
uint16 data;
|
||||
uint16 scriptRetVal = 0;
|
||||
int debug_print = 0;
|
||||
int n_buf;
|
||||
int bitstate;
|
||||
// int bitstate;
|
||||
int operandChar;
|
||||
int i;
|
||||
int unhandled = 0;
|
||||
@@ -236,36 +186,33 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
if ((thread == _dbg_thread) && _dbg_singlestep) {
|
||||
if (_dbg_dostep) {
|
||||
debug_print = 1;
|
||||
thread->sleepTime = 0;
|
||||
instr_limit = 1;
|
||||
thread->_sleepTime = 0;
|
||||
instructionLimit = 1;
|
||||
_dbg_dostep = 0;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MemoryReadStream/*Endian*/ scriptS(currentScript()->bytecode->bytecode_p, currentScript()->bytecode->bytecode_len/*, IS_BIG_ENDIAN*/);
|
||||
MemoryReadStream scriptS(thread->_moduleBase, thread->_moduleBaseSize);
|
||||
|
||||
dataBuffer(2)->length = currentScript()->bytecode->bytecode_len / sizeof(ScriptDataWord);
|
||||
dataBuffer(2)->data = (ScriptDataWord *) currentScript()->bytecode->bytecode_p;
|
||||
scriptS.seek(thread->_instructionOffset);
|
||||
|
||||
scriptS.seek(thread->instructionOffset);
|
||||
|
||||
for (instr_count = 0; instr_count < instr_limit; instr_count++) {
|
||||
if (thread->flags & (kTFlagAsleep))
|
||||
for (instructionCount = 0; instructionCount < instructionLimit; instructionCount++) {
|
||||
if (thread->_flags & (kTFlagAsleep))
|
||||
break;
|
||||
|
||||
saved_offset = thread->instructionOffset;
|
||||
saved_offset = thread->_instructionOffset;
|
||||
operandChar = scriptS.readByte();
|
||||
// debug print (opCode name etc) should be placed here
|
||||
// SDebugPrintInstr(thread)
|
||||
|
||||
debug(8, "Executing thread offset: %lu (%x) stack: %d", thread->instructionOffset, operandChar, thread->stackSize());
|
||||
debug(8, "Executing thread offset: %lu (%x) stack: %d", thread->_instructionOffset, operandChar, thread->pushedSize());
|
||||
switch (operandChar) {
|
||||
case 0x01: // nextblock
|
||||
// Some sort of "jump to the start of the next memory
|
||||
// page" instruction, I think.
|
||||
thread->instructionOffset = 1024 * ((thread->instructionOffset / 1024) + 1);
|
||||
thread->_instructionOffset = 1024 * ((thread->_instructionOffset / 1024) + 1);
|
||||
break;
|
||||
|
||||
// STACK INSTRUCTIONS
|
||||
@@ -284,7 +231,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
break;
|
||||
case 0x06: // Push word (PUSH)
|
||||
case 0x08: // Push word (PSHD) (dialogue string index)
|
||||
param1 = (ScriptDataWord)scriptS.readUint16LE();
|
||||
param1 = scriptS.readUint16LE();
|
||||
thread->push(param1);
|
||||
break;
|
||||
|
||||
@@ -292,47 +239,47 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
|
||||
case 0x0B: // Test flag (TSTF)
|
||||
n_buf = scriptS.readByte();
|
||||
param1 = (ScriptDataWord)scriptS.readUint16LE();
|
||||
getBit(n_buf, param1, &bitstate);
|
||||
thread->push(bitstate);
|
||||
param1 = scriptS.readUint16LE();
|
||||
//getBit(n_buf, param1, &bitstate);
|
||||
// thread->push(bitstate);
|
||||
break;
|
||||
case 0x0C: // Get word (GETW)
|
||||
n_buf = scriptS.readByte();
|
||||
param1 = scriptS.readUint16LE();
|
||||
getWord(n_buf, param1, &data);
|
||||
thread->push(data);
|
||||
//getWord(n_buf, param1, &data);
|
||||
// thread->push(data);
|
||||
break;
|
||||
case 0x0F: // Modify flag (MODF)
|
||||
n_buf = scriptS.readByte();
|
||||
param1 = (ScriptDataWord)scriptS.readUint16LE();
|
||||
param1 = scriptS.readUint16LE();
|
||||
data = thread->stackTop();
|
||||
if (data) {
|
||||
/* if (data) {
|
||||
setBit(n_buf, param1, 1);
|
||||
} else {
|
||||
setBit(n_buf, param1, 0);
|
||||
}
|
||||
}*/
|
||||
break;
|
||||
case 0x10: // Put word (PUTW)
|
||||
n_buf = scriptS.readByte();
|
||||
param1 = (ScriptDataWord)scriptS.readUint16LE();
|
||||
param1 = scriptS.readUint16LE();
|
||||
data = thread->stackTop();
|
||||
putWord(n_buf, param1, data);
|
||||
// putWord(n_buf, param1, data);
|
||||
break;
|
||||
case 0x13: // Modify flag and pop (MDFP)
|
||||
n_buf = scriptS.readByte();
|
||||
param1 = (ScriptDataWord)scriptS.readUint16LE();
|
||||
param1 = scriptS.readUint16LE();
|
||||
data = thread->pop();
|
||||
if (data) {
|
||||
/* if (data) {
|
||||
setBit(n_buf, param1, 1);
|
||||
} else {
|
||||
setBit(n_buf, param1, 0);
|
||||
}
|
||||
}*/
|
||||
break;
|
||||
case 0x14: // Put word and pop (PTWP)
|
||||
n_buf = scriptS.readByte();
|
||||
param1 = (ScriptDataWord)scriptS.readUint16LE();
|
||||
param1 = scriptS.readUint16LE();
|
||||
data = thread->stackTop();
|
||||
putWord(n_buf, param1, data);
|
||||
// putWord(n_buf, param1, data);
|
||||
break;
|
||||
|
||||
// CONTROL INSTRUCTIONS
|
||||
@@ -346,14 +293,14 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
temp = scriptS.readByte();
|
||||
if (temp != 2)
|
||||
error("Calling dynamically generated script? Wow");
|
||||
param1 = (ScriptDataWord)scriptS.readUint16LE();
|
||||
param1 = scriptS.readUint16LE();
|
||||
data = scriptS.pos();
|
||||
thread->push(n_args);
|
||||
// NOTE: The original pushes the program
|
||||
// counter as a pointer here. But I don't think
|
||||
// we will have to do that.
|
||||
thread->push(data);
|
||||
thread->instructionOffset = (unsigned long)param1;
|
||||
thread->_instructionOffset = param1;
|
||||
}
|
||||
break;
|
||||
case opCcall: // Call function
|
||||
@@ -374,39 +321,38 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
scriptFunction = _scriptFunctionsList[functionNumber].scriptFunction;
|
||||
scriptFunctionReturnValue = (this->*scriptFunction)(thread, argumentsCount);
|
||||
if (scriptFunctionReturnValue != SUCCESS) {
|
||||
_vm->_console->DebugPrintf(S_WARN_PREFIX "%X: Script function %d failed.\n", thread->instructionOffset, scriptFunctionReturnValue);
|
||||
_vm->_console->DebugPrintf(S_WARN_PREFIX "%X: Script function %d failed.\n", thread->_instructionOffset, scriptFunctionReturnValue);
|
||||
}
|
||||
|
||||
if (functionNumber == 16) { // SF_gotoScene
|
||||
instr_count = instr_limit; // break the loop
|
||||
instructionCount = instructionLimit; // break the loop
|
||||
break;
|
||||
}
|
||||
|
||||
if (operandChar == opCcall) // CALL function
|
||||
thread->push(thread->retVal);
|
||||
thread->push(thread->_returnValue);
|
||||
|
||||
if (thread->flags & kTFlagAsleep)
|
||||
instr_count = instr_limit; // break out of loop!
|
||||
if (thread->_flags & kTFlagAsleep)
|
||||
instructionCount = instructionLimit; // break out of loop!
|
||||
}
|
||||
break;
|
||||
case opEnter: // Enter a function
|
||||
thread->push(thread->framePtr);
|
||||
setFramePtr(thread, thread->stackPtr);
|
||||
param1 = scriptS.readUint16LE();
|
||||
thread->stackPtr -= (param1 / 2);
|
||||
thread->push(thread->_frameIndex);
|
||||
thread->_frameIndex = thread->_stackTopIndex;
|
||||
thread->_stackTopIndex -= (scriptS.readUint16LE() / 2);
|
||||
break;
|
||||
case opReturn: // Return with value
|
||||
scriptRetVal = thread->pop();
|
||||
// Fall through
|
||||
case opReturnV: // Return with void
|
||||
thread->stackPtr = thread->framePtr;
|
||||
setFramePtr(thread, thread->pop());
|
||||
if (thread->stackSize() == 0) {
|
||||
thread->_stackTopIndex = thread->_frameIndex;
|
||||
thread->_frameIndex = thread->pop();
|
||||
if (thread->pushedSize() == 0) {
|
||||
_vm->_console->DebugPrintf("Script execution complete.\n");
|
||||
thread->flags |= kTFlagFinished;
|
||||
thread->_flags |= kTFlagFinished;
|
||||
return;
|
||||
} else {
|
||||
thread->instructionOffset = thread->pop();
|
||||
thread->_instructionOffset = thread->pop();
|
||||
/* int n_args = */ thread->pop();
|
||||
if (operandChar == opReturn)
|
||||
thread->push(scriptRetVal);
|
||||
@@ -418,14 +364,14 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
// (JMP): Unconditional jump
|
||||
case 0x1D:
|
||||
param1 = scriptS.readUint16LE();
|
||||
thread->instructionOffset = (unsigned long)param1;
|
||||
thread->_instructionOffset = (unsigned long)param1;
|
||||
break;
|
||||
// (JNZP): Jump if nonzero + POP
|
||||
case 0x1E:
|
||||
param1 = scriptS.readUint16LE();
|
||||
data = thread->pop();
|
||||
if (data) {
|
||||
thread->instructionOffset = (unsigned long)param1;
|
||||
thread->_instructionOffset = (unsigned long)param1;
|
||||
}
|
||||
break;
|
||||
// (JZP): Jump if zero + POP
|
||||
@@ -433,7 +379,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
param1 = scriptS.readUint16LE();
|
||||
data = thread->pop();
|
||||
if (!data) {
|
||||
thread->instructionOffset = (unsigned long)param1;
|
||||
thread->_instructionOffset = (unsigned long)param1;
|
||||
}
|
||||
break;
|
||||
// (JNZ): Jump if nonzero
|
||||
@@ -441,7 +387,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
param1 = scriptS.readUint16LE();
|
||||
data = thread->stackTop();
|
||||
if (data) {
|
||||
thread->instructionOffset = (unsigned long)param1;
|
||||
thread->_instructionOffset = (unsigned long)param1;
|
||||
}
|
||||
break;
|
||||
// (JZ): Jump if zero
|
||||
@@ -449,14 +395,14 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
param1 = scriptS.readUint16LE();
|
||||
data = thread->stackTop();
|
||||
if (!data) {
|
||||
thread->instructionOffset = (unsigned long)param1;
|
||||
thread->_instructionOffset = (unsigned long)param1;
|
||||
}
|
||||
break;
|
||||
// (SWCH): Switch
|
||||
case 0x22:
|
||||
{
|
||||
int n_switch;
|
||||
unsigned int switch_num;
|
||||
uint16 switch_num;
|
||||
unsigned int switch_jmp;
|
||||
unsigned int default_jmp;
|
||||
int case_found = 0;
|
||||
@@ -468,8 +414,8 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
switch_num = scriptS.readUint16LE();
|
||||
switch_jmp = scriptS.readUint16LE();
|
||||
// Found the specified case
|
||||
if (data == (ScriptDataWord) switch_num) {
|
||||
thread->instructionOffset = switch_jmp;
|
||||
if (data == switch_num) {
|
||||
thread->_instructionOffset = switch_jmp;
|
||||
case_found = 1;
|
||||
break;
|
||||
}
|
||||
@@ -478,7 +424,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
// Jump to default case
|
||||
if (!case_found) {
|
||||
default_jmp = scriptS.readUint16LE();
|
||||
thread->instructionOffset = default_jmp;
|
||||
thread->_instructionOffset = default_jmp;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -496,7 +442,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
uint16 offset = scriptS.readUint16LE();
|
||||
|
||||
if (branch_probability > probability) {
|
||||
thread->instructionOffset = offset;
|
||||
thread->_instructionOffset = offset;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -525,28 +471,28 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
case 0x28: // inc_v increment, don't push
|
||||
n_buf = scriptS.readByte();
|
||||
param1 = scriptS.readUint16LE();
|
||||
getWord(n_buf, param1, &data);
|
||||
putWord(n_buf, param1, data + 1);
|
||||
//getWord(n_buf, param1, &data);
|
||||
//putWord(n_buf, param1, data + 1);
|
||||
break;
|
||||
case 0x29: // dec_v decrement, don't push
|
||||
n_buf = scriptS.readByte();
|
||||
param1 = scriptS.readUint16LE();
|
||||
getWord(n_buf, param1, &data);
|
||||
putWord(n_buf, param1, data - 1);
|
||||
//getWord(n_buf, param1, &data);
|
||||
//putWord(n_buf, param1, data - 1);
|
||||
break;
|
||||
case 0x2A: // postinc
|
||||
n_buf = scriptS.readByte();
|
||||
param1 = scriptS.readUint16LE();
|
||||
getWord(n_buf, param1, &data);
|
||||
thread->push(data);
|
||||
putWord(n_buf, param1, data + 1);
|
||||
//getWord(n_buf, param1, &data);
|
||||
// thread->push(data);
|
||||
//putWord(n_buf, param1, data + 1);
|
||||
break;
|
||||
case 0x2B: // postdec
|
||||
n_buf = scriptS.readByte();
|
||||
param1 = scriptS.readUint16LE();
|
||||
getWord(n_buf, param1, &data);
|
||||
thread->push(data);
|
||||
putWord(n_buf, param1, data - 1);
|
||||
//getWord(n_buf, param1, &data);
|
||||
// thread->push(data);
|
||||
//putWord(n_buf, param1, data - 1);
|
||||
break;
|
||||
|
||||
// ARITHMETIC INSTRUCTIONS
|
||||
@@ -558,7 +504,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
iparam2 = (long)param2;
|
||||
iparam1 = (long)param1;
|
||||
iresult = iparam1 + iparam2;
|
||||
thread->push((ScriptDataWord) iresult);
|
||||
thread->push( iresult);
|
||||
break;
|
||||
// (SUB): Subtraction
|
||||
case 0x2D:
|
||||
@@ -567,7 +513,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
iparam2 = (long)param2;
|
||||
iparam1 = (long)param1;
|
||||
iresult = iparam1 - iparam2;
|
||||
thread->push((ScriptDataWord) iresult);
|
||||
thread->push( iresult);
|
||||
break;
|
||||
// (MULT): Integer multiplication
|
||||
case 0x2E:
|
||||
@@ -576,7 +522,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
iparam2 = (long)param2;
|
||||
iparam1 = (long)param1;
|
||||
iresult = iparam1 * iparam2;
|
||||
thread->push((ScriptDataWord) iresult);
|
||||
thread->push( iresult);
|
||||
break;
|
||||
// (DIV): Integer division
|
||||
case 0x2F:
|
||||
@@ -585,7 +531,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
iparam2 = (long)param2;
|
||||
iparam1 = (long)param1;
|
||||
iresult = iparam1 / iparam2;
|
||||
thread->push((ScriptDataWord) iresult);
|
||||
thread->push( iresult);
|
||||
break;
|
||||
// (MOD) Modulus
|
||||
case 0x30:
|
||||
@@ -594,7 +540,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
iparam2 = (long)param2;
|
||||
iparam1 = (long)param1;
|
||||
iresult = iparam1 % iparam2;
|
||||
thread->push((ScriptDataWord) iresult);
|
||||
thread->push( iresult);
|
||||
break;
|
||||
// (EQU) Test equality
|
||||
case 0x33:
|
||||
@@ -747,7 +693,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
data = first = thread->stackTop();
|
||||
for (i = 0; i < stringsCount; i++) {
|
||||
data = thread->pop();
|
||||
strings[i] = getScriptString(data);
|
||||
strings[i] = thread->_strings->getString(data);
|
||||
}
|
||||
// now data contains last string index
|
||||
|
||||
@@ -756,10 +702,8 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
sampleResourceId = RID_SCENE1_VOICE_009 + data - 288;
|
||||
}
|
||||
} else {
|
||||
if (isVoiceLUTPresent()) {
|
||||
if (currentScript()->voice->n_voices > first) {
|
||||
sampleResourceId = currentScript()->voice->voices[first];
|
||||
}
|
||||
if (thread->_voiceLUT->voicesCount > first) {
|
||||
sampleResourceId = thread->_voiceLUT->voices[first];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,7 +711,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
|
||||
if (!(speechFlags & kSpeakAsync)) {
|
||||
thread->wait(kWaitTypeSpeech);
|
||||
thread->instructionOffset = scriptS.pos();
|
||||
thread->_instructionOffset = scriptS.pos();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -793,7 +737,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
|
||||
case opReply: // (DLGO): Add a dialogue option to interface
|
||||
{
|
||||
ScriptDataWord n = 0;
|
||||
uint16 n = 0;
|
||||
const char *str;
|
||||
int replyNum = scriptS.readByte();
|
||||
int flags = scriptS.readByte();
|
||||
@@ -803,7 +747,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
str = getScriptString(thread->pop());
|
||||
str = thread->_strings->getString(thread->pop());
|
||||
if (_vm->_interface->converseAddText(str, replyNum, flags, n))
|
||||
warning("Error adding ConverseText (%s, %d, %d, %d)", str, replyNum, flags, n);
|
||||
}
|
||||
@@ -812,7 +756,7 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
scriptS.readUint16LE();
|
||||
scriptS.readUint16LE();
|
||||
iparam1 = (long)scriptS.readByte();
|
||||
thread->instructionOffset += iparam1;
|
||||
thread->_instructionOffset += iparam1;
|
||||
break;
|
||||
|
||||
// End instruction list
|
||||
@@ -823,14 +767,14 @@ void Script::runThread(ScriptThread *thread, int instr_limit) {
|
||||
}
|
||||
|
||||
// Set instruction offset only if a previous instruction didn't branch
|
||||
if (saved_offset == thread->instructionOffset) {
|
||||
thread->instructionOffset = scriptS.pos();
|
||||
if (saved_offset == thread->_instructionOffset) {
|
||||
thread->_instructionOffset = scriptS.pos();
|
||||
} else {
|
||||
if (thread->instructionOffset >= scriptS.size()) {
|
||||
if (thread->_instructionOffset >= scriptS.size()) {
|
||||
scriptError(thread, "Out of range script execution");
|
||||
return;
|
||||
} else {
|
||||
scriptS.seek(thread->instructionOffset);
|
||||
scriptS.seek(thread->_instructionOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user