ScummVM API documentation
cc_instance.h
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 modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (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, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef AGS_ENGINE_SCRIPT_CC_INSTANCE_H
23 #define AGS_ENGINE_SCRIPT_CC_INSTANCE_H
24 
25 #include "common/std/memory.h"
26 #include "common/std/map.h"
27 #include "ags/engine/ac/timer.h"
28 #include "ags/shared/script/cc_internal.h"
29 #include "ags/shared/script/cc_script.h" // ccScript
30 #include "ags/engine/script/non_blocking_script_function.h"
31 #include "ags/shared/util/string.h"
32 
33 namespace AGS3 {
34 
35 using namespace AGS;
36 
37 #define INSTF_SHAREDATA 1
38 #define INSTF_ABORTED 2
39 #define INSTF_FREE 4
40 #define INSTF_RUNNING 8 // set by main code to confirm script isn't stuck
41 
42 // Size of stack in RuntimeScriptValues (aka distinct variables)
43 #define CC_STACK_SIZE 256
44 // Size of stack in bytes (raw data storage)
45 #define CC_STACK_DATA_SIZE (1024 * sizeof(int32_t))
46 #define MAX_CALL_STACK 128
47 #define MAX_FUNCTION_PARAMS 20
48 
49 // 256 because we use 8 bits to hold instance number
50 #define MAX_LOADED_INSTANCES 256
51 
52 #define INSTANCE_ID_SHIFT 24LL
53 #define INSTANCE_ID_MASK 0x00000000000000ffLL
54 #define INSTANCE_ID_REMOVEMASK 0x0000000000ffffffLL
55 
56 // Script executor debugging flag:
57 // enables mistake checks, but slows things down!
58 #ifndef DEBUG_CC_EXEC
59 #define DEBUG_CC_EXEC (0)
60 #endif
61 
63  ScriptInstruction() = default;
64  ScriptInstruction(int code, int instid) : Code(code), InstanceId(instid) {}
65 
66  int32_t Code = 0;
67  int32_t InstanceId = 0;
68 };
69 
71  ScriptInstruction Instruction;
72  RuntimeScriptValue Args[MAX_SCMD_ARGS];
73  int ArgCount = 0;
74 
75  // Helper functions for clarity of intent:
76  // returns argN, 1-based
77  inline const RuntimeScriptValue &Arg1() const { return Args[0]; }
78  inline const RuntimeScriptValue &Arg2() const { return Args[1]; }
79  inline const RuntimeScriptValue &Arg3() const { return Args[2]; }
80  // returns argN as a integer literal
81  inline int Arg1i() const { return Args[0].IValue; }
82  inline int Arg2i() const { return Args[1].IValue; }
83  inline int Arg3i() const { return Args[2].IValue; }
84 };
85 
87  ScriptVariable() {
88  ScAddress = -1; // address = 0 is valid one, -1 means undefined
89  }
90 
91  int32_t ScAddress; // original 32-bit relative data address, written in compiled script;
92  // if we are to use Map or HashMap, this could be used as Key
93  RuntimeScriptValue RValue;
94 };
95 
96 struct FunctionCallStack;
97 
100  : Line(0) {
101  }
102 
103  ScriptPosition(const Shared::String &section, int32_t line)
104  : Section(section)
105  , Line(line) {
106  }
107 
108  Shared::String Section;
109  int32_t Line;
110 };
111 
112 
113 // Running instance of the script
114 struct ccInstance {
115 public:
118 public:
119  int32_t flags;
120  PScVarMap globalvars;
121  char *globaldata;
122  int32_t globaldatasize;
123  // Executed byte-code. Unlike ccScript's code array which is int32_t, the one
124  // in ccInstance must be intptr_t to accommodate real pointers placed after
125  // performing fixups.
126  intptr_t *code;
127  ccInstance *runningInst; // might point to another instance if in far call
128  int32_t codesize;
129  char *strings;
130  int32_t stringssize;
131  RuntimeScriptValue *exports;
132  RuntimeScriptValue *stack;
133  int num_stackentries;
134  // An array for keeping stack data; stack entries reference unknown data from here
135  // TODO: probably change to dynamic array later
136  char *stackdata; // for storing stack data of unknown type
137  char *stackdata_ptr;// works similar to original stack pointer, points to the next unused byte in stack data array
138  int32_t stackdatasize; // conventional size of stack data in bytes
139  //
140  RuntimeScriptValue registers[CC_NUM_REGISTERS];
141  int32_t pc; // program counter
142  int32_t line_number; // source code line number
143  PScript instanceof;
144  int loadedInstanceId;
145  int returnValue;
146 
147  int callStackSize;
148  int32_t callStackLineNumber[MAX_CALL_STACK];
149  int32_t callStackAddr[MAX_CALL_STACK];
150  ccInstance *callStackCodeInst[MAX_CALL_STACK];
151 
152  // array of real import indexes used in script
153  uint32_t *resolved_imports;
154  int numimports;
155 
156  char *code_fixups;
157 
158  // returns the currently executing instance, or NULL if none
159  static ccInstance *GetCurrentInstance(void);
160  // clears recorded stack of current instances
161  // FIXME: reimplement this in a safer way, this must be done automatically
162  // when destroying all script instances, e.g. on game quit.
163  static void FreeInstanceStack();
164  // create a runnable instance of the supplied script
165  static std::unique_ptr<ccInstance> CreateFromScript(PScript script);
166  static std::unique_ptr<ccInstance> CreateEx(PScript scri, const ccInstance *joined);
167  static void SetExecTimeout(unsigned sys_poll_ms, unsigned abort_ms, unsigned abort_loops);
168 
169  ccInstance();
170  ~ccInstance();
171  // Create a runnable instance of the same script, sharing global memory
173  // Specifies that when the current function returns to the script, it
174  // will stop and return from CallInstance
175  void Abort();
176  // Aborts instance, then frees the memory later when it is done with
177  void AbortAndDestroy();
178 
179  // Call an exported function in the script
180  int CallScriptFunction(const char *funcname, int32_t num_params, const RuntimeScriptValue *params);
181 
182  // Get the script's execution position and callstack as human-readable text
183  Shared::String GetCallStack(int max_lines = INT_MAX) const;
184  // Get the script's execution position
185  void GetScriptPosition(ScriptPosition &script_pos) const;
186  // Get the address of an exported symbol (function or variable) in the script
187  RuntimeScriptValue GetSymbolAddress(const char *symname) const;
188  void DumpInstruction(const ScriptOperation &op) const;
189  // Tells whether this instance is in the process of executing the byte-code
190  bool IsBeingRun() const;
191  // Notifies that the game was being updated (script not hanging)
192  void NotifyAlive();
193 
194  // For each import, find the instance that corresponds to it and save it
195  // in resolved_imports[]. Return whether the function is successful
196  bool ResolveScriptImports(const ccScript *scri);
197 
198  // Using resolved_imports[], resolve the IMPORT fixups
199  // Also change CALLEXT op-codes to CALLAS when they pertain to a script instance
200  bool ResolveImportFixups(const ccScript *scri);
201 
202 private:
203  bool _Create(PScript scri, const ccInstance *joined);
204  // free the memory associated with the instance
205  void Free();
206 
207  bool CreateGlobalVars(const ccScript *scri);
208  bool AddGlobalVar(const ScriptVariable &glvar);
209  ScriptVariable *FindGlobalVar(int32_t var_addr);
210  bool CreateRuntimeCodeFixups(const ccScript *scri);
211 
212  // Begin executing script starting from the given bytecode index
213  int Run(int32_t curpc);
214 
215  // Stack processing
216  // Push writes new value and increments stack ptr;
217  // stack ptr now points to the __next empty__ entry
218  void PushValueToStack(const RuntimeScriptValue &rval);
219  void PushDataToStack(int32_t num_bytes);
220  // Pop decrements stack ptr, returns last stored value and invalidates! stack tail;
221  // stack ptr now points to the __next empty__ entry
222  RuntimeScriptValue PopValueFromStack();
223  // helper function to pop & dump several values
224  void PopValuesFromStack(int32_t num_entries);
225  void PopDataFromStack(int32_t num_bytes);
226  // Return stack ptr at given offset from stack tail;
227  // Offset is in data bytes; program stack ptr is __not__ changed
228  RuntimeScriptValue GetStackPtrOffsetRw(int32_t rw_offset);
229 
230  // Function call stack processing
231  void PushToFuncCallStack(FunctionCallStack &func_callstack, const RuntimeScriptValue &rval);
232  void PopFromFuncCallStack(FunctionCallStack &func_callstack, int32_t num_entries);
233 
234  // Last time the script was noted of being "alive"
235  AGS_Clock::time_point _lastAliveTs;
236 };
237 
238 extern void script_commands_init();
239 extern void script_commands_free();
240 
241 } // namespace AGS3
242 
243 #endif
Definition: achievements_tables.h:27
Definition: map.h:204
Definition: runtime_script_value.h:63
Definition: cc_instance.h:98
Definition: ptr.h:572
Definition: cc_instance.h:62
Definition: cc_instance.h:70
Definition: geometry.h:118
Definition: string.h:62
Definition: cc_script.h:37
Definition: ptr.h:159
Definition: cc_instance.h:114
Definition: ags.h:40
Definition: cc_instance.h:86