Lua: Make static constructor methods for MMAP_STRUCT and ZIPWRITER
[lsnes.git] / src / lua / memory.cpp
blob92b74095f2d11dcc7958132f6b7b2327b059c4d3
1 #include "core/command.hpp"
2 #include "lua/internal.hpp"
3 #include "core/debug.hpp"
4 #include "core/memorymanip.hpp"
5 #include "core/memorywatch.hpp"
6 #include "core/moviedata.hpp"
7 #include "core/moviefile.hpp"
8 #include "core/rom.hpp"
9 #include "library/sha256.hpp"
10 #include "library/string.hpp"
11 #include "library/minmax.hpp"
12 #include "library/hex.hpp"
13 #include "library/int24.hpp"
15 namespace
17 uint64_t get_vmabase(lua::state& L, const std::string& vma)
19 for(auto i : lsnes_memory.get_regions())
20 if(i->name == vma)
21 return i->base;
22 throw std::runtime_error("No such VMA");
25 uint64_t get_read_address(lua::state& L, int& base, const char* fn)
27 uint64_t vmabase = 0;
28 if(L.type(base) == LUA_TSTRING) {
29 vmabase = get_vmabase(L, L.get_string(base, fn));
30 base++;
32 uint64_t addr = L.get_numeric_argument<uint64_t>(base++, fn) + vmabase;
33 return addr;
36 template<typename T, T (memory_space::*rfun)(uint64_t addr)>
37 class lua_read_memory : public lua::function
39 public:
40 lua_read_memory(const std::string& name) : lua::function(lua_func_misc, name) {}
41 int invoke(lua::state& L)
43 int base = 1;
44 uint64_t addr = get_read_address(L, base, "lua_read_memory");
45 L.pushnumber(static_cast<T>((lsnes_memory.*rfun)(addr)));
46 return 1;
50 template<typename T, bool (memory_space::*wfun)(uint64_t addr, T value)>
51 class lua_write_memory : public lua::function
53 public:
54 lua_write_memory(const std::string& name) : lua::function(lua_func_misc, name) {}
55 int invoke(lua::state& L)
57 int base = 1;
58 uint64_t addr = get_read_address(L, base, "lua_write_memory");
59 T value = L.get_numeric_argument<T>(base + 2, fname.c_str());
60 (lsnes_memory.*wfun)(addr, value);
61 return 0;
65 class mmap_base
67 public:
68 ~mmap_base() {}
69 virtual void read(lua::state& L, uint64_t addr) = 0;
70 virtual void write(lua::state& L, uint64_t addr) = 0;
74 template<typename T, T (memory_space::*rfun)(uint64_t addr), bool (memory_space::*wfun)(uint64_t addr,
75 T value)>
76 class lua_mmap_memory_helper : public mmap_base
78 public:
79 ~lua_mmap_memory_helper() {}
80 void read(lua::state& L, uint64_t addr)
82 L.pushnumber(static_cast<T>((lsnes_memory.*rfun)(addr)));
85 void write(lua::state& L, uint64_t addr)
87 T value = L.get_numeric_argument<T>(3, "aperture(write)");
88 (lsnes_memory.*wfun)(addr, value);
93 class lua_mmap_struct
95 public:
96 lua_mmap_struct(lua::state& L);
98 ~lua_mmap_struct()
102 int index(lua::state& L, const std::string& fname)
104 const char* c = L.tostring(2);
105 if(!c) {
106 L.pushnil();
107 return 1;
109 std::string c2(c);
110 if(!mappings.count(c2)) {
111 L.pushnil();
112 return 1;
114 auto& x = mappings[c2];
115 x.first->read(L, x.second);
116 return 1;
118 int newindex(lua::state& L, const std::string& fname)
120 const char* c = L.tostring(2);
121 if(!c)
122 return 0;
123 std::string c2(c);
124 if(!mappings.count(c2))
125 return 0;
126 auto& x = mappings[c2];
127 x.first->write(L, x.second);
128 return 0;
130 static int create(lua::state& L, lua::parameters& P)
132 lua::_class<lua_mmap_struct>::create(L);
133 return 1;
135 int map(lua::state& L, const std::string& fname);
136 std::string print()
138 size_t s = mappings.size();
139 return (stringfmt() << s << " " << ((s != 1) ? "mappings" : "mapping")).str();
141 private:
142 std::map<std::string, std::pair<mmap_base*, uint64_t>> mappings;
145 namespace
147 int aperture_read_fun(lua_State* _L)
149 lua::state& L = *reinterpret_cast<lua::state*>(lua_touserdata(_L, lua_upvalueindex(4)));
150 uint64_t base = L.tonumber(lua_upvalueindex(1));
151 uint64_t size = 0xFFFFFFFFFFFFFFFFULL;
152 if(L.type(lua_upvalueindex(2)) == LUA_TNUMBER)
153 size = L.tonumber(lua_upvalueindex(2));
154 mmap_base* fn = reinterpret_cast<mmap_base*>(L.touserdata(lua_upvalueindex(3)));
155 uint64_t addr = L.get_numeric_argument<uint64_t>(2, "aperture(read)");
156 if(addr > size || addr + base < addr) {
157 L.pushnumber(0);
158 return 1;
160 addr += base;
161 fn->read(L, addr);
162 return 1;
165 int aperture_write_fun(lua_State* _L)
167 lua::state& L = *reinterpret_cast<lua::state*>(lua_touserdata(_L, lua_upvalueindex(4)));
168 uint64_t base = L.tonumber(lua_upvalueindex(1));
169 uint64_t size = 0xFFFFFFFFFFFFFFFFULL;
170 if(L.type(lua_upvalueindex(2)) == LUA_TNUMBER)
171 size = L.tonumber(lua_upvalueindex(2));
172 mmap_base* fn = reinterpret_cast<mmap_base*>(L.touserdata(lua_upvalueindex(3)));
173 uint64_t addr = L.get_numeric_argument<uint64_t>(2, "aperture(write)");
174 if(addr > size || addr + base < addr)
175 return 0;
176 addr += base;
177 fn->write(L, addr);
178 return 0;
181 void aperture_make_fun(lua::state& L, uint64_t base, uint64_t size, mmap_base& type)
183 L.newtable();
184 L.newtable();
185 L.pushstring( "__index");
186 L.pushnumber(base);
187 if(!(size + 1))
188 L.pushnil();
189 else
190 L.pushnumber(size);
191 L.pushlightuserdata(&type);
192 L.pushlightuserdata(&L);
193 L.pushcclosure(aperture_read_fun, 4);
194 L.settable(-3);
195 L.pushstring("__newindex");
196 L.pushnumber(base);
197 if(!(size + 1))
198 L.pushnil();
199 else
200 L.pushnumber(size);
201 L.pushlightuserdata(&type);
202 L.pushlightuserdata(&L);
203 L.pushcclosure(aperture_write_fun, 4);
204 L.settable(-3);
205 L.setmetatable(-2);
208 struct lua_debug_callback
210 uint64_t addr;
211 debug_type type;
212 debug_handle h;
213 bool dead;
214 const void* lua_fn;
215 static int dtor(lua_State* L)
217 lua_debug_callback* D = (lua_debug_callback*)lua_touserdata(L, 1);
218 return D->_dtor(L);
220 int _dtor(lua_State* L);
222 std::map<uint64_t, std::list<lua_debug_callback*>> cbs;
224 int lua_debug_callback::_dtor(lua_State* L)
226 if(dead) return 0;
227 dead = true;
228 lua_pushlightuserdata(L, &type);
229 lua_pushnil(L);
230 lua_rawset(L, LUA_REGISTRYINDEX);
231 debug_remove_callback(addr, type, h);
232 for(auto j = cbs[addr].begin(); j != cbs[addr].end(); j++)
233 if(*j == this) {
234 cbs[addr].erase(j);
235 break;
237 if(cbs[addr].empty())
238 cbs.erase(addr);
239 return 0;
242 void do_lua_error(lua::state& L, int ret)
244 if(!ret) return;
245 switch(ret) {
246 case LUA_ERRRUN:
247 messages << "Error in Lua memory callback: " << L.get_string(-1, "errhnd") << std::endl;
248 L.pop(1);
249 return;
250 case LUA_ERRMEM:
251 messages << "Error in Lua memory callback (Out of memory)" << std::endl;
252 return;
253 case LUA_ERRERR:
254 messages << "Error in Lua memory callback (Double fault)" << std::endl;
255 return;
256 default:
257 messages << "Error in Lua memory callback (\?\?\?)" << std::endl;
258 return;
262 template<debug_type type, bool reg> class lua_registerX : public lua::function
264 public:
265 lua_registerX(const std::string& name) : lua::function(lua_func_misc, name) {}
266 int invoke(lua::state& L)
268 uint64_t addr;
269 int base = 1;
270 if(L.type(1) == LUA_TNIL && type != DEBUG_TRACE) {
271 addr = 0xFFFFFFFFFFFFFFFFULL;
272 base = 2;
273 } else if(type != DEBUG_TRACE)
274 addr = get_read_address(L, base, fname.c_str());
275 else
276 addr = L.get_numeric_argument<uint64_t>(base++, fname.c_str());
277 if(L.type(base) != LUA_TFUNCTION)
278 throw std::runtime_error("Expected last argument to " + fname + " to be function");
279 if(reg) {
280 handle_registerX(L, addr, base);
281 L.pushvalue(base);
282 return 1;
283 } else {
284 handle_unregisterX(L, addr, base);
285 return 0;
288 void handle_registerX(lua::state& L, uint64_t addr, int lfn)
290 auto& cbl = cbs[addr];
292 //Put the context in userdata so it can be gc'd when Lua context is terminated.
293 lua_debug_callback* D = (lua_debug_callback*)L.newuserdata(sizeof(lua_debug_callback));
294 L.newtable();
295 L.pushstring("__gc");
296 L.pushcclosure(&lua_debug_callback::dtor, 0);
297 L.rawset(-3);
298 L.setmetatable(-2);
299 L.pushlightuserdata(&D->addr);
300 L.pushvalue(-2);
301 L.rawset(LUA_REGISTRYINDEX);
302 L.pop(1); //Pop the copy of object.
304 cbl.push_back(D);
306 D->dead = false;
307 D->addr = addr;
308 D->type = type;
309 D->lua_fn = L.topointer(lfn);
310 lua::state* LL = &L.get_master();
311 void* D2 = &D->type;
312 if(type != DEBUG_TRACE)
313 D->h = debug_add_callback(addr, type, [LL, D2](uint64_t addr, uint64_t value) {
314 LL->pushlightuserdata(D2);
315 LL->rawget(LUA_REGISTRYINDEX);
316 LL->pushnumber(addr);
317 LL->pushnumber(value);
318 do_lua_error(*LL, LL->pcall(2, 0, 0));
319 }, [LL, D]() {
320 LL->pushlightuserdata(&D->addr);
321 LL->pushnil();
322 LL->rawset(LUA_REGISTRYINDEX);
323 D->_dtor(LL->handle());
325 else
326 D->h = debug_add_trace_callback(addr, [LL, D2](uint64_t proc, const char* str) {
327 LL->pushlightuserdata(D2);
328 LL->rawget(LUA_REGISTRYINDEX);
329 LL->pushnumber(proc);
330 LL->pushstring(str);
331 do_lua_error(*LL, LL->pcall(2, 0, 0));
332 }, [LL, D]() {
333 LL->pushlightuserdata(&D->addr);
334 LL->pushnil();
335 LL->rawset(LUA_REGISTRYINDEX);
336 D->_dtor(LL->handle());
338 L.pushlightuserdata(D2);
339 L.pushvalue(lfn);
340 L.rawset(LUA_REGISTRYINDEX);
342 void handle_unregisterX(lua::state& L, uint64_t addr, int lfn)
344 if(!cbs.count(addr))
345 return;
346 auto& cbl = cbs[addr];
347 for(auto i = cbl.begin(); i != cbl.end(); i++) {
348 if((*i)->type != type) continue;
349 if(L.topointer(lfn) != (*i)->lua_fn) continue;
350 L.pushlightuserdata(&(*i)->type);
351 L.pushnil();
352 L.rawset(LUA_REGISTRYINDEX);
353 (*i)->_dtor(L.handle());
354 //Lua will GC the object.
355 break;
360 command::fnptr<> callbacks_show_lua(lsnes_cmd, "show-lua-callbacks", "", "",
361 []() throw(std::bad_alloc, std::runtime_error) {
362 for(auto& i : cbs)
363 for(auto& j : i.second)
364 messages << "addr=" << j->addr << " type=" << j->type << " handle="
365 << j->h.handle << " dead=" << j->dead << " lua_fn="
366 << j->lua_fn << std::endl;
369 class lua_mmap_memory : public lua::function
371 public:
372 lua_mmap_memory(const std::string& name, mmap_base& _h) : lua::function(lua_func_misc, name), h(_h) {}
373 int invoke(lua::state& L)
375 if(L.isnoneornil(1)) {
376 aperture_make_fun(L, 0, 0xFFFFFFFFFFFFFFFFULL, h);
377 return 1;
379 int base = 1;
380 uint64_t addr = get_read_address(L, base, "lua_mmap_memory");
381 uint64_t size = L.get_numeric_argument<uint64_t>(base, fname.c_str());
382 if(!size)
383 throw std::runtime_error("Aperture with zero size is not valid");
384 aperture_make_fun(L, addr, size - 1, h);
385 return 1;
387 mmap_base& h;
390 lua::fnptr vmacount(lua_func_misc, "memory.vma_count", [](lua::state& L, const std::string& fname)
391 -> int {
392 L.pushnumber(lsnes_memory.get_regions().size());
393 return 1;
396 lua::fnptr cheat(lua_func_misc, "memory.cheat", [](lua::state& L, const std::string& fname)
397 -> int {
398 int base = 1;
399 uint64_t addr = get_read_address(L, base, fname.c_str());
400 if(L.type(base) == LUA_TNIL || L.type(base) == LUA_TNONE) {
401 debug_clear_cheat(addr);
402 } else {
403 uint64_t value = L.get_numeric_argument<uint64_t>(base, fname.c_str());
404 debug_set_cheat(addr, value);
406 return 0;
409 lua::fnptr xmask(lua_func_misc, "memory.setxmask", [](lua::state& L, const std::string& fname)
410 -> int {
411 uint64_t value = L.get_numeric_argument<uint64_t>(1, fname.c_str());
412 debug_setxmask(value);
413 return 0;
416 int handle_push_vma(lua::state& L, memory_region& r)
418 L.newtable();
419 L.pushstring("region_name");
420 L.pushlstring(r.name.c_str(), r.name.size());
421 L.settable(-3);
422 L.pushstring("baseaddr");
423 L.pushnumber(r.base);
424 L.settable(-3);
425 L.pushstring("size");
426 L.pushnumber(r.size);
427 L.settable(-3);
428 L.pushstring("lastaddr");
429 L.pushnumber(r.last_address());
430 L.settable(-3);
431 L.pushstring("readonly");
432 L.pushboolean(r.readonly);
433 L.settable(-3);
434 L.pushstring("iospace");
435 L.pushboolean(r.special);
436 L.settable(-3);
437 L.pushstring("native_endian");
438 L.pushboolean(r.endian == 0);
439 L.settable(-3);
440 L.pushstring("endian");
441 L.pushnumber(r.endian);
442 L.settable(-3);
443 return 1;
446 lua::fnptr readvma(lua_func_misc, "memory.read_vma", [](lua::state& L, const std::string& fname)
447 -> int {
448 std::list<memory_region*> regions = lsnes_memory.get_regions();
449 uint32_t num = L.get_numeric_argument<uint32_t>(1, fname.c_str());
450 uint32_t j = 0;
451 for(auto i = regions.begin(); i != regions.end(); i++, j++)
452 if(j == num)
453 return handle_push_vma(L, **i);
454 L.pushnil();
455 return 1;
458 lua::fnptr findvma(lua_func_misc, "memory.find_vma", [](lua::state& L, const std::string& fname)
459 -> int {
460 uint64_t addr = L.get_numeric_argument<uint64_t>(1, fname.c_str());
461 auto r = lsnes_memory.lookup(addr);
462 if(r.first)
463 return handle_push_vma(L, *r.first);
464 L.pushnil();
465 return 1;
468 const char* hexes = "0123456789ABCDEF";
470 lua::fnptr hashstate(lua_func_misc, "memory.hash_state", [](lua::state& L, const std::string& fname)
471 -> int {
472 char hash[64];
473 auto x = our_rom.save_core_state();
474 size_t offset = x.size() - 32;
475 L.pushlstring(hex::b_to((uint8_t*)&x[offset], 32));
476 return 1;
479 #define BLOCKSIZE 256
481 lua::fnptr hashmemory(lua_func_misc, "memory.hash_region", [](lua::state& L, const std::string& fname)
482 -> int {
483 std::string hash;
484 int base = 1;
485 uint64_t addr = get_read_address(L, base, fname.c_str());
486 uint64_t size = L.get_numeric_argument<uint64_t>(base, fname.c_str());
487 char buffer[BLOCKSIZE];
488 sha256 h;
489 while(size > BLOCKSIZE) {
490 for(size_t i = 0; i < BLOCKSIZE; i++)
491 buffer[i] = lsnes_memory.read<uint8_t>(addr + i);
492 h.write(buffer, BLOCKSIZE);
493 addr += BLOCKSIZE;
494 size -= BLOCKSIZE;
496 for(size_t i = 0; i < size; i++)
497 buffer[i] = lsnes_memory.read<uint8_t>(addr + i);
498 h.write(buffer, size);
499 hash = h.read();
500 L.pushlstring(hash.c_str(), 64);
501 return 1;
504 lua::fnptr readmemoryr(lua_func_misc, "memory.readregion", [](lua::state& L, const std::string& fname)
505 -> int {
506 std::string hash;
507 int base = 1;
508 uint64_t addr = get_read_address(L, base, fname.c_str());
509 uint64_t size = L.get_numeric_argument<uint64_t>(base, fname.c_str());
510 L.newtable();
511 char buffer[BLOCKSIZE];
512 uint64_t ctr = 0;
513 while(size > 0) {
514 size_t rsize = min(size, static_cast<uint64_t>(BLOCKSIZE));
515 lsnes_memory.read_range(addr, buffer, rsize);
516 for(size_t i = 0; i < rsize; i++) {
517 L.pushnumber(ctr++);
518 L.pushnumber(static_cast<unsigned char>(buffer[i]));
519 L.settable(-3);
521 addr += rsize;
522 size -= rsize;
524 return 1;
527 lua::fnptr writememoryr(lua_func_misc, "memory.writeregion", [](lua::state& L,
528 const std::string& fname) -> int {
529 std::string hash;
530 int base = 1;
531 uint64_t addr = get_read_address(L, base, fname.c_str());
532 uint64_t size = L.get_numeric_argument<uint64_t>(base, fname.c_str());
533 char buffer[BLOCKSIZE];
534 uint64_t ctr = 0;
535 while(size > 0) {
536 size_t rsize = min(size, static_cast<uint64_t>(BLOCKSIZE));
537 for(size_t i = 0; i < rsize; i++) {
538 L.pushnumber(ctr++);
539 L.gettable(3);
540 buffer[i] = L.tointeger(-1);
541 L.pop(1);
543 lsnes_memory.write_range(addr, buffer, rsize);
544 addr += rsize;
545 size -= rsize;
547 return 1;
550 template<bool write, bool sign> int memory_scattergather(lua::state& L, const std::string& fname)
552 uint64_t val = 0;
553 int ptr = 1;
554 unsigned shift = 0;
555 uint64_t addr = 0;
556 uint64_t vmabase = 0;
557 if(write)
558 val = L.get_numeric_argument<uint64_t>(ptr++, fname.c_str());
559 while(L.type(ptr) != LUA_TNIL && L.type(ptr) != LUA_TNONE) {
560 if(L.type(ptr) == LUA_TBOOLEAN) {
561 if(L.toboolean(ptr++))
562 addr++;
563 else
564 addr--;
565 } else if(L.type(ptr) == LUA_TSTRING) {
566 vmabase = get_vmabase(L, L.get_string(ptr++, fname.c_str()));
567 continue;
568 } else
569 addr = L.get_numeric_argument<uint64_t>(ptr++, fname.c_str());
570 if(write)
571 lsnes_memory.write<uint8_t>(addr + vmabase, val >> shift);
572 else
573 val = val + ((uint64_t)lsnes_memory.read<uint8_t>(addr + vmabase) << shift);
574 shift += 8;
576 if(!write) {
577 int64_t sval = val;
578 if(val >= (1ULL << (shift - 1))) sval -= (1ULL << shift);
579 if(sign) L.pushnumber(sval); else L.pushnumber(val);
581 return write ? 0 : 1;
584 lua::fnptr scattergather1(lua_func_misc, "memory.read_sg", [](lua::state& L, const std::string& fname)
585 -> int {
586 return memory_scattergather<false, false>(L, fname);
589 lua::fnptr scattergather2(lua_func_misc, "memory.sread_sg", [](lua::state& L,
590 const std::string& fname) -> int {
591 return memory_scattergather<false, true>(L, fname);
594 lua::fnptr scattergather3(lua_func_misc, "memory.write_sg", [](lua::state& L,
595 const std::string& fname) -> int {
596 return memory_scattergather<true, false>(L, fname);
599 lua_read_memory<uint8_t, &memory_space::read<uint8_t>> rub("memory.readbyte");
600 lua_read_memory<int8_t, &memory_space::read<int8_t>> rsb("memory.readsbyte");
601 lua_read_memory<uint16_t, &memory_space::read<uint16_t>> ruw("memory.readword");
602 lua_read_memory<int16_t, &memory_space::read<int16_t>> rsw("memory.readsword");
603 lua_read_memory<ss_uint24_t, &memory_space::read<ss_uint24_t>> ruh("memory.readhword");
604 lua_read_memory<ss_int24_t, &memory_space::read<ss_int24_t>> rsh("memory.readshword");
605 lua_read_memory<uint32_t, &memory_space::read<uint32_t>> rud("memory.readdword");
606 lua_read_memory<int32_t, &memory_space::read<int32_t>> rsd("memory.readsdword");
607 lua_read_memory<uint64_t, &memory_space::read<uint64_t>> ruq("memory.readqword");
608 lua_read_memory<int64_t, &memory_space::read<int64_t>> rsq("memory.readsqword");
609 lua_read_memory<float, &memory_space::read<float>> rf4("memory.readfloat");
610 lua_read_memory<double, &memory_space::read<double>> rf8("memory.readdouble");
611 lua_write_memory<uint8_t, &memory_space::write<uint8_t>> wb("memory.writebyte");
612 lua_write_memory<uint16_t, &memory_space::write<uint16_t>> ww("memory.writeword");
613 lua_write_memory<ss_uint24_t, &memory_space::write<ss_uint24_t>> wh("memory.writehword");
614 lua_write_memory<uint32_t, &memory_space::write<uint32_t>> wd("memory.writedword");
615 lua_write_memory<uint64_t, &memory_space::write<uint64_t>> wq("memory.writeqword");
616 lua_write_memory<float, &memory_space::write<float>> wf4("memory.writefloat");
617 lua_write_memory<double, &memory_space::write<double>> wf8("memory.writedouble");
618 lua_mmap_memory_helper<uint8_t, &memory_space::read<uint8_t>, &memory_space::write<uint8_t>> mhub;
619 lua_mmap_memory_helper<int8_t, &memory_space::read<int8_t>, &memory_space::write<int8_t>> mhsb;
620 lua_mmap_memory_helper<uint16_t, &memory_space::read<uint16_t>, &memory_space::write<uint16_t>> mhuw;
621 lua_mmap_memory_helper<int16_t, &memory_space::read<int16_t>, &memory_space::write<int16_t>> mhsw;
622 lua_mmap_memory_helper<ss_uint24_t, &memory_space::read<ss_uint24_t>, &memory_space::write<ss_uint24_t>> mhuh;
623 lua_mmap_memory_helper<ss_int24_t, &memory_space::read<ss_int24_t>, &memory_space::write<ss_int24_t>> mhsh;
624 lua_mmap_memory_helper<uint32_t, &memory_space::read<uint32_t>, &memory_space::write<uint32_t>> mhud;
625 lua_mmap_memory_helper<int32_t, &memory_space::read<int32_t>, &memory_space::write<int32_t>> mhsd;
626 lua_mmap_memory_helper<uint64_t, &memory_space::read<uint64_t>, &memory_space::write<uint64_t>> mhuq;
627 lua_mmap_memory_helper<int64_t, &memory_space::read<int64_t>, &memory_space::write<int64_t>> mhsq;
628 lua_mmap_memory_helper<float, &memory_space::read<float>, &memory_space::write<float>> mhf4;
629 lua_mmap_memory_helper<double, &memory_space::read<double>, &memory_space::write<double>> mhf8;
630 lua_mmap_memory mub("memory.mapbyte", mhub);
631 lua_mmap_memory msb("memory.mapsbyte", mhsb);
632 lua_mmap_memory muw("memory.mapword", mhuw);
633 lua_mmap_memory msw("memory.mapsword", mhsw);
634 lua_mmap_memory muh("memory.maphword", mhuh);
635 lua_mmap_memory msh("memory.mapshword", mhsh);
636 lua_mmap_memory mud("memory.mapdword", mhud);
637 lua_mmap_memory msd("memory.mapsdword", mhsd);
638 lua_mmap_memory muq("memory.mapqword", mhuq);
639 lua_mmap_memory msq("memory.mapsqword", mhsq);
640 lua_mmap_memory mf4("memory.mapfloat", mhf4);
641 lua_mmap_memory mf8("memory.mapdouble", mhf8);
642 lua_registerX<DEBUG_READ, true> mrr("memory.registerread");
643 lua_registerX<DEBUG_READ, false> murr("memory.unregisterread");
644 lua_registerX<DEBUG_WRITE, true> mrw("memory.registerwrite");
645 lua_registerX<DEBUG_WRITE, false> murw("memory.unregisterwrite");
646 lua_registerX<DEBUG_EXEC, true> mrx("memory.registerexec");
647 lua_registerX<DEBUG_EXEC, false> murx("memory.unregisterexec");
648 lua_registerX<DEBUG_TRACE, true> mrt("memory.registertrace");
649 lua_registerX<DEBUG_TRACE, false> murt("memory.unregistertrace");
651 lua::_class<lua_mmap_struct> class_mmap_struct(lua_class_memory, "MMAP_STRUCT", {
652 {"new", &lua_mmap_struct::create},
653 }, {
654 {"__index", &lua_mmap_struct::index},
655 {"__newindex", &lua_mmap_struct::newindex},
656 {"__call", &lua_mmap_struct::map},
660 int lua_mmap_struct::map(lua::state& L, const std::string& fname)
662 const char* name = L.tostring(2);
663 int base = 0;
664 uint64_t vmabase = 0;
665 if(L.type(3) == LUA_TSTRING) {
666 vmabase = get_vmabase(L, L.get_string(3, fname.c_str()));
667 base = 1;
669 uint64_t addr = L.get_numeric_argument<uint64_t>(base + 3, fname.c_str());
670 const char* type = L.tostring(base + 4);
671 if(!name)
672 (stringfmt() << fname << ": Bad name").throwex();
673 if(!type)
674 (stringfmt() << fname << ": Bad type").throwex();
675 std::string name2(name);
676 std::string type2(type);
677 if(type2 == "byte")
678 mappings[name2] = std::make_pair(&mhub, addr);
679 else if(type2 == "sbyte")
680 mappings[name2] = std::make_pair(&mhsb, addr);
681 else if(type2 == "word")
682 mappings[name2] = std::make_pair(&mhuw, addr);
683 else if(type2 == "sword")
684 mappings[name2] = std::make_pair(&mhsw, addr);
685 else if(type2 == "hword")
686 mappings[name2] = std::make_pair(&mhuh, addr);
687 else if(type2 == "shword")
688 mappings[name2] = std::make_pair(&mhsh, addr);
689 else if(type2 == "dword")
690 mappings[name2] = std::make_pair(&mhud, addr);
691 else if(type2 == "sdword")
692 mappings[name2] = std::make_pair(&mhsd, addr);
693 else if(type2 == "qword")
694 mappings[name2] = std::make_pair(&mhuq, addr);
695 else if(type2 == "sqword")
696 mappings[name2] = std::make_pair(&mhsq, addr);
697 else if(type2 == "float")
698 mappings[name2] = std::make_pair(&mhf4, addr);
699 else if(type2 == "double")
700 mappings[name2] = std::make_pair(&mhf8, addr);
701 else
702 (stringfmt() << fname << ": Bad type").throwex();
703 return 0;
706 lua_mmap_struct::lua_mmap_struct(lua::state& L)