2004-04-12 21:40:49 +00:00
|
|
|
/* ScummVM - Scumm Interpreter
|
|
|
|
* Copyright (C) 2004 The ScummVM project
|
|
|
|
*
|
|
|
|
* The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* $Header$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// Scripting module thread management component
|
2004-08-02 16:20:35 +00:00
|
|
|
#include "saga/saga.h"
|
|
|
|
#include "saga/yslib.h"
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-08-02 16:20:35 +00:00
|
|
|
#include "saga/gfx.h"
|
|
|
|
#include "saga/actor.h"
|
2004-08-10 18:31:33 +00:00
|
|
|
#include "saga/console.h"
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-08-02 16:20:35 +00:00
|
|
|
#include "saga/script.h"
|
|
|
|
#include "saga/script_mod.h"
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-08-02 16:20:35 +00:00
|
|
|
#include "saga/sdata.h"
|
|
|
|
#include "saga/sstack.h"
|
|
|
|
#include "saga/sthread.h"
|
|
|
|
#include "saga/sfuncs.h"
|
2004-04-12 21:40:49 +00:00
|
|
|
|
|
|
|
namespace Saga {
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
R_SCRIPT_THREAD *STHREAD_Create() {
|
2004-04-12 21:40:49 +00:00
|
|
|
YS_DL_NODE *new_node;
|
|
|
|
R_SCRIPT_THREAD *new_thread;
|
|
|
|
|
|
|
|
int result;
|
|
|
|
|
2004-08-01 23:47:19 +00:00
|
|
|
if (!_vm->_script->isInitialized()) {
|
2004-04-12 21:40:49 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
new_thread = (R_SCRIPT_THREAD *)calloc(1, sizeof *new_thread);
|
|
|
|
if (new_thread == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
result = SSTACK_Create(&(new_thread->stack), R_DEF_THREAD_STACKSIZE, STACK_GROW);
|
2004-04-12 21:40:49 +00:00
|
|
|
|
|
|
|
if (result != STACK_SUCCESS) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-08-01 23:47:19 +00:00
|
|
|
new_node = ys_dll_add_head(_vm->_script->threadList(), new_thread, sizeof *new_thread);
|
2004-04-12 21:40:49 +00:00
|
|
|
|
|
|
|
free(new_thread);
|
|
|
|
|
|
|
|
return (R_SCRIPT_THREAD *)ys_dll_get_data(new_node);
|
|
|
|
}
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
int STHREAD_Destroy(R_SCRIPT_THREAD *thread) {
|
2004-04-12 21:40:49 +00:00
|
|
|
if (thread == NULL) {
|
|
|
|
return R_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
SSTACK_Destroy(thread->stack);
|
|
|
|
|
|
|
|
return R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
int STHREAD_ExecThreads(int msec) {
|
2004-04-12 21:40:49 +00:00
|
|
|
YS_DL_NODE *walk_p;
|
|
|
|
R_SCRIPT_THREAD *thread;
|
|
|
|
|
2004-08-01 23:47:19 +00:00
|
|
|
if (!_vm->_script->isInitialized()) {
|
2004-04-12 21:40:49 +00:00
|
|
|
return R_FAILURE;
|
|
|
|
}
|
|
|
|
|
2004-08-01 23:47:19 +00:00
|
|
|
for (walk_p = ys_dll_head(_vm->_script->threadList()); walk_p != NULL; walk_p = ys_dll_next(walk_p)) {
|
2004-04-12 21:40:49 +00:00
|
|
|
thread = (R_SCRIPT_THREAD *)ys_dll_get_data(walk_p);
|
|
|
|
if (thread->executing) {
|
|
|
|
STHREAD_Run(thread, STHREAD_DEF_INSTR_COUNT, msec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2004-08-12 01:11:11 +00:00
|
|
|
void STHREAD_completeThread(void) {
|
|
|
|
for (int i = 0; i < 40 && (ys_dll_head(_vm->_script->threadList()) != NULL); i++)
|
|
|
|
STHREAD_ExecThreads(0);
|
|
|
|
}
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
int STHREAD_SetEntrypoint(R_SCRIPT_THREAD *thread, int ep_num) {
|
2004-04-12 21:40:49 +00:00
|
|
|
R_SCRIPT_BYTECODE *bytecode;
|
|
|
|
int max_entrypoint;
|
|
|
|
|
2004-08-01 23:47:19 +00:00
|
|
|
assert(_vm->_script->isInitialized());
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-08-01 23:47:19 +00:00
|
|
|
bytecode = _vm->_script->currentScript()->bytecode;
|
2004-04-12 21:40:49 +00:00
|
|
|
max_entrypoint = bytecode->n_entrypoints;
|
|
|
|
|
|
|
|
if ((ep_num < 0) || (ep_num >= max_entrypoint)) {
|
|
|
|
return R_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
thread->ep_num = ep_num;
|
|
|
|
thread->ep_offset = bytecode->entrypoints[ep_num].offset;
|
|
|
|
|
|
|
|
return R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
int STHREAD_Execute(R_SCRIPT_THREAD *thread, int ep_num) {
|
2004-08-01 23:47:19 +00:00
|
|
|
assert(_vm->_script->isInitialized());
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-08-01 23:47:19 +00:00
|
|
|
if ((_vm->_script->currentScript() == NULL) || (!_vm->_script->currentScript()->loaded)) {
|
2004-04-12 21:40:49 +00:00
|
|
|
return R_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
STHREAD_SetEntrypoint(thread, ep_num);
|
|
|
|
|
|
|
|
thread->i_offset = thread->ep_offset;
|
|
|
|
thread->executing = 1;
|
|
|
|
|
|
|
|
return R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
unsigned char *GetReadPtr(R_SCRIPT_THREAD *thread) {
|
2004-08-01 23:47:19 +00:00
|
|
|
return _vm->_script->currentScript()->bytecode->bytecode_p + thread->i_offset;
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
unsigned long GetReadOffset(const byte *read_p) {
|
2004-08-01 23:47:19 +00:00
|
|
|
return (unsigned long)(read_p - (unsigned char *)_vm->_script->currentScript()->bytecode->bytecode_p);
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
2004-05-04 03:33:03 +00:00
|
|
|
size_t GetReadLen(R_SCRIPT_THREAD *thread) {
|
2004-08-01 23:47:19 +00:00
|
|
|
return _vm->_script->currentScript()->bytecode->bytecode_len - thread->i_offset;
|
2004-05-04 03:33:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
int STHREAD_HoldSem(R_SEMAPHORE *sem) {
|
2004-04-12 21:40:49 +00:00
|
|
|
if (sem == NULL) {
|
|
|
|
return R_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
sem->hold_count++;
|
|
|
|
|
|
|
|
return R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
int STHREAD_ReleaseSem(R_SEMAPHORE *sem) {
|
2004-04-12 21:40:49 +00:00
|
|
|
if (sem == NULL) {
|
|
|
|
return R_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
sem->hold_count--;
|
|
|
|
if (sem->hold_count < 0) {
|
|
|
|
sem->hold_count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
int STHREAD_DebugStep() {
|
2004-08-01 22:48:40 +00:00
|
|
|
if (_vm->_script->_dbg_singlestep) {
|
|
|
|
_vm->_script->_dbg_dostep = 1;
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
int STHREAD_Run(R_SCRIPT_THREAD *thread, int instr_limit, int msec) {
|
2004-04-12 21:40:49 +00:00
|
|
|
int instr_count;
|
2004-04-30 23:02:23 +00:00
|
|
|
uint32 saved_offset;
|
2004-04-12 21:40:49 +00:00
|
|
|
SDataWord_T param1;
|
|
|
|
SDataWord_T param2;
|
|
|
|
long iparam1;
|
|
|
|
long iparam2;
|
|
|
|
long iresult;
|
|
|
|
|
|
|
|
SDataWord_T data;
|
|
|
|
int debug_print = 0;
|
|
|
|
int n_buf;
|
|
|
|
int bitstate;
|
|
|
|
int result;
|
|
|
|
int in_char;
|
|
|
|
int i;
|
|
|
|
int unhandled = 0;
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// Handle debug single-stepping
|
2004-08-01 22:48:40 +00:00
|
|
|
if ((thread == _vm->_script->_dbg_thread) && _vm->_script->_dbg_singlestep) {
|
|
|
|
if (_vm->_script->_dbg_dostep) {
|
2004-04-12 21:40:49 +00:00
|
|
|
debug_print = 1;
|
|
|
|
thread->sleep_time = 0;
|
|
|
|
instr_limit = 1;
|
2004-08-01 22:48:40 +00:00
|
|
|
_vm->_script->_dbg_dostep = 0;
|
2004-04-12 21:40:49 +00:00
|
|
|
} else {
|
|
|
|
return R_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
saved_offset = thread->i_offset;
|
2004-08-12 01:11:11 +00:00
|
|
|
|
2004-08-01 23:24:22 +00:00
|
|
|
MemoryReadStream readS(GetReadPtr(thread), GetReadLen(thread));
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-08-01 23:24:22 +00:00
|
|
|
in_char = readS.readByte();
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-08-12 01:11:11 +00:00
|
|
|
debug(0, "Executing thread offset: %lu (%x)", thread->i_offset, in_char);
|
|
|
|
|
2004-04-12 21:40:49 +00:00
|
|
|
switch (in_char) {
|
2004-05-01 16:15:55 +00:00
|
|
|
// Align (ALGN)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x01:
|
|
|
|
break;
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// STACK INSTRUCTIONS
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// Push nothing (PSHN)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x02:
|
|
|
|
SSTACK_PushNull(thread->stack);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// Pop nothing (POPN)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x03:
|
|
|
|
SSTACK_Pop(thread->stack, NULL);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// Push false (PSHF)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x04:
|
|
|
|
SSTACK_Push(thread->stack, 0);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// Push true (PSHT)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x05:
|
|
|
|
SSTACK_Push(thread->stack, 1);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// Push word (PUSH)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x06:
|
2004-08-01 23:24:22 +00:00
|
|
|
param1 = (SDataWord_T)readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
SSTACK_Push(thread->stack, param1);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// Push word (PSHD) (dialogue string index)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x08:
|
2004-08-01 23:24:22 +00:00
|
|
|
param1 = (SDataWord_T)readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
SSTACK_Push(thread->stack, param1);
|
|
|
|
break;
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// DATA INSTRUCTIONS
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// Test flag (TSTF)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x0B:
|
2004-08-01 23:24:22 +00:00
|
|
|
n_buf = readS.readByte();
|
|
|
|
param1 = (SDataWord_T)readS.readUint16LE();
|
2004-08-01 19:53:29 +00:00
|
|
|
_vm->_sdata->getBit(n_buf, param1, &bitstate);
|
2004-04-12 21:40:49 +00:00
|
|
|
SSTACK_Push(thread->stack, bitstate);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// Get word (GETW)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x0C:
|
2004-08-01 23:24:22 +00:00
|
|
|
n_buf = readS.readByte();
|
|
|
|
param1 = readS.readUint16LE();
|
2004-08-01 19:53:29 +00:00
|
|
|
_vm->_sdata->getWord(n_buf, param1, &data);
|
2004-04-12 21:40:49 +00:00
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// Modify flag (MODF)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x0F:
|
2004-08-01 23:24:22 +00:00
|
|
|
n_buf = readS.readByte();
|
|
|
|
param1 = (SDataWord_T)readS.readUint16LE();
|
2004-08-01 19:53:29 +00:00
|
|
|
bitstate = _vm->_sdata->readWordU(param1);
|
2004-04-12 21:40:49 +00:00
|
|
|
SSTACK_Top(thread->stack, &data);
|
|
|
|
if (bitstate) {
|
2004-08-01 19:53:29 +00:00
|
|
|
_vm->_sdata->setBit(n_buf, data, 1);
|
2004-04-12 21:40:49 +00:00
|
|
|
} else {
|
2004-08-01 19:53:29 +00:00
|
|
|
_vm->_sdata->setBit(n_buf, data, 0);
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// Put word (PUTW)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x10:
|
2004-08-01 23:24:22 +00:00
|
|
|
n_buf = readS.readByte();
|
|
|
|
param1 = (SDataWord_T)readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
SSTACK_Top(thread->stack, &data);
|
2004-08-01 19:53:29 +00:00
|
|
|
_vm->_sdata->putWord(n_buf, param1, data);
|
2004-04-12 21:40:49 +00:00
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// Modify flag and pop (MDFP)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x13:
|
2004-08-01 23:24:22 +00:00
|
|
|
n_buf = readS.readByte();
|
|
|
|
param1 = (SDataWord_T)readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
2004-08-01 19:53:29 +00:00
|
|
|
bitstate = _vm->_sdata->readWordU(param1);
|
2004-04-12 21:40:49 +00:00
|
|
|
if (bitstate) {
|
2004-08-01 19:53:29 +00:00
|
|
|
_vm->_sdata->setBit(n_buf, param1, 1);
|
2004-04-12 21:40:49 +00:00
|
|
|
} else {
|
2004-08-01 19:53:29 +00:00
|
|
|
_vm->_sdata->setBit(n_buf, param1, 0);
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// Put word and pop (PTWP)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x14:
|
2004-08-01 23:24:22 +00:00
|
|
|
n_buf = readS.readByte();
|
|
|
|
param1 = (SDataWord_T)readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
SSTACK_Top(thread->stack, &data);
|
2004-08-01 19:53:29 +00:00
|
|
|
_vm->_sdata->putWord(n_buf, param1, data);
|
2004-04-12 21:40:49 +00:00
|
|
|
break;
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// CONTROL INSTRUCTIONS
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// (GOSB): Call subscript ?
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x17:
|
|
|
|
{
|
|
|
|
int temp;
|
|
|
|
int temp2;
|
|
|
|
|
2004-08-01 23:24:22 +00:00
|
|
|
temp = readS.readByte();
|
|
|
|
temp2 = readS.readByte();
|
|
|
|
param1 = (SDataWord_T)readS.readUint16LE();
|
|
|
|
data = readS.pos();
|
2004-05-01 16:15:55 +00:00
|
|
|
//SSTACK_Push(thread->stack, (SDataWord_T)temp);
|
2004-04-12 21:40:49 +00:00
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
thread->i_offset = (unsigned long)param1;
|
|
|
|
}
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (CALL): Call function
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x19:
|
|
|
|
case 0x18:
|
|
|
|
{
|
|
|
|
int n_args;
|
2004-04-30 23:02:23 +00:00
|
|
|
uint16 func_num;
|
2004-04-25 14:42:14 +00:00
|
|
|
int FIXME_SHADOWED_result;
|
2004-04-12 21:40:49 +00:00
|
|
|
SFunc_T sfunc;
|
|
|
|
|
2004-08-01 23:24:22 +00:00
|
|
|
n_args = readS.readByte();
|
|
|
|
func_num = readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
if (func_num >= R_SFUNC_NUM) {
|
2004-08-10 18:31:33 +00:00
|
|
|
_vm->_console->print(S_ERROR_PREFIX "Invalid script function number: (%X)\n", func_num);
|
2004-04-12 21:40:49 +00:00
|
|
|
thread->executing = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sfunc = SFuncList[func_num].sfunc_fp;
|
|
|
|
if (sfunc == NULL) {
|
2004-08-10 18:31:33 +00:00
|
|
|
_vm->_console->print(S_WARN_PREFIX "%X: Undefined script function number: (%X)\n",
|
2004-05-01 16:15:55 +00:00
|
|
|
thread->i_offset, func_num);
|
2004-08-10 18:31:33 +00:00
|
|
|
_vm->_console->print(S_WARN_PREFIX "Removing %d operand(s) from stack.\n", n_args);
|
2004-04-12 21:40:49 +00:00
|
|
|
for (i = 0; i < n_args; i++) {
|
2004-05-01 16:15:55 +00:00
|
|
|
SSTACK_Pop(thread->stack, NULL);
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
} else {
|
2004-04-25 14:42:14 +00:00
|
|
|
FIXME_SHADOWED_result = sfunc(thread);
|
|
|
|
if (FIXME_SHADOWED_result != R_SUCCESS) {
|
2004-08-10 18:31:33 +00:00
|
|
|
_vm->_console->print(S_WARN_PREFIX "%X: Script function %d failed.\n", thread->i_offset, func_num);
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (ENTR) Enter the dragon
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x1A:
|
2004-08-01 23:24:22 +00:00
|
|
|
param1 = readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (?) Unknown
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x1B:
|
|
|
|
unhandled = 1;
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (EXIT) End subscript
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x1C:
|
|
|
|
result = SSTACK_Pop(thread->stack, &data);
|
|
|
|
if (result != STACK_SUCCESS) {
|
2004-08-10 18:31:33 +00:00
|
|
|
_vm->_console->print("Script execution complete.");
|
2004-04-12 21:40:49 +00:00
|
|
|
thread->executing = 0;
|
|
|
|
} else {
|
|
|
|
thread->i_offset = data;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// BRANCH INSTRUCTIONS
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// (JMP): Unconditional jump
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x1D:
|
2004-08-01 23:24:22 +00:00
|
|
|
param1 = readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
thread->i_offset = (unsigned long)param1;
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (JNZP): Jump if nonzero + POP
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x1E:
|
2004-08-01 23:24:22 +00:00
|
|
|
param1 = readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
SSTACK_Pop(thread->stack, &data);
|
|
|
|
if (data) {
|
|
|
|
thread->i_offset = (unsigned long)param1;
|
|
|
|
}
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (JZP): Jump if zero + POP
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x1F:
|
2004-08-01 23:24:22 +00:00
|
|
|
param1 = readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
SSTACK_Pop(thread->stack, &data);
|
|
|
|
if (!data) {
|
|
|
|
thread->i_offset = (unsigned long)param1;
|
|
|
|
}
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (JNZ): Jump if nonzero
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x20:
|
2004-08-01 23:24:22 +00:00
|
|
|
param1 = readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
SSTACK_Top(thread->stack, &data);
|
|
|
|
if (data) {
|
|
|
|
thread->i_offset = (unsigned long)param1;
|
|
|
|
}
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (JZ): Jump if zero
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x21:
|
2004-08-01 23:24:22 +00:00
|
|
|
param1 = readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
SSTACK_Top(thread->stack, &data);
|
|
|
|
if (!data) {
|
|
|
|
thread->i_offset = (unsigned long)param1;
|
|
|
|
}
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (JMPR): Relative jump
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x57:
|
2004-05-01 16:15:55 +00:00
|
|
|
// ignored?
|
2004-08-01 23:24:22 +00:00
|
|
|
readS.readUint16LE();
|
|
|
|
readS.readUint16LE();
|
|
|
|
iparam1 = (long)readS.readByte();
|
2004-04-12 21:40:49 +00:00
|
|
|
thread->i_offset += iparam1;
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (SWCH): Switch
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x22:
|
|
|
|
{
|
|
|
|
int n_switch;
|
|
|
|
unsigned int switch_num;
|
|
|
|
unsigned int switch_jmp;
|
|
|
|
unsigned int default_jmp;
|
|
|
|
int case_found = 0;
|
|
|
|
|
|
|
|
SSTACK_Pop(thread->stack, &data);
|
2004-08-01 23:24:22 +00:00
|
|
|
n_switch = readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
for (i = 0; i < n_switch; i++) {
|
2004-08-01 23:24:22 +00:00
|
|
|
switch_num = readS.readUint16LE();
|
|
|
|
switch_jmp = readS.readUint16LE();
|
2004-05-01 16:15:55 +00:00
|
|
|
// Found the specified case
|
2004-04-12 21:40:49 +00:00
|
|
|
if (data == (SDataWord_T) switch_num) {
|
|
|
|
thread->i_offset = switch_jmp;
|
|
|
|
case_found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// Jump to default case
|
2004-04-12 21:40:49 +00:00
|
|
|
if (!case_found) {
|
2004-08-01 23:24:22 +00:00
|
|
|
default_jmp = readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
thread->i_offset = default_jmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (RJMP): Random branch
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x24:
|
|
|
|
{
|
|
|
|
int n_branch;
|
|
|
|
unsigned int branch_wt;
|
|
|
|
unsigned int branch_jmp;
|
|
|
|
int rand_sel = 0;
|
|
|
|
int branch_found = 0;
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// Ignored?
|
2004-08-01 23:24:22 +00:00
|
|
|
readS.readUint16LE();
|
|
|
|
n_branch = readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
for (i = 0; i < n_branch; i++) {
|
2004-08-01 23:24:22 +00:00
|
|
|
branch_wt = readS.readUint16LE();
|
|
|
|
branch_jmp = readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
if (rand_sel == i) {
|
|
|
|
thread->i_offset = branch_jmp;
|
|
|
|
branch_found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!branch_found) {
|
2004-08-10 18:31:33 +00:00
|
|
|
_vm->_console->print(S_ERROR_PREFIX "%X: Random jump target out of " "bounds.", thread->i_offset);
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// MISC. INSTRUCTIONS
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// (NEG) Negate stack by 2's complement
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x25:
|
|
|
|
SSTACK_Pop(thread->stack, &data);
|
|
|
|
data = ~data;
|
|
|
|
data++;
|
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (TSTZ) Test for zero
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x26:
|
|
|
|
SSTACK_Pop(thread->stack, &data);
|
|
|
|
data = data ? 0 : 1;
|
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (NOT) Binary not
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x27:
|
|
|
|
SSTACK_Pop(thread->stack, &data);
|
|
|
|
data = ~data;
|
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (?)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x28:
|
|
|
|
unhandled = 1;
|
|
|
|
printf("??? ");
|
2004-08-01 23:24:22 +00:00
|
|
|
readS.readByte();
|
|
|
|
readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (?)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x29:
|
|
|
|
unhandled = 1;
|
|
|
|
printf("??? ");
|
2004-08-01 23:24:22 +00:00
|
|
|
readS.readByte();
|
|
|
|
readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (?)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x2A:
|
|
|
|
unhandled = 1;
|
|
|
|
printf("??? ");
|
2004-08-01 23:24:22 +00:00
|
|
|
readS.readByte();
|
|
|
|
readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (?)
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x2B:
|
|
|
|
unhandled = 1;
|
|
|
|
printf("??? ");
|
2004-08-01 23:24:22 +00:00
|
|
|
readS.readByte();
|
|
|
|
readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
break;
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// ARITHMETIC INSTRUCTIONS
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// (ADD): Addition
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x2C:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
iparam2 = (long)param2;
|
|
|
|
iparam1 = (long)param1;
|
|
|
|
iresult = iparam1 + iparam2;
|
|
|
|
SSTACK_Push(thread->stack, (SDataWord_T) iresult);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (SUB): Subtraction
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x2D:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
iparam2 = (long)param2;
|
|
|
|
iparam1 = (long)param1;
|
|
|
|
iresult = iparam1 - iparam2;
|
|
|
|
SSTACK_Push(thread->stack, (SDataWord_T) iresult);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (MULT): Integer multiplication
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x2E:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
iparam2 = (long)param2;
|
|
|
|
iparam1 = (long)param1;
|
|
|
|
iresult = iparam1 * iparam2;
|
|
|
|
SSTACK_Push(thread->stack, (SDataWord_T) iresult);
|
|
|
|
break;
|
2004-05-13 01:41:23 +00:00
|
|
|
// (DIV): Integer division
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x2F:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
iparam2 = (long)param2;
|
|
|
|
iparam1 = (long)param1;
|
|
|
|
iresult = iparam1 / iparam2;
|
|
|
|
SSTACK_Push(thread->stack, (SDataWord_T) iresult);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (MOD) Modulus
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x30:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
iparam2 = (long)param2;
|
|
|
|
iparam1 = (long)param1;
|
|
|
|
iresult = iparam1 % iparam2;
|
|
|
|
SSTACK_Push(thread->stack, (SDataWord_T) iresult);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (EQU) Test equality
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x33:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
iparam2 = (long)param2;
|
|
|
|
iparam1 = (long)param1;
|
|
|
|
data = (iparam1 == iparam2) ? 1 : 0;
|
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (NEQU) Test inequality
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x34:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
iparam2 = (long)param2;
|
|
|
|
iparam1 = (long)param1;
|
|
|
|
data = (iparam1 != iparam2) ? 1 : 0;
|
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (GRT) Test Greater-than
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x35:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
iparam2 = (long)param2;
|
|
|
|
iparam1 = (long)param1;
|
|
|
|
data = (iparam1 > iparam2) ? 1 : 0;
|
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (LST) Test Less-than
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x36:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
iparam2 = (long)param2;
|
|
|
|
iparam1 = (long)param1;
|
|
|
|
data = (iparam1 < iparam2) ? 1 : 0;
|
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (GRTE) Test Greater-than or Equal to
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x37:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
iparam2 = (long)param2;
|
|
|
|
iparam1 = (long)param1;
|
|
|
|
data = (iparam1 >= iparam2) ? 1 : 0;
|
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (LSTE) Test Less-than or Equal to
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x38:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
iparam2 = (long)param2;
|
|
|
|
iparam1 = (long)param1;
|
|
|
|
data = (iparam1 <= iparam2) ? 1 : 0;
|
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
break;
|
2004-05-13 01:41:23 +00:00
|
|
|
|
|
|
|
// BITWISE INSTRUCTIONS
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// (SHR): Arithmetic binary shift right
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x3F:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
iparam2 = (long)param2;
|
2004-05-01 16:15:55 +00:00
|
|
|
// Preserve most significant bit
|
|
|
|
data = (0x01 << ((sizeof param1 * CHAR_BIT) - 1)) & param1;
|
2004-04-12 21:40:49 +00:00
|
|
|
for (i = 0; i < (int)iparam2; i++) {
|
|
|
|
param1 >>= 1;
|
|
|
|
param1 |= data;
|
|
|
|
}
|
|
|
|
SSTACK_Push(thread->stack, param1);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (SHL) Binary shift left
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x40:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
param1 <<= param2;
|
|
|
|
SSTACK_Push(thread->stack, param1);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (AND) Binary AND
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x41:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
param1 &= param2;
|
|
|
|
SSTACK_Push(thread->stack, param1);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (OR) Binary OR
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x42:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
param1 |= param2;
|
|
|
|
SSTACK_Push(thread->stack, param1);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (XOR) Binary XOR
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x43:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
param1 ^= param2;
|
|
|
|
SSTACK_Push(thread->stack, param1);
|
|
|
|
break;
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// BOOLEAN LOGIC INSTRUCTIONS
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// (LAND): Logical AND
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x44:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
data = (param1 && param2) ? 1 : 0;
|
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (LOR): Logical OR
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x45:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
data = (param1 || param2) ? 1 : 0;
|
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (LXOR): Logical XOR
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x46:
|
|
|
|
SSTACK_Pop(thread->stack, ¶m2);
|
|
|
|
SSTACK_Pop(thread->stack, ¶m1);
|
|
|
|
data = ((param1) ? !(param2) : !!(param2));
|
|
|
|
SSTACK_Push(thread->stack, data);
|
|
|
|
break;
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// GAME INSTRUCTIONS
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// (DLGP): Play Character Dialogue
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x53:
|
|
|
|
{
|
|
|
|
int n_voices;
|
|
|
|
int a_index;
|
|
|
|
int voice_rn;
|
|
|
|
|
2004-08-01 23:24:22 +00:00
|
|
|
n_voices = readS.readByte();
|
|
|
|
param1 = (SDataWord_T) readS.readUint16LE();
|
2004-05-01 16:15:55 +00:00
|
|
|
// ignored ?
|
2004-08-01 23:24:22 +00:00
|
|
|
readS.readByte();
|
|
|
|
readS.readUint16LE();
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-08-02 15:47:42 +00:00
|
|
|
a_index = _vm->_actor->getActorIndex(param1);
|
2004-04-12 21:40:49 +00:00
|
|
|
if (a_index < 0) {
|
2004-08-10 18:31:33 +00:00
|
|
|
_vm->_console->print(S_WARN_PREFIX "%X: DLGP Actor id not found.", thread->i_offset);
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < n_voices; i++) {
|
|
|
|
SSTACK_Pop(thread->stack, &data);
|
|
|
|
if (a_index < 0)
|
|
|
|
continue;
|
2004-08-01 23:47:19 +00:00
|
|
|
if (!_vm->_script->isVoiceLUTPresent()) {
|
2004-04-12 21:40:49 +00:00
|
|
|
voice_rn = -1;
|
|
|
|
} else {
|
2004-08-01 23:47:19 +00:00
|
|
|
voice_rn = _vm->_script->currentScript()->voice->voices[data];
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
2004-08-02 15:47:42 +00:00
|
|
|
_vm->_actor->speak(a_index, _vm->_script->currentScript()->diag-> str[data], voice_rn, &thread->sem);
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (DLGS): Initialize dialogue interface
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x54:
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (DLGX): Run dialogue interface
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x55:
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
// (DLGO): Add a dialogue option to interface
|
2004-04-12 21:40:49 +00:00
|
|
|
case 0x56:
|
|
|
|
{
|
2004-04-25 14:42:14 +00:00
|
|
|
int FIXME_SHADOWED_param1;
|
|
|
|
int FIXME_SHADOWED_param2;
|
|
|
|
int FIXME_SHADOWED_param3;
|
2004-04-12 21:40:49 +00:00
|
|
|
|
|
|
|
printf("DLGO | ");
|
2004-08-01 23:24:22 +00:00
|
|
|
FIXME_SHADOWED_param1 = readS.readByte();
|
|
|
|
FIXME_SHADOWED_param2 = readS.readByte();
|
2004-04-25 14:42:14 +00:00
|
|
|
printf("%02X %02X ", FIXME_SHADOWED_param1, FIXME_SHADOWED_param2);
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-04-25 14:42:14 +00:00
|
|
|
if (FIXME_SHADOWED_param2 > 0) {
|
2004-08-01 23:24:22 +00:00
|
|
|
FIXME_SHADOWED_param3 = readS.readUint16LE();
|
2004-04-25 14:42:14 +00:00
|
|
|
printf("%04X", FIXME_SHADOWED_param3);
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// End instruction list
|
2004-04-12 21:40:49 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
|
2004-08-10 18:31:33 +00:00
|
|
|
_vm->_console->print(S_ERROR_PREFIX "%X: Invalid opcode encountered: " "(%X).\n", thread->i_offset, in_char);
|
2004-04-12 21:40:49 +00:00
|
|
|
thread->executing = 0;
|
|
|
|
break;
|
2004-05-01 16:15:55 +00:00
|
|
|
}
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-05-01 16:15:55 +00:00
|
|
|
// Set instruction offset only if a previous instruction didn't branch
|
2004-04-12 21:40:49 +00:00
|
|
|
if (saved_offset == thread->i_offset) {
|
2004-08-01 23:24:22 +00:00
|
|
|
thread->i_offset = readS.pos();
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
if (unhandled) {
|
2004-08-10 18:31:33 +00:00
|
|
|
_vm->_console->print(S_ERROR_PREFIX "%X: Unhandled opcode.\n", thread->i_offset);
|
2004-04-12 21:40:49 +00:00
|
|
|
thread->executing = 0;
|
|
|
|
}
|
|
|
|
if (thread->executing && debug_print) {
|
|
|
|
SDEBUG_PrintInstr(thread);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // End of namespace Saga
|
|
|
|
|