Revert "Remove Lua 5.1 support"
[lsnes.git] / src / lua / core.cpp
blob3e973a4cb1333a2728245be3eb354818a7efb1b2
1 #include "core/command.hpp"
2 #include "lua/internal.hpp"
3 #include "core/framerate.hpp"
4 #include "core/instance.hpp"
5 #include "core/moviefile.hpp"
6 #include "core/moviedata.hpp"
7 #include "core/rom.hpp"
8 #include "core/window.hpp"
9 #include "interface/romtype.hpp"
10 #include "library/string.hpp"
11 #include <sstream>
13 namespace
15 std::string luavalue_to_string(lua::state& L, int index, std::set<const void*>& printed, bool quote)
17 switch(L.type(index)) {
18 case LUA_TNONE:
19 return "none";
20 case LUA_TNIL:
21 return "nil";
22 case LUA_TBOOLEAN:
23 return L.toboolean(index) ? "true" : "false";
24 case LUA_TNUMBER:
25 return (stringfmt() << L.tonumber(index)).str();
26 case LUA_TSTRING: {
27 const char* tmp2;
28 size_t len;
29 tmp2 = L.tolstring(index, &len);
30 if(quote)
31 return "\"" + std::string(tmp2, tmp2 + len) + "\"";
32 else
33 return std::string(tmp2, tmp2 + len);
35 case LUA_TLIGHTUSERDATA:
36 return (stringfmt() << "Lightuserdata:" << L.touserdata(index)).str();
37 case LUA_TFUNCTION:
38 return (stringfmt() << "Function:" << L.topointer(index)).str();
39 case LUA_TTHREAD:
40 return (stringfmt() << "Thread:" << L.topointer(index)).str();
41 break;
42 case LUA_TUSERDATA:
43 return (stringfmt() << "Userdata<" << try_recognize_userdata(L, index) << "@"
44 << L.touserdata(index) << ">:[" << try_print_userdata(L, index) << "]").str();
45 case LUA_TTABLE: {
46 //Fun with recursion.
47 const void* ptr = L.topointer(index);
48 if(printed.count(ptr))
49 return (stringfmt() << "<table:" << ptr << ">").str();
50 printed.insert(ptr);
51 std::ostringstream s;
52 s << "<" << ptr << ">{";
53 L.pushnil();
54 bool first = true;
55 while(L.next(index)) {
56 if(!first)
57 s << ", ";
58 int stacktop = L.gettop();
59 s << "[" << luavalue_to_string(L, stacktop - 1, printed, true) << "]="
60 << luavalue_to_string(L, stacktop, printed, true);
61 first = false;
62 L.pop(1);
64 s << "}";
65 return s.str();
67 default:
68 return (stringfmt() << "???:" << L.topointer(index)).str();
72 int identify_class(lua::state& L, lua::parameters& P)
74 if(!P.is_userdata())
75 return 0;
76 L.pushlstring(try_recognize_userdata(L, 1));
77 return 1;
80 int tostringx(lua::state& L, lua::parameters& P)
82 std::set<const void*> tmp2;
83 std::string y = luavalue_to_string(L, 1, tmp2, false);
84 L.pushlstring(y);
85 return 1;
88 int print2(lua::state& L, lua::parameters& P)
90 std::string toprint;
91 bool first = true;
92 while(P.more()) {
93 int i = P.skip();
94 std::set<const void*> tmp2;
95 std::string tmp = luavalue_to_string(L, i, tmp2, false);
96 if(first)
97 toprint = tmp;
98 else
99 toprint = toprint + "\t" + tmp;
100 first = false;
102 platform::message(toprint);
103 return 0;
106 int exec(lua::state& L, lua::parameters& P)
108 std::string text;
110 P(text);
112 CORE().command->invoke(text);
113 return 0;
116 int lookup_class(lua::state& L, lua::parameters& P)
118 std::string clazz;
120 P(clazz);
122 return lua::class_base::lookup_and_push(L, clazz) ? 1 : 0;
125 int all_classes(lua::state& L, lua::parameters& P)
127 auto c = lua::class_base::all_classes(L);
128 int count = 0;
129 for(auto& i : c) {
130 L.pushlstring(i);
131 count++;
133 return count;
136 int emulator_ready(lua::state& L, lua::parameters& P)
138 L.pushboolean(true);
139 return 1;
142 int utime(lua::state& L, lua::parameters& P)
144 uint64_t t = framerate_regulator::get_utime();
145 L.pushnumber(t / 1000000);
146 L.pushnumber(t % 1000000);
147 return 2;
150 int set_idle_timeout(lua::state& L, lua::parameters& P)
152 auto& core = CORE();
153 uint64_t dt;
155 P(dt);
157 core.lua2->idle_hook_time = framerate_regulator::get_utime() + dt;
158 return 0;
161 int set_timer_timeout(lua::state& L, lua::parameters& P)
163 auto& core = CORE();
164 uint64_t dt;
166 P(dt);
168 core.lua2->timer_hook_time = framerate_regulator::get_utime() + dt;
169 return 0;
172 int bus_address(lua::state& L, lua::parameters& P)
174 auto& core = CORE();
175 uint64_t addr;
177 P(addr);
179 auto busrange = core.rom->get_bus_map();
180 if(!busrange.second)
181 throw std::runtime_error("This platform does not have bus mapping");
182 L.pushnumber(busrange.first + (addr % busrange.second));
183 return 1;
186 int get_lag_flag(lua::state& L, lua::parameters& P)
188 auto& core = CORE();
189 L.pushboolean(!core.rom->get_pflag());
190 return 1;
193 int set_lag_flag(lua::state& L, lua::parameters& P)
195 auto& core = CORE();
196 bool flag;
198 P(flag);
200 core.rom->set_pflag(!flag);
201 return 0;
204 lua::functions LUA_misc_fns(lua_func_misc, "", {
205 {"print2", print2},
206 {"exec", exec},
207 {"emulator_ready", emulator_ready},
208 {"utime", utime},
209 {"set_idle_timeout", set_idle_timeout},
210 {"set_timer_timeout", set_timer_timeout},
211 {"bus_address", bus_address},
212 {"memory.get_lag_flag", get_lag_flag},
213 {"memory.set_lag_flag", set_lag_flag},
216 lua::functions LUA_pure_fns(lua_func_bit, "", {
217 {"identify_class", identify_class},
218 {"tostringx", tostringx},
219 {"lookup_class", lookup_class},
220 {"all_classes", all_classes},