mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 21:31:53 +00:00
350 lines
11 KiB
C++
350 lines
11 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*
|
|
* Based on the original sources
|
|
* Faery Tale II -- The Halls of the Dead
|
|
* (c) 1993-1996 The Wyrmkeep Entertainment Co.
|
|
*/
|
|
|
|
#ifndef SAGA2_SCRIPT_H
|
|
#define SAGA2_SCRIPT_H
|
|
|
|
#include "saga2/objects.h"
|
|
#include "saga2/calendar.h"
|
|
|
|
namespace Saga2 {
|
|
|
|
typedef int16 ThreadID;
|
|
|
|
// Various result codes returned from runScript
|
|
|
|
enum scriptResult {
|
|
|
|
// Code returned when attempt to run a non-existent script
|
|
kScriptResultNoScript = 0,
|
|
|
|
// Code returned when script was aborted before completion
|
|
kScriptResultAborted,
|
|
|
|
// Code returned when script finished
|
|
kScriptResultFinished,
|
|
|
|
// Script spun off as async thread; no answer available.
|
|
kScriptResultAsync
|
|
};
|
|
|
|
// Variables specific to a thread
|
|
|
|
struct scriptCallFrame {
|
|
|
|
// ID of object who's method is being called (which can be the same
|
|
// as one of the other objects below).
|
|
ObjectID invokedObject = Nothing;
|
|
ActiveItemID invokedTAI;
|
|
|
|
// ID of the objects in the interaction.
|
|
ObjectID enactor = Nothing, // actor who caused interaction
|
|
directObject = Nothing, // the object being acted on
|
|
indirectObject = Nothing; // the object being used
|
|
// with the other one
|
|
ActiveItemID directTAI, // the tile activity instance
|
|
// being used
|
|
indirectTAI; // the tile activity instance
|
|
// upon which the object is being
|
|
// used
|
|
|
|
int16 responseType = -1; // used with knowledge package
|
|
|
|
int16 methodNum = -1; // which method being invoked
|
|
|
|
// Misc fields used in passing parameters to scripts.
|
|
int16 idNum = 0; // a misc. id number
|
|
int16 value = 0; // a misc. parameter value
|
|
TilePoint coords; // a misc. tilepoint
|
|
|
|
int16 returnVal = 0; // return value of script
|
|
};
|
|
|
|
// Standard return codes from scripts in the "returnVal" field
|
|
|
|
enum {
|
|
// Code returned by script when script decides requested
|
|
// action is not possible, and the calling C-code should
|
|
// take action to inform user
|
|
kActionResultFailure = 0,
|
|
|
|
// Code returned by script when script completes the action
|
|
// successfully and C-code should not complete the action
|
|
kActionResultSuccess,
|
|
|
|
// Code returned by script when requested action should complete
|
|
// the action
|
|
kActionResultNotDone
|
|
};
|
|
|
|
// Method used to refer to a SAGA object
|
|
|
|
struct SegmentRef {
|
|
uint16 segment; // segment / resource number
|
|
uint16 offset; // offset within segment
|
|
};
|
|
|
|
// Segment numbers of "builtin" SAGA data structures,
|
|
// such as actors and TAGS
|
|
|
|
enum builtinTypes {
|
|
kBuiltinTypeObject = -1,
|
|
kBuiltinTypeTAG = -2,
|
|
kBuiltinAbstract = -3,
|
|
kBuiltinTypeMission = -4
|
|
};
|
|
|
|
/* ===================================================================== *
|
|
SAGA management functions
|
|
* ===================================================================== */
|
|
|
|
// Load the SAGA data segment from the resource file
|
|
void initSAGADataSeg();
|
|
|
|
void saveSAGADataSeg(Common::OutSaveFile *outS);
|
|
void loadSAGADataSeg(Common::InSaveFile *in);
|
|
|
|
// Dispose of the SAGA data segment -- do nothing
|
|
inline void cleanupSAGADataSeg() {}
|
|
|
|
/* ===================================================================== *
|
|
Thread management functions
|
|
* ===================================================================== */
|
|
|
|
class Thread;
|
|
|
|
// Initialize the SAGA thread list
|
|
void initSAGAThreads();
|
|
|
|
void saveSAGAThreads(Common::OutSaveFile *outS);
|
|
void loadSAGAThreads(Common::InSaveFile *in, int32 chunkSize);
|
|
|
|
// Dispose of the active SAGA threads
|
|
void cleanupSAGAThreads();
|
|
|
|
// Dispose of an active SAGA thread
|
|
void deleteThread(Thread *p);
|
|
|
|
void newThread(Thread *p, ThreadID id);
|
|
|
|
void newThread(Thread *p);
|
|
|
|
// Return the ID of the specified SAGA thread
|
|
ThreadID getThreadID(Thread *thread);
|
|
|
|
// Return a pointer to a SAGA thread, given a thread ID
|
|
Thread *getThreadAddress(ThreadID id);
|
|
|
|
/* ===================================================================== *
|
|
Class Thread: An execution context of a script
|
|
* ===================================================================== */
|
|
|
|
// A script task is called a thread
|
|
|
|
scriptResult runMethod(
|
|
uint16 scriptClassID, // which script class
|
|
int16 bType, // builtin type
|
|
uint16 index, // object index
|
|
uint16 methodNum, // method number to call
|
|
scriptCallFrame &args);
|
|
|
|
class Thread {
|
|
|
|
friend char *STRING(int strNum);
|
|
|
|
friend scriptResult runScript(uint16 exportEntryNum, scriptCallFrame &args);
|
|
|
|
friend void wakeUpThread(ThreadID, int16);
|
|
|
|
public:
|
|
SegmentRef _programCounter; // current PC location
|
|
|
|
uint8 *_stackPtr; // current stack location
|
|
byte *_codeSeg; // base of current data segment
|
|
// *_stringBase; // base of string resource
|
|
|
|
uint8 *_stackBase; // base of module stack
|
|
|
|
enum threadFlags {
|
|
kTFWaiting = (1 << 0), // thread waiting for event
|
|
kTFFinished = (1 << 1), // thread finished normally
|
|
kTFAborted = (1 << 2), // thread is aborted
|
|
kTFExtended = (1 << 3), // this is an extended sequence
|
|
kTFExpectResult = (1 << 4), // script is expecting result on stack
|
|
kTFSynchronous = (1 << 5), // when this bit is set this thread will
|
|
// run until it is finished or this bit
|
|
// is cleared
|
|
|
|
kTFAsleep = (kTFWaiting | kTFFinished | kTFAborted)
|
|
};
|
|
|
|
int16 _stackSize, // allocated size of stack
|
|
_flags, // execution flags
|
|
_framePtr, // pointer to call frame
|
|
_returnVal; // return value from ccalls
|
|
|
|
bool _valid;
|
|
|
|
// Various signals that a script can wait upon
|
|
enum WaitTypes {
|
|
kWaitNone = 0, // waiting for nothing
|
|
kWaitDelay, // waiting for a timer
|
|
kWaitFrameDelay, // waiting for frame count
|
|
kWaitOther, // waiting for to be awoken
|
|
kWaitTagSemaphore // waiting for a tag semaphore
|
|
|
|
// kWaitSpeech, // waiting for speech to finish
|
|
// kWaitDialogEnd, // waiting for my dialog to finish
|
|
// kWaitDialogBegin, // waiting for other dialog to finish
|
|
// kWaitWalk, // waiting to finish walking
|
|
// kWaitRequest, // a request is up
|
|
};
|
|
|
|
WaitTypes _waitType; // what we're waiting for
|
|
union {
|
|
Alarm _waitAlarm; // for time-delay
|
|
FrameAlarm _waitFrameAlarm; // for frame count delay
|
|
ActiveItem *_waitParam; // for other waiting
|
|
};
|
|
|
|
scriptCallFrame _threadArgs; // arguments from C to thread
|
|
|
|
// For 'cfunc' member functions, the address of the object who's
|
|
// member function is being invoked.
|
|
void *_thisObject;
|
|
uint16 _argCount; // number of args to cfunc
|
|
|
|
// Constructor
|
|
Thread(uint16 segNum, uint16 segOff, scriptCallFrame &args);
|
|
|
|
// Constructor -- reconstruct from archive buffer
|
|
Thread(void **buf);
|
|
|
|
Thread(Common::SeekableReadStream *stream, ThreadID id);
|
|
|
|
// Destructor
|
|
~Thread();
|
|
|
|
// Return the number of bytes need to archive this thread in an
|
|
// arhive buffer
|
|
int32 archiveSize();
|
|
|
|
// Create an archive of this thread in an archive buffer
|
|
void *archive(void *buf);
|
|
|
|
void write(Common::MemoryWriteStreamDynamic *out);
|
|
|
|
// Dispatch all asynchronous threads
|
|
static void dispatch();
|
|
|
|
// Intepret a single thread
|
|
scriptResult run();
|
|
|
|
// Tells thread to wait for an event
|
|
void waitForEvent(WaitTypes wt, ActiveItem *param) {
|
|
_flags |= kTFWaiting;
|
|
_waitType = wt;
|
|
_waitParam = param;
|
|
}
|
|
|
|
// Convert to extended script, and back to synchonous script
|
|
void setExtended();
|
|
void clearExtended();
|
|
|
|
bool interpret();
|
|
private:
|
|
uint8 *strAddress(int strNum);
|
|
|
|
};
|
|
|
|
const int maxTimeSlice = 16, // max instructions per call
|
|
kStackSize = 512; // thread stack size
|
|
|
|
/* ============================================================================ *
|
|
C-Function dispatch table
|
|
* ============================================================================ */
|
|
|
|
typedef int16 C_Call(int16 *);
|
|
|
|
struct CallTable {
|
|
C_Call **table;
|
|
uint16 numEntries;
|
|
uint16 classID;
|
|
};
|
|
|
|
extern CallTable globalCFuncs,
|
|
actorCFuncs,
|
|
tagCFuncs,
|
|
missionCFuncs;
|
|
|
|
//extern C_Call *ccall_table[];
|
|
//extern int16 ccall_count;
|
|
|
|
/* ===================================================================== *
|
|
Externals
|
|
* ===================================================================== */
|
|
|
|
extern Thread *thisThread; // task queue
|
|
|
|
// Thread control
|
|
//void killThread( Thread *th );
|
|
|
|
/*
|
|
void wakeUpActorThread(WaitTypes wakeupType, void *obj);
|
|
void wakeUpThreads(WaitTypes wakeupType);
|
|
void wakeUpThreadsDelayed(WaitTypes wakeupType, int newdelay);
|
|
void abortObjectThreads(Thread *keep, uint16 id);
|
|
bool abortAllThreads(void);
|
|
*/
|
|
|
|
// Run a script function
|
|
scriptResult runScript(uint16 exportEntryNum, scriptCallFrame &args);
|
|
|
|
// Run a script class method.
|
|
scriptResult runObjectMethod(
|
|
ObjectID id, uint16 methodNum, scriptCallFrame &args);
|
|
|
|
scriptResult runTagMethod(
|
|
uint16 tagNum, uint16 methodNum, scriptCallFrame &args);
|
|
|
|
|
|
struct ResImportTable {
|
|
int16 deadActorProto,
|
|
reserved[2];
|
|
int16 EXP_spellEffect_CreateFireWisp,
|
|
EXP_spellEffect_CreateWindWisp,
|
|
EXP_spellEffect_CreateWraith,
|
|
EXP_spellEffect_TeleportToShrine,
|
|
EXP_spellEffect_Rejoin,
|
|
EXP_spellEffect_Timequake,
|
|
EXP_spellEffect_CreateFood;
|
|
};
|
|
|
|
extern ResImportTable *resImports;
|
|
|
|
} // end of namespace Saga2
|
|
|
|
#endif
|