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
23 #ifndef AGS_PLUGINS_PLUGIN_BASE_H
24 #define AGS_PLUGINS_PLUGIN_BASE_H
25
26 #include "ags/shared/util/string.h"
27 #include "common/hashmap.h"
28 #include "common/hash-str.h"
29 #include "common/textconsole.h"
30
31 namespace AGS3 {
32
33 class IAGSEditor;
34 class IAGSEngine;
35
36 namespace Plugins {
37
38 #define SCRIPT_METHOD(NAME, PROC) addMethod(#NAME, &PROC)
39
40 #define SCRIPT_HASH_MACRO(TheClass, BaseClass, RegisterMethod) \
41 private: \
42 typedef void (TheClass::*MethodPtr)(ScriptMethodParams ¶ms); \
43 Common::HashMap<Common::String, MethodPtr> _methods; \
44 inline void addMethod(const Common::String &name, MethodPtr fn) { \
45 _methods[name] = fn; \
46 _engine->RegisterMethod(name.c_str(), this); \
47 } \
48 public: \
49 void execMethod(const Common::String &name, ScriptMethodParams ¶ms) override { \
50 if (_methods.contains(name)) \
51 (this->*_methods[name])(params); \
52 else \
53 BaseClass::execMethod(name, params); \
54 }
55 #define SCRIPT_HASH(TheClass) SCRIPT_HASH_MACRO(TheClass, PluginBase, RegisterScriptFunction)
56 #define BUILT_IN_HASH(TheClass) SCRIPT_HASH_MACRO(TheClass, ScriptContainer, RegisterBuiltInFunction)
57 #define SCRIPT_HASH_SUB(TheClass, BaseClass) SCRIPT_HASH_MACRO(TheClass, BaseClass, RegisterScriptFunction)
58
PARAM_TO_FLOAT(int32 xi)59 inline float PARAM_TO_FLOAT(int32 xi) {
60 float x;
61 memcpy(&x, &xi, sizeof(float));
62 return x;
63 }
64
PARAM_FROM_FLOAT(float x)65 inline int32 PARAM_FROM_FLOAT(float x) {
66 int32 xi;
67 memcpy(&xi, &x, sizeof(float));
68 return xi;
69 }
70
71 #define PARAMS1(T1, N1) \
72 T1 N1 = (T1)params[0]
73 #define PARAMS2(T1, N1, T2, N2) \
74 T1 N1 = (T1)params[0]; \
75 T2 N2 = (T2)params[1]
76 #define PARAMS3(T1, N1, T2, N2, T3, N3) \
77 T1 N1 = (T1)params[0]; \
78 T2 N2 = (T2)params[1]; \
79 T3 N3 = (T3)params[2]
80 #define PARAMS4(T1, N1, T2, N2, T3, N3, T4, N4) \
81 T1 N1 = (T1)params[0]; \
82 T2 N2 = (T2)params[1]; \
83 T3 N3 = (T3)params[2]; \
84 T4 N4 = (T4)params[3]
85 #define PARAMS5(T1, N1, T2, N2, T3, N3, T4, N4, T5, N5) \
86 T1 N1 = (T1)params[0]; \
87 T2 N2 = (T2)params[1]; \
88 T3 N3 = (T3)params[2]; \
89 T4 N4 = (T4)params[3]; \
90 T5 N5 = (T5)params[4]
91 #define PARAMS6(T1, N1, T2, N2, T3, N3, T4, N4, T5, N5, T6, N6) \
92 T1 N1 = (T1)params[0]; \
93 T2 N2 = (T2)params[1]; \
94 T3 N3 = (T3)params[2]; \
95 T4 N4 = (T4)params[3]; \
96 T5 N5 = (T5)params[4]; \
97 T6 N6 = (T6)params[5]
98 #define PARAMS7(T1, N1, T2, N2, T3, N3, T4, N4, T5, N5, T6, N6, T7, N7) \
99 T1 N1 = (T1)params[0]; \
100 T2 N2 = (T2)params[1]; \
101 T3 N3 = (T3)params[2]; \
102 T4 N4 = (T4)params[3]; \
103 T5 N5 = (T5)params[4]; \
104 T6 N6 = (T6)params[5]; \
105 T7 N7 = (T7)params[6]
106 #define PARAMS8(T1, N1, T2, N2, T3, N3, T4, N4, T5, N5, T6, N6, T7, N7, T8, N8) \
107 T1 N1 = (T1)params[0]; \
108 T2 N2 = (T2)params[1]; \
109 T3 N3 = (T3)params[2]; \
110 T4 N4 = (T4)params[3]; \
111 T5 N5 = (T5)params[4]; \
112 T6 N6 = (T6)params[5]; \
113 T7 N7 = (T7)params[6]; \
114 T8 N8 = (T8)params[7]
115 #define PARAMS9(T1, N1, T2, N2, T3, N3, T4, N4, T5, N5, T6, N6, T7, N7, T8, N8, T9, N9) \
116 T1 N1 = (T1)params[0]; \
117 T2 N2 = (T2)params[1]; \
118 T3 N3 = (T3)params[2]; \
119 T4 N4 = (T4)params[3]; \
120 T5 N5 = (T5)params[4]; \
121 T6 N6 = (T6)params[5]; \
122 T7 N7 = (T7)params[6]; \
123 T8 N8 = (T8)params[7]; \
124 T9 N9 = (T9)params[8]
125
126 class ScriptMethodParams;
127 class ScriptContainer;
128
129 using string = const char *;
130 typedef uint32 HWND;
131
132 class ScriptMethodParams : public Common::Array<intptr_t> {
133 public:
134 NumberPtr _result;
135
136 ScriptMethodParams();
137 ScriptMethodParams(int val1);
138 ScriptMethodParams(int val1, int val2);
139 ScriptMethodParams(int val1, int val2, int val3);
140 ScriptMethodParams(int val1, int val2, int val3, int val4);
141
142 /**
143 * Form of Common::String::format for the parameters array.
144 * @param formatIndex Param index of the format specifier string
145 */
146 Common::String format(int formatIndex);
147 };
148
149 /**
150 * Shared base class for plugins and classes exposed to plugins
151 */
152 class ScriptContainer {
153 public:
ScriptContainer()154 ScriptContainer() {}
~ScriptContainer()155 virtual ~ScriptContainer() {}
156
157 protected:
158 IAGSEngine *_engine = nullptr;
159 public:
AGS_EngineStartup(IAGSEngine * engine)160 virtual void AGS_EngineStartup(IAGSEngine *engine) {
161 _engine = engine;
162 }
163
execMethod(const Common::String & name,ScriptMethodParams & params)164 virtual void execMethod(const Common::String &name, ScriptMethodParams ¶ms) {
165 error("Plugin does not contain method - %s", name.c_str());
166 }
167 };
168
169 /**
170 * Base class for the implementation of AGS plugins
171 */
172 class PluginBase: public ScriptContainer {
173 public:
PluginBase()174 PluginBase() {}
~PluginBase()175 virtual ~PluginBase() {}
176
177 virtual const char *AGS_GetPluginName() = 0;
AGS_PluginV2()178 virtual int AGS_PluginV2() const { return 1; }
AGS_EditorStartup(IAGSEditor *)179 virtual int AGS_EditorStartup(IAGSEditor *) { return 0; }
AGS_EditorShutdown()180 virtual void AGS_EditorShutdown() {}
AGS_EditorProperties(HWND)181 virtual void AGS_EditorProperties(HWND) {}
AGS_EditorSaveGame(char *,int)182 virtual int AGS_EditorSaveGame(char *, int) { return 0; }
AGS_EditorLoadGame(char *,int)183 virtual void AGS_EditorLoadGame(char *, int) {}
AGS_EngineShutdown()184 virtual void AGS_EngineShutdown() {}
AGS_EngineOnEvent(int,NumberPtr)185 virtual int64 AGS_EngineOnEvent(int, NumberPtr) { return 0; }
AGS_EngineDebugHook(const char *,int,int)186 virtual int AGS_EngineDebugHook(const char *, int, int) { return 0; }
AGS_EngineInitGfx(const char * driverID,void * data)187 virtual void AGS_EngineInitGfx(const char *driverID, void *data) {}
188 };
189
190 class PluginMethod {
191 private:
192 ScriptContainer *_sc;
193 Common::String _name;
194 public:
PluginMethod()195 PluginMethod() : _sc(nullptr) {}
PluginMethod(ScriptContainer * sc,const Common::String & name)196 PluginMethod(ScriptContainer *sc, const Common::String &name) :
197 _sc(sc), _name(name) {
198 }
199
200 operator bool() const {
201 return _sc != nullptr;
202 }
203
operator()204 NumberPtr operator()(ScriptMethodParams ¶ms) const {
205 _sc->execMethod(_name, params);
206 return params._result;
207 }
208
operator()209 NumberPtr operator()(intptr_t val1) const {
210 ScriptMethodParams params(val1);
211 _sc->execMethod(_name, params);
212 return params._result;
213 }
operator()214 NumberPtr operator()(intptr_t val1, intptr_t val2) const {
215 ScriptMethodParams params(val1, val2);
216 _sc->execMethod(_name, params);
217 return params._result;
218 }
operator()219 NumberPtr operator()(intptr_t val1, intptr_t val2, intptr_t val3) const {
220 ScriptMethodParams params(val1, val2, val3);
221 _sc->execMethod(_name, params);
222 return params._result;
223 }
operator()224 NumberPtr operator()(intptr_t val1, intptr_t val2, intptr_t val3, intptr_t val4) const {
225 ScriptMethodParams params(val1, val2, val3, val4);
226 _sc->execMethod(_name, params);
227 return params._result;
228 }
229 };
230
231 extern PluginBase *pluginOpen(const char *filename);
232
233 extern int pluginClose(Plugins::PluginBase *lib);
234
235 extern const char *pluginError();
236
237 } // namespace Plugins
238 } // namespace AGS3
239
240 #endif
241