this repo has no description
1// MIT License
2
3// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
4
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23#include "core/core.h"
24
25#include <stdlib.h>
26#include <lua.h>
27#include <lauxlib.h>
28#include <lualib.h>
29#include <ctype.h>
30
31extern bool parse_note(const char* noteStr, s32* note, s32* octave);
32
33static inline s32 getLuaNumber(lua_State* lua, s32 index)
34{
35 return (s32)lua_tonumber(lua, index);
36}
37
38static void registerLuaFunction(tic_core* core, lua_CFunction func, const char *name)
39{
40 lua_pushlightuserdata(core->currentVM, core);
41 lua_pushcclosure(core->currentVM, func, 1);
42 lua_setglobal(core->currentVM, name);
43}
44
45static tic_core* getLuaCore(lua_State* lua)
46{
47 tic_core* core = lua_touserdata(lua, lua_upvalueindex(1));
48 return core;
49}
50
51static s32 lua_peek(lua_State* lua)
52{
53 s32 top = lua_gettop(lua);
54 tic_core* core = getLuaCore(lua);
55 tic_mem* tic = (tic_mem*)core;
56
57 if(top >= 1)
58 {
59 s32 address = getLuaNumber(lua, 1);
60 s32 bits = BITS_IN_BYTE;
61
62 if(top == 2)
63 bits = getLuaNumber(lua, 2);
64
65 lua_pushinteger(lua, core->api.peek(tic, address, bits));
66 return 1;
67 }
68 else luaL_error(lua, "invalid parameters, peek(addr,bits)\n");
69
70 return 0;
71}
72
73static s32 lua_poke(lua_State* lua)
74{
75 s32 top = lua_gettop(lua);
76 tic_core* core = getLuaCore(lua);
77 tic_mem* tic = (tic_mem*)core;
78
79 if(top >= 2)
80 {
81 s32 address = getLuaNumber(lua, 1);
82 u8 value = getLuaNumber(lua, 2);
83 s32 bits = BITS_IN_BYTE;
84
85 if(top == 3)
86 bits = getLuaNumber(lua, 3);
87
88 core->api.poke(tic, address, value, bits);
89 }
90 else luaL_error(lua, "invalid parameters, poke(addr,val,bits)\n");
91
92 return 0;
93}
94
95static s32 lua_peek1(lua_State* lua)
96{
97 s32 top = lua_gettop(lua);
98 tic_core* core = getLuaCore(lua);
99 tic_mem* tic = (tic_mem*)core;
100
101 if(top == 1)
102 {
103 s32 address = getLuaNumber(lua, 1);
104 lua_pushinteger(lua, core->api.peek1(tic, address));
105 return 1;
106 }
107 else luaL_error(lua, "invalid parameters, peek1(addr)\n");
108
109 return 0;
110}
111
112static s32 lua_poke1(lua_State* lua)
113{
114 s32 top = lua_gettop(lua);
115 tic_core* core = getLuaCore(lua);
116 tic_mem* tic = (tic_mem*)core;
117
118 if(top == 2)
119 {
120 s32 address = getLuaNumber(lua, 1);
121 u8 value = getLuaNumber(lua, 2);
122
123 core->api.poke1(tic, address, value);
124 }
125 else luaL_error(lua, "invalid parameters, poke1(addr,val)\n");
126
127 return 0;
128}
129
130static s32 lua_peek2(lua_State* lua)
131{
132 s32 top = lua_gettop(lua);
133 tic_core* core = getLuaCore(lua);
134 tic_mem* tic = (tic_mem*)core;
135
136 if(top == 1)
137 {
138 s32 address = getLuaNumber(lua, 1);
139 lua_pushinteger(lua, core->api.peek2(tic, address));
140 return 1;
141 }
142 else luaL_error(lua, "invalid parameters, peek2(addr)\n");
143
144 return 0;
145}
146
147static s32 lua_poke2(lua_State* lua)
148{
149 s32 top = lua_gettop(lua);
150 tic_core* core = getLuaCore(lua);
151 tic_mem* tic = (tic_mem*)core;
152
153 if(top == 2)
154 {
155 s32 address = getLuaNumber(lua, 1);
156 u8 value = getLuaNumber(lua, 2);
157
158 core->api.poke2(tic, address, value);
159 }
160 else luaL_error(lua, "invalid parameters, poke2(addr,val)\n");
161
162 return 0;
163}
164
165static s32 lua_peek4(lua_State* lua)
166{
167 s32 top = lua_gettop(lua);
168 tic_core* core = getLuaCore(lua);
169 tic_mem* tic = (tic_mem*)core;
170
171 if(top == 1)
172 {
173 s32 address = getLuaNumber(lua, 1);
174 lua_pushinteger(lua, core->api.peek4(tic, address));
175 return 1;
176 }
177 else luaL_error(lua, "invalid parameters, peek4(addr)\n");
178
179 return 0;
180}
181
182static s32 lua_poke4(lua_State* lua)
183{
184 s32 top = lua_gettop(lua);
185 tic_core* core = getLuaCore(lua);
186 tic_mem* tic = (tic_mem*)core;
187
188 if(top == 2)
189 {
190 s32 address = getLuaNumber(lua, 1);
191 u8 value = getLuaNumber(lua, 2);
192
193 core->api.poke4(tic, address, value);
194 }
195 else luaL_error(lua, "invalid parameters, poke4(addr,val)\n");
196
197 return 0;
198}
199
200static s32 lua_cls(lua_State* lua)
201{
202 s32 top = lua_gettop(lua);
203
204 tic_core* core = getLuaCore(lua);
205 tic_mem* tic = (tic_mem*)core;
206
207 core->api.cls(tic, top == 1 ? getLuaNumber(lua, 1) : 0);
208
209 return 0;
210}
211
212static s32 lua_paint(lua_State* lua)
213{
214 s32 top = lua_gettop(lua);
215
216 if(top >= 3 && top <= 4)
217 {
218 s32 x = getLuaNumber(lua, 1);
219 s32 y = getLuaNumber(lua, 2);
220 s32 color = getLuaNumber(lua, 3);
221 s32 bordercolor = top >= 4 ? getLuaNumber(lua, 4) : -1;
222
223 tic_core* core = getLuaCore(lua);
224 tic_mem* tic = (tic_mem*)core;
225
226 core->api.paint(tic, x, y, color, bordercolor);
227 }
228 else luaL_error(lua, "invalid parameters, paint(x y color [bordercolor])\n");
229
230 return 0;
231}
232
233static s32 lua_pix(lua_State* lua)
234{
235 s32 top = lua_gettop(lua);
236
237 if(top >= 2)
238 {
239 s32 x = getLuaNumber(lua, 1);
240 s32 y = getLuaNumber(lua, 2);
241
242 tic_core* core = getLuaCore(lua);
243 tic_mem* tic = (tic_mem*)core;
244
245 if(top >= 3)
246 {
247 s32 color = getLuaNumber(lua, 3);
248 core->api.pix(tic, x, y, color, false);
249 }
250 else
251 {
252 lua_pushinteger(lua, core->api.pix(tic, x, y, 0, true));
253 return 1;
254 }
255
256 }
257 else luaL_error(lua, "invalid parameters, pix(x y [color])\n");
258
259 return 0;
260}
261
262static s32 lua_line(lua_State* lua)
263{
264 s32 top = lua_gettop(lua);
265
266 if(top == 5)
267 {
268 float x0 = lua_tonumber(lua, 1);
269 float y0 = lua_tonumber(lua, 2);
270 float x1 = lua_tonumber(lua, 3);
271 float y1 = lua_tonumber(lua, 4);
272 s32 color = getLuaNumber(lua, 5);
273
274 tic_core* core = getLuaCore(lua);
275 tic_mem* tic = (tic_mem*)core;
276
277 core->api.line(tic, x0, y0, x1, y1, color);
278 }
279 else luaL_error(lua, "invalid parameters, line(x0,y0,x1,y1,color)\n");
280
281 return 0;
282}
283
284static s32 lua_rect(lua_State* lua)
285{
286 s32 top = lua_gettop(lua);
287
288 if(top == 5)
289 {
290 s32 x = getLuaNumber(lua, 1);
291 s32 y = getLuaNumber(lua, 2);
292 s32 w = getLuaNumber(lua, 3);
293 s32 h = getLuaNumber(lua, 4);
294 s32 color = getLuaNumber(lua, 5);
295
296 tic_core* core = getLuaCore(lua);
297 tic_mem* tic = (tic_mem*)core;
298
299 core->api.rect(tic, x, y, w, h, color);
300 }
301 else luaL_error(lua, "invalid parameters, rect(x,y,w,h,color)\n");
302
303 return 0;
304}
305
306static s32 lua_rectb(lua_State* lua)
307{
308 s32 top = lua_gettop(lua);
309
310 if(top == 5)
311 {
312 s32 x = getLuaNumber(lua, 1);
313 s32 y = getLuaNumber(lua, 2);
314 s32 w = getLuaNumber(lua, 3);
315 s32 h = getLuaNumber(lua, 4);
316 s32 color = getLuaNumber(lua, 5);
317
318 tic_core* core = getLuaCore(lua);
319 tic_mem* tic = (tic_mem*)core;
320
321 core->api.rectb(tic, x, y, w, h, color);
322 }
323 else luaL_error(lua, "invalid parameters, rectb(x,y,w,h,color)\n");
324
325 return 0;
326}
327
328static s32 lua_circ(lua_State* lua)
329{
330 s32 top = lua_gettop(lua);
331
332 if(top == 4)
333 {
334 tic_core* core = getLuaCore(lua);
335 tic_mem* tic = (tic_mem*)core;
336
337 s32 x = getLuaNumber(lua, 1);
338 s32 y = getLuaNumber(lua, 2);
339 s32 radius = getLuaNumber(lua, 3);
340 s32 color = getLuaNumber(lua, 4);
341
342 core->api.circ(tic, x, y, radius, color);
343 }
344 else luaL_error(lua, "invalid parameters, circ(x,y,radius,color)\n");
345
346 return 0;
347}
348
349static s32 lua_circb(lua_State* lua)
350{
351 s32 top = lua_gettop(lua);
352
353 if(top == 4)
354 {
355 tic_core* core = getLuaCore(lua);
356 tic_mem* tic = (tic_mem*)core;
357
358 s32 x = getLuaNumber(lua, 1);
359 s32 y = getLuaNumber(lua, 2);
360 s32 radius = getLuaNumber(lua, 3);
361 s32 color = getLuaNumber(lua, 4);
362
363 core->api.circb(tic, x, y, radius, color);
364 }
365 else luaL_error(lua, "invalid parameters, circb(x,y,radius,color)\n");
366
367 return 0;
368}
369
370static s32 lua_elli(lua_State* lua)
371{
372 s32 top = lua_gettop(lua);
373
374 if(top == 5)
375 {
376 tic_core* core = getLuaCore(lua);
377 tic_mem* tic = (tic_mem*)core;
378
379 s32 x = getLuaNumber(lua, 1);
380 s32 y = getLuaNumber(lua, 2);
381 s32 a = getLuaNumber(lua, 3);
382 s32 b = getLuaNumber(lua, 4);
383 s32 color = getLuaNumber(lua, 5);
384
385 core->api.elli(tic, x, y, a, b, color);
386 }
387 else luaL_error(lua, "invalid parameters, elli(x,y,a,b,color)\n");
388
389 return 0;
390}
391
392static s32 lua_ellib(lua_State* lua)
393{
394 s32 top = lua_gettop(lua);
395
396 if(top == 5)
397 {
398 tic_core* core = getLuaCore(lua);
399 tic_mem* tic = (tic_mem*)core;
400
401 s32 x = getLuaNumber(lua, 1);
402 s32 y = getLuaNumber(lua, 2);
403 s32 a = getLuaNumber(lua, 3);
404 s32 b = getLuaNumber(lua, 4);
405 s32 color = getLuaNumber(lua, 5);
406
407 core->api.ellib(tic, x, y, a, b, color);
408 }
409 else luaL_error(lua, "invalid parameters, ellib(x,y,a,b,color)\n");
410
411 return 0;
412}
413
414static s32 lua_tri(lua_State* lua)
415{
416 s32 top = lua_gettop(lua);
417
418 if(top == 7)
419 {
420 float pt[6];
421
422 for(s32 i = 0; i < COUNT_OF(pt); i++)
423 pt[i] = lua_tonumber(lua, i+1);
424
425 s32 color = getLuaNumber(lua, 7);
426
427 tic_core* core = getLuaCore(lua);
428 tic_mem* tic = (tic_mem*)core;
429
430 core->api.tri(tic, pt[0], pt[1], pt[2], pt[3], pt[4], pt[5], color);
431 }
432 else luaL_error(lua, "invalid parameters, tri(x1,y1,x2,y2,x3,y3,color)\n");
433
434 return 0;
435}
436
437static s32 lua_trib(lua_State* lua)
438{
439 s32 top = lua_gettop(lua);
440
441 if(top == 7)
442 {
443 float pt[6];
444
445 for(s32 i = 0; i < COUNT_OF(pt); i++)
446 pt[i] = lua_tonumber(lua, i+1);
447
448 s32 color = getLuaNumber(lua, 7);
449
450 tic_core* core = getLuaCore(lua);
451 tic_mem* tic = (tic_mem*)core;
452
453 core->api.trib(tic, pt[0], pt[1], pt[2], pt[3], pt[4], pt[5], color);
454 }
455 else luaL_error(lua, "invalid parameters, trib(x1,y1,x2,y2,x3,y3,color)\n");
456
457 return 0;
458}
459
460#if defined(BUILD_DEPRECATED)
461
462static s32 lua_textri(lua_State* lua)
463{
464 s32 top = lua_gettop(lua);
465
466 if (top >= 12)
467 {
468 float pt[12];
469
470 for (s32 i = 0; i < COUNT_OF(pt); i++)
471 pt[i] = (float)lua_tonumber(lua, i + 1);
472
473 tic_core* core = getLuaCore(lua);
474 tic_mem* tic = (tic_mem*)core;
475 static u8 colors[TIC_PALETTE_SIZE];
476 s32 count = 0;
477 bool use_map = false;
478
479 // check for use map
480 if (top >= 13)
481 use_map = lua_toboolean(lua, 13);
482
483 // check for chroma
484 if(top >= 14)
485 {
486 if(lua_istable(lua, 14))
487 {
488 for(s32 i = 1; i <= TIC_PALETTE_SIZE; i++)
489 {
490 lua_rawgeti(lua, 14, i);
491 if(lua_isnumber(lua, -1))
492 {
493 colors[i-1] = getLuaNumber(lua, -1);
494 count++;
495 lua_pop(lua, 1);
496 }
497 else
498 {
499 lua_pop(lua, 1);
500 break;
501 }
502 }
503 }
504 else
505 {
506 colors[0] = getLuaNumber(lua, 14);
507 count = 1;
508 }
509 }
510
511 core->api.textri(tic,
512 pt[0], pt[1], // xy 1
513 pt[2], pt[3], // xy 2
514 pt[4], pt[5], // xy 3
515 pt[6], pt[7], // uv 1
516 pt[8], pt[9], // uv 2
517 pt[10], pt[11], // uv 3
518 use_map, // use map
519 colors, count); // chroma
520 }
521
522 return 0;
523}
524
525#endif
526
527static s32 lua_ttri(lua_State* lua)
528{
529 s32 top = lua_gettop(lua);
530
531 if (top >= 12)
532 {
533 float pt[12];
534
535 for (s32 i = 0; i < COUNT_OF(pt); i++)
536 pt[i] = (float)lua_tonumber(lua, i + 1);
537
538 tic_core* core = getLuaCore(lua);
539 tic_mem* tic = (tic_mem*)core;
540 static u8 colors[TIC_PALETTE_SIZE];
541 s32 count = 0;
542 tic_texture_src src = tic_tiles_texture;
543
544 // check for texture src
545 if (top >= 13)
546 {
547 src = lua_isboolean(lua, 13)
548 ? (lua_toboolean(lua, 13) ? tic_map_texture : tic_tiles_texture)
549 : lua_tointeger(lua, 13);
550 }
551 // check for chroma
552 if(top >= 14)
553 {
554 if(lua_istable(lua, 14))
555 {
556 for(s32 i = 1; i <= TIC_PALETTE_SIZE; i++)
557 {
558 lua_rawgeti(lua, 14, i);
559 if(lua_isnumber(lua, -1))
560 {
561 colors[i-1] = getLuaNumber(lua, -1);
562 count++;
563 lua_pop(lua, 1);
564 }
565 else
566 {
567 lua_pop(lua, 1);
568 break;
569 }
570 }
571 }
572 else
573 {
574 colors[0] = getLuaNumber(lua, 14);
575 count = 1;
576 }
577 }
578
579 float z[3] = {0, 0, 0};
580 bool depth = false;
581
582 if(top == 17)
583 {
584 for (s32 i = 0; i < COUNT_OF(z); i++)
585 z[i] = (float)lua_tonumber(lua, i + 15);
586
587 depth = true;
588 }
589
590 core->api.ttri(tic, pt[0], pt[1], // xy 1
591 pt[2], pt[3], // xy 2
592 pt[4], pt[5], // xy 3
593 pt[6], pt[7], // uv 1
594 pt[8], pt[9], // uv 2
595 pt[10], pt[11], // uv 3
596 src, // texture source
597 colors, count, // chroma
598 z[0], z[1], z[2], depth); // depth
599 }
600 else luaL_error(lua, "invalid parameters, ttri(x1,y1,x2,y2,x3,y3,u1,v1,u2,v2,u3,v3,[src=0],[chroma=off],[z1=0],[z2=0],[z3=0])\n");
601 return 0;
602}
603
604
605static s32 lua_clip(lua_State* lua)
606{
607 s32 top = lua_gettop(lua);
608
609 if(top == 0)
610 {
611 tic_core* core = getLuaCore(lua);
612 tic_mem* tic = (tic_mem*)core;
613
614 core->api.clip(tic, 0, 0, TIC80_WIDTH, TIC80_HEIGHT);
615 }
616 else if(top == 4)
617 {
618 s32 x = getLuaNumber(lua, 1);
619 s32 y = getLuaNumber(lua, 2);
620 s32 w = getLuaNumber(lua, 3);
621 s32 h = getLuaNumber(lua, 4);
622
623 tic_core* core = getLuaCore(lua);
624 tic_mem* tic = (tic_mem*)core;
625
626 core->api.clip((tic_mem*)getLuaCore(lua), x, y, w, h);
627 }
628 else luaL_error(lua, "invalid parameters, use clip(x,y,w,h) or clip()\n");
629
630 return 0;
631}
632
633static s32 lua_btnp(lua_State* lua)
634{
635 tic_core* core = getLuaCore(lua);
636 tic_mem* tic = (tic_mem*)core;
637
638 s32 top = lua_gettop(lua);
639
640 if (top == 0)
641 {
642 lua_pushinteger(lua, core->api.btnp(tic, -1, -1, -1));
643 }
644 else if(top == 1)
645 {
646 s32 index = getLuaNumber(lua, 1) & 0x1f;
647
648 lua_pushboolean(lua, core->api.btnp(tic, index, -1, -1));
649 }
650 else if (top == 3)
651 {
652 s32 index = getLuaNumber(lua, 1) & 0x1f;
653 u32 hold = getLuaNumber(lua, 2);
654 u32 period = getLuaNumber(lua, 3);
655
656 lua_pushboolean(lua, core->api.btnp(tic, index, hold, period));
657 }
658 else
659 {
660 luaL_error(lua, "invalid params, btnp [ id [ hold period ] ]\n");
661 return 0;
662 }
663
664 return 1;
665}
666
667static s32 lua_btn(lua_State* lua)
668{
669 tic_core* core = getLuaCore(lua);
670 tic_mem* tic = (tic_mem*)core;
671
672 s32 top = lua_gettop(lua);
673
674 if (top == 0)
675 {
676 lua_pushinteger(lua, core->api.btn(tic, -1));
677 }
678 else if (top == 1)
679 {
680 bool pressed = core->api.btn(tic, getLuaNumber(lua, 1) & 0x1f);
681 lua_pushboolean(lua, pressed);
682 }
683 else
684 {
685 luaL_error(lua, "invalid params, btn [ id ]\n");
686 return 0;
687 }
688
689 return 1;
690}
691
692static s32 lua_spr(lua_State* lua)
693{
694 s32 top = lua_gettop(lua);
695
696 s32 index = 0;
697 s32 x = 0;
698 s32 y = 0;
699 s32 w = 1;
700 s32 h = 1;
701 s32 scale = 1;
702 tic_flip flip = tic_no_flip;
703 tic_rotate rotate = tic_no_rotate;
704 static u8 colors[TIC_PALETTE_SIZE];
705 s32 count = 0;
706
707 if(top >= 1)
708 {
709 index = getLuaNumber(lua, 1);
710
711 if(top >= 3)
712 {
713 x = getLuaNumber(lua, 2);
714 y = getLuaNumber(lua, 3);
715
716 if(top >= 4)
717 {
718 if(lua_istable(lua, 4))
719 {
720 for(s32 i = 1; i <= TIC_PALETTE_SIZE; i++)
721 {
722 lua_rawgeti(lua, 4, i);
723 if(lua_isnumber(lua, -1))
724 {
725 colors[i-1] = getLuaNumber(lua, -1);
726 count++;
727 lua_pop(lua, 1);
728 }
729 else
730 {
731 lua_pop(lua, 1);
732 break;
733 }
734 }
735 }
736 else
737 {
738 colors[0] = getLuaNumber(lua, 4);
739 count = 1;
740 }
741
742 if(top >= 5)
743 {
744 scale = getLuaNumber(lua, 5);
745
746 if(top >= 6)
747 {
748 flip = getLuaNumber(lua, 6);
749
750 if(top >= 7)
751 {
752 rotate = getLuaNumber(lua, 7);
753
754 if(top >= 9)
755 {
756 w = getLuaNumber(lua, 8);
757 h = getLuaNumber(lua, 9);
758 }
759 }
760 }
761 }
762 }
763 }
764 }
765
766 tic_core* core = getLuaCore(lua);
767 tic_mem* tic = (tic_mem*)core;
768
769 core->api.spr(tic, index, x, y, w, h, colors, count, scale, flip, rotate);
770
771 return 0;
772}
773
774static s32 lua_mget(lua_State* lua)
775{
776 s32 top = lua_gettop(lua);
777
778 if(top == 2)
779 {
780 s32 x = getLuaNumber(lua, 1);
781 s32 y = getLuaNumber(lua, 2);
782
783 tic_core* core = getLuaCore(lua);
784 tic_mem* tic = (tic_mem*)core;
785
786 u8 value = core->api.mget(tic, x, y);
787 lua_pushinteger(lua, value);
788 return 1;
789 }
790 else luaL_error(lua, "invalid params, mget(x,y)\n");
791
792 return 0;
793}
794
795static s32 lua_mset(lua_State* lua)
796{
797 s32 top = lua_gettop(lua);
798
799 if(top == 3)
800 {
801 s32 x = getLuaNumber(lua, 1);
802 s32 y = getLuaNumber(lua, 2);
803 u8 val = getLuaNumber(lua, 3);
804
805 tic_core* core = getLuaCore(lua);
806 tic_mem* tic = (tic_mem*)core;
807
808 core->api.mset(tic, x, y, val);
809 }
810 else luaL_error(lua, "invalid params, mget(x,y)\n");
811
812 return 0;
813}
814
815typedef struct
816{
817 lua_State* lua;
818 s32 reg;
819} RemapData;
820
821static void remapCallback(void* data, s32 x, s32 y, RemapResult* result)
822{
823 RemapData* remap = (RemapData*)data;
824 lua_State* lua = remap->lua;
825
826 lua_rawgeti(lua, LUA_REGISTRYINDEX, remap->reg);
827 lua_pushinteger(lua, result->index);
828 lua_pushinteger(lua, x);
829 lua_pushinteger(lua, y);
830 lua_pcall(lua, 3, 3, 0);
831
832 result->index = getLuaNumber(lua, -3);
833 result->flip = getLuaNumber(lua, -2);
834 result->rotate = getLuaNumber(lua, -1);
835}
836
837static s32 lua_map(lua_State* lua)
838{
839 s32 x = 0;
840 s32 y = 0;
841 s32 w = TIC_MAP_SCREEN_WIDTH;
842 s32 h = TIC_MAP_SCREEN_HEIGHT;
843 s32 sx = 0;
844 s32 sy = 0;
845 s32 scale = 1;
846 static u8 colors[TIC_PALETTE_SIZE];
847 s32 count = 0;
848
849 s32 top = lua_gettop(lua);
850
851 if(top >= 2)
852 {
853 x = getLuaNumber(lua, 1);
854 y = getLuaNumber(lua, 2);
855
856 if(top >= 4)
857 {
858 w = getLuaNumber(lua, 3);
859 h = getLuaNumber(lua, 4);
860
861 if(top >= 6)
862 {
863 sx = getLuaNumber(lua, 5);
864 sy = getLuaNumber(lua, 6);
865
866 if(top >= 7)
867 {
868 if(lua_istable(lua, 7))
869 {
870 for(s32 i = 1; i <= TIC_PALETTE_SIZE; i++)
871 {
872 lua_rawgeti(lua, 7, i);
873 if(lua_isnumber(lua, -1))
874 {
875 colors[i-1] = getLuaNumber(lua, -1);
876 count++;
877 lua_pop(lua, 1);
878 }
879 else
880 {
881 lua_pop(lua, 1);
882 break;
883 }
884 }
885 }
886 else
887 {
888 colors[0] = getLuaNumber(lua, 7);
889 count = 1;
890 }
891
892 if(top >= 8)
893 {
894 scale = getLuaNumber(lua, 8);
895
896 if(top >= 9)
897 {
898 if (lua_isfunction(lua, 9))
899 {
900 s32 remap = luaL_ref(lua, LUA_REGISTRYINDEX);
901
902 RemapData data = {lua, remap};
903
904 tic_core* core = getLuaCore(lua);
905 tic_mem* tic = (tic_mem*)core;
906
907 core->api.map(tic, x, y, w, h, sx, sy, colors, count, scale, remapCallback, &data);
908
909 luaL_unref(lua, LUA_REGISTRYINDEX, data.reg);
910
911 return 0;
912 }
913 }
914 }
915 }
916 }
917 }
918 }
919
920 tic_core* core = getLuaCore(lua);
921 tic_mem* tic = (tic_mem*)core;
922
923 core->api.map((tic_mem*)getLuaCore(lua), x, y, w, h, sx, sy, colors, count, scale, NULL, NULL);
924
925 return 0;
926}
927
928static s32 lua_music(lua_State* lua)
929{
930 s32 top = lua_gettop(lua);
931 tic_core* core = getLuaCore(lua);
932 tic_mem* tic = (tic_mem*)core;
933
934 if(top == 0) core->api.music(tic, -1, 0, 0, false, false, -1, -1);
935 else if(top >= 1)
936 {
937 s32 track = getLuaNumber(lua, 1);
938
939 if(track > MUSIC_TRACKS - 1)
940 {
941 luaL_error(lua, "invalid music track index");
942 return 0;
943 }
944
945 core->api.music(tic, -1, 0, 0, false, false, -1, -1);
946
947 s32 frame = -1;
948 s32 row = -1;
949 bool loop = true;
950 bool sustain = false;
951 s32 tempo = -1;
952 s32 speed = -1;
953
954 if(top >= 2)
955 {
956 frame = getLuaNumber(lua, 2);
957
958 if(top >= 3)
959 {
960 row = getLuaNumber(lua, 3);
961
962 if(top >= 4)
963 {
964 loop = lua_toboolean(lua, 4);
965
966 if (top >= 5)
967 {
968 sustain = lua_toboolean(lua, 5);
969
970 if (top >= 6)
971 {
972 tempo = getLuaNumber(lua, 6);
973
974 if (top >= 7)
975 {
976 speed = getLuaNumber(lua, 7);
977 }
978 }
979 }
980
981 }
982 }
983 }
984
985 core->api.music(tic, track, frame, row, loop, sustain, tempo, speed);
986 }
987 else luaL_error(lua, "invalid params, use music(track)\n");
988
989 return 0;
990}
991
992static s32 lua_sfx(lua_State* lua)
993{
994 s32 top = lua_gettop(lua);
995
996 if(top >= 1)
997 {
998 tic_core* core = getLuaCore(lua);
999 tic_mem* tic = (tic_mem*)core;
1000
1001 s32 note = -1;
1002 s32 octave = -1;
1003 s32 duration = -1;
1004 s32 channel = 0;
1005 s32 volumes[TIC80_SAMPLE_CHANNELS] = {MAX_VOLUME, MAX_VOLUME};
1006 s32 speed = SFX_DEF_SPEED;
1007
1008 s32 index = getLuaNumber(lua, 1);
1009
1010 if(index < SFX_COUNT)
1011 {
1012 if (index >= 0)
1013 {
1014 tic_sample* effect = tic->ram->sfx.samples.data + index;
1015
1016 note = effect->note;
1017 octave = effect->octave;
1018 speed = effect->speed;
1019 }
1020
1021 if(top >= 2)
1022 {
1023 if(lua_isinteger(lua, 2))
1024 {
1025 s32 id = getLuaNumber(lua, 2);
1026 note = id % NOTES;
1027 octave = id / NOTES;
1028 }
1029 else if(lua_isstring(lua, 2))
1030 {
1031 const char* noteStr = lua_tostring(lua, 2);
1032
1033 if(!parse_note(noteStr, ¬e, &octave))
1034 {
1035 luaL_error(lua, "invalid note, should be like C#4\n");
1036 return 0;
1037 }
1038 }
1039
1040 if(top >= 3)
1041 {
1042 duration = getLuaNumber(lua, 3);
1043
1044 if(top >= 4)
1045 {
1046 channel = getLuaNumber(lua, 4);
1047
1048 if(top >= 5)
1049 {
1050 if(lua_istable(lua, 5))
1051 {
1052 for(s32 i = 0; i < COUNT_OF(volumes); i++)
1053 {
1054 volumes[i] = lua_rawgeti(lua, 5, i + 1);
1055 lua_pop(lua, 1);
1056 }
1057 }
1058 else volumes[0] = volumes[1] = getLuaNumber(lua, 5);
1059
1060 if(top >= 6)
1061 {
1062 speed = getLuaNumber(lua, 6);
1063 }
1064 }
1065 }
1066 }
1067 }
1068
1069 if (channel >= 0 && channel < TIC_SOUND_CHANNELS)
1070 {
1071 core->api.sfx(tic, index, note, octave, duration, channel, volumes[0] & 0xf, volumes[1] & 0xf, speed);
1072 }
1073 else luaL_error(lua, "unknown channel\n");
1074 }
1075 else luaL_error(lua, "unknown sfx index\n");
1076 }
1077 else luaL_error(lua, "invalid sfx params\n");
1078
1079 return 0;
1080}
1081
1082static s32 lua_vbank(lua_State* lua)
1083{
1084 tic_core* core = getLuaCore(lua);
1085 tic_mem* tic = (tic_mem*)core;
1086
1087 s32 prev = core->state.vbank.id;
1088
1089 if(lua_gettop(lua) == 1)
1090 core->api.vbank(tic, getLuaNumber(lua, 1));
1091
1092 lua_pushinteger(lua, prev);
1093 return 1;
1094}
1095
1096static s32 lua_sync(lua_State* lua)
1097{
1098 tic_core* core = getLuaCore(lua);
1099 tic_mem* tic = (tic_mem*)core;
1100
1101 bool toCart = false;
1102 u32 mask = 0;
1103 s32 bank = 0;
1104
1105 if(lua_gettop(lua) >= 1)
1106 {
1107 mask = getLuaNumber(lua, 1);
1108
1109 if(lua_gettop(lua) >= 2)
1110 {
1111 bank = getLuaNumber(lua, 2);
1112
1113 if(lua_gettop(lua) >= 3)
1114 {
1115 toCart = lua_toboolean(lua, 3);
1116 }
1117 }
1118 }
1119
1120 if(bank >= 0 && bank < TIC_BANKS)
1121 core->api.sync(tic, mask, bank, toCart);
1122 else
1123 luaL_error(lua, "sync() error, invalid bank");
1124
1125 return 0;
1126}
1127
1128static s32 lua_reset(lua_State* lua)
1129{
1130 tic_core* core = getLuaCore(lua);
1131
1132 core->state.initialized = false;
1133
1134 return 0;
1135}
1136
1137static s32 lua_key(lua_State* lua)
1138{
1139 tic_core* core = getLuaCore(lua);
1140 tic_mem* tic = &core->memory;
1141
1142 s32 top = lua_gettop(lua);
1143
1144 if (top == 0)
1145 {
1146 lua_pushboolean(lua, core->api.key(tic, tic_key_unknown));
1147 }
1148 else if (top == 1)
1149 {
1150 tic_key key = getLuaNumber(lua, 1);
1151
1152 if(key < tic_keys_count)
1153 lua_pushboolean(lua, core->api.key(tic, key));
1154 else
1155 {
1156 luaL_error(lua, "unknown keyboard code\n");
1157 return 0;
1158 }
1159 }
1160 else
1161 {
1162 luaL_error(lua, "invalid params, key [code]\n");
1163 return 0;
1164 }
1165
1166 return 1;
1167}
1168
1169static s32 lua_keyp(lua_State* lua)
1170{
1171 tic_core* core = getLuaCore(lua);
1172 tic_mem* tic = &core->memory;
1173
1174 s32 top = lua_gettop(lua);
1175
1176 if (top == 0)
1177 {
1178 lua_pushboolean(lua, core->api.keyp(tic, tic_key_unknown, -1, -1));
1179 }
1180 else
1181 {
1182 tic_key key = getLuaNumber(lua, 1);
1183
1184 if(key >= tic_keys_count)
1185 {
1186 luaL_error(lua, "unknown keyboard code\n");
1187 }
1188 else
1189 {
1190 if(top == 1)
1191 {
1192 lua_pushboolean(lua, core->api.keyp(tic, key, -1, -1));
1193 }
1194 else if(top == 3)
1195 {
1196 u32 hold = getLuaNumber(lua, 2);
1197 u32 period = getLuaNumber(lua, 3);
1198
1199 lua_pushboolean(lua, core->api.keyp(tic, key, hold, period));
1200 }
1201 else
1202 {
1203 luaL_error(lua, "invalid params, keyp [ code [ hold period ] ]\n");
1204 return 0;
1205 }
1206 }
1207 }
1208
1209 return 1;
1210}
1211
1212static s32 lua_memcpy(lua_State* lua)
1213{
1214 s32 top = lua_gettop(lua);
1215
1216 if(top == 3)
1217 {
1218 s32 dest = getLuaNumber(lua, 1);
1219 s32 src = getLuaNumber(lua, 2);
1220 s32 size = getLuaNumber(lua, 3);
1221
1222 tic_core* core = getLuaCore(lua);
1223 tic_mem* tic = (tic_mem*)core;
1224 core->api.memcpy(tic, dest, src, size);
1225 }
1226 else luaL_error(lua, "invalid params, memcpy(dest,src,size)\n");
1227
1228 return 0;
1229}
1230
1231static s32 lua_memset(lua_State* lua)
1232{
1233 s32 top = lua_gettop(lua);
1234
1235 if(top == 3)
1236 {
1237 s32 dest = getLuaNumber(lua, 1);
1238 u8 value = getLuaNumber(lua, 2);
1239 s32 size = getLuaNumber(lua, 3);
1240
1241 tic_core* core = getLuaCore(lua);
1242 tic_mem* tic = (tic_mem*)core;
1243
1244 core->api.memset(tic, dest, value, size);
1245 }
1246 else luaL_error(lua, "invalid params, memset(dest,val,size)\n");
1247
1248 return 0;
1249}
1250
1251static const char* printString(lua_State* lua, s32 index)
1252{
1253 lua_getglobal(lua, "tostring");
1254 lua_pushvalue(lua, -1);
1255 lua_pushvalue(lua, index);
1256 lua_call(lua, 1, 1);
1257
1258 const char* text = lua_tostring(lua, -1);
1259
1260 lua_pop(lua, 2);
1261
1262 return text;
1263}
1264
1265static s32 lua_font(lua_State* lua)
1266{
1267 tic_core* core = getLuaCore(lua);
1268 tic_mem* tic = (tic_mem*)core;
1269 s32 top = lua_gettop(lua);
1270
1271 if(top >= 1)
1272 {
1273 const char* text = printString(lua, 1);
1274 s32 x = 0;
1275 s32 y = 0;
1276 s32 width = TIC_SPRITESIZE;
1277 s32 height = TIC_SPRITESIZE;
1278 u8 chromakey = 0;
1279 bool fixed = false;
1280 s32 scale = 1;
1281 bool alt = false;
1282
1283 if(top >= 3)
1284 {
1285 x = getLuaNumber(lua, 2);
1286 y = getLuaNumber(lua, 3);
1287
1288 if(top >= 4)
1289 {
1290 chromakey = getLuaNumber(lua, 4);
1291
1292 if(top >= 6)
1293 {
1294 width = getLuaNumber(lua, 5);
1295 height = getLuaNumber(lua, 6);
1296
1297 if(top >= 7)
1298 {
1299 fixed = lua_toboolean(lua, 7);
1300
1301 if(top >= 8)
1302 {
1303 scale = getLuaNumber(lua, 8);
1304
1305 if(top >= 9)
1306 {
1307 alt = lua_toboolean(lua, 9);
1308 }
1309 }
1310 }
1311 }
1312 }
1313 }
1314
1315 if(scale == 0)
1316 {
1317 lua_pushinteger(lua, 0);
1318 return 1;
1319 }
1320
1321 s32 size = core->api.font(tic, text, x, y, &chromakey, 1, width, height, fixed, scale, alt);
1322
1323 lua_pushinteger(lua, size);
1324
1325 return 1;
1326 }
1327
1328 return 0;
1329}
1330
1331static s32 lua_print(lua_State* lua)
1332{
1333 s32 top = lua_gettop(lua);
1334
1335 if(top >= 1)
1336 {
1337 tic_core* core = getLuaCore(lua);
1338 tic_mem* tic = (tic_mem*)core;
1339
1340 s32 x = 0;
1341 s32 y = 0;
1342 s32 color = TIC_DEFAULT_COLOR;
1343 bool fixed = false;
1344 s32 scale = 1;
1345 bool alt = false;
1346
1347 const char* text = printString(lua, 1);
1348
1349 if(top >= 3)
1350 {
1351 x = getLuaNumber(lua, 2);
1352 y = getLuaNumber(lua, 3);
1353
1354 if(top >= 4)
1355 {
1356 color = getLuaNumber(lua, 4) % TIC_PALETTE_SIZE;
1357
1358 if(top >= 5)
1359 {
1360 fixed = lua_toboolean(lua, 5);
1361
1362 if(top >= 6)
1363 {
1364 scale = getLuaNumber(lua, 6);
1365
1366 if(top >= 7)
1367 {
1368 alt = lua_toboolean(lua, 7);
1369 }
1370 }
1371 }
1372 }
1373 }
1374
1375 if(scale == 0)
1376 {
1377 lua_pushinteger(lua, 0);
1378 return 1;
1379 }
1380
1381 s32 size = core->api.print(tic, text ? text : "nil", x, y, color, fixed, scale, alt);
1382
1383 lua_pushinteger(lua, size);
1384
1385 return 1;
1386 }
1387
1388 return 0;
1389}
1390
1391static s32 lua_trace(lua_State *lua)
1392{
1393 s32 top = lua_gettop(lua);
1394 tic_core* core = getLuaCore(lua);
1395 tic_mem* tic = (tic_mem*)core;
1396
1397 if(top >= 1)
1398 {
1399 const char* text = printString(lua, 1);
1400 u8 color = TIC_DEFAULT_COLOR;
1401
1402 if(top >= 2)
1403 {
1404 color = getLuaNumber(lua, 2);
1405 }
1406
1407 core->api.trace(tic, text, color);
1408 }
1409 else luaL_error(lua, "invalid params, trace(text,[color])\n");
1410
1411 return 0;
1412}
1413
1414static s32 lua_pmem(lua_State *lua)
1415{
1416 s32 top = lua_gettop(lua);
1417 tic_core* core = getLuaCore(lua);
1418 tic_mem* tic = &core->memory;
1419
1420 if(top >= 1)
1421 {
1422 u32 index = getLuaNumber(lua, 1);
1423
1424 if(index < TIC_PERSISTENT_SIZE)
1425 {
1426 u32 val = core->api.pmem(tic, index, 0, false);
1427
1428 if(top >= 2)
1429 {
1430 core->api.pmem(tic, index, (u32)lua_tointeger(lua, 2), true);
1431 }
1432
1433 lua_pushinteger(lua, val);
1434
1435 return 1;
1436 }
1437
1438 luaL_error(lua, "invalid persistent tic index\n");
1439 }
1440 else luaL_error(lua, "invalid params, pmem(index [val]) -> val\n");
1441
1442 return 0;
1443}
1444
1445static s32 lua_time(lua_State *lua)
1446{
1447 tic_core* core = getLuaCore(lua);
1448 tic_mem* tic = (tic_mem*)core;
1449
1450 lua_pushnumber(lua, core->api.time(tic));
1451
1452 return 1;
1453}
1454
1455static s32 lua_tstamp(lua_State *lua)
1456{
1457 tic_core* core = getLuaCore(lua);
1458 tic_mem* tic = (tic_mem*)core;
1459
1460 lua_pushnumber(lua, core->api.tstamp(tic));
1461
1462 return 1;
1463}
1464
1465static s32 lua_exit(lua_State *lua)
1466{
1467 tic_core* core = getLuaCore(lua);
1468 tic_mem* tic = (tic_mem*)core;
1469
1470 core->api.exit(tic);
1471
1472 return 0;
1473}
1474
1475static s32 lua_mouse(lua_State *lua)
1476{
1477 tic_core* core = getLuaCore(lua);
1478
1479 {
1480 tic_point pos = core->api.mouse((tic_mem*)core);
1481
1482 lua_pushinteger(lua, pos.x);
1483 lua_pushinteger(lua, pos.y);
1484 }
1485
1486 const tic80_mouse* mouse = &core->memory.ram->input.mouse;
1487
1488 lua_pushboolean(lua, mouse->left);
1489 lua_pushboolean(lua, mouse->middle);
1490 lua_pushboolean(lua, mouse->right);
1491 lua_pushinteger(lua, mouse->scrollx);
1492 lua_pushinteger(lua, mouse->scrolly);
1493
1494 return 7;
1495}
1496
1497static s32 lua_fget(lua_State* lua)
1498{
1499 tic_core* core = getLuaCore(lua);
1500 tic_mem* tic = (tic_mem*)core;
1501 s32 top = lua_gettop(lua);
1502
1503 if(top >= 1)
1504 {
1505 u32 index = getLuaNumber(lua, 1);
1506
1507 if(top >= 2)
1508 {
1509 u32 flag = getLuaNumber(lua, 2);
1510 lua_pushboolean(lua, core->api.fget(tic, index, flag));
1511 return 1;
1512 }
1513 }
1514
1515 luaL_error(lua, "invalid params, fget(sprite,flag)\n");
1516
1517 return 0;
1518}
1519
1520static s32 lua_fset(lua_State* lua)
1521{
1522 tic_core* core = getLuaCore(lua);
1523 tic_mem* tic = (tic_mem*)core;
1524 s32 top = lua_gettop(lua);
1525
1526 if(top >= 1)
1527 {
1528 u32 index = getLuaNumber(lua, 1);
1529
1530 if(top >= 2)
1531 {
1532 u32 flag = getLuaNumber(lua, 2);
1533
1534 if(top >= 3)
1535 {
1536 bool value = lua_toboolean(lua, 3);
1537 core->api.fset(tic, index, flag, value);
1538 return 0;
1539 }
1540 }
1541 }
1542
1543 luaL_error(lua, "invalid params, fset(sprite,flag,value)\n");
1544
1545 return 0;
1546}
1547
1548static s32 lua_fft(lua_State* lua)
1549{
1550 tic_core* core = getLuaCore(lua);
1551
1552 tic_mem* tic = (tic_mem*)getLuaCore(lua);
1553 s32 top = lua_gettop(lua);
1554
1555 if (top >= 1)
1556 {
1557 s32 start_freq = getLuaNumber(lua, 1);
1558 s32 end_freq = -1;
1559
1560 if (top >= 2)
1561 {
1562 end_freq = getLuaNumber(lua, 2);
1563 }
1564
1565 lua_pushnumber(lua, core->api.fft(tic, start_freq, end_freq));
1566 return 1;
1567 }
1568
1569 luaL_error(lua, "invalid params, fft(start_freq, end_freq=-1)\n");
1570 return 0;
1571}
1572
1573static s32 lua_ffts(lua_State* lua)
1574{
1575 tic_core* core = getLuaCore(lua);
1576
1577 tic_mem* tic = (tic_mem*)getLuaCore(lua);
1578 s32 top = lua_gettop(lua);
1579
1580 if (top >= 1)
1581 {
1582 s32 start_freq = getLuaNumber(lua, 1);
1583 s32 end_freq = -1;
1584
1585 if (top >= 2)
1586 {
1587 end_freq = getLuaNumber(lua, 2);
1588 }
1589
1590 lua_pushnumber(lua, core->api.ffts(tic, start_freq, end_freq));
1591 return 1;
1592 }
1593
1594 luaL_error(lua, "invalid params, ffts(start_freq, end_freq=-1)\n");
1595 return 0;
1596}
1597
1598static int lua_dofile(lua_State *lua)
1599{
1600 luaL_error(lua, "unknown method: \"dofile\"\n");
1601
1602 return 0;
1603}
1604
1605static int lua_loadfile(lua_State *lua)
1606{
1607 luaL_error(lua, "unknown method: \"loadfile\"\n");
1608
1609 return 0;
1610}
1611
1612void luaapi_open(lua_State *lua)
1613{
1614 static const luaL_Reg loadedlibs[] =
1615 {
1616 { "_G", luaopen_base },
1617 { LUA_LOADLIBNAME, luaopen_package },
1618 { LUA_COLIBNAME, luaopen_coroutine },
1619 { LUA_TABLIBNAME, luaopen_table },
1620 { LUA_STRLIBNAME, luaopen_string },
1621 { LUA_MATHLIBNAME, luaopen_math },
1622 { LUA_DBLIBNAME, luaopen_debug },
1623 { NULL, NULL }
1624 };
1625
1626 for (const luaL_Reg *lib = loadedlibs; lib->func; lib++)
1627 {
1628 luaL_requiref(lua, lib->name, lib->func, 1);
1629 lua_pop(lua, 1);
1630 }
1631}
1632
1633void luaapi_init(tic_core* core)
1634{
1635 static const struct{lua_CFunction func; const char* name;} ApiItems[] =
1636 {
1637#define API_FUNC_DEF(name, ...) {(lua_CFunction)(lua_ ## name), #name},
1638 TIC_API_LIST(API_FUNC_DEF)
1639#undef API_FUNC_DEF
1640
1641#if defined(BUILD_DEPRECATED)
1642 {(lua_CFunction)lua_textri, "textri"},
1643#endif
1644 };
1645
1646 for (s32 i = 0; i < COUNT_OF(ApiItems); i++)
1647 registerLuaFunction(core, ApiItems[i].func, ApiItems[i].name);
1648
1649 registerLuaFunction(core, lua_dofile, "dofile");
1650 registerLuaFunction(core, lua_loadfile, "loadfile");
1651}
1652
1653void luaapi_close(tic_mem* tic)
1654{
1655 tic_core* core = (tic_core*)tic;
1656
1657 if(core->currentVM)
1658 {
1659 lua_close(core->currentVM);
1660 core->currentVM = NULL;
1661 }
1662}
1663
1664/*
1665** Message handler which appends stract trace to exceptions.
1666** This function was extractred from lua.c.
1667*/
1668static int msghandler (lua_State *lua)
1669{
1670 const char *msg = lua_tostring(lua, 1);
1671 if (msg == NULL) /* is error object not a string? */
1672 {
1673 if (luaL_callmeta(lua, 1, "__tostring") && /* does it have a metamethod */
1674 lua_type(lua, -1) == LUA_TSTRING) /* that produces a string? */
1675 return 1; /* that is the message */
1676 else
1677 msg = lua_pushfstring(lua, "(error object is a %s value)", luaL_typename(lua, 1));
1678 }
1679 /* call the debug.traceback function instead of luaL_traceback so */
1680 /* customized sourcemap-aware debug.traceback can give better line numbers */
1681 lua_getglobal(lua, "debug");
1682 lua_pushstring(lua, "traceback");
1683 lua_gettable(lua, -2);
1684 lua_pushstring(lua, msg);
1685 lua_call(lua, 1, 1);
1686 return 1; /* return the traceback */
1687}
1688
1689/*
1690** Interface to 'lua_pcall', which sets appropriate message handler function.
1691** Please use this function for all top level lua functions.
1692** This function was extractred from lua.c (and stripped of signal handling)
1693*/
1694static s32 docall (lua_State *lua, s32 narg, s32 nres)
1695{
1696 s32 status = 0;
1697 s32 base = lua_gettop(lua) - narg; /* function index */
1698 lua_pushcfunction(lua, msghandler); /* push message handler */
1699 lua_insert(lua, base); /* put it under function and args */
1700 status = lua_pcall(lua, narg, nres, base);
1701 lua_remove(lua, base); /* remove message handler from the stack */
1702 return status;
1703}
1704
1705void luaapi_tick(tic_mem* tic)
1706{
1707 tic_core* core = (tic_core*)tic;
1708
1709 lua_State* lua = core->currentVM;
1710
1711 if(lua)
1712 {
1713 lua_getglobal(lua, TIC_FN);
1714 if(lua_isfunction(lua, -1))
1715 {
1716 if(docall(lua, 0, 0) != LUA_OK)
1717 {
1718 core->data->error(core->data->data, lua_tostring(lua, -1));
1719 return;
1720 }
1721
1722#if defined(BUILD_DEPRECATED)
1723 // call OVR() callback for backward compatibility
1724 {
1725 lua_getglobal(lua, OVR_FN);
1726 if(lua_isfunction(lua, -1))
1727 {
1728 OVR(core)
1729 {
1730 if(docall(lua, 0, 0) != LUA_OK)
1731 core->data->error(core->data->data, lua_tostring(lua, -1));
1732 }
1733 }
1734 else lua_pop(lua, 1);
1735 }
1736#endif
1737 }
1738 else
1739 {
1740 lua_pop(lua, 1);
1741 core->data->error(core->data->data, "'function TIC()...' isn't found :(");
1742 }
1743 }
1744}
1745
1746void callLuaIntCallback(tic_mem* tic, s32 value, void* data, const char* name)
1747{
1748 tic_core* core = (tic_core*)tic;
1749 lua_State* lua = core->currentVM;
1750
1751 if (lua)
1752 {
1753 lua_getglobal(lua, name);
1754 if(lua_isfunction(lua, -1))
1755 {
1756 lua_pushinteger(lua, value);
1757 if(docall(lua, 1, 0) != LUA_OK)
1758 core->data->error(core->data->data, lua_tostring(lua, -1));
1759 }
1760 else lua_pop(lua, 1);
1761 }
1762}
1763
1764void luaapi_scn(tic_mem* tic, s32 row, void* data)
1765{
1766 callLuaIntCallback(tic, row, data, SCN_FN);
1767
1768 // try to call old scanline
1769 callLuaIntCallback(tic, row, data, "scanline");
1770}
1771
1772void luaapi_bdr(tic_mem* tic, s32 row, void* data)
1773{
1774 callLuaIntCallback(tic, row, data, BDR_FN);
1775}
1776
1777void luaapi_menu(tic_mem* tic, s32 index, void* data)
1778{
1779 callLuaIntCallback(tic, index, data, MENU_FN);
1780}
1781
1782void luaapi_boot(tic_mem* tic)
1783{
1784 tic_core* core = (tic_core*)tic;
1785 lua_State* lua = core->currentVM;
1786
1787 if (lua)
1788 {
1789 lua_getglobal(lua, BOOT_FN);
1790 if(lua_isfunction(lua, -1))
1791 {
1792 if(docall(lua, 0, 0) != LUA_OK)
1793 core->data->error(core->data->data, lua_tostring(lua, -1));
1794 }
1795 else lua_pop(lua, 1);
1796 }
1797}