Upload UI
[lsnes.git] / src / lua / actions.cpp
blobea82dee330dc80f99ecf20a8b31856d64f7d9183
1 #include "lua/internal.hpp"
2 #include "interface/romtype.hpp"
3 #include "core/moviedata.hpp"
5 namespace
7 function_ptr_luafun c_action(lua_func_misc, "memory.action", [](lua_state& L, const std::string& fname)
8 -> int {
9 std::string name = L.get_string(1, fname.c_str());
10 const interface_action* act = NULL;
11 for(auto i : our_rom.rtype->get_actions())
12 if(i->get_symbol() == name) {
13 act = i;
14 break;
16 if(!act)
17 throw std::runtime_error("No such action");
18 if(!(our_rom.rtype->action_flags(act->id) & 1))
19 throw std::runtime_error("Action not enabled.");
20 std::vector<interface_action_paramval> params;
21 unsigned idx = 2;
22 for(auto i : act->params) {
23 regex_results r;
24 interface_action_paramval pv;
25 if(r = regex("string(:(.*))?", i.model)) {
26 pv.s = L.get_string(idx, fname.c_str());
27 bool bad = false;;
28 try {
29 if(r[2] != "" && !regex_match(r[2], pv.s))
30 bad = true;
31 } catch(...) {
32 messages << "Internal error: Bad constraint in '" << i.model << "'."
33 << std::endl;
34 throw std::runtime_error("Internal error");
36 if(bad)
37 throw std::runtime_error("String does not satisfy constraints.");
38 } else if(r = regex("int:([0-9]+),([0-9]+)", i.model)) {
39 int64_t low, high, v;
40 try {
41 low = parse_value<int64_t>(r[1]);
42 high = parse_value<int64_t>(r[2]);
43 } catch(...) {
44 messages << "Internal error: Unknown limits in '" << i.model << "'."
45 << std::endl;
46 throw std::runtime_error("Internal error");
48 pv.i = L.get_numeric_argument<uint64_t>(idx, fname.c_str());
49 if(pv.i < low || pv.i > high) {
50 throw std::runtime_error("Parameter out of limits.");
52 } else if(r = regex("enum:(.*)", i.model)) {
53 std::string p = L.get_string(idx, fname.c_str());
54 unsigned num = 0;
55 try {
56 JSON::node e(r[1]);
57 for(auto i2 : e) {
58 std::string n;
59 if(i2.type() == JSON::string)
60 n = i2.as_string8();
61 else if(i2.type() == JSON::array)
62 n = i2.index(0).as_string8();
63 else
64 throw std::runtime_error("Choice not array nor "
65 "string");
66 if(n == p)
67 goto out;
68 num++;
70 } catch(std::exception& e) {
71 messages << "JSON parse error parsing " << "model: "
72 << e.what() << std::endl;
73 throw std::runtime_error("Internal error");
75 throw std::runtime_error("Invalid choice for enumeration.");
76 out:
77 pv.i = num;
78 } else if(regex_match("bool", i.model)) {
79 pv.b = L.get_bool(idx, fname.c_str());
80 } else if(regex_match("toggle", i.model)) {
81 idx--;
82 } else {
83 messages << "Internal error: Unknown parameter model '" << i.model << "'."
84 << std::endl;
85 throw std::runtime_error("Internal error");
87 params.push_back(pv);
88 idx++;
90 if(L.type(idx) != LUA_TNONE) {
91 throw std::runtime_error("Excess arguments for action");
93 our_rom.rtype->execute_action(act->id, params);
94 return 0;
95 });