Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.         dZ80 scripting support for opcode traps
  3. */
  4.  
  5. #include <stdio.h>
  6. #include <assert.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include <ctype.h>
  10.  
  11. #include "dissz80p.h"
  12. #include "lualib.h"
  13. #include "lauxlib.h"
  14.  
  15. const static char *hexChars = "0123456789ABCDEF";
  16.  
  17. /* Lua dZ80 extensions */
  18. static int d_RegTrap(lua_State *ls);
  19. static int d_AddComment(lua_State *ls);
  20. static int d_AddToDis(lua_State *ls);
  21. static int d_AddToDisTab(lua_State *ls);
  22. static int d_GetByte(lua_State *ls);
  23. static int d_LookByte(lua_State *ls);
  24. static int d_DB(lua_State *ls);
  25. static int d_FlushLine(lua_State *ls);
  26. static int d_IsCodeByte(lua_State *ls);
  27. static int d_GetPC(lua_State *ls);
  28. static int d_LookByteAddr(lua_State *ls);
  29. static int d_GetPass(lua_State *ls);
  30. static int d_Message(lua_State *ls);
  31.  
  32.  
  33. int InitOpcodeTraps(DISZ80 *d)
  34. {
  35.         int             err;
  36.         char    buf[_MAX_PATH + 64];
  37.  
  38.         if (d->scriptFileName[0])
  39.                 {
  40.                 if (d->pTrapMap == NULL)
  41.                         {
  42.                         if ((d->pTrapMap = AllocateMap(d, "Couldn't allocate memory for the opcode trap map.", 256)) == NULL)
  43.                                 {
  44.                                 DisZ80CleanUp(d);
  45.                                 return DERR_OUTOFMEM;
  46.                                 }
  47.                         }
  48.                
  49.                 err = InitScripting(d);
  50.                 if (err != DERR_NONE)
  51.                         return err;
  52.  
  53.                 err = lua_dofile(d->ls, d->scriptFileName);
  54.                 if (err)
  55.                         {
  56.                         switch(err)
  57.                                 {
  58.                                 case 2:
  59.                                         sprintf(buf, "Couldn't open the script file \"%s\"", d->scriptFileName);
  60.                                         dZ80_Error(d, buf);
  61.                                         return DERR_COULDNTOPENFILE;
  62.  
  63.                                 default:
  64.                                         return DERR_SCRIPTERROR;
  65.                                 }
  66.                         }
  67.                 }
  68.  
  69.         return DERR_NONE;
  70. }
  71.  
  72.  
  73. int LuaErrorHandler(lua_State *ls)
  74. {
  75.         char            buf[256];
  76.         DISZ80          *d;
  77.         const char      *s;
  78.        
  79.         d = GetD(ls);
  80.         s = lua_tostring(ls, 1);
  81.         if (s == NULL)
  82.                 s = "(no message)";
  83.         sprintf(buf, "Script error: %s\n", s);
  84.  
  85.         dZ80_Error(d, buf);
  86.         return 0;
  87. }
  88.  
  89. int ShutdownScripting(DISZ80 *d)
  90. {
  91.         if (d->ls != NULL)
  92.                 {
  93.                 lua_close(d->ls);
  94.                 d->ls = NULL;
  95.                 }
  96.  
  97.         return DERR_NONE;
  98. }
  99.  
  100. int InitScripting(DISZ80 *d)
  101. {
  102.         char    buf[256];
  103.         int             err;
  104.  
  105.         if (d->ls == NULL)
  106.                 {
  107.                 d->ls = lua_open(0);
  108.  
  109.                 if (d->ls == NULL)
  110.                         return DERR_OUTOFMEM;
  111.                
  112.                 lua_baselibopen(d->ls);
  113.                 lua_strlibopen(d->ls);
  114.  
  115.                 lua_pushuserdata(d->ls, d);
  116.                 lua_setglobal(d->ls, "DISZ80STRUC");
  117.  
  118.                 lua_register(d->ls, LUA_ERRORMESSAGE, LuaErrorHandler);
  119.  
  120. /* Register the dZ80 support functions */
  121.                 lua_register(d->ls, "d_RegTrap",                d_RegTrap);
  122.                 lua_register(d->ls, "d_AddComment",     d_AddComment);
  123.                 lua_register(d->ls, "d_AddToDis",               d_AddToDis);
  124.                 lua_register(d->ls, "d_AddToDisTab",    d_AddToDisTab);
  125.                 lua_register(d->ls, "d_GetByte",                d_GetByte);
  126.                 lua_register(d->ls, "d_LookByte",               d_LookByte);
  127.                 lua_register(d->ls, "d_DB",                     d_DB);
  128.                 lua_register(d->ls, "d_FlushLine",              d_FlushLine);
  129.                 lua_register(d->ls, "d_IsCodeByte",             d_IsCodeByte);
  130.                 lua_register(d->ls, "d_GetPC",                  d_GetPC);
  131.                 lua_register(d->ls, "d_LookByteAddr",   d_LookByteAddr);
  132.                 lua_register(d->ls, "d_GetPass",                d_GetPass);
  133.                 lua_register(d->ls, "d_Message",                d_Message);
  134.  
  135. /* Register the general support functions */
  136.                 lua_register(d->ls, "hex",                              d_FromHex);
  137.  
  138. /* Set up the trap registration functions */
  139.                 sprintf(buf,
  140.                         "__dz80_pre={}\n"
  141.                         "__dz80_post={}\n"
  142.                         "function d_PreTrap(op, fn) __dz80_pre[op]=fn d_RegTrap(op, %d) end\n"
  143.                         "function d_PostTrap(op, fn) __dz80_post[op]=fn d_RegTrap(op, %d) end\n",
  144.                         D_SCRIPT_PRE, D_SCRIPT_POST);
  145.  
  146.                 err = lua_dostring(d->ls, buf);
  147.                 if (err)
  148.                         return DERR_SCRIPTERROR;
  149.                 }
  150.  
  151.         return DERR_NONE;
  152. }
  153.  
  154.  
  155. /*
  156.         ExecPreTrap
  157.  
  158.         Execute the pre-decode trap
  159. */
  160.  
  161. int ExecPreTrap(DISZ80 *d)
  162. {
  163.         int             ni;
  164.         lua_State       *ls;
  165.  
  166.         if (d->pTrapMap != NULL)
  167.                 {
  168.                 if (d->pTrapMap[d->firstByte] & D_SCRIPT_PRE)
  169.                         {
  170.                         ni = d->numInstructions;
  171.  
  172.                         ls = d->ls;
  173.                         assert(ls != NULL);
  174.  
  175.                         lua_getglobal(ls, "__dz80_pre");
  176.                         lua_pushnumber(ls, d->firstByte);
  177.                         lua_gettable(ls, -2);
  178.                         lua_call(ls, 0, 0);                     /* call the opcode trap function */
  179.                         lua_pop(ls, 1);                         /* remove the table name */
  180.  
  181.                         return (ni != d->numInstructions);
  182.                         }
  183.                 }
  184.  
  185.         return 0;
  186. }
  187.  
  188.  
  189.  
  190. /*
  191.         ExecPostTrap
  192.  
  193.         Execute the post-decode trap
  194. */
  195.  
  196. void ExecPostTrap(DISZ80 *d)
  197. {
  198.         lua_State       *ls;
  199.  
  200.         if (d->pTrapMap != NULL)
  201.                 {
  202.                 if (d->pTrapMap[d->firstByte] & D_SCRIPT_POST)
  203.                         {
  204.                         ls = d->ls;
  205.                         assert(ls != NULL);
  206.  
  207.                         lua_getglobal(ls, "__dz80_post");
  208.                         lua_pushnumber(ls, d->firstByte);
  209.                         lua_gettable(ls, -2);
  210.                         lua_call(ls, 0, 0);                     /* call the opcode trap function */
  211.                         lua_pop(ls, 1);                         /* remove the table name */
  212.                         }
  213.                 }
  214.  
  215.         return;
  216. }
  217.  
  218.  
  219. /*
  220.         Lua's dZ80 Interface
  221. */
  222.  
  223. DISZ80 *GetD(lua_State *ls)
  224.         {
  225.         DISZ80 *d;
  226.  
  227.         lua_getglobal(ls, "DISZ80STRUC");
  228.  
  229.         d = (DISZ80 *)lua_touserdata(ls, -1);
  230.         assert(d != NULL);
  231.        
  232.         lua_pop(ls, 1);
  233.         return d;
  234.         }
  235.  
  236.  
  237. /*
  238.         d_RegTrap(opcode, type)
  239. */
  240.  
  241. static int d_RegTrap(lua_State *ls)
  242.         {
  243.         DISZ80  *d;
  244.         int     op, type;
  245.  
  246.         d = GetD(ls);
  247.        
  248.         op = luaL_check_long(ls, 1);
  249.         assert(op >= 0 && op < 256);
  250.  
  251.         type = luaL_check_long(ls, 2);
  252.  
  253.         d->pTrapMap[op] |= (unsigned char)type;
  254.         return 0;
  255.         }
  256.  
  257.  
  258. static int d_AddComment(lua_State *ls)
  259.         {
  260.         DISZ80          *d;
  261.         const char      *str;
  262.         size_t          len;
  263.  
  264.         d = GetD(ls);
  265.         str = luaL_check_lstr(ls, 1, &len);
  266.  
  267.         AddToDisComment(d, (char *)str);
  268.         return 0;
  269.         }
  270.  
  271.  
  272. static int d_AddToDis(lua_State *ls)
  273.         {
  274.         DISZ80          *d;
  275.         const char      *str;
  276.         size_t          len;
  277.  
  278.         d = GetD(ls);
  279.         str = luaL_check_lstr(ls, 1, &len);
  280.  
  281.         AddToDis(d, (char *)str);
  282.         return 0;
  283.         }
  284.  
  285.  
  286. static int d_AddToDisTab(lua_State *ls)
  287.         {
  288.         DISZ80          *d;
  289.         const char      *str;
  290.         size_t          len;
  291.  
  292.         d = GetD(ls);
  293.         str = luaL_check_lstr(ls, 1, &len);
  294.  
  295.         AddToDisTab(d, (char *)str);
  296.         return 0;
  297.         }
  298.  
  299.  
  300. static int d_GetByte(lua_State *ls)
  301.         {
  302.         DISZ80          *d;
  303.         BYTE            b;
  304.        
  305.         d = GetD(ls);
  306.  
  307.         if (!WithinDisRange(d))
  308.                 lua_error(ls, "d_GetByte requesting a byte past the user end address");
  309.  
  310.         b = GetNextOpCode(d);
  311.         lua_pushnumber(ls, (double)b);
  312.         return 1;
  313.         }
  314.  
  315.  
  316. static int d_LookByte(lua_State *ls)
  317.         {
  318.         DISZ80          *d;
  319.         BYTE            b;
  320.         int             offset;
  321.  
  322.         d = GetD(ls);
  323.         offset = luaL_check_long(ls, 1);
  324.                
  325.         b = LookOpcode(d, offset);
  326.         lua_pushnumber(ls, (double)b);
  327.         return 1;
  328.         }
  329.  
  330.  
  331. static int d_DB(lua_State *ls)
  332.         {
  333.         DISZ80          *d;
  334.         int             b, n, i;
  335.  
  336.         d = GetD(ls);
  337.  
  338.         n = 0;
  339.         while (lua_isnumber(ls, n+1))
  340.                 n++;
  341.  
  342.         if (n)
  343.                 {
  344.                 AddToDisTabDB(d);
  345.                        
  346.                 for(i=1; i <= n; i++)
  347.                         {
  348.                         b = luaL_check_long(ls, i) & 0xff;
  349.                         if (i > 1)
  350.                                 AddToDis(d, ",");
  351.                         Add8BitNum(d, b);
  352.                         }
  353.                 }
  354.  
  355.         return 0;
  356.         }
  357.  
  358.  
  359. static int d_FlushLine(lua_State *ls)
  360. {
  361.         DISZ80          *d;
  362.         int             err;
  363.  
  364.         d = GetD(ls);
  365.         err = WriteDisLine(d, d->lastPC);
  366.         lua_pushnumber(ls, (double)err);
  367.         return 1;
  368. }
  369.  
  370.  
  371. static int d_IsCodeByte(lua_State *ls)
  372.         {
  373.         DISZ80          *d;
  374.         int             addr, isCodeByte;
  375.  
  376.         isCodeByte = 1;
  377.  
  378.         d = GetD(ls);
  379.         addr = luaL_check_long(ls, 1);
  380.        
  381.         if (d->opMap != NULL)
  382.                 {
  383.                 if (!ISCODEBYTE(d, addr))
  384.                         isCodeByte = 0;
  385.                 }
  386.        
  387.         lua_pushnumber(ls, (double)isCodeByte);
  388.         return 1;
  389.         }
  390.  
  391.  
  392. static int d_GetPC(lua_State *ls)
  393.         {
  394.         DISZ80          *d;
  395.  
  396.         d = GetD(ls);
  397.         lua_pushnumber(ls, (double)d->PC);
  398.         return 1;
  399.         }
  400.  
  401.  
  402. static int d_LookByteAddr(lua_State *ls)
  403.         {
  404.         DISZ80          *d;
  405.         int             addr;
  406.  
  407.         d = GetD(ls);
  408.         addr = luaL_check_long(ls, 1);
  409.         lua_pushnumber(ls, (double)d->Z80MemBase[addr]);
  410.         return 1;
  411.         }
  412.  
  413.  
  414. static int d_GetPass(lua_State *ls)
  415.         {
  416.         DISZ80          *d;
  417.        
  418.         d = GetD(ls);
  419.         lua_pushnumber(ls, (double)d->currentPass);
  420.         return 1;
  421.         }
  422.  
  423.  
  424. static int d_Message(lua_State *ls)
  425.         {
  426.         DISZ80          *d;
  427.         const char      *ps;
  428.  
  429.         ps = luaL_check_string(ls, 1);
  430.         d = GetD(ls);
  431.         dZ80_ShowMsg(d, (char *)ps);
  432.         return 0;
  433.         }
  434.  
  435.  
  436. int d_FromHex(lua_State *ls)
  437.         {
  438.         DWORD           h;
  439.         const char      *ps, *p;
  440.         char            c;
  441.  
  442.         h = 0;
  443.         c = 0;
  444.  
  445.         ps = luaL_check_string(ls, 1);
  446.        
  447.         while (c = *ps++)
  448.                 {
  449.                 p = strchr(hexChars, toupper(c));
  450.                 if (p == NULL)
  451.                         break;
  452.  
  453.                 h = (p - hexChars) + 16 * h;
  454.                 }
  455.  
  456. /* If c is not zero, we've exited the conversion loop prematurely so there must have been an error */
  457.         if (c)
  458.                 luaL_argerror(ls, 1, "bad hex number");
  459.                
  460.         lua_pushnumber(ls, (double)h);
  461.         return 1;
  462.         }
  463.  
  464.  
  465.  
  466.