Redo text rendering (adds halo support to gui.text())
[lsnes.git] / src / lua / core.cpp
blob9993d62fe8e1bad5580fd03b31b18858b30e235f
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/string.hpp"
12 #include <sstream>
14 namespace
16 std::string luavalue_to_string(lua::state& L, int index, std::set<const void*>& printed, bool quote)
18 switch(L.type(index)) {
19 case LUA_TNONE:
20 return "none";
21 case LUA_TNIL:
22 return "nil";
23 case LUA_TBOOLEAN:
24 return L.toboolean(index) ? "true" : "false";
25 case LUA_TNUMBER:
26 if(L.isinteger(index))
27 return (stringfmt() << L.tointeger(index)).str();
28 else
29 return (stringfmt() << L.tonumber(index)).str();
30 case LUA_TSTRING: {
31 const char* tmp2;
32 size_t len;
33 tmp2 = L.tolstring(index, &len);
34 if(quote)
35 return "\"" + std::string(tmp2, tmp2 + len) + "\"";
36 else
37 return std::string(tmp2, tmp2 + len);
39 case LUA_TLIGHTUSERDATA:
40 return (stringfmt() << "Lightuserdata:" << L.touserdata(index)).str();
41 case LUA_TFUNCTION:
42 return (stringfmt() << "Function:" << L.topointer(index)).str();
43 case LUA_TTHREAD:
44 return (stringfmt() << "Thread:" << L.topointer(index)).str();
45 break;
46 case LUA_TUSERDATA:
47 return (stringfmt() << "Userdata<" << try_recognize_userdata(L, index) << "@"
48 << L.touserdata(index) << ">:[" << try_print_userdata(L, index) << "]").str();
49 case LUA_TTABLE: {
50 //Fun with recursion.
51 const void* ptr = L.topointer(index);
52 if(printed.count(ptr))
53 return (stringfmt() << "<table:" << ptr << ">").str();
54 printed.insert(ptr);
55 std::ostringstream s;
56 s << "<" << ptr << ">{";
57 L.pushnil();
58 bool first = true;
59 while(L.next(index)) {
60 if(!first)
61 s << ", ";
62 int stacktop = L.gettop();
63 s << "[" << luavalue_to_string(L, stacktop - 1, printed, true) << "]="
64 << luavalue_to_string(L, stacktop, printed, true);
65 first = false;
66 L.pop(1);
68 s << "}";
69 return s.str();
71 default:
72 return (stringfmt() << "???:" << L.topointer(index)).str();
76 int identify_class(lua::state& L, lua::parameters& P)
78 if(!P.is_userdata())
79 return 0;
80 L.pushlstring(try_recognize_userdata(L, 1));
81 return 1;
84 int tostringx(lua::state& L, lua::parameters& P)
86 std::set<const void*> tmp2;
87 std::string y = luavalue_to_string(L, 1, tmp2, false);
88 L.pushlstring(y);
89 return 1;
92 int print2(lua::state& L, lua::parameters& P)
94 std::string toprint;
95 bool first = true;
96 while(P.more()) {
97 int i = P.skip();
98 std::set<const void*> tmp2;
99 std::string tmp = luavalue_to_string(L, i, tmp2, false);
100 if(first)
101 toprint = tmp;
102 else
103 toprint = toprint + "\t" + tmp;
104 first = false;
106 platform::message(toprint);
107 return 0;
110 int exec(lua::state& L, lua::parameters& P)
112 std::string text;
114 P(text);
116 CORE().command->invoke(text);
117 return 0;
120 int lookup_class(lua::state& L, lua::parameters& P)
122 std::string clazz;
124 P(clazz);
126 return lua::class_base::lookup_and_push(L, clazz) ? 1 : 0;
129 int all_classes(lua::state& L, lua::parameters& P)
131 auto c = lua::class_base::all_classes(L);
132 int count = 0;
133 for(auto& i : c) {
134 L.pushlstring(i);
135 count++;
137 return count;
140 int emulator_ready(lua::state& L, lua::parameters& P)
142 L.pushboolean(true);
143 return 1;
146 int utime(lua::state& L, lua::parameters& P)
148 uint64_t t = framerate_regulator::get_utime();
149 L.pushnumber(t / 1000000);
150 L.pushnumber(t % 1000000);
151 return 2;
154 int set_idle_timeout(lua::state& L, lua::parameters& P)
156 auto& core = CORE();
157 uint64_t dt;
159 P(dt);
161 core.lua2->idle_hook_time = framerate_regulator::get_utime() + dt;
162 return 0;
165 int set_timer_timeout(lua::state& L, lua::parameters& P)
167 auto& core = CORE();
168 uint64_t dt;
170 P(dt);
172 core.lua2->timer_hook_time = framerate_regulator::get_utime() + dt;
173 return 0;
176 int bus_address(lua::state& L, lua::parameters& P)
178 auto& core = CORE();
179 uint64_t addr;
181 P(addr);
183 auto busrange = core.rom->get_bus_map();
184 if(!busrange.second)
185 throw std::runtime_error("This platform does not have bus mapping");
186 L.pushnumber(busrange.first + (addr % busrange.second));
187 return 1;
190 int get_lag_flag(lua::state& L, lua::parameters& P)
192 auto& core = CORE();
193 L.pushboolean(!core.rom->get_pflag());
194 return 1;
197 int set_lag_flag(lua::state& L, lua::parameters& P)
199 auto& core = CORE();
200 bool flag;
202 P(flag);
204 core.rom->set_pflag(!flag);
205 return 0;
208 int get_lua_memory_use(lua::state& L, lua::parameters& P)
210 L.pushnumber(L.get_memory_use());
211 L.pushnumber(L.get_memory_limit());
212 return 2;
215 int get_runmode(lua::state& L, lua::parameters& P)
217 auto& core = CORE();
218 auto m = core.runmode->get();
219 if(m == emulator_runmode::QUIT) L.pushstring("quit");
220 else if(m == emulator_runmode::NORMAL) L.pushstring("normal");
221 else if(m == emulator_runmode::LOAD) L.pushstring("load");
222 else if(m == emulator_runmode::ADVANCE_FRAME) L.pushstring("advance_frame");
223 else if(m == emulator_runmode::ADVANCE_SUBFRAME) L.pushstring("advance_subframe");
224 else if(m == emulator_runmode::SKIPLAG) L.pushstring("skiplag");
225 else if(m == emulator_runmode::SKIPLAG_PENDING) L.pushstring("skiplag_pending");
226 else if(m == emulator_runmode::PAUSE) L.pushstring("pause");
227 else if(m == emulator_runmode::PAUSE_BREAK) L.pushstring("pause_break");
228 else if(m == emulator_runmode::CORRUPT) L.pushstring("corrupt");
229 else L.pushstring("unknown");
230 return 1;
233 int lsnes_features(lua::state& L, lua::parameters& P)
235 bool ok = false;
236 std::string arg;
237 P(arg);
238 if(arg == "text-halos") ok = true;
239 L.pushboolean(ok);
240 return 1;
243 lua::functions LUA_misc_fns(lua_func_misc, "", {
244 {"print2", print2},
245 {"exec", exec},
246 {"emulator_ready", emulator_ready},
247 {"utime", utime},
248 {"set_idle_timeout", set_idle_timeout},
249 {"set_timer_timeout", set_timer_timeout},
250 {"bus_address", bus_address},
251 {"get_lua_memory_use", get_lua_memory_use},
252 {"lsnes_features", lsnes_features},
253 {"memory.get_lag_flag", get_lag_flag},
254 {"memory.set_lag_flag", set_lag_flag},
255 {"gui.get_runmode", get_runmode},
258 lua::functions LUA_pure_fns(lua_func_bit, "", {
259 {"identify_class", identify_class},
260 {"tostringx", tostringx},
261 {"lookup_class", lookup_class},
262 {"all_classes", all_classes},