1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM 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 #include "engines/grim/grim.h"
24 #include "engines/grim/lua_v1.h"
25 #include "engines/grim/resource.h"
26 #include "engines/grim/bitmap.h"
27 #include "engines/grim/primitives.h"
28 #include "engines/grim/iris.h"
29 #include "engines/grim/gfx_base.h"
30 #include "engines/grim/set.h"
31 #include "actor.h"
32
33 #include "engines/grim/movie/movie.h"
34
35 #include "engines/grim/lua/lua.h"
36
37 namespace Grim {
38
GetImage()39 void Lua_V1::GetImage() {
40 lua_Object nameObj = lua_getparam(1);
41 if (!lua_isstring(nameObj)) {
42 lua_pushnil();
43 return;
44 }
45 const char *bitmapName = lua_getstring(nameObj);
46 Bitmap *b = Bitmap::create(bitmapName);
47 lua_pushusertag(b->getId(), MKTAG('V','B','U','F'));
48 }
49
FreeImage()50 void Lua_V1::FreeImage() {
51 lua_Object param = lua_getparam(1);
52 if (!lua_isuserdata(param) || lua_tag(param) != MKTAG('V','B','U','F'))
53 return;
54 Bitmap *bitmap = getbitmap(param);
55 delete bitmap;
56 }
57
BlastImage()58 void Lua_V1::BlastImage() {
59 lua_Object param = lua_getparam(1);
60 if (!lua_isuserdata(param) || lua_tag(param) != MKTAG('V','B','U','F'))
61 return;
62 Bitmap *bitmap = getbitmap(param);
63 lua_Object xObj = lua_getparam(2);
64 lua_Object yObj = lua_getparam(3);
65 if (!lua_isnumber(xObj) || !lua_isnumber(yObj))
66 return;
67
68 int x = (int)lua_getnumber(xObj);
69 int y = (int)lua_getnumber(yObj);
70 // bool transparent = getbool(4); // TODO transparent/masked copy into display
71 bitmap->draw(x, y);
72 }
73
CleanBuffer()74 void Lua_V1::CleanBuffer() {
75 g_driver->copyStoredToDisplay();
76 }
77
StartFullscreenMovie()78 void Lua_V1::StartFullscreenMovie() {
79 lua_Object name = lua_getparam(1);
80 if (!lua_isstring(name)) {
81 lua_pushnil();
82 return;
83 }
84 Lua_V1::CleanBuffer();
85
86 GrimEngine::EngineMode prevEngineMode = g_grim->getMode();
87 g_grim->setMode(GrimEngine::SmushMode);
88 g_grim->setMovieSubtitle(nullptr);
89 bool looping = getbool(2);
90 bool result = g_movie->play(lua_getstring(name), looping, 0, 0);
91 if (!result)
92 g_grim->setMode(prevEngineMode);
93 pushbool(result);
94 }
95
StartMovie()96 void Lua_V1::StartMovie() {
97 lua_Object name = lua_getparam(1);
98 if (!lua_isstring(name)) {
99 lua_pushnil();
100 return;
101 }
102 int x = 0, y = 0;
103 if (!lua_isnil(lua_getparam(3)))
104 x = (int)lua_getnumber(lua_getparam(3));
105 if (!lua_isnil(lua_getparam(4)))
106 y = (int)lua_getnumber(lua_getparam(4));
107
108 GrimEngine::EngineMode prevEngineMode = g_grim->getMode();
109 g_grim->setMode(GrimEngine::NormalMode);
110
111 bool looping = getbool(2);
112 bool result = g_movie->play(lua_getstring(name), looping, x, y);
113 g_grim->setMovieSetup();
114 if (!result)
115 g_grim->setMode(prevEngineMode);
116 pushbool(result);
117 }
118
119 /* Fullscreen movie playing query and normal movie
120 * query should actually detect correctly and not
121 * just return true whenever ANY movie is playing
122 */
IsFullscreenMoviePlaying()123 void Lua_V1::IsFullscreenMoviePlaying() {
124 pushbool(g_movie->isPlaying());
125 }
126
IsMoviePlaying()127 void Lua_V1::IsMoviePlaying() {
128 // Previously, if the game was *not* the demo, this checked also if the mode
129 // was GrimEngine::NormalMode. This doesn't seem to be what original does, and causes
130 // bug #301 because the movie eldepot.snm is played before legslide.snm ends.
131 pushbool(g_movie->isPlaying());
132 }
133
StopMovie()134 void Lua_V1::StopMovie() {
135 g_movie->stop();
136 // Delete subtitles that may have not expired.
137 g_grim->setMovieSubtitle(nullptr);
138 }
139
PauseMovie()140 void Lua_V1::PauseMovie() {
141 g_movie->pause(lua_isnil(lua_getparam(1)) == 0);
142 }
143
PurgePrimitiveQueue()144 void Lua_V1::PurgePrimitiveQueue() {
145 PrimitiveObject::getPool().deleteObjects();
146 }
147
DrawPolygon()148 void Lua_V1::DrawPolygon() {
149 lua_Object tableObj1 = lua_getparam(1);
150 if (!lua_istable(tableObj1)) {
151 lua_pushnil();
152 return;
153 }
154
155 //int layer = 2;
156 Color color;
157 lua_Object tableObj2 = lua_getparam(2);
158 if (lua_istable(tableObj2)) {
159 lua_pushobject(tableObj2);
160 lua_pushstring("color");
161 lua_Object colorObj = lua_gettable();
162 if (lua_isuserdata(colorObj) && lua_tag(colorObj) == MKTAG('C','O','L','R')) {
163 color = getcolor(colorObj);
164 }
165 lua_pushobject(tableObj2);
166 lua_pushstring("layer");
167 lua_Object layerObj = lua_gettable();
168 if (lua_isnumber(layerObj))
169 /*layer = (int)*/lua_getnumber(layerObj);
170 }
171
172 // This code only supports 4 point polygons because the game doesn't
173 // use other than that. However, the original engine can support
174 // many points per polygon
175 lua_Object pointObj;
176 Common::Point p[4];
177 for (int i = 0; i < 4; i++) {
178 // Get X
179 lua_pushobject(tableObj1);
180 lua_pushnumber(i * 2 + 1);
181 pointObj = lua_gettable();
182 if (!lua_isnumber(pointObj)) {
183 warning("Lua_V1::DrawPolygon: %i Point Parameter X isn't a number!", i * 2 + 1);
184 return;
185 }
186 if (g_grim->getGameType() == GType_GRIM)
187 p[i].x = (int)lua_getnumber(pointObj);
188 else
189 p[i].x = (int)((lua_getnumber(pointObj) + 1) * 320);
190
191 // Get Y
192 lua_pushobject(tableObj1);
193 lua_pushnumber(i * 2 + 2);
194 pointObj = lua_gettable();
195 if (!lua_isnumber(pointObj)) {
196 warning("Lua_V1::DrawPolygon: %i Point Parameter Y isn't a number!", i * 2 + 2);
197 return;
198 }
199 if (g_grim->getGameType() == GType_GRIM)
200 p[i].y = (int)lua_getnumber(pointObj);
201 else
202 p[i].y = (int)((1 - lua_getnumber(pointObj)) * 240);
203 }
204
205 PrimitiveObject *prim = new PrimitiveObject();
206 prim->createPolygon(p[0], p[1], p[2], p[3], color);
207 lua_pushusertag(prim->getId(), MKTAG('P','R','I','M'));
208 }
209
DrawLine()210 void Lua_V1::DrawLine() {
211 Common::Point p1, p2;
212 Color color;
213 lua_Object x1Obj = lua_getparam(1);
214 lua_Object y1Obj = lua_getparam(2);
215 lua_Object x2Obj = lua_getparam(3);
216 lua_Object y2Obj = lua_getparam(4);
217 lua_Object tableObj = lua_getparam(5);
218
219 if (!lua_isnumber(x1Obj) || !lua_isnumber(y1Obj) || !lua_isnumber(x2Obj) || !lua_isnumber(y2Obj)) {
220 lua_pushnil();
221 return;
222 }
223
224 if (g_grim->getGameType() == GType_GRIM) {
225 p1.x = (int)lua_getnumber(x1Obj);
226 p1.y = (int)lua_getnumber(y1Obj);
227 p2.x = (int)lua_getnumber(x2Obj);
228 p2.y = (int)lua_getnumber(y2Obj);
229 } else {
230 p1.x = (int)((lua_getnumber(x1Obj) + 1) * 320);
231 p1.y = (int)((1 - lua_getnumber(y1Obj)) * 240);
232 p2.x = (int)((lua_getnumber(x2Obj) + 1) * 320);
233 p2.y = (int)((1 - lua_getnumber(y2Obj)) * 240);
234 }
235
236 //int layer = 2;
237 if (lua_istable(tableObj)) {
238 lua_pushobject(tableObj);
239 lua_pushstring("color");
240 lua_Object colorObj = lua_gettable();
241 if (lua_isuserdata(colorObj) && lua_tag(colorObj) == MKTAG('C','O','L','R')) {
242 color = getcolor(colorObj);
243 }
244 lua_pushobject(tableObj);
245 lua_pushstring("layer");
246 lua_Object layerObj = lua_gettable();
247 if (lua_isnumber(layerObj))
248 /*layer = (int)*/lua_getnumber(layerObj);
249 }
250
251 PrimitiveObject *p = new PrimitiveObject();
252 p->createLine(p1, p2, color); // TODO Add layer support
253 lua_pushusertag(p->getId(), MKTAG('P','R','I','M'));
254 }
255
ChangePrimitive()256 void Lua_V1::ChangePrimitive() {
257 lua_Object param1 = lua_getparam(1);
258 if (!lua_isuserdata(param1) || lua_tag(param1) != MKTAG('P','R','I','M'))
259 return;
260
261 lua_Object tableObj = lua_getparam(2);
262 if (!lua_istable(tableObj))
263 return;
264
265 PrimitiveObject *pmodify = getprimitive(param1);
266 assert(pmodify);
267
268 Color color;
269 lua_pushobject(tableObj);
270 lua_pushstring("color");
271 lua_Object colorObj = lua_gettable();
272 if (lua_isuserdata(colorObj) && lua_tag(colorObj) == MKTAG('C','O','L','R')) {
273 color = getcolor(colorObj);
274 pmodify->setColor(color);
275 }
276
277 lua_pushobject(tableObj);
278 lua_pushstring("layer");
279 lua_Object layer = lua_gettable();
280 if (lua_isnumber(layer)) {
281 // TODO pmodify->setLayer(lua_getnumber(layer));
282 warning("Not implemented: PrimitiveObject::setLayer. Layer: %d", (int)lua_getnumber(layer));
283 }
284
285 lua_pushobject(tableObj);
286 lua_pushstring("xoffset");
287 lua_Object xObj = lua_gettable();
288 lua_pushobject(tableObj);
289 lua_pushstring("yoffset");
290 lua_Object yObj = lua_gettable();
291 if (lua_isnumber(xObj) || lua_isnumber(yObj)) {
292 //int x = 0;
293 //int y = 0;
294 if (lua_isnumber(xObj))
295 /*x = (int)*/lua_getnumber(xObj);
296 if (lua_isnumber(yObj))
297 /*y = (int)*/lua_getnumber(yObj);
298 // TODO pmodify->setOffets(x, y);
299 assert(0);
300 }
301
302 lua_pushobject(tableObj);
303 lua_pushstring("x");
304 xObj = lua_gettable();
305 lua_pushobject(tableObj);
306 lua_pushstring("y");
307 yObj = lua_gettable();
308 if (lua_isnumber(xObj) || lua_isnumber(yObj)) {
309 int x = -1;
310 int y = -1;
311 if (lua_isnumber(xObj)) {
312 if (g_grim->getGameType() == GType_GRIM)
313 x = (int)lua_getnumber(xObj);
314 else
315 x = (int)((lua_getnumber(xObj) + 1) * 320);
316 }
317 if (lua_isnumber(yObj)) {
318 if (g_grim->getGameType() == GType_GRIM)
319 y = (int)lua_getnumber(yObj);
320 else
321 y = (int)((1 - lua_getnumber(yObj)) * 240);
322 }
323 pmodify->setPos(x, y);
324 }
325
326 lua_pushobject(tableObj);
327 lua_pushstring("x2");
328 xObj = lua_gettable();
329 lua_pushobject(tableObj);
330 lua_pushstring("y2");
331 yObj = lua_gettable();
332 if (lua_isnumber(xObj) || lua_isnumber(yObj)) {
333 int x = -1;
334 int y = -1;
335 if (lua_isnumber(xObj)) {
336 if (g_grim->getGameType() == GType_GRIM)
337 x = (int)lua_getnumber(xObj);
338 else
339 x = (int)((lua_getnumber(xObj) + 1) * 320);
340 }
341 if (lua_isnumber(yObj)) {
342 if (g_grim->getGameType() == GType_GRIM)
343 y = (int)lua_getnumber(yObj);
344 else
345 y = (int)((1 - lua_getnumber(yObj)) * 240);
346 }
347 pmodify->setEndpoint(x, y);
348 }
349
350 lua_pushobject(tableObj);
351 lua_pushstring("width");
352 lua_Object width = lua_gettable();
353 lua_pushobject(tableObj);
354 lua_pushstring("height");
355 lua_Object height = lua_gettable();
356 if (lua_isnumber(width) || lua_isnumber(height)) {
357 //int x = -1;
358 //int y = -1;
359 if (lua_isnumber(width))
360 /*x = (int)*/lua_getnumber(width);
361 if (lua_isnumber(height))
362 /*y = (int)*/lua_getnumber(height);
363 // TODO pmodify->setSize(x, y);
364 assert(0);
365 }
366 }
367
DrawRectangle()368 void Lua_V1::DrawRectangle() {
369 Common::Point p1, p2;
370 Color color;
371 lua_Object x1Obj = lua_getparam(1);
372 lua_Object y1Obj = lua_getparam(2);
373 lua_Object x2Obj = lua_getparam(3);
374 lua_Object y2Obj = lua_getparam(4);
375 lua_Object tableObj = lua_getparam(5);
376
377 if (!lua_isnumber(x1Obj) || !lua_isnumber(y1Obj) || !lua_isnumber(x2Obj) || !lua_isnumber(y2Obj)) {
378 lua_pushnil();
379 return;
380 }
381
382 if (g_grim->getGameType() == GType_GRIM) {
383 p1.x = (int)lua_getnumber(x1Obj);
384 p1.y = (int)lua_getnumber(y1Obj);
385 p2.x = (int)lua_getnumber(x2Obj);
386 p2.y = (int)lua_getnumber(y2Obj);
387 } else {
388 p1.x = (int)((lua_getnumber(x1Obj) + 1) * 320);
389 p1.y = (int)((1 - lua_getnumber(y1Obj)) * 240);
390 p2.x = (int)((lua_getnumber(x2Obj) + 1) * 320);
391 p2.y = (int)((1 - lua_getnumber(y2Obj)) * 240);
392 }
393 bool filled = false;
394
395 if (lua_istable(tableObj)) {
396 lua_pushobject(tableObj);
397 lua_pushstring("color");
398 lua_Object colorObj = lua_gettable();
399 if (lua_isuserdata(colorObj) && lua_tag(colorObj) == MKTAG('C','O','L','R')) {
400 color = getcolor(colorObj);
401 }
402
403 lua_pushobject(tableObj);
404 lua_pushstring("filled");
405 lua_Object objFilled = lua_gettable();
406 if (!lua_isnil(objFilled))
407 filled = true;
408 }
409
410 PrimitiveObject *p = new PrimitiveObject();
411 p->createRectangle(p1, p2, color, filled);
412 lua_pushusertag(p->getId(), MKTAG('P','R','I','M')); // FIXME: we use PRIM usetag here
413 }
414
BlastRect()415 void Lua_V1::BlastRect() {
416 Common::Point p1, p2;
417 Color color;
418 lua_Object x1Obj = lua_getparam(1);
419 lua_Object y1Obj = lua_getparam(2);
420 lua_Object x2Obj = lua_getparam(3);
421 lua_Object y2Obj = lua_getparam(4);
422 lua_Object tableObj = lua_getparam(5);
423
424 if (!lua_isnumber(x1Obj) || !lua_isnumber(y1Obj) || !lua_isnumber(x2Obj) || !lua_isnumber(y2Obj)) {
425 lua_pushnil();
426 return;
427 }
428 if (g_grim->getGameType() == GType_GRIM) {
429 p1.x = (int)lua_getnumber(x1Obj);
430 p1.y = (int)lua_getnumber(y1Obj);
431 p2.x = (int)lua_getnumber(x2Obj);
432 p2.y = (int)lua_getnumber(y2Obj);
433 } else {
434 p1.x = (int)((lua_getnumber(x1Obj) + 1) * 320);
435 p1.y = (int)((1 - lua_getnumber(y1Obj)) * 240);
436 p2.x = (int)((lua_getnumber(x2Obj) + 1) * 320);
437 p2.y = (int)((1 - lua_getnumber(y2Obj)) * 240);
438 }
439 bool filled = false;
440
441 if (lua_istable(tableObj)) {
442 lua_pushobject(tableObj);
443 lua_pushstring("color");
444 lua_Object colorObj = lua_gettable();
445 if (lua_isuserdata(colorObj) && lua_tag(colorObj) == MKTAG('C','O','L','R')) {
446 color = getcolor(colorObj);
447 }
448
449 lua_pushobject(tableObj);
450 lua_pushstring("filled");
451 lua_Object objFilled = lua_gettable();
452 if (!lua_isnil(objFilled))
453 filled = true;
454 }
455
456 PrimitiveObject *p = new PrimitiveObject();
457 p->createRectangle(p1, p2, color, filled);
458 p->draw();
459 delete p;
460 }
461
KillPrimitive()462 void Lua_V1::KillPrimitive() {
463 lua_Object primObj = lua_getparam(1);
464
465 if (!lua_isuserdata(primObj) || lua_tag(primObj) != MKTAG('P','R','I','M'))
466 return;
467
468 PrimitiveObject *prim = getprimitive(primObj);
469 delete prim;
470 }
471
DimScreen()472 void Lua_V1::DimScreen() {
473 g_driver->storeDisplay();
474 g_driver->dimScreen();
475 }
476
DimRegion()477 void Lua_V1::DimRegion() {
478 int x = (int)lua_getnumber(lua_getparam(1));
479 int y = (int)lua_getnumber(lua_getparam(2));
480 int w = (int)lua_getnumber(lua_getparam(3));
481 int h = (int)lua_getnumber(lua_getparam(4));
482 float level = lua_getnumber(lua_getparam(5));
483 g_driver->dimRegion(x, y, w, h, level);
484 }
485
ScreenShot()486 void Lua_V1::ScreenShot() {
487 int width = (int)lua_getnumber(lua_getparam(1));
488 int height = (int)lua_getnumber(lua_getparam(2));
489 GrimEngine::EngineMode mode = g_grim->getMode();
490 g_grim->setMode(GrimEngine::NormalMode);
491 g_grim->updateDisplayScene();
492 Bitmap *screenshot = g_driver->getScreenshot(width, height, false);
493 g_grim->setMode(mode);
494 if (screenshot) {
495 lua_pushusertag(screenshot->getId(), MKTAG('V','B','U','F'));
496 } else {
497 lua_pushnil();
498 }
499 }
500
SetGamma()501 void Lua_V1::SetGamma() {
502 lua_Object levelObj = lua_getparam(1);
503
504 if (!lua_isnumber(levelObj))
505 return;
506 double level = lua_getnumber(levelObj);
507
508 // FIXME: func(level)
509 warning("Lua_V1::SetGamma, implement opcode, level: %f", level);
510 }
511
Display()512 void Lua_V1::Display() {
513 if (g_grim->getFlipEnable()) {
514 g_driver->flipBuffer();
515 }
516 }
517
EngineDisplay()518 void Lua_V1::EngineDisplay() {
519 // it enable/disable updating display
520 g_grim->setFlipEnable((bool)lua_getnumber(lua_getparam(1)));
521 }
522
ForceRefresh()523 void Lua_V1::ForceRefresh() {
524 // Nothing to do, no off-screen buffers
525 }
526
RenderModeUser()527 void Lua_V1::RenderModeUser() {
528 lua_Object param1 = lua_getparam(1);
529 if (!lua_isnil(param1) && g_grim->getMode() != GrimEngine::DrawMode) {
530 g_grim->setPreviousMode(g_grim->getMode());
531 g_movie->pause(true);
532 g_grim->setMode(GrimEngine::DrawMode);
533 } else if (lua_isnil(param1) && g_grim->getMode() == GrimEngine::DrawMode) {
534 g_movie->pause(false);
535 g_grim->setMode(g_grim->getPreviousMode());
536 }
537 }
538
IrisUp()539 void Lua_V1::IrisUp() {
540 lua_Object xObj = lua_getparam(1);
541 lua_Object yObj = lua_getparam(2);
542 lua_Object timeObj = lua_getparam(3);
543
544 g_grim->playIrisAnimation(Iris::Open, (int)lua_getnumber(xObj), (int)lua_getnumber(yObj), (int)lua_getnumber(timeObj));
545 }
546
IrisDown()547 void Lua_V1::IrisDown() {
548 lua_Object xObj = lua_getparam(1);
549 lua_Object yObj = lua_getparam(2);
550 lua_Object timeObj = lua_getparam(3);
551
552 g_grim->playIrisAnimation(Iris::Close, (int)lua_getnumber(xObj), (int)lua_getnumber(yObj), (int)lua_getnumber(timeObj));
553 }
554
PreRender()555 void Lua_V1::PreRender() {
556 g_driver->renderBitmaps(getbool(1));
557 g_driver->renderZBitmaps(getbool(2));
558 }
559
560 } // end of namespace Grim
561