1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  *
22  * Based on the original sources
23  *   Faery Tale II -- The Halls of the Dead
24  *   (c) 1993-1996 The Wyrmkeep Entertainment Co.
25  */
26 
27 #ifndef SAGA2_SCRIPT_H
28 #define SAGA2_SCRIPT_H
29 
30 #include "saga2/objects.h"
31 #include "saga2/calender.h"
32 
33 namespace Saga2 {
34 
35 typedef int16   ThreadID;
36 
37 //  Various result codes returned from runScript
38 
39 enum scriptResult {
40 
41 	//  Code returned when attempt to run a non-existant script
42 	scriptResultNoScript = 0,
43 
44 	//  Code returned when script was aborted before completion
45 	scriptResultAborted,
46 
47 	//  Code returned when script finished
48 	scriptResultFinished,
49 
50 	//  Script spun off as async thread; no answer available.
51 	scriptResultAsync
52 };
53 
54 //  Variables specific to a thread
55 
56 struct scriptCallFrame {
57 
58 	//  ID of object who's method is being called (which can be the same
59 	//  as one of the other objects below).
60 	ObjectID        invokedObject;
61 	ActiveItemID    invokedTAI;
62 
63 	//  ID of the objects in the interaction.
64 	ObjectID        enactor,                // actor who caused interaction
65 	                directObject,           // the object being acted on
66 	                indirectObject;         // the object being used
67 	// with the other one
68 	ActiveItemID    directTAI,              // the tile activity instance
69 	                // being used
70 	                indirectTAI;            // the tile activity instance
71 	// upon which the object is being
72 	// used
73 
74 	int16           responseType;           // used with knowledge package
75 
76 	int16           methodNum;              // which method being invoked
77 
78 	//  Misc fields used in passing parameters to scripts.
79 	int16           idNum;                  // a misc. id number
80 	int16           value;                  // a misc. parameter value
81 	TilePoint       coords;                 // a misc. tilepoint
82 
83 	int16           returnVal;              // return value of script
84 };
85 
86 //  Standard return codes from scripts in the "returnVal" field
87 
88 enum {
89 	//  Code returned by script when script decides requested
90 	//  action is not possible, and the calling C-code should
91 	//  take action to inform user
92 	actionResultFailure = 0,
93 
94 	//  Code returned by script when script completes the action
95 	//  successfully and C-code should not complete the action
96 	actionResultSuccess,
97 
98 	//  Code returned by script when requested action should complete
99 	//  the action
100 	actionResultNotDone
101 };
102 
103 //  Method used to refer to a SAGA object
104 
105 struct SegmentRef {
106 	uint16              segment;            // segment / resource number
107 	uint16              offset;             // offset within segment
108 };
109 
110 //  Segment numbers of "builtin" SAGA data structures,
111 //  such as actors and TAGS
112 
113 enum builtinTypes {
114 	builtinTypeObject = -1,
115 	builtinTypeTAG = -2,
116 	builtinAbstract = -3,
117 	builtinTypeMission = -4
118 };
119 
120 /* ===================================================================== *
121    SAGA management functions
122  * ===================================================================== */
123 
124 //  Load the SAGA data segment from the resource file
125 void initSAGADataSeg(void);
126 
127 void saveSAGADataSeg(Common::OutSaveFile *outS);
128 void loadSAGADataSeg(Common::InSaveFile *in);
129 
130 //  Dispose of the SAGA data segment -- do nothing
cleanupSAGADataSeg(void)131 inline void cleanupSAGADataSeg(void) {}
132 
133 /* ===================================================================== *
134    Thread management functions
135  * ===================================================================== */
136 
137 class Thread;
138 
139 //  Initialize the SAGA thread list
140 void initSAGAThreads(void);
141 
142 void saveSAGAThreads(Common::OutSaveFile *outS);
143 void loadSAGAThreads(Common::InSaveFile *in, int32 chunkSize);
144 
145 //  Dispose of the active SAGA threads
146 void cleanupSAGAThreads(void);
147 
148 //  Dispose of an active SAGA thread
149 void deleteThread(Thread *p);
150 
151 void newThread(Thread *p, ThreadID id);
152 
153 void newThread(Thread *p);
154 
155 //  Return the ID of the specified SAGA thread
156 ThreadID getThreadID(Thread *thread);
157 
158 //  Return a pointer to a SAGA thread, given a thread ID
159 Thread *getThreadAddress(ThreadID id);
160 
161 /* ===================================================================== *
162    Class Thread: An execution context of a script
163  * ===================================================================== */
164 
165 //  A script task is called a thread
166 
167 scriptResult runMethod(
168 	uint16          scriptClassID,      // which script class
169 	int16           bType,              // builtin type
170 	uint16          index,              // object index
171 	uint16          methodNum,          // method number to call
172 	scriptCallFrame &args);
173 
174 class Thread {
175 
176 	friend          char *STRING(int strNum);
177 
178 	friend scriptResult runScript(
179 	    uint16 exportEntryNum, scriptCallFrame &args);
180 
181 	friend void wakeUpThread(ThreadID, int16);
182 
183 public:
184 	SegmentRef      programCounter;         // current PC location
185 
186 	uint8           *stackPtr;              // current stack location
187 	byte            *codeSeg;                // base of current data segment
188 //					*stringBase;         // base of string resource
189 
190 	uint8           *stackBase;             // base of module stack
191 
192 	enum threadFlags {
193 		waiting     = (1 << 0),             // thread waiting for event
194 		finished    = (1 << 1),             // thread finished normally
195 		aborted     = (1 << 2),             // thread is aborted
196 		extended    = (1 << 3),             // this is an extended sequence
197 		expectResult = (1 << 4),            // script is expecting result on stack
198 		synchronous = (1 << 5),             // when this bit is set this thread will
199 		// run until it is finished or this bit
200 		// is cleared
201 
202 		asleep      = (waiting | finished | aborted)
203 	};
204 
205 	int16           stackSize,              // allocated size of stack
206 	                flags,                  // execution flags
207 	                framePtr,               // pointer to call frame
208 	                returnVal;              // return value from ccalls
209 
210 	bool            _valid;
211 
212 	//  Various signals that a script can wait upon
213 	enum WaitTypes {
214 		waitNone = 0,                       // waiting for nothing
215 		waitDelay,                          // waiting for a timer
216 		waitFrameDelay,                     // waiting for frame count
217 		waitOther,                          // waiting for to be awoken
218 		waitTagSemaphore                    // waiting for a tag semaphore
219 
220 //		waitSpeech,                         // waiting for speech to finish
221 //		waitDialogEnd,                      // waiting for my dialog to finish
222 //		waitDialogBegin,                    // waiting for other dialog to finish
223 //		waitWalk,                           // waiting to finish walking
224 //		waitRequest,                        // a request is up
225 	};
226 
227 	enum WaitTypes  waitType;               // what we're waiting for
228 	union {
229 		Alarm       waitAlarm;              // for time-delay
230 		FrameAlarm  waitFrameAlarm;         // for frame count delay
231 		ActiveItem *waitParam;              // for other waiting
232 	};
233 
234 	scriptCallFrame threadArgs;             // arguments from C to thread
235 
236 	//  For 'cfunc' member functions, the address of the object who's
237 	//  member function is being invoked.
238 	void            *thisObject;
239 	uint16          argCount;               // number of args to cfunc
240 
241 	//  Constructor
242 	Thread(uint16 segNum, uint16 segOff, scriptCallFrame &args);
243 
244 	//  Constructor -- reconstruct from archive buffer
245 	Thread(void **buf);
246 
247 	Thread(Common::SeekableReadStream *stream, ThreadID id);
248 
249 	//  Destructor
250 	~Thread();
251 
252 	//  Return the number of bytes need to archive this thread in an
253 	//  arhive buffer
254 	int32 archiveSize(void);
255 
256 	//  Create an archive of this thread in an archive buffer
257 	void *archive(void *buf);
258 
259 	void write(Common::MemoryWriteStreamDynamic *out);
260 
261 	//  Dispatch all asynchronous threads
262 	static void dispatch(void);
263 
264 	//  Intepret a single thread
265 	scriptResult run(void);
266 
267 	//  Tells thread to wait for an event
waitForEvent(enum WaitTypes wt,ActiveItem * param)268 	void waitForEvent(enum WaitTypes wt, ActiveItem *param) {
269 		flags |= waiting;
270 		waitType = wt;
271 		waitParam = param;
272 	}
273 
274 	//  Convert to extended script, and back to synchonous script
275 	void setExtended(void);
276 	void clearExtended(void);
277 
278 	bool interpret(void);
279 private:
280 	uint8 *strAddress(int strNum);
281 
282 };
283 
284 const int               maxTimeSlice = 16,  // max instructions per call
285                         kStackSize = 512;    // thread stack size
286 
287 /* ============================================================================ *
288    C-Function dispatch table
289  * ============================================================================ */
290 
291 typedef int16       C_Call(int16 *);
292 
293 struct CallTable {
294 	C_Call          **table;
295 	uint16          numEntries;
296 	uint16          classID;
297 };
298 
299 extern CallTable    globalCFuncs,
300        actorCFuncs,
301        tagCFuncs,
302        missionCFuncs;
303 
304 //extern C_Call     *ccall_table[];
305 //extern int16      ccall_count;
306 
307 /* ===================================================================== *
308    Externals
309  * ===================================================================== */
310 
311 extern Thread           *thisThread;        // task queue
312 
313 //  Thread control
314 //void killThread( Thread *th );
315 
316 /*
317 void wakeUpActorThread( enum WaitTypes wakeupType, void *obj );
318 void wakeUpThreads( enum WaitTypes wakeupType );
319 void wakeUpThreadsDelayed( enum WaitTypes wakeupType, int newdelay );
320 void abortObjectThreads( Thread *keep, uint16 id );
321 bool abortAllThreads( void );
322 */
323 
324 //  Run a script function
325 scriptResult runScript(uint16 exportEntryNum, scriptCallFrame &args);
326 
327 //  Run a script class method.
328 scriptResult runObjectMethod(
329     ObjectID id, uint16 methodNum, scriptCallFrame &args);
330 
331 scriptResult runTagMethod(
332     uint16 tagNum, uint16 methodNum, scriptCallFrame &args);
333 
334 
335 struct ResImportTable {
336 	int16           deadActorProto,
337 	                reserved[2];
338 	int16           EXP_spellEffect_CreateFireWisp,
339 	                EXP_spellEffect_CreateWindWisp,
340 	                EXP_spellEffect_CreateWraith,
341 	                EXP_spellEffect_TeleportToShrine,
342 	                EXP_spellEffect_Rejoin,
343 	                EXP_spellEffect_Timequake,
344 	                EXP_spellEffect_CreateFood      ;
345 };
346 
347 extern ResImportTable       *resImports;
348 
349 } // end of namespace Saga2
350 
351 #endif
352