lsnes rr2-β24
[lsnes.git] / src / lua / address.cpp
blobaa39ade404cd29846c20147c87481c3390d57943
1 #include "core/instance.hpp"
2 #include "core/messages.hpp"
3 #include "library/lua-base.hpp"
4 #include "library/lua-params.hpp"
5 #include "library/lua-class.hpp"
6 #include "library/memoryspace.hpp"
7 #include "library/serialization.hpp"
8 #include "library/string.hpp"
9 #include "lua/address.hpp"
10 #include "lua/internal.hpp"
12 namespace
14 template<typename T> T bswap(T val)
16 T val2 = val;
17 serialization::swap_endian(val2);
18 return val2;
22 uint64_t lua_get_vmabase(const std::string& vma)
24 for(auto i : CORE().memory->get_regions())
25 if(i->name == vma)
26 return i->base;
27 throw std::runtime_error("No such VMA");
30 uint64_t lua_get_read_address(lua::parameters& P)
32 static std::map<std::string, char> deprecation_keys;
33 char* deprecation = &deprecation_keys[P.get_fname()];
34 uint64_t vmabase = 0;
35 if(P.is<lua_address>()) {
36 return P.arg<lua_address*>()->get();
37 } else if(P.is_string())
38 vmabase = lua_get_vmabase(P.arg<std::string>());
39 else {
40 //Deprecated.
41 if(P.get_state().do_once(deprecation))
42 messages << P.get_fname() << ": Global memory form is deprecated." << std::endl;
44 auto addr = P.arg<uint64_t>();
45 return addr + vmabase;
48 lua_address::lua_address(lua::state& L)
52 int lua_address::create(lua::state& L, lua::parameters& P)
54 lua_address* a = lua::_class<lua_address>::create(L);
55 P(a->vma, a->addr);
56 return 1;
59 std::string lua_address::print()
61 return (stringfmt() << vma << "+0x" << std::hex << addr).str();
64 uint64_t lua_address::get()
66 for(auto i : CORE().memory->get_regions())
67 if(i->name == vma) {
68 if(i->size > addr)
69 return i->base + addr;
70 (stringfmt() << "Address outside boound of memory area '" << vma << "' (" << std::hex
71 << addr << ">=" << std::hex << i->size << ")").throwex();
73 throw std::runtime_error("No such memory area '" + vma + "'");
76 std::string lua_address::get_vma()
78 return vma;
81 uint64_t lua_address::get_offset()
83 for(auto i : CORE().memory->get_regions())
84 if(i->name == vma) {
85 if(i->size > addr)
86 return addr;
87 (stringfmt() << "Address outside boound of memory area '" << vma << "' (" << std::hex
88 << addr << ">=" << std::hex << i->size << ")").throwex();
90 throw std::runtime_error("No such memory area '" + vma + "'");
93 int lua_address::l_get(lua::state& L, lua::parameters& P)
95 L.pushnumber(get());
96 return 1;
99 int lua_address::l_get_vma(lua::state& L, lua::parameters& P)
101 L.pushlstring(get_vma());
102 return 1;
105 int lua_address::l_get_offset(lua::state& L, lua::parameters& P)
107 L.pushnumber(get_offset());
108 return 1;
111 int lua_address::l_shift(lua::state& L, lua::parameters& P)
113 int addrs = 1;
114 int64_t a = 0, b = 0, c = 0;
116 P(P.skipped(), a);
117 if(P.more()) {
118 addrs++;
119 P(b);
121 if(P.more()) {
122 addrs++;
123 P(c);
126 lua_address* adr = lua::_class<lua_address>::create(L);
127 adr->vma = vma;
128 adr->addr = addr;
129 switch(addrs) {
130 case 1:
131 adr->addr += a;
132 break;
133 case 2:
134 adr->addr += a * b;
135 break;
136 case 3:
137 adr->addr += a * b + c;
138 break;
140 return 1;
143 int lua_address::l_replace(lua::state& L, lua::parameters& P)
145 uint64_t newoffset;
146 int bits;
148 P(P.skipped(), newoffset, P.optional(bits, -1));
150 lua_address* adr = lua::_class<lua_address>::create(L);
151 adr->vma = vma;
152 if(bits < 0)
153 adr->addr = newoffset;
154 else {
155 uint64_t mask = ((1 << bits) - 1);
156 adr->addr = (addr & ~mask) | (newoffset & mask);
158 return 1;
161 template<class T, bool _bswap> int lua_address::rw(lua::state& L, lua::parameters& P)
163 auto& core = CORE();
164 T val;
166 P(P.skipped());
168 if(P.is_novalue()) {
169 //Read.
170 T val = core.memory->read<T>(get());
171 if(_bswap) val = bswap(val);
172 L.pushnumber(val);
173 return 1;
174 } else if(P.is_number()) {
175 //Write.
176 P(val);
177 if(_bswap) val = bswap(val);
178 core.memory->write<T>(get(), val);
179 return 0;
180 } else
181 P.expected("number or nil");
182 return 0; //NOTREACHED
185 size_t lua_address::overcommit()
187 return 0;
190 namespace
192 lua::_class<lua_address> LUA_class_address(lua_class_memory, "ADDRESS", {
193 {"new", lua_address::create},
194 }, {
195 {"addr", &lua_address::l_get},
196 {"vma", &lua_address::l_get_vma},
197 {"offset", &lua_address::l_get_offset},
198 {"add", &lua_address::l_shift},
199 {"replace", &lua_address::l_replace},
200 {"sbyte", &lua_address::rw<int8_t, false>},
201 {"byte", &lua_address::rw<uint8_t, false>},
202 {"sword", &lua_address::rw<int16_t, false>},
203 {"word", &lua_address::rw<uint16_t, false>},
204 {"shword", &lua_address::rw<ss_int24_t, false>},
205 {"hword", &lua_address::rw<ss_uint24_t, false>},
206 {"sdword", &lua_address::rw<int32_t, false>},
207 {"dword", &lua_address::rw<uint32_t, false>},
208 {"sqword", &lua_address::rw<int64_t, false>},
209 {"qword", &lua_address::rw<uint64_t, false>},
210 {"float", &lua_address::rw<float, false>},
211 {"double", &lua_address::rw<double, false>},
212 {"isbyte", &lua_address::rw<int8_t, true>},
213 {"ibyte", &lua_address::rw<uint8_t, true>},
214 {"isword", &lua_address::rw<int16_t, true>},
215 {"iword", &lua_address::rw<uint16_t, true>},
216 {"ishword", &lua_address::rw<ss_int24_t, true>},
217 {"ihword", &lua_address::rw<ss_uint24_t, true>},
218 {"isdword", &lua_address::rw<int32_t, true>},
219 {"idword", &lua_address::rw<uint32_t, true>},
220 {"isqword", &lua_address::rw<int64_t, true>},
221 {"iqword", &lua_address::rw<uint64_t, true>},
222 {"ifloat", &lua_address::rw<float, true>},
223 {"idouble", &lua_address::rw<double, true>},
224 }, &lua_address::print);