this repo has no description
at main 1797 lines 44 kB view raw
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, &note, &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}