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 &params); \
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 &params) 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 &params) {
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 &params) 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