lsnes rr2-β24
[lsnes.git] / src / lua / core.cpp
blob14ee6f36deb7b4e000096185e7b4b9be9a1f75fe
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/runmode.hpp"
9 #include "core/window.hpp"
10 #include "interface/romtype.hpp"
11 #include "library/directory.hpp"
12 #include "library/zip.hpp"
13 #include "library/string.hpp"
14 #include <sstream>
16 namespace
18 std::string luavalue_to_string(lua::state& L, int index, std::set<const void*>& printed, bool quote)
20 switch(L.type(index)) {
21 case LUA_TNONE:
22 return "none";
23 case LUA_TNIL:
24 return "nil";
25 case LUA_TBOOLEAN:
26 return L.toboolean(index) ? "true" : "false";
27 case LUA_TNUMBER:
28 if(L.isinteger(index))
29 return (stringfmt() << L.tointeger(index)).str();
30 else
31 return (stringfmt() << L.tonumber(index)).str();
32 case LUA_TSTRING: {
33 const char* tmp2;
34 size_t len;
35 tmp2 = L.tolstring(index, &len);
36 if(quote)
37 return "\"" + std::string(tmp2, tmp2 + len) + "\"";
38 else
39 return std::string(tmp2, tmp2 + len);
41 case LUA_TLIGHTUSERDATA:
42 return (stringfmt() << "Lightuserdata:" << L.touserdata(index)).str();
43 case LUA_TFUNCTION:
44 return (stringfmt() << "Function:" << L.topointer(index)).str();
45 case LUA_TTHREAD:
46 return (stringfmt() << "Thread:" << L.topointer(index)).str();
47 break;
48 case LUA_TUSERDATA:
49 return (stringfmt() << "Userdata<" << try_recognize_userdata(L, index) << "@"
50 << L.touserdata(index) << ">:[" << try_print_userdata(L, index) << "]").str();
51 case LUA_TTABLE: {
52 //Fun with recursion.
53 const void* ptr = L.topointer(index);
54 if(printed.count(ptr))
55 return (stringfmt() << "<table:" << ptr << ">").str();
56 printed.insert(ptr);
57 std::ostringstream s;
58 s << "<" << ptr << ">{";
59 L.pushnil();
60 bool first = true;
61 while(L.next(index)) {
62 if(!first)
63 s << ", ";
64 int stacktop = L.gettop();
65 s << "[" << luavalue_to_string(L, stacktop - 1, printed, true) << "]="
66 << luavalue_to_string(L, stacktop, printed, true);
67 first = false;
68 L.pop(1);
70 s << "}";
71 return s.str();
73 default:
74 return (stringfmt() << "???:" << L.topointer(index)).str();
78 int identify_class(lua::state& L, lua::parameters& P)
80 if(!P.is_userdata())
81 return 0;
82 L.pushlstring(try_recognize_userdata(L, 1));
83 return 1;
86 int tostringx(lua::state& L, lua::parameters& P)
88 std::set<const void*> tmp2;
89 std::string y = luavalue_to_string(L, 1, tmp2, false);
90 L.pushlstring(y);
91 return 1;
94 int print2(lua::state& L, lua::parameters& P)
96 std::string toprint;
97 bool first = true;
98 while(P.more()) {
99 int i = P.skip();
100 std::set<const void*> tmp2;
101 std::string tmp = luavalue_to_string(L, i, tmp2, false);
102 if(first)
103 toprint = tmp;
104 else
105 toprint = toprint + "\t" + tmp;
106 first = false;
108 platform::message(toprint);
109 return 0;
112 int exec(lua::state& L, lua::parameters& P)
114 std::string text;
116 P(text);
118 CORE().command->invoke(text);
119 return 0;
122 int lookup_class(lua::state& L, lua::parameters& P)
124 std::string clazz;
126 P(clazz);
128 return lua::class_base::lookup_and_push(L, clazz) ? 1 : 0;
131 int all_classes(lua::state& L, lua::parameters& P)
133 auto c = lua::class_base::all_classes(L);
134 int count = 0;
135 for(auto& i : c) {
136 L.pushlstring(i);
137 count++;
139 return count;
142 int emulator_ready(lua::state& L, lua::parameters& P)
144 L.pushboolean(true);
145 return 1;
148 int utime(lua::state& L, lua::parameters& P)
150 uint64_t t = framerate_regulator::get_utime();
151 L.pushnumber(t / 1000000);
152 L.pushnumber(t % 1000000);
153 return 2;
156 int set_idle_timeout(lua::state& L, lua::parameters& P)
158 auto& core = CORE();
159 uint64_t dt;
161 P(dt);
163 core.lua2->idle_hook_time = framerate_regulator::get_utime() + dt;
164 return 0;
167 int set_timer_timeout(lua::state& L, lua::parameters& P)
169 auto& core = CORE();
170 uint64_t dt;
172 P(dt);
174 core.lua2->timer_hook_time = framerate_regulator::get_utime() + dt;
175 return 0;
178 int bus_address(lua::state& L, lua::parameters& P)
180 auto& core = CORE();
181 uint64_t addr;
183 P(addr);
185 auto busrange = core.rom->get_bus_map();
186 if(!busrange.second)
187 throw std::runtime_error("This platform does not have bus mapping");
188 L.pushnumber(busrange.first + (addr % busrange.second));
189 return 1;
192 int get_lag_flag(lua::state& L, lua::parameters& P)
194 auto& core = CORE();
195 L.pushboolean(!core.rom->get_pflag());
196 return 1;
199 int set_lag_flag(lua::state& L, lua::parameters& P)
201 auto& core = CORE();
202 bool flag;
204 P(flag);
206 core.rom->set_pflag(!flag);
207 return 0;
210 int get_lua_memory_use(lua::state& L, lua::parameters& P)
212 L.pushnumber(L.get_memory_use());
213 L.pushnumber(L.get_memory_limit());
214 return 2;
217 int get_runmode(lua::state& L, lua::parameters& P)
219 auto& core = CORE();
220 auto m = core.runmode->get();
221 if(m == emulator_runmode::QUIT) L.pushstring("quit");
222 else if(m == emulator_runmode::NORMAL) L.pushstring("normal");
223 else if(m == emulator_runmode::LOAD) L.pushstring("load");
224 else if(m == emulator_runmode::ADVANCE_FRAME) L.pushstring("advance_frame");
225 else if(m == emulator_runmode::ADVANCE_SUBFRAME) L.pushstring("advance_subframe");
226 else if(m == emulator_runmode::SKIPLAG) L.pushstring("skiplag");
227 else if(m == emulator_runmode::SKIPLAG_PENDING) L.pushstring("skiplag_pending");
228 else if(m == emulator_runmode::PAUSE) L.pushstring("pause");
229 else if(m == emulator_runmode::PAUSE_BREAK) L.pushstring("pause_break");
230 else if(m == emulator_runmode::CORRUPT) L.pushstring("corrupt");
231 else L.pushstring("unknown");
232 return 1;
235 int lsnes_features(lua::state& L, lua::parameters& P)
237 bool ok = false;
238 std::string arg;
239 P(arg);
240 if(arg == "text-halos") ok = true;
241 L.pushboolean(ok);
242 return 1;
245 int get_directory_contents(lua::state& L, lua::parameters& P)
247 std::string arg1, arg2, pattern;
248 P(arg1, P.optional(arg2, ""), P.optional(pattern, ".*"));
249 std::string arg = zip::resolverel(arg1, arg2);
250 auto dirlist = directory::enumerate(arg, pattern);
251 unsigned key = 1;
252 L.newtable();
253 for(auto i : dirlist) {
254 L.pushnumber(key++);
255 L.pushlstring(i);
256 L.settable(-3);
258 return 1;
261 int get_file_type(lua::state& L, lua::parameters& P)
263 std::string arg, type;
264 P(arg);
265 if(!directory::exists(arg)) {
266 L.pushnil();
267 } else if(directory::is_regular(arg)) {
268 L.pushstring("regular");
269 } else if(directory::is_directory(arg)) {
270 L.pushstring("directory");
271 } else {
272 L.pushstring("unknown");
274 return 1;
277 lua::functions LUA_misc_fns(lua_func_misc, "", {
278 {"print2", print2},
279 {"exec", exec},
280 {"emulator_ready", emulator_ready},
281 {"utime", utime},
282 {"set_idle_timeout", set_idle_timeout},
283 {"set_timer_timeout", set_timer_timeout},
284 {"bus_address", bus_address},
285 {"get_lua_memory_use", get_lua_memory_use},
286 {"get_directory_contents", get_directory_contents},
287 {"get_file_type", get_file_type},
288 {"lsnes_features", lsnes_features},
289 {"memory.get_lag_flag", get_lag_flag},
290 {"memory.set_lag_flag", set_lag_flag},
291 {"gui.get_runmode", get_runmode},
294 lua::functions LUA_pure_fns(lua_func_bit, "", {
295 {"identify_class", identify_class},
296 {"tostringx", tostringx},
297 {"lookup_class", lookup_class},
298 {"all_classes", all_classes},