mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-30 23:43:10 +00:00
Started to rework script threads. Partially moved to thread flags.
Scene skipping now works, but scripts aren't chained yet. svn-id: r15688
This commit is contained in:
parent
dc796c9399
commit
b4df9bb2c1
@ -104,7 +104,10 @@ int SagaEngine::processInput() {
|
||||
break;
|
||||
case 27: // Esc
|
||||
// Skip to next scene skip target
|
||||
_vm->_scene->skipScene();
|
||||
if (!_vm->_interface->getMode() == kPanelNone) // FIXME: hack
|
||||
_vm->_script->SThreadAbortAll();
|
||||
else
|
||||
_vm->_scene->skipScene();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -218,7 +218,7 @@ Interface::Interface(SagaEngine *vm) : _vm(vm), _initialized(false) {
|
||||
_activeVerb = I_VERB_WALKTO;
|
||||
|
||||
_active = 0;
|
||||
_panelMode = PANEL_COMMAND;
|
||||
_panelMode = kPanelNone;
|
||||
*_statusText = 0;
|
||||
|
||||
_initialized = true;
|
||||
@ -241,7 +241,7 @@ int Interface::deactivate() {
|
||||
return R_SUCCESS;
|
||||
}
|
||||
|
||||
int Interface::setMode(R_PANEL_MODES mode) {
|
||||
int Interface::setMode(int mode) {
|
||||
// TODO: Is this where we should hide/show the mouse cursor?
|
||||
|
||||
_panelMode = mode;
|
||||
@ -311,7 +311,7 @@ int Interface::draw() {
|
||||
_vm->_gfx->drawRect(back_buf, &rect, _iDesc.status_bgcol);
|
||||
|
||||
// Draw command panel background
|
||||
if (_panelMode == PANEL_COMMAND) {
|
||||
if (_panelMode == kPanelCommand) {
|
||||
xbase = _cPanel.x;
|
||||
ybase = _cPanel.y;
|
||||
|
||||
@ -337,7 +337,7 @@ int Interface::draw() {
|
||||
|
||||
_vm->_sprite->draw(back_buf, _defPortraits, _leftPortrait, lportrait_x, lportrait_y);
|
||||
|
||||
if (_panelMode == PANEL_DIALOGUE && _iDesc.rportrait_x >= 0) {
|
||||
if (_panelMode == kPanelDialogue && _iDesc.rportrait_x >= 0) {
|
||||
rportrait_x = xbase + _iDesc.rportrait_x;
|
||||
rportrait_y = ybase + _iDesc.rportrait_y;
|
||||
|
||||
@ -366,7 +366,7 @@ int Interface::update(const Point& imousePt, int update_flag) {
|
||||
// Get game display info
|
||||
GAME_GetDisplayInfo(&g_di);
|
||||
|
||||
if (_panelMode == PANEL_COMMAND) {
|
||||
if (_panelMode == kPanelCommand) {
|
||||
// Update playfield space ( only if cursor is inside )
|
||||
if (imouse_y < g_di.scene_h) {
|
||||
// Mouse is in playfield space
|
||||
|
@ -77,8 +77,9 @@ enum INTERFACE_UPDATE_FLAGS {
|
||||
#define IHNM_RPORTRAIT_Y -1
|
||||
|
||||
enum R_PANEL_MODES {
|
||||
PANEL_COMMAND,
|
||||
PANEL_DIALOGUE
|
||||
kPanelNone,
|
||||
kPanelCommand,
|
||||
kPanelDialogue
|
||||
};
|
||||
|
||||
enum R_BUTTON_FLAGS {
|
||||
@ -164,7 +165,8 @@ class Interface {
|
||||
int registerLang();
|
||||
int activate();
|
||||
int deactivate();
|
||||
int setMode(R_PANEL_MODES mode);
|
||||
int setMode(int mode);
|
||||
int getMode(void) { return _panelMode; }
|
||||
int setStatusText(const char *new_txt);
|
||||
int loadScenePortraits(int res);
|
||||
int setLeftPortrait(int portrait);
|
||||
@ -188,7 +190,7 @@ class Interface {
|
||||
int _active;
|
||||
R_RSCFILE_CONTEXT *_interfaceContext;
|
||||
R_INTERFACE_DESC _iDesc;
|
||||
R_PANEL_MODES _panelMode;
|
||||
int _panelMode;
|
||||
R_INTERFACE_PANEL _cPanel;
|
||||
R_INTERFACE_PANEL _dPanel;
|
||||
char _statusText[R_STATUS_TEXT_LEN];
|
||||
|
@ -64,6 +64,8 @@ Script::Script() {
|
||||
_scriptLUTEntryLen = 0;
|
||||
_currentScript = 0;
|
||||
_threadList = 0;
|
||||
_abortEnabled = true;
|
||||
_skipSpeeches = false;
|
||||
memset(_dataBuf, 0, sizeof(_dataBuf));
|
||||
|
||||
debug(0, "Initializing scripting subsystem");
|
||||
|
@ -62,7 +62,7 @@ enum R_SCRIPT_VERBS {
|
||||
S_VERB_GIVE
|
||||
};
|
||||
|
||||
#define STHREAD_DEF_INSTR_COUNT 8
|
||||
#define STHREAD_TIMESLICE 8
|
||||
|
||||
struct R_SEMAPHORE {
|
||||
int hold_count;
|
||||
@ -75,15 +75,35 @@ enum {
|
||||
kVarActor
|
||||
};
|
||||
|
||||
struct R_SCRIPT_THREAD {
|
||||
int executing;
|
||||
enum {
|
||||
kTFlagNone = 0,
|
||||
kTFlagWaiting = 1, // wait for even denoted in waitType
|
||||
kTFlagFinished = 2,
|
||||
kTFlagAborted = 4,
|
||||
kTFlagAsleep = 7 // Combination of all flags which can halt a thread
|
||||
};
|
||||
|
||||
int sleep_time;
|
||||
enum {
|
||||
kTWaitNone = 0, // waiting for nothing
|
||||
kTWaitDelay, // waiting for a timer
|
||||
kTWaitSpeech, // waiting for speech to finish
|
||||
kTWaitDialogEnd, // waiting for my dialog to finish
|
||||
kTWaitDialogBegin, // waiting for other dialog to finish
|
||||
kTWaitWalk, // waiting to finish walking
|
||||
kTWaitRequest, // a request is up
|
||||
kTWaitPause
|
||||
};
|
||||
|
||||
struct R_SCRIPT_THREAD {
|
||||
int flags;
|
||||
int waitType;
|
||||
|
||||
uint sleepTime;
|
||||
int ep_num; // Entrypoint number
|
||||
unsigned long ep_offset; // Entrypoint offset
|
||||
unsigned long i_offset; // Instruction offset
|
||||
|
||||
R_SEMAPHORE sem;
|
||||
R_SEMAPHORE sem; // FIXME: no equivalent. should be replaced with flags
|
||||
|
||||
// The scripts are allowed to access the stack like any other memory
|
||||
// area. It's therefore probably quite important that our stacks work
|
||||
@ -195,6 +215,9 @@ protected:
|
||||
R_SCRIPT_DATABUF *_dataBuf[R_SCRIPT_DATABUF_NUM];
|
||||
YS_DL_LIST *_threadList;
|
||||
|
||||
bool _skipSpeeches;
|
||||
bool _abortEnabled;
|
||||
|
||||
public:
|
||||
int _dbg_singlestep;
|
||||
int _dbg_dostep;
|
||||
@ -204,19 +227,20 @@ public:
|
||||
public:
|
||||
R_SCRIPT_THREAD *SThreadCreate();
|
||||
int SThreadExecute(R_SCRIPT_THREAD *thread, int ep_num);
|
||||
int SThreadExecThreads(int msec);
|
||||
int SThreadExecThreads(uint msec);
|
||||
int SThreadHoldSem(R_SEMAPHORE *sem);
|
||||
int SThreadReleaseSem(R_SEMAPHORE *sem);
|
||||
int SThreadDebugStep();
|
||||
void SThreadCompleteThread(void);
|
||||
int SThreadDestroy(R_SCRIPT_THREAD *thread);
|
||||
void SThreadAbortAll(void);
|
||||
|
||||
private:
|
||||
void setFramePtr(R_SCRIPT_THREAD *thread, int newPtr);
|
||||
unsigned char *SThreadGetReadPtr(R_SCRIPT_THREAD *thread);
|
||||
unsigned long SThreadGetReadOffset(const byte *read_p);
|
||||
size_t SThreadGetReadLen(R_SCRIPT_THREAD *thread);
|
||||
int SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit, int msec);
|
||||
int SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit);
|
||||
int SThreadSetEntrypoint(R_SCRIPT_THREAD *thread, int ep_num);
|
||||
|
||||
private:
|
||||
@ -276,6 +300,7 @@ private:
|
||||
int SF_playMusic(R_SCRIPTFUNC_PARAMS);
|
||||
int SF_enableEscape(R_SCRIPTFUNC_PARAMS);
|
||||
int SF_playSound(R_SCRIPTFUNC_PARAMS);
|
||||
int SF_gotoScene(R_SCRIPTFUNC_PARAMS);
|
||||
};
|
||||
|
||||
} // End of namespace Saga
|
||||
|
@ -59,7 +59,7 @@ void Script::setupScriptFuncList(void) {
|
||||
{13, 0, NULL},
|
||||
{14, 2, OPCODE(SF_faceTowards)},
|
||||
{15, 2, OPCODE(SF_setFollower)},
|
||||
{16, 0, NULL},
|
||||
{16, 2, OPCODE(SF_gotoScene)},
|
||||
{17, 0, NULL},
|
||||
{18, 0, NULL},
|
||||
{19, 0, NULL},
|
||||
@ -127,14 +127,17 @@ void Script::setupScriptFuncList(void) {
|
||||
|
||||
// Script function #1 (0x01) blocking
|
||||
// Suspends thread execution for the specified time period
|
||||
// Param1: time to suspend ( units? )
|
||||
int Script::SF_sleep(R_SCRIPTFUNC_PARAMS) {
|
||||
SDataWord_T time_param;
|
||||
int time;
|
||||
long time;
|
||||
|
||||
time_param = thread->pop();
|
||||
time = _vm->_sdata->readWordU(time_param);
|
||||
thread->sleep_time = time * 10;
|
||||
if (!_skipSpeeches) {
|
||||
time_param = thread->pop();
|
||||
time = _vm->_sdata->readWordU(time_param);
|
||||
time = time * 10; // 72.8 ticks per second
|
||||
thread->flags |= kTFlagWaiting; // put thread to sleep
|
||||
thread->waitType = kTWaitDelay;
|
||||
}
|
||||
return R_SUCCESS;
|
||||
}
|
||||
|
||||
@ -171,7 +174,7 @@ int Script::SF_setStatusText(R_SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #5 (0x05)
|
||||
int Script::SF_commandMode(R_SCRIPTFUNC_PARAMS) {
|
||||
return _vm->_interface->setMode(PANEL_COMMAND);
|
||||
return _vm->_interface->setMode(kPanelCommand);
|
||||
}
|
||||
|
||||
// Script function #6 (0x06) blocking
|
||||
@ -276,7 +279,7 @@ int Script::SF_freezeInterface(R_SCRIPTFUNC_PARAMS) {
|
||||
// Script function #12 (0x0C)
|
||||
// Disables mouse input, etc.
|
||||
int Script::SF_dialogMode(R_SCRIPTFUNC_PARAMS) {
|
||||
return _vm->_interface->setMode(PANEL_DIALOGUE);
|
||||
return _vm->_interface->setMode(kPanelDialogue);
|
||||
}
|
||||
|
||||
// Script function #14 (0x0E)
|
||||
@ -293,6 +296,13 @@ int Script::SF_setFollower(R_SCRIPTFUNC_PARAMS) {
|
||||
return R_SUCCESS;
|
||||
}
|
||||
|
||||
// Script function #16 (0x10)
|
||||
int Script::SF_gotoScene(R_SCRIPTFUNC_PARAMS) {
|
||||
thread->pop();
|
||||
thread->pop();
|
||||
return R_SUCCESS;
|
||||
}
|
||||
|
||||
// Script function #23 (0x17)
|
||||
int Script::SF_setBgdAnimSpeed(R_SCRIPTFUNC_PARAMS) {
|
||||
thread->pop();
|
||||
@ -641,9 +651,7 @@ int Script::SF_placeActor(R_SCRIPTFUNC_PARAMS) {
|
||||
// game cinematic. Pushes a zero or positive value if the game
|
||||
// has not been interrupted.
|
||||
int Script::SF_checkUserInterrupt(R_SCRIPTFUNC_PARAMS) {
|
||||
thread->retVal = 0;
|
||||
|
||||
// INCOMPLETE
|
||||
thread->retVal = (_skipSpeeches == true);
|
||||
|
||||
return R_SUCCESS;
|
||||
}
|
||||
@ -734,7 +742,13 @@ int Script::SF_playMusic(R_SCRIPTFUNC_PARAMS) {
|
||||
|
||||
// Script function #69
|
||||
int Script::SF_enableEscape(R_SCRIPTFUNC_PARAMS) {
|
||||
thread->pop();
|
||||
if (thread->pop())
|
||||
_abortEnabled = true;
|
||||
else {
|
||||
_skipSpeeches = false;
|
||||
_abortEnabled = false;
|
||||
}
|
||||
|
||||
return R_SUCCESS;
|
||||
}
|
||||
|
||||
|
103
saga/sthread.cpp
103
saga/sthread.cpp
@ -62,6 +62,9 @@ R_SCRIPT_THREAD *Script::SThreadCreate() {
|
||||
new_thread->stackPtr = ARRAYSIZE(new_thread->stackBuf) - 1;
|
||||
setFramePtr(new_thread, new_thread->stackPtr);
|
||||
|
||||
new_thread->flags = kTFlagWaiting;
|
||||
new_thread->waitType = kTWaitPause;
|
||||
|
||||
dataBuffer(4)->len = ARRAYSIZE(new_thread->threadVars);
|
||||
dataBuffer(4)->data = new_thread->threadVars;
|
||||
|
||||
@ -69,26 +72,66 @@ R_SCRIPT_THREAD *Script::SThreadCreate() {
|
||||
}
|
||||
|
||||
int Script::SThreadDestroy(R_SCRIPT_THREAD *thread) {
|
||||
YS_DL_NODE *walk_p;
|
||||
R_SCRIPT_THREAD *th;
|
||||
|
||||
if (thread == NULL) {
|
||||
return R_FAILURE;
|
||||
}
|
||||
|
||||
for (walk_p = ys_dll_head(threadList()); walk_p != NULL; walk_p = ys_dll_next(walk_p)) {
|
||||
th = (R_SCRIPT_THREAD *)ys_dll_get_data(walk_p);
|
||||
if (thread == th) {
|
||||
ys_dll_delete(walk_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return R_SUCCESS;
|
||||
}
|
||||
|
||||
int Script::SThreadExecThreads(int msec) {
|
||||
YS_DL_NODE *walk_p;
|
||||
int Script::SThreadExecThreads(uint msec) {
|
||||
YS_DL_NODE *walk_p, *next_p;
|
||||
R_SCRIPT_THREAD *thread;
|
||||
|
||||
if (!isInitialized()) {
|
||||
return R_FAILURE;
|
||||
}
|
||||
|
||||
for (walk_p = ys_dll_head(threadList()); walk_p != NULL; walk_p = ys_dll_next(walk_p)) {
|
||||
walk_p = ys_dll_head(threadList());
|
||||
|
||||
while (walk_p != NULL) {
|
||||
next_p = ys_dll_next(walk_p);
|
||||
|
||||
thread = (R_SCRIPT_THREAD *)ys_dll_get_data(walk_p);
|
||||
if (thread->executing) {
|
||||
SThreadRun(thread, STHREAD_DEF_INSTR_COUNT, msec);
|
||||
|
||||
if (thread->flags & (kTFlagFinished | kTFlagAborted)) {
|
||||
//if (thread->flags & kTFlagFinished) // FIXME. Missing function
|
||||
|
||||
SThreadDestroy(thread);
|
||||
walk_p = next_p;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (thread->flags & kTFlagWaiting) {
|
||||
switch(thread->waitType) {
|
||||
case kTWaitDelay:
|
||||
if (thread->sleepTime < msec) {
|
||||
thread->sleepTime = 0;
|
||||
} else {
|
||||
thread->sleepTime -= msec;
|
||||
}
|
||||
|
||||
if (thread->sleepTime == 0)
|
||||
thread->flags &= ~kTFlagWaiting;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(thread->flags & kTFlagWaiting))
|
||||
SThreadRun(thread, STHREAD_TIMESLICE);
|
||||
|
||||
walk_p = next_p;
|
||||
}
|
||||
|
||||
return R_SUCCESS;
|
||||
@ -128,11 +171,21 @@ int Script::SThreadExecute(R_SCRIPT_THREAD *thread, int ep_num) {
|
||||
SThreadSetEntrypoint(thread, ep_num);
|
||||
|
||||
thread->i_offset = thread->ep_offset;
|
||||
thread->executing = 1;
|
||||
thread->flags = kTFlagNone;
|
||||
|
||||
return R_SUCCESS;
|
||||
}
|
||||
|
||||
void Script::SThreadAbortAll(void) {
|
||||
// TODO: stop current speech
|
||||
|
||||
if (_abortEnabled)
|
||||
_skipSpeeches = true;
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
_vm->_script->SThreadExecThreads(0);
|
||||
}
|
||||
|
||||
unsigned char *Script::SThreadGetReadPtr(R_SCRIPT_THREAD *thread) {
|
||||
return currentScript()->bytecode->bytecode_p + thread->i_offset;
|
||||
}
|
||||
@ -177,7 +230,7 @@ int Script::SThreadDebugStep() {
|
||||
return R_SUCCESS;
|
||||
}
|
||||
|
||||
int Script::SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit, int msec) {
|
||||
int Script::SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit) {
|
||||
int instr_count;
|
||||
uint32 saved_offset;
|
||||
SDataWord_T param1;
|
||||
@ -199,7 +252,7 @@ int Script::SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit, int msec) {
|
||||
if ((thread == _dbg_thread) && _dbg_singlestep) {
|
||||
if (_dbg_dostep) {
|
||||
debug_print = 1;
|
||||
thread->sleep_time = 0;
|
||||
thread->sleepTime = 0;
|
||||
instr_limit = 1;
|
||||
_dbg_dostep = 0;
|
||||
} else {
|
||||
@ -215,18 +268,8 @@ int Script::SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit, int msec) {
|
||||
scriptS.seek(thread->i_offset);
|
||||
|
||||
for (instr_count = 0; instr_count < instr_limit; instr_count++) {
|
||||
if ((!thread->executing) || (thread->sem.hold_count)) {
|
||||
break;
|
||||
}
|
||||
|
||||
thread->sleep_time -= msec;
|
||||
if (thread->sleep_time < 0) {
|
||||
thread->sleep_time = 0;
|
||||
}
|
||||
|
||||
if (thread->sleep_time) {
|
||||
break;
|
||||
}
|
||||
if (thread->sem.hold_count)
|
||||
break;
|
||||
|
||||
saved_offset = thread->i_offset;
|
||||
in_char = scriptS.readByte();
|
||||
@ -341,7 +384,7 @@ int Script::SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit, int msec) {
|
||||
func_num = scriptS.readUint16LE();
|
||||
if (func_num >= R_SFUNC_NUM) {
|
||||
_vm->_console->print(S_ERROR_PREFIX "Invalid script function number: (%X)\n", func_num);
|
||||
thread->executing = 0;
|
||||
thread->flags |= kTFlagAborted;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -359,8 +402,16 @@ int Script::SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit, int msec) {
|
||||
_vm->_console->print(S_WARN_PREFIX "%X: Script function %d failed.\n", thread->i_offset, func_num);
|
||||
}
|
||||
|
||||
if (in_char == 0x18)
|
||||
if (func_num == 16) { // SF_gotoScene
|
||||
instr_count = instr_limit; // break the loop
|
||||
break;
|
||||
}
|
||||
|
||||
if (in_char == 0x18) // CALL function
|
||||
thread->push(thread->retVal);
|
||||
|
||||
if (thread->flags & kTFlagAsleep)
|
||||
instr_count = instr_limit; // break out of loop!
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -378,7 +429,7 @@ int Script::SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit, int msec) {
|
||||
setFramePtr(thread, thread->pop());
|
||||
if (thread->stackSize() == 0) {
|
||||
_vm->_console->print("Script execution complete.");
|
||||
thread->executing = 0;
|
||||
thread->flags |= kTFlagFinished;
|
||||
} else {
|
||||
thread->i_offset = thread->pop();
|
||||
/* int n_args = */ thread->pop();
|
||||
@ -765,7 +816,7 @@ int Script::SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit, int msec) {
|
||||
default:
|
||||
|
||||
_vm->_console->print(S_ERROR_PREFIX "%X: Invalid opcode encountered: " "(%X).\n", thread->i_offset, in_char);
|
||||
thread->executing = 0;
|
||||
thread->flags |= kTFlagAborted;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -777,9 +828,9 @@ int Script::SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit, int msec) {
|
||||
}
|
||||
if (unhandled) {
|
||||
_vm->_console->print(S_ERROR_PREFIX "%X: Unhandled opcode.\n", thread->i_offset);
|
||||
thread->executing = 0;
|
||||
thread->flags |= kTFlagAborted;
|
||||
}
|
||||
if (thread->executing && debug_print) {
|
||||
if ((thread->flags == kTFlagNone) && debug_print) {
|
||||
SDebugPrintInstr(thread);
|
||||
}
|
||||
}
|
||||
|
@ -59,8 +59,8 @@ Scene.c
|
||||
|
||||
Interp.c
|
||||
========
|
||||
dispatchThreads() STHREAD_ExecThreads()
|
||||
runThread() STHREAD_completeThread()
|
||||
dispatchThreads() SThreadExecThreads()
|
||||
runThread() SThreadCompleteThread()
|
||||
moduleList _scriptLUT
|
||||
ModuleEntry->codeID _scriptLUT->script_rn
|
||||
ModuleEntry->strID _scriptLUT->diag_list_rn
|
||||
@ -69,3 +69,7 @@ Interp.c
|
||||
threadBase.theObject threadVars[kVarObject]
|
||||
threadBase.withObject threadVars[kVarWithObject]
|
||||
threadBase.theActor threadVars[kVarActor]
|
||||
|
||||
Actor.c
|
||||
=======
|
||||
abortAllSpeeches() SThreadAbortAll()
|
||||
|
Loading…
x
Reference in New Issue
Block a user