1 //------------------------------------------------------------------------
2 // COAL General Stuff
3 //------------------------------------------------------------------------
4 //
5 // Copyright (c) 2006-2009 The EDGE Team.
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 //------------------------------------------------------------------------
18
19 #include "i_defs.h"
20
21 #include "coal/coal.h"
22
23 #include "epi/file.h"
24 #include "epi/filesystem.h"
25 #include "epi/path.h"
26
27 #include "ddf/main.h"
28
29 #include "vm_coal.h"
30 #include "dm_state.h"
31 #include "e_main.h"
32 #include "g_game.h"
33 #include "version.h"
34
35 #include "e_player.h"
36 #include "hu_font.h"
37 #include "hu_draw.h"
38 #include "r_modes.h"
39 #include "w_wad.h"
40 #include "z_zone.h"
41
42
43 // user interface VM
44 coal::vm_c *ui_vm;
45
46
VM_Printer(const char * msg,...)47 void VM_Printer(const char *msg, ...)
48 {
49 static char buffer[1024];
50
51 va_list argptr;
52
53 va_start(argptr, msg);
54 vsnprintf(buffer, sizeof(buffer), msg, argptr);
55 va_end(argptr);
56
57 buffer[sizeof(buffer)-1] = 0;
58
59 I_Printf("COAL: %s", buffer);
60 }
61
62
VM_SetFloat(coal::vm_c * vm,const char * name,double value)63 void VM_SetFloat(coal::vm_c *vm, const char *name, double value)
64 {
65 // FIXME !!!!! VM_SetFloat
66 }
67
VM_SetString(coal::vm_c * vm,const char * name,const char * value)68 void VM_SetString(coal::vm_c *vm, const char *name, const char *value)
69 {
70 // TODO
71 }
72
73
VM_CallFunction(coal::vm_c * vm,const char * name)74 void VM_CallFunction(coal::vm_c *vm, const char *name)
75 {
76 int func = vm->FindFunction(name);
77
78 if (func == coal::vm_c::NOT_FOUND)
79 I_Error("Missing coal function: %s\n", name);
80
81 if (vm->Execute(func) != 0)
82 I_Error("Coal script terminated with an error.\n");
83 }
84
85
86 //------------------------------------------------------------------------
87 // SYSTEM MODULE
88 //------------------------------------------------------------------------
89
90
91 // sys.error(str)
92 //
SYS_error(coal::vm_c * vm,int argc)93 static void SYS_error(coal::vm_c *vm, int argc)
94 {
95 const char * s = vm->AccessParamString(0);
96
97 I_Error("%s\n", s);
98 }
99
100 // sys.print(str)
101 //
SYS_print(coal::vm_c * vm,int argc)102 static void SYS_print(coal::vm_c *vm, int argc)
103 {
104 const char * s = vm->AccessParamString(0);
105
106 I_Printf("%s\n", s);
107 }
108
109 // sys.debug_print(str)
110 //
SYS_debug_print(coal::vm_c * vm,int argc)111 static void SYS_debug_print(coal::vm_c *vm, int argc)
112 {
113 const char * s = vm->AccessParamString(0);
114
115 I_Debugf("%s\n", s);
116 }
117
118
119 // sys.edge_version()
120 //
SYS_edge_version(coal::vm_c * vm,int argc)121 static void SYS_edge_version(coal::vm_c *vm, int argc)
122 {
123 vm->ReturnFloat(EDGEVER / 100.0);
124 }
125
126
127
128 //------------------------------------------------------------------------
129 // MATH MODULE
130 //------------------------------------------------------------------------
131
132
133 // math.rint(val)
MATH_rint(coal::vm_c * vm,int argc)134 static void MATH_rint(coal::vm_c *vm, int argc)
135 {
136 double val = *vm->AccessParam(0);
137 vm->ReturnFloat(I_ROUND(val));
138 }
139
140 // math.floor(val)
MATH_floor(coal::vm_c * vm,int argc)141 static void MATH_floor(coal::vm_c *vm, int argc)
142 {
143 double val = *vm->AccessParam(0);
144 vm->ReturnFloat(floor(val));
145 }
146
147 // math.ceil(val)
MATH_ceil(coal::vm_c * vm,int argc)148 static void MATH_ceil(coal::vm_c *vm, int argc)
149 {
150 double val = *vm->AccessParam(0);
151 vm->ReturnFloat(ceil(val));
152 }
153
154
155 // math.random()
MATH_random(coal::vm_c * vm,int argc)156 static void MATH_random(coal::vm_c *vm, int argc)
157 {
158 int r = rand();
159
160 r = (r ^ (r >> 18)) & 0xFFFF;
161
162 vm->ReturnFloat(r / double(0x10000));
163 }
164
165
166 // math.cos(val)
MATH_cos(coal::vm_c * vm,int argc)167 static void MATH_cos(coal::vm_c *vm, int argc)
168 {
169 double val = *vm->AccessParam(0);
170 vm->ReturnFloat(cos(val * M_PI / 180.0));
171 }
172
173 // math.sin(val)
MATH_sin(coal::vm_c * vm,int argc)174 static void MATH_sin(coal::vm_c *vm, int argc)
175 {
176 double val = *vm->AccessParam(0);
177 vm->ReturnFloat(sin(val * M_PI / 180.0));
178 }
179
180 // math.tan(val)
MATH_tan(coal::vm_c * vm,int argc)181 static void MATH_tan(coal::vm_c *vm, int argc)
182 {
183 double val = *vm->AccessParam(0);
184 vm->ReturnFloat(tan(val * M_PI / 180.0));
185 }
186
187 // math.acos(val)
MATH_acos(coal::vm_c * vm,int argc)188 static void MATH_acos(coal::vm_c *vm, int argc)
189 {
190 double val = *vm->AccessParam(0);
191 vm->ReturnFloat(acos(val) * 180.0 / M_PI);
192 }
193
194 // math.asin(val)
MATH_asin(coal::vm_c * vm,int argc)195 static void MATH_asin(coal::vm_c *vm, int argc)
196 {
197 double val = *vm->AccessParam(0);
198 vm->ReturnFloat(asin(val) * 180.0 / M_PI);
199 }
200
201 // math.atan(val)
MATH_atan(coal::vm_c * vm,int argc)202 static void MATH_atan(coal::vm_c *vm, int argc)
203 {
204 double val = *vm->AccessParam(0);
205 vm->ReturnFloat(atan(val) * 180.0 / M_PI);
206 }
207
208 // math.atan2(x, y)
MATH_atan2(coal::vm_c * vm,int argc)209 static void MATH_atan2(coal::vm_c *vm, int argc)
210 {
211 double x = *vm->AccessParam(0);
212 double y = *vm->AccessParam(1);
213
214 vm->ReturnFloat(atan2(y, x) * 180.0 / M_PI);
215 }
216
217 // math.log(val)
MATH_log(coal::vm_c * vm,int argc)218 static void MATH_log(coal::vm_c *vm, int argc)
219 {
220 double val = *vm->AccessParam(0);
221
222 if (val <= 0)
223 I_Error("math.log: illegal input: %g\n", val);
224
225 vm->ReturnFloat(log(val));
226 }
227
228
229
230 //------------------------------------------------------------------------
231 // STRINGS MODULE
232 //------------------------------------------------------------------------
233
234
235 // strings.len(s)
236 //
STRINGS_len(coal::vm_c * vm,int argc)237 static void STRINGS_len(coal::vm_c *vm, int argc)
238 {
239 const char * s = vm->AccessParamString(0);
240
241 vm->ReturnFloat(strlen(s));
242 }
243
244
245 // strings.sub(s, start, end)
246 //
STRINGS_sub(coal::vm_c * vm,int argc)247 static void STRINGS_sub(coal::vm_c *vm, int argc)
248 {
249 const char * s = vm->AccessParamString(0);
250
251 int start = (int) *vm->AccessParam(1);
252 int end = (int) *vm->AccessParam(2);
253 int len = strlen(s);
254
255 // negative values are relative to END of the string (-1 = last character)
256 if (start < 0) start += len + 1;
257 if (end < 0) end += len + 1;
258
259 if (start < 1) start = 1;
260 if (end > len) end = len;
261
262 if (end < start)
263 {
264 vm->ReturnString("");
265 return;
266 }
267
268 SYS_ASSERT(end >= 1 && start <= len);
269
270 // translate into C talk
271 start--;
272 end--;
273
274 int new_len = (end - start + 1);
275
276 vm->ReturnString(s + start, new_len);
277 }
278
279
280 // strings.tonumber(s)
281 //
STRINGS_tonumber(coal::vm_c * vm,int argc)282 static void STRINGS_tonumber(coal::vm_c *vm, int argc)
283 {
284 const char * s = vm->AccessParamString(0);
285
286 vm->ReturnFloat(atof(s));
287 }
288
289
290 //------------------------------------------------------------------------
291
VM_RegisterBASE(coal::vm_c * vm)292 void VM_RegisterBASE(coal::vm_c *vm)
293 {
294 // SYSTEM
295 vm->AddNativeFunction("sys.error", SYS_error);
296 vm->AddNativeFunction("sys.print", SYS_print);
297 vm->AddNativeFunction("sys.debug_print", SYS_debug_print);
298 vm->AddNativeFunction("sys.edge_version", SYS_edge_version);
299
300 // MATH
301 vm->AddNativeFunction("math.rint", MATH_rint);
302 vm->AddNativeFunction("math.floor", MATH_floor);
303 vm->AddNativeFunction("math.ceil", MATH_ceil);
304 vm->AddNativeFunction("math.random", MATH_random);
305
306 vm->AddNativeFunction("math.cos", MATH_cos);
307 vm->AddNativeFunction("math.sin", MATH_sin);
308 vm->AddNativeFunction("math.tan", MATH_tan);
309 vm->AddNativeFunction("math.acos", MATH_acos);
310 vm->AddNativeFunction("math.asin", MATH_asin);
311 vm->AddNativeFunction("math.atan", MATH_atan);
312 vm->AddNativeFunction("math.atan2", MATH_atan2);
313 vm->AddNativeFunction("math.log", MATH_log);
314
315 // STRINGS
316 vm->AddNativeFunction("strings.len", STRINGS_len);
317 vm->AddNativeFunction("strings.sub", STRINGS_sub);
318 vm->AddNativeFunction("strings.tonumber", STRINGS_tonumber);
319 }
320
321
VM_InitCoal()322 void VM_InitCoal()
323 {
324 ui_vm = coal::CreateVM();
325
326 ui_vm->SetPrinter(VM_Printer);
327
328 VM_RegisterBASE(ui_vm);
329 VM_RegisterHUD();
330 VM_RegisterPlaysim();
331 }
332
VM_QuitCoal()333 void VM_QuitCoal()
334 {
335 if (ui_vm)
336 {
337 delete ui_vm;
338 ui_vm = NULL;
339 }
340 }
341
342
VM_LoadCoalFire(const char * filename)343 void VM_LoadCoalFire(const char *filename)
344 {
345 epi::file_c *F = epi::FS_Open(filename, epi::file_c::ACCESS_READ | epi::file_c::ACCESS_BINARY);
346
347 if (! F)
348 I_Error("Could not open coal script: %s\n", filename);
349
350 I_Printf("Compiling COAL script: %s\n", filename);
351
352 byte *data = F->LoadIntoMemory();
353
354 if (! ui_vm->CompileFile((char *)data, filename))
355 I_Error("Errors compiling coal script: %s\n", filename);
356
357 delete[] data;
358 delete F;
359 }
360
VM_LoadLumpOfCoal(int lump)361 void VM_LoadLumpOfCoal(int lump)
362 {
363 const char *name = W_GetLumpName(lump);
364
365 int length;
366 byte *data = W_ReadLumpAlloc(lump, &length);
367
368 I_Printf("Compiling %s lump\n", name);
369
370 if (! ui_vm->CompileFile((char *)data, name))
371 I_Error("Errors compiling %s lump.\n", name);
372
373 delete[] data;
374 }
375
376
VM_LoadScripts()377 void VM_LoadScripts()
378 {
379 std::string script_dir = epi::PATH_Join(game_dir.c_str(), "doom_ddf");
380 std::string fn;
381
382 fn = epi::PATH_Join(script_dir.c_str(), "coal_api.ec");
383 VM_LoadCoalFire(fn.c_str());
384
385 fn = epi::PATH_Join(script_dir.c_str(), "coal_hud.ec");
386 VM_LoadCoalFire(fn.c_str());
387
388 fn.clear();
389 script_dir.clear();
390
391 W_ReadCoalLumps();
392 }
393
394
395 //--- editor settings ---
396 // vi:ts=4:sw=4:noexpandtab
397