Cleanup lua code by introducing lua::functions
[lsnes.git] / src / lua / memory.cpp
blob9770b6a2622ca8ac617e425ee66e4997ec5aa4cb
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(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::parameters& P)
27 uint64_t vmabase = 0;
28 if(P.is_string())
29 vmabase = get_vmabase(P.arg<std::string>());
30 auto addr = P.arg<uint64_t>();
31 return addr + vmabase;
34 template<typename T, T (memory_space::*rfun)(uint64_t addr),
35 bool (memory_space::*wfun)(uint64_t addr, T value)>
36 void do_rw(lua::state& L, uint64_t addr, bool wrflag)
38 if(wrflag) {
39 T value = L.get_numeric_argument<T>(3, "aperture(write)");
40 (lsnes_memory.*wfun)(addr, value);
41 } else
42 L.pushnumber(static_cast<T>((lsnes_memory.*rfun)(addr)));
45 template<typename T, T (memory_space::*rfun)(uint64_t addr)>
46 int lua_read_memory(lua::state& L, lua::parameters& P)
48 auto addr = get_read_address(P);
49 L.pushnumber(static_cast<T>((lsnes_memory.*rfun)(addr)));
50 return 1;
53 template<typename T, bool (memory_space::*wfun)(uint64_t addr, T value)>
54 int lua_write_memory(lua::state& L, lua::parameters& P)
56 auto addr = get_read_address(P);
57 T value = P.arg<T>();
58 (lsnes_memory.*wfun)(addr, value);
59 return 0;
63 class lua_mmap_struct
65 public:
66 lua_mmap_struct(lua::state& L);
68 ~lua_mmap_struct()
72 int index(lua::state& L, lua::parameters& P)
74 const char* c = L.tostring(2);
75 if(!c) {
76 L.pushnil();
77 return 1;
79 std::string c2(c);
80 if(!mappings.count(c2)) {
81 L.pushnil();
82 return 1;
84 auto& x = mappings[c2];
85 x.rw(L, x.addr, false);
86 return 1;
88 int newindex(lua::state& L, lua::parameters& P)
90 const char* c = L.tostring(2);
91 if(!c)
92 return 0;
93 std::string c2(c);
94 if(!mappings.count(c2))
95 return 0;
96 auto& x = mappings[c2];
97 x.rw(L, x.addr, true);
98 return 0;
100 static int create(lua::state& L, lua::parameters& P)
102 lua::_class<lua_mmap_struct>::create(L);
103 return 1;
105 int map(lua::state& L, lua::parameters& P);
106 std::string print()
108 size_t s = mappings.size();
109 return (stringfmt() << s << " " << ((s != 1) ? "mappings" : "mapping")).str();
111 private:
112 struct mapping
114 mapping() {}
115 mapping(uint64_t _addr, void (*_rw)(lua::state& L, uint64_t addr, bool wrflag))
116 : addr(_addr), rw(_rw)
119 uint64_t addr;
120 void (*rw)(lua::state& L, uint64_t addr, bool wrflag);
122 std::map<std::string, mapping> mappings;
125 namespace
127 template<typename T, T (memory_space::*rfun)(uint64_t addr)>
128 int aperture_read_fun(lua_State* _L)
130 lua::state& mL = *reinterpret_cast<lua::state*>(lua_touserdata(_L, lua_upvalueindex(3)));
131 lua::state L(mL, _L);
133 uint64_t base = L.tonumber(lua_upvalueindex(1));
134 uint64_t size = 0xFFFFFFFFFFFFFFFFULL;
135 if(L.type(lua_upvalueindex(2)) == LUA_TNUMBER)
136 size = L.tonumber(lua_upvalueindex(2));
137 uint64_t addr = L.get_numeric_argument<uint64_t>(2, "aperture(read)");
138 if(addr > size || addr + base < addr) {
139 L.pushnumber(0);
140 return 1;
142 addr += base;
143 L.pushnumber(static_cast<T>((lsnes_memory.*rfun)(addr)));
144 return 1;
147 template<typename T, bool (memory_space::*wfun)(uint64_t addr, T value)>
148 int aperture_write_fun(lua_State* _L)
150 lua::state& mL = *reinterpret_cast<lua::state*>(lua_touserdata(_L, lua_upvalueindex(3)));
151 lua::state L(mL, _L);
153 uint64_t base = L.tonumber(lua_upvalueindex(1));
154 uint64_t size = 0xFFFFFFFFFFFFFFFFULL;
155 if(L.type(lua_upvalueindex(2)) == LUA_TNUMBER)
156 size = L.tonumber(lua_upvalueindex(2));
157 uint64_t addr = L.get_numeric_argument<uint64_t>(2, "aperture(write)");
158 if(addr > size || addr + base < addr)
159 return 0;
160 addr += base;
161 T value = L.get_numeric_argument<T>(3, "aperture(write)");
162 (lsnes_memory.*wfun)(addr, value);
163 return 0;
166 template<typename T, T (memory_space::*rfun)(uint64_t addr), bool (memory_space::*wfun)(uint64_t addr,
167 T value)>
168 void aperture_make_fun(lua::state& L, uint64_t base, uint64_t size)
170 L.newtable();
171 L.newtable();
172 L.pushstring( "__index");
173 L.pushnumber(base);
174 if(!(size + 1))
175 L.pushnil();
176 else
177 L.pushnumber(size);
178 L.pushlightuserdata(&L);
179 L.pushcclosure(aperture_read_fun<T, rfun>, 3);
180 L.settable(-3);
181 L.pushstring("__newindex");
182 L.pushnumber(base);
183 if(!(size + 1))
184 L.pushnil();
185 else
186 L.pushnumber(size);
187 L.pushlightuserdata(&L);
188 L.pushcclosure(aperture_write_fun<T, wfun>, 3);
189 L.settable(-3);
190 L.setmetatable(-2);
193 struct lua_debug_callback
195 uint64_t addr;
196 debug_type type;
197 debug_handle h;
198 bool dead;
199 const void* lua_fn;
200 static int dtor(lua_State* L)
202 lua_debug_callback* D = (lua_debug_callback*)lua_touserdata(L, 1);
203 return D->_dtor(L);
205 int _dtor(lua_State* L);
207 std::map<uint64_t, std::list<lua_debug_callback*>> cbs;
209 int lua_debug_callback::_dtor(lua_State* L)
211 if(dead) return 0;
212 dead = true;
213 lua_pushlightuserdata(L, &type);
214 lua_pushnil(L);
215 lua_rawset(L, LUA_REGISTRYINDEX);
216 debug_remove_callback(addr, type, h);
217 for(auto j = cbs[addr].begin(); j != cbs[addr].end(); j++)
218 if(*j == this) {
219 cbs[addr].erase(j);
220 break;
222 if(cbs[addr].empty())
223 cbs.erase(addr);
224 return 0;
227 void do_lua_error(lua::state& L, int ret)
229 if(!ret) return;
230 switch(ret) {
231 case LUA_ERRRUN:
232 messages << "Error in Lua memory callback: " << L.get_string(-1, "errhnd") << std::endl;
233 L.pop(1);
234 return;
235 case LUA_ERRMEM:
236 messages << "Error in Lua memory callback (Out of memory)" << std::endl;
237 return;
238 case LUA_ERRERR:
239 messages << "Error in Lua memory callback (Double fault)" << std::endl;
240 return;
241 default:
242 messages << "Error in Lua memory callback (\?\?\?)" << std::endl;
243 return;
247 template<debug_type type, bool reg>
248 void handle_registerX(lua::state& L, uint64_t addr, int lfn)
250 auto& cbl = cbs[addr];
252 //Put the context in userdata so it can be gc'd when Lua context is terminated.
253 lua_debug_callback* D = (lua_debug_callback*)L.newuserdata(sizeof(lua_debug_callback));
254 L.newtable();
255 L.pushstring("__gc");
256 L.pushcclosure(&lua_debug_callback::dtor, 0);
257 L.rawset(-3);
258 L.setmetatable(-2);
259 L.pushlightuserdata(&D->addr);
260 L.pushvalue(-2);
261 L.rawset(LUA_REGISTRYINDEX);
262 L.pop(1); //Pop the copy of object.
264 cbl.push_back(D);
266 D->dead = false;
267 D->addr = addr;
268 D->type = type;
269 D->lua_fn = L.topointer(lfn);
270 lua::state* LL = &L.get_master();
271 void* D2 = &D->type;
272 if(type != DEBUG_TRACE)
273 D->h = debug_add_callback(addr, type, [LL, D2](uint64_t addr, uint64_t value) {
274 LL->pushlightuserdata(D2);
275 LL->rawget(LUA_REGISTRYINDEX);
276 LL->pushnumber(addr);
277 LL->pushnumber(value);
278 do_lua_error(*LL, LL->pcall(2, 0, 0));
279 }, [LL, D]() {
280 LL->pushlightuserdata(&D->addr);
281 LL->pushnil();
282 LL->rawset(LUA_REGISTRYINDEX);
283 D->_dtor(LL->handle());
285 else
286 D->h = debug_add_trace_callback(addr, [LL, D2](uint64_t proc, const char* str) {
287 LL->pushlightuserdata(D2);
288 LL->rawget(LUA_REGISTRYINDEX);
289 LL->pushnumber(proc);
290 LL->pushstring(str);
291 do_lua_error(*LL, LL->pcall(2, 0, 0));
292 }, [LL, D]() {
293 LL->pushlightuserdata(&D->addr);
294 LL->pushnil();
295 LL->rawset(LUA_REGISTRYINDEX);
296 D->_dtor(LL->handle());
298 L.pushlightuserdata(D2);
299 L.pushvalue(lfn);
300 L.rawset(LUA_REGISTRYINDEX);
303 template<debug_type type, bool reg>
304 void handle_unregisterX(lua::state& L, uint64_t addr, int lfn)
306 if(!cbs.count(addr))
307 return;
308 auto& cbl = cbs[addr];
309 for(auto i = cbl.begin(); i != cbl.end(); i++) {
310 if((*i)->type != type) continue;
311 if(L.topointer(lfn) != (*i)->lua_fn) continue;
312 L.pushlightuserdata(&(*i)->type);
313 L.pushnil();
314 L.rawset(LUA_REGISTRYINDEX);
315 (*i)->_dtor(L.handle());
316 //Lua will GC the object.
317 break;
321 template<debug_type type, bool reg>
322 int lua_registerX(lua::state& L, lua::parameters& P)
324 uint64_t addr;
325 int lfn;
326 if(P.is_nil() && type != DEBUG_TRACE) {
327 addr = 0xFFFFFFFFFFFFFFFFULL;
328 P.skip();
329 } else if(type != DEBUG_TRACE)
330 addr = get_read_address(P);
331 else
332 P(addr);
333 P(P.function(lfn));
335 if(reg) {
336 handle_registerX<type, reg>(L, addr, lfn);
337 L.pushvalue(lfn);
338 return 1;
339 } else {
340 handle_unregisterX<type, reg>(L, addr, lfn);
341 return 0;
345 command::fnptr<> callbacks_show_lua(lsnes_cmd, "show-lua-callbacks", "", "",
346 []() throw(std::bad_alloc, std::runtime_error) {
347 for(auto& i : cbs)
348 for(auto& j : i.second)
349 messages << "addr=" << j->addr << " type=" << j->type << " handle="
350 << j->h.handle << " dead=" << j->dead << " lua_fn="
351 << j->lua_fn << std::endl;
354 template<typename T, T (memory_space::*rfun)(uint64_t addr), bool (memory_space::*wfun)(uint64_t addr,
355 T value)>
356 int lua_mmap_memory(lua::state& L, lua::parameters& P)
358 if(P.is_novalue()) {
359 aperture_make_fun<T, rfun, wfun>(L.get_master(), 0, 0xFFFFFFFFFFFFFFFFULL);
360 return 1;
362 auto addr = get_read_address(P);
363 auto size = P.arg<uint64_t>();
364 if(!size)
365 throw std::runtime_error("Aperture with zero size is not valid");
366 aperture_make_fun<T, rfun, wfun>(L.get_master(), addr, size - 1);
367 return 1;
370 int handle_push_vma(lua::state& L, memory_region& r)
372 L.newtable();
373 L.pushstring("region_name");
374 L.pushlstring(r.name.c_str(), r.name.size());
375 L.settable(-3);
376 L.pushstring("baseaddr");
377 L.pushnumber(r.base);
378 L.settable(-3);
379 L.pushstring("size");
380 L.pushnumber(r.size);
381 L.settable(-3);
382 L.pushstring("lastaddr");
383 L.pushnumber(r.last_address());
384 L.settable(-3);
385 L.pushstring("readonly");
386 L.pushboolean(r.readonly);
387 L.settable(-3);
388 L.pushstring("iospace");
389 L.pushboolean(r.special);
390 L.settable(-3);
391 L.pushstring("native_endian");
392 L.pushboolean(r.endian == 0);
393 L.settable(-3);
394 L.pushstring("endian");
395 L.pushnumber(r.endian);
396 L.settable(-3);
397 return 1;
400 template<bool write, bool sign> int memory_scattergather(lua::state& L, lua::parameters& P)
402 uint64_t val = 0;
403 unsigned shift = 0;
404 uint64_t addr = 0;
405 uint64_t vmabase = 0;
406 if(write)
407 val = P.arg<uint64_t>();
408 while(P.more()) {
409 if(P.is_boolean()) {
410 if(P.arg<bool>())
411 addr++;
412 else
413 addr--;
414 } else if(P.is_string()) {
415 vmabase = get_vmabase(P.arg<std::string>());
416 continue;
417 } else
418 addr = P.arg<uint64_t>();
419 if(write)
420 lsnes_memory.write<uint8_t>(addr + vmabase, val >> shift);
421 else
422 val = val + ((uint64_t)lsnes_memory.read<uint8_t>(addr + vmabase) << shift);
423 shift += 8;
425 if(!write) {
426 int64_t sval = val;
427 if(val >= (1ULL << (shift - 1))) sval -= (1ULL << shift);
428 if(sign) L.pushnumber(sval); else L.pushnumber(val);
430 return write ? 0 : 1;
433 const char* hexes = "0123456789ABCDEF";
435 #define BLOCKSIZE 256
437 int vma_count(lua::state& L, lua::parameters& P)
439 L.pushnumber(lsnes_memory.get_regions().size());
440 return 1;
443 int cheat(lua::state& L, lua::parameters& P)
445 uint64_t addr, value;
447 addr = get_read_address(P);
449 if(P.is_novalue()) {
450 debug_clear_cheat(addr);
451 } else {
452 P(value);
453 debug_set_cheat(addr, value);
455 return 0;
458 int setxmask(lua::state& L, lua::parameters& P)
460 auto value = P.arg<uint64_t>();
461 debug_setxmask(value);
462 return 0;
465 int read_vma(lua::state& L, lua::parameters& P)
467 uint32_t num;
469 P(num);
471 std::list<memory_region*> regions = lsnes_memory.get_regions();
472 uint32_t j = 0;
473 for(auto i = regions.begin(); i != regions.end(); i++, j++)
474 if(j == num)
475 return handle_push_vma(L, **i);
476 L.pushnil();
477 return 1;
480 int find_vma(lua::state& L, lua::parameters& P)
482 uint64_t addr;
484 P(addr);
486 auto r = lsnes_memory.lookup(addr);
487 if(r.first)
488 return handle_push_vma(L, *r.first);
489 L.pushnil();
490 return 1;
493 int hash_state(lua::state& L, lua::parameters& P)
495 char hash[64];
496 auto x = our_rom.save_core_state();
497 size_t offset = x.size() - 32;
498 L.pushlstring(hex::b_to((uint8_t*)&x[offset], 32));
499 return 1;
502 int hash_region(lua::state& L, lua::parameters& P)
504 std::string hash;
505 uint64_t addr, size;
507 addr = get_read_address(P);
508 P(size);
510 char buffer[BLOCKSIZE];
511 sha256 h;
512 while(size > BLOCKSIZE) {
513 for(size_t i = 0; i < BLOCKSIZE; i++)
514 buffer[i] = lsnes_memory.read<uint8_t>(addr + i);
515 h.write(buffer, BLOCKSIZE);
516 addr += BLOCKSIZE;
517 size -= BLOCKSIZE;
519 for(size_t i = 0; i < size; i++)
520 buffer[i] = lsnes_memory.read<uint8_t>(addr + i);
521 h.write(buffer, size);
522 hash = h.read();
523 L.pushlstring(hash.c_str(), 64);
524 return 1;
527 int readregion(lua::state& L, lua::parameters& P)
529 uint64_t addr, size;
531 addr = get_read_address(P);
532 P(size);
534 L.newtable();
535 char buffer[BLOCKSIZE];
536 uint64_t ctr = 0;
537 while(size > 0) {
538 size_t rsize = min(size, static_cast<uint64_t>(BLOCKSIZE));
539 lsnes_memory.read_range(addr, buffer, rsize);
540 for(size_t i = 0; i < rsize; i++) {
541 L.pushnumber(ctr++);
542 L.pushnumber(static_cast<unsigned char>(buffer[i]));
543 L.settable(-3);
545 addr += rsize;
546 size -= rsize;
548 return 1;
551 int writeregion(lua::state& L, lua::parameters& P)
553 uint64_t addr, size;
554 int ltbl;
556 addr = get_read_address(P);
557 P(size, P.table(ltbl));
559 char buffer[BLOCKSIZE];
560 uint64_t ctr = 0;
561 while(size > 0) {
562 size_t rsize = min(size, static_cast<uint64_t>(BLOCKSIZE));
563 for(size_t i = 0; i < rsize; i++) {
564 L.pushnumber(ctr++);
565 L.gettable(ltbl);
566 buffer[i] = L.tointeger(-1);
567 L.pop(1);
569 lsnes_memory.write_range(addr, buffer, rsize);
570 addr += rsize;
571 size -= rsize;
573 return 1;
576 lua::functions memoryfuncs(lua_func_misc, "memory", {
577 {"vma_count", vma_count},
578 {"cheat", cheat},
579 {"setxmask", setxmask},
580 {"read_vma", read_vma},
581 {"find_vma", find_vma},
582 {"hash_state", hash_state},
583 {"hash_region", hash_region},
584 {"readregion", readregion},
585 {"writeregion", readregion},
586 {"read_sg", memory_scattergather<false, false>},
587 {"sread_sg", memory_scattergather<false, true>},
588 {"write_sg", memory_scattergather<true, false>},
589 {"readbyte", lua_read_memory<uint8_t, &memory_space::read<uint8_t>>},
590 {"readsbyte", lua_read_memory<int8_t, &memory_space::read<int8_t>>},
591 {"readword", lua_read_memory<uint16_t, &memory_space::read<uint16_t>>},
592 {"readsword", lua_read_memory<int16_t, &memory_space::read<int16_t>>},
593 {"readhword", lua_read_memory<ss_uint24_t, &memory_space::read<ss_uint24_t>>},
594 {"readshword", lua_read_memory<ss_int24_t, &memory_space::read<ss_int24_t>>},
595 {"readdword", lua_read_memory<uint32_t, &memory_space::read<uint32_t>>},
596 {"readsdword", lua_read_memory<int32_t, &memory_space::read<int32_t>>},
597 {"readqword", lua_read_memory<uint64_t, &memory_space::read<uint64_t>>},
598 {"readsqword", lua_read_memory<int64_t, &memory_space::read<int64_t>>},
599 {"readfloat", lua_read_memory<float, &memory_space::read<float>>},
600 {"readdouble", lua_read_memory<double, &memory_space::read<double>>},
601 {"writebyte", lua_write_memory<uint8_t, &memory_space::write<uint8_t>>},
602 {"writeword", lua_write_memory<uint16_t, &memory_space::write<uint16_t>>},
603 {"writehword", lua_write_memory<ss_uint24_t, &memory_space::write<ss_uint24_t>>},
604 {"writedword", lua_write_memory<uint32_t, &memory_space::write<uint32_t>>},
605 {"writeqword", lua_write_memory<uint64_t, &memory_space::write<uint64_t>>},
606 {"writefloat", lua_write_memory<float, &memory_space::write<float>>},
607 {"writedouble", lua_write_memory<double, &memory_space::write<double>>},
608 {"mapbyte", lua_mmap_memory<uint8_t, &memory_space::read<uint8_t>, &memory_space::write<uint8_t>>},
609 {"mapsbyte", lua_mmap_memory<int8_t, &memory_space::read<int8_t>, &memory_space::write<int8_t>>},
610 {"mapword", lua_mmap_memory<uint16_t, &memory_space::read<uint16_t>, &memory_space::write<uint16_t>>},
611 {"mapsword", lua_mmap_memory<int16_t, &memory_space::read<int16_t>, &memory_space::write<int16_t>>},
612 {"maphword", lua_mmap_memory<ss_uint24_t, &memory_space::read<ss_uint24_t>,
613 &memory_space::write<ss_uint24_t>>},
614 {"mapshword", lua_mmap_memory<ss_int24_t, &memory_space::read<ss_int24_t>,
615 &memory_space::write<ss_int24_t>>},
616 {"mapdword", lua_mmap_memory<uint32_t, &memory_space::read<uint32_t>,
617 &memory_space::write<uint32_t>>},
618 {"mapsdword", lua_mmap_memory<int32_t, &memory_space::read<int32_t>, &memory_space::write<int32_t>>},
619 {"mapqword", lua_mmap_memory<uint64_t, &memory_space::read<uint64_t>,
620 &memory_space::write<uint64_t>>},
621 {"mapsqword", lua_mmap_memory<int64_t, &memory_space::read<int64_t>, &memory_space::write<int64_t>>},
622 {"mapfloat", lua_mmap_memory<float, &memory_space::read<float>, &memory_space::write<float>>},
623 {"mapdouble", lua_mmap_memory<double, &memory_space::read<double>, &memory_space::write<double>>},
624 {"registerread", lua_registerX<DEBUG_READ, true>},
625 {"unregisterread", lua_registerX<DEBUG_READ, false>},
626 {"registerwrite", lua_registerX<DEBUG_WRITE, true>},
627 {"unregisterwrite", lua_registerX<DEBUG_WRITE, false>},
628 {"registerexec", lua_registerX<DEBUG_EXEC, true>},
629 {"unregisterexec", lua_registerX<DEBUG_EXEC, false>},
630 {"registertrace", lua_registerX<DEBUG_TRACE, true>},
631 {"unregistertrace", lua_registerX<DEBUG_TRACE, false>},
634 lua::_class<lua_mmap_struct> class_mmap_struct(lua_class_memory, "MMAP_STRUCT", {
635 {"new", &lua_mmap_struct::create},
636 }, {
637 {"__index", &lua_mmap_struct::index},
638 {"__newindex", &lua_mmap_struct::newindex},
639 {"__call", &lua_mmap_struct::map},
640 }, &lua_mmap_struct::print);
643 int lua_mmap_struct::map(lua::state& L, lua::parameters& P)
645 std::string name, type;
646 uint64_t vmabase = 0, addr;
648 P(P.skipped(), name);
649 if(P.is_string())
650 vmabase = get_vmabase(P.arg<std::string>());
651 P(addr, type);
652 addr += vmabase;
654 if(type == "byte")
655 mappings[name] = mapping(addr, do_rw<uint8_t, &memory_space::read<uint8_t>,
656 &memory_space::write<uint8_t>>);
657 else if(type == "sbyte")
658 mappings[name] = mapping(addr, do_rw<int8_t, &memory_space::read<int8_t>,
659 &memory_space::write<int8_t>>);
660 else if(type == "word")
661 mappings[name] = mapping(addr, do_rw<uint16_t, &memory_space::read<uint16_t>,
662 &memory_space::write<uint16_t>>);
663 else if(type == "sword")
664 mappings[name] = mapping(addr, do_rw<int16_t, &memory_space::read<int16_t>,
665 &memory_space::write<int16_t>>);
666 else if(type == "hword")
667 mappings[name] = mapping(addr, do_rw<ss_uint24_t, &memory_space::read<ss_uint24_t>,
668 &memory_space::write<ss_uint24_t>>);
669 else if(type == "shword")
670 mappings[name] = mapping(addr, do_rw<ss_int24_t, &memory_space::read<ss_int24_t>,
671 &memory_space::write<ss_int24_t>>);
672 else if(type == "dword")
673 mappings[name] = mapping(addr, do_rw<uint32_t, &memory_space::read<uint32_t>,
674 &memory_space::write<uint32_t>>);
675 else if(type == "sdword")
676 mappings[name] = mapping(addr, do_rw<int32_t, &memory_space::read<int32_t>,
677 &memory_space::write<int32_t>>);
678 else if(type == "qword")
679 mappings[name] = mapping(addr, do_rw<uint64_t, &memory_space::read<uint64_t>,
680 &memory_space::write<uint64_t>>);
681 else if(type == "sqword")
682 mappings[name] = mapping(addr, do_rw<int64_t, &memory_space::read<int64_t>,
683 &memory_space::write<int64_t>>);
684 else if(type == "float")
685 mappings[name] = mapping(addr, do_rw<float, &memory_space::read<float>,
686 &memory_space::write<float>>);
687 else if(type == "double")
688 mappings[name] = mapping(addr, do_rw<double, &memory_space::read<double>,
689 &memory_space::write<double>>);
690 else
691 (stringfmt() << P.get_fname() << ": Bad type").throwex();
692 return 0;
695 lua_mmap_struct::lua_mmap_struct(lua::state& L)