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/skein.hpp"
12 #include "library/minmax.hpp"
13 #include "library/hex.hpp"
14 #include "library/int24.hpp"
16 uint64_t lua_get_vmabase(const std::string
& vma
)
18 for(auto i
: lsnes_memory
.get_regions())
21 throw std::runtime_error("No such VMA");
24 uint64_t lua_get_read_address(lua::parameters
& P
)
26 static std::map
<std::string
, char> deprecation_keys
;
27 char* deprecation
= &deprecation_keys
[P
.get_fname()];
30 vmabase
= lua_get_vmabase(P
.arg
<std::string
>());
33 if(P
.get_state().do_once(deprecation
))
34 messages
<< P
.get_fname() << ": Global memory form is deprecated." << std::endl
;
36 auto addr
= P
.arg
<uint64_t>();
37 return addr
+ vmabase
;
42 template<typename T
, T (memory_space::*rfun
)(uint64_t addr
),
43 bool (memory_space::*wfun
)(uint64_t addr
, T value
)>
44 void do_rw(lua::state
& L
, uint64_t addr
, bool wrflag
)
47 T value
= L
.get_numeric_argument
<T
>(3, "aperture(write)");
48 (lsnes_memory
.*wfun
)(addr
, value
);
50 L
.pushnumber(static_cast<T
>((lsnes_memory
.*rfun
)(addr
)));
53 template<typename T
, T (memory_space::*rfun
)(uint64_t addr
)>
54 int lua_read_memory(lua::state
& L
, lua::parameters
& P
)
56 auto addr
= lua_get_read_address(P
);
57 L
.pushnumber(static_cast<T
>((lsnes_memory
.*rfun
)(addr
)));
61 template<typename T
, bool (memory_space::*wfun
)(uint64_t addr
, T value
)>
62 int lua_write_memory(lua::state
& L
, lua::parameters
& P
)
64 auto addr
= lua_get_read_address(P
);
66 (lsnes_memory
.*wfun
)(addr
, value
);
74 lua_mmap_struct(lua::state
& L
);
75 static size_t overcommit() { return 0; }
81 int index(lua::state
& L
, lua::parameters
& P
)
83 const char* c
= L
.tostring(2);
89 if(!mappings
.count(c2
)) {
93 auto& x
= mappings
[c2
];
94 x
.rw(L
, x
.addr
, false);
97 int newindex(lua::state
& L
, lua::parameters
& P
)
99 const char* c
= L
.tostring(2);
103 if(!mappings
.count(c2
))
105 auto& x
= mappings
[c2
];
106 x
.rw(L
, x
.addr
, true);
109 static int create(lua::state
& L
, lua::parameters
& P
)
111 lua::_class
<lua_mmap_struct
>::create(L
);
114 int map(lua::state
& L
, lua::parameters
& P
);
117 size_t s
= mappings
.size();
118 return (stringfmt() << s
<< " " << ((s
!= 1) ? "mappings" : "mapping")).str();
124 mapping(uint64_t _addr
, void (*_rw
)(lua::state
& L
, uint64_t addr
, bool wrflag
))
125 : addr(_addr
), rw(_rw
)
129 void (*rw
)(lua::state
& L
, uint64_t addr
, bool wrflag
);
131 std::map
<std::string
, mapping
> mappings
;
136 template<typename T
, T (memory_space::*rfun
)(uint64_t addr
)>
137 int aperture_read_fun(lua_State
* _L
)
139 lua::state
& mL
= *reinterpret_cast<lua::state
*>(lua_touserdata(_L
, lua_upvalueindex(3)));
140 lua::state
L(mL
, _L
);
142 uint64_t base
= L
.tonumber(lua_upvalueindex(1));
143 uint64_t size
= 0xFFFFFFFFFFFFFFFFULL
;
144 if(L
.type(lua_upvalueindex(2)) == LUA_TNUMBER
)
145 size
= L
.tonumber(lua_upvalueindex(2));
146 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(2, "aperture(read)");
147 if(addr
> size
|| addr
+ base
< addr
) {
152 L
.pushnumber(static_cast<T
>((lsnes_memory
.*rfun
)(addr
)));
156 template<typename T
, bool (memory_space::*wfun
)(uint64_t addr
, T value
)>
157 int aperture_write_fun(lua_State
* _L
)
159 lua::state
& mL
= *reinterpret_cast<lua::state
*>(lua_touserdata(_L
, lua_upvalueindex(3)));
160 lua::state
L(mL
, _L
);
162 uint64_t base
= L
.tonumber(lua_upvalueindex(1));
163 uint64_t size
= 0xFFFFFFFFFFFFFFFFULL
;
164 if(L
.type(lua_upvalueindex(2)) == LUA_TNUMBER
)
165 size
= L
.tonumber(lua_upvalueindex(2));
166 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(2, "aperture(write)");
167 if(addr
> size
|| addr
+ base
< addr
)
170 T value
= L
.get_numeric_argument
<T
>(3, "aperture(write)");
171 (lsnes_memory
.*wfun
)(addr
, value
);
175 template<typename T
, T (memory_space::*rfun
)(uint64_t addr
), bool (memory_space::*wfun
)(uint64_t addr
,
177 void aperture_make_fun(lua::state
& L
, uint64_t base
, uint64_t size
)
181 L
.pushstring( "__index");
187 L
.pushlightuserdata(&L
);
188 L
.pushcclosure(aperture_read_fun
<T
, rfun
>, 3);
190 L
.pushstring("__newindex");
196 L
.pushlightuserdata(&L
);
197 L
.pushcclosure(aperture_write_fun
<T
, wfun
>, 3);
202 struct lua_debug_callback
209 static int dtor(lua_State
* L
)
211 lua_debug_callback
* D
= (lua_debug_callback
*)lua_touserdata(L
, 1);
214 int _dtor(lua_State
* L
);
216 std::map
<uint64_t, std::list
<lua_debug_callback
*>> cbs
;
218 int lua_debug_callback::_dtor(lua_State
* L
)
222 lua_pushlightuserdata(L
, &type
);
224 lua_rawset(L
, LUA_REGISTRYINDEX
);
225 debug_remove_callback(addr
, type
, h
);
226 for(auto j
= cbs
[addr
].begin(); j
!= cbs
[addr
].end(); j
++)
231 if(cbs
[addr
].empty())
236 void do_lua_error(lua::state
& L
, int ret
)
241 messages
<< "Error in Lua memory callback: " << L
.get_string(-1, "errhnd") << std::endl
;
245 messages
<< "Error in Lua memory callback (Out of memory)" << std::endl
;
248 messages
<< "Error in Lua memory callback (Double fault)" << std::endl
;
251 messages
<< "Error in Lua memory callback (\?\?\?)" << std::endl
;
257 template<debug_type type
>
258 void handle_registerX(lua::state
& L
, uint64_t addr
, int lfn
)
260 auto& cbl
= cbs
[addr
];
262 //Put the context in userdata so it can be gc'd when Lua context is terminated.
263 lua_debug_callback
* D
= (lua_debug_callback
*)L
.newuserdata(sizeof(lua_debug_callback
));
265 L
.pushstring("__gc");
266 L
.pushcclosure(&lua_debug_callback::dtor
, 0);
269 L
.pushlightuserdata(&D
->addr
);
271 L
.rawset(LUA_REGISTRYINDEX
);
272 L
.pop(1); //Pop the copy of object.
279 D
->lua_fn
= L
.topointer(lfn
);
280 lua::state
* LL
= &L
.get_master();
282 if(type
!= DEBUG_TRACE
)
283 D
->h
= debug_add_callback(addr
, type
, [LL
, D2
](uint64_t addr
, uint64_t value
) {
284 LL
->pushlightuserdata(D2
);
285 LL
->rawget(LUA_REGISTRYINDEX
);
286 LL
->pushnumber(addr
);
287 LL
->pushnumber(value
);
288 do_lua_error(*LL
, LL
->pcall(2, 0, 0));
290 LL
->pushlightuserdata(&D
->addr
);
292 LL
->rawset(LUA_REGISTRYINDEX
);
293 D
->_dtor(LL
->handle());
296 D
->h
= debug_add_trace_callback(addr
, [LL
, D2
](uint64_t proc
, const char* str
, bool true_insn
) {
297 LL
->pushlightuserdata(D2
);
298 LL
->rawget(LUA_REGISTRYINDEX
);
299 LL
->pushnumber(proc
);
301 LL
->pushboolean(true_insn
);
302 do_lua_error(*LL
, LL
->pcall(3, 0, 0));
304 LL
->pushlightuserdata(&D
->addr
);
306 LL
->rawset(LUA_REGISTRYINDEX
);
307 D
->_dtor(LL
->handle());
309 L
.pushlightuserdata(D2
);
311 L
.rawset(LUA_REGISTRYINDEX
);
314 template<debug_type type
>
315 void handle_unregisterX(lua::state
& L
, uint64_t addr
, int lfn
)
319 auto& cbl
= cbs
[addr
];
320 for(auto i
= cbl
.begin(); i
!= cbl
.end(); i
++) {
321 if((*i
)->type
!= type
) continue;
322 if(L
.topointer(lfn
) != (*i
)->lua_fn
) continue;
323 L
.pushlightuserdata(&(*i
)->type
);
325 L
.rawset(LUA_REGISTRYINDEX
);
326 (*i
)->_dtor(L
.handle());
327 //Lua will GC the object.
332 typedef void(*dummy1_t
)(lua::state
& L
, uint64_t addr
, int lfn
);
333 dummy1_t dummy_628963286932869328692386963
[] = {
334 handle_registerX
<DEBUG_READ
>,
335 handle_registerX
<DEBUG_WRITE
>,
336 handle_registerX
<DEBUG_EXEC
>,
337 handle_unregisterX
<DEBUG_READ
>,
338 handle_unregisterX
<DEBUG_WRITE
>,
339 handle_unregisterX
<DEBUG_EXEC
>,
344 template<debug_type type
, bool reg
>
345 int lua_registerX(lua::state
& L
, lua::parameters
& P
)
349 if(P
.is_nil() && type
!= DEBUG_TRACE
) {
350 addr
= 0xFFFFFFFFFFFFFFFFULL
;
352 } else if(type
!= DEBUG_TRACE
)
353 addr
= lua_get_read_address(P
);
359 handle_registerX
<type
>(L
, addr
, lfn
);
363 handle_unregisterX
<type
>(L
, addr
, lfn
);
368 command::fnptr
<> callbacks_show_lua(lsnes_cmd
, "show-lua-callbacks", "", "",
369 []() throw(std::bad_alloc
, std::runtime_error
) {
371 for(auto& j
: i
.second
)
372 messages
<< "addr=" << j
->addr
<< " type=" << j
->type
<< " handle="
373 << j
->h
.handle
<< " dead=" << j
->dead
<< " lua_fn="
374 << j
->lua_fn
<< std::endl
;
377 template<typename T
, T (memory_space::*rfun
)(uint64_t addr
), bool (memory_space::*wfun
)(uint64_t addr
,
379 int lua_mmap_memory(lua::state
& L
, lua::parameters
& P
)
382 static char deprecation
;
383 if(L
.do_once(&deprecation
))
384 messages
<< P
.get_fname() << ": Mapping entiere space is deprecated." << std::endl
;
385 aperture_make_fun
<T
, rfun
, wfun
>(L
.get_master(), 0, 0xFFFFFFFFFFFFFFFFULL
);
388 auto addr
= lua_get_read_address(P
);
389 auto size
= P
.arg
<uint64_t>();
391 throw std::runtime_error("Aperture with zero size is not valid");
392 aperture_make_fun
<T
, rfun
, wfun
>(L
.get_master(), addr
, size
- 1);
396 int handle_push_vma(lua::state
& L
, memory_region
& r
)
399 L
.pushstring("region_name");
400 L
.pushlstring(r
.name
.c_str(), r
.name
.size());
402 L
.pushstring("baseaddr");
403 L
.pushnumber(r
.base
);
405 L
.pushstring("size");
406 L
.pushnumber(r
.size
);
408 L
.pushstring("lastaddr");
409 L
.pushnumber(r
.last_address());
411 L
.pushstring("readonly");
412 L
.pushboolean(r
.readonly
);
414 L
.pushstring("iospace");
415 L
.pushboolean(r
.special
);
417 L
.pushstring("native_endian");
418 L
.pushboolean(r
.endian
== 0);
420 L
.pushstring("endian");
421 L
.pushnumber(r
.endian
);
426 template<bool write
, bool sign
> int memory_scattergather(lua::state
& L
, lua::parameters
& P
)
428 static char deprecation
;
432 uint64_t vmabase
= 0;
433 bool have_vmabase
= false;
435 val
= P
.arg
<uint64_t>();
442 } else if(P
.is_string()) {
443 vmabase
= lua_get_vmabase(P
.arg
<std::string
>());
447 addr
= P
.arg
<uint64_t>();
448 if(!have_vmabase
&& L
.do_once(&deprecation
))
449 messages
<< P
.get_fname() << ": Global memory form is deprecated." << std::endl
;
451 lsnes_memory
.write
<uint8_t>(addr
+ vmabase
, val
>> shift
);
453 val
= val
+ ((uint64_t)lsnes_memory
.read
<uint8_t>(addr
+ vmabase
) << shift
);
458 if(val
>= (1ULL << (shift
- 1))) sval
-= (1ULL << shift
);
459 if(sign
) L
.pushnumber(sval
); else L
.pushnumber(val
);
461 return write
? 0 : 1;
464 #define BLOCKSIZE 256
466 int vma_count(lua::state
& L
, lua::parameters
& P
)
468 L
.pushnumber(lsnes_memory
.get_regions().size());
472 int cheat(lua::state
& L
, lua::parameters
& P
)
474 uint64_t addr
, value
;
476 addr
= lua_get_read_address(P
);
479 debug_clear_cheat(addr
);
482 debug_set_cheat(addr
, value
);
487 int setxmask(lua::state
& L
, lua::parameters
& P
)
489 auto value
= P
.arg
<uint64_t>();
490 debug_setxmask(value
);
494 int read_vma(lua::state
& L
, lua::parameters
& P
)
500 std::list
<memory_region
*> regions
= lsnes_memory
.get_regions();
502 for(auto i
= regions
.begin(); i
!= regions
.end(); i
++, j
++)
504 return handle_push_vma(L
, **i
);
509 int find_vma(lua::state
& L
, lua::parameters
& P
)
515 auto r
= lsnes_memory
.lookup(addr
);
517 return handle_push_vma(L
, *r
.first
);
522 int hash_state(lua::state
& L
, lua::parameters
& P
)
524 auto x
= our_rom
.save_core_state();
525 size_t offset
= x
.size() - 32;
526 L
.pushlstring(hex::b_to((uint8_t*)&x
[offset
], 32));
530 template<typename H
, void(*update
)(H
& state
, const char* mem
, size_t memsize
),
531 std::string(*read
)(H
& state
), bool extra
>
532 int hash_core(H
& state
, lua::state
& L
, lua::parameters
& P
)
535 uint64_t addr
, size
, low
, high
;
536 uint64_t stride
= 0, rows
= 1;
537 bool mappable
= true;
538 char buffer
[BLOCKSIZE
];
540 addr
= lua_get_read_address(P
);
543 P(P
.optional(rows
, 1));
548 rpair(low
, high
) = memoryspace_row_bounds(addr
, size
, rows
, stride
);
549 if(low
> high
|| high
- low
+ 1 == 0)
552 char* pbuffer
= mappable
? lsnes_memory
.get_physical_mapping(low
, high
- low
+ 1) : NULL
;
555 uint64_t offset
= addr
- low
;
556 for(uint64_t i
= 0; i
< rows
; i
++) {
557 update(state
, pbuffer
+ offset
, size
);
561 uint64_t offset
= addr
;
562 for(uint64_t i
= 0; i
< rows
; i
++) {
565 size_t ssz
= min(sz
, static_cast<size_t>(BLOCKSIZE
));
566 for(size_t i
= 0; i
< ssz
; i
++)
567 buffer
[i
] = lsnes_memory
.read
<uint8_t>(offset
+ i
);
570 update(state
, buffer
, ssz
);
572 offset
+= (stride
- size
);
580 void lua_sha256_update(sha256
& s
, const char* ptr
, size_t size
)
585 std::string
lua_sha256_read(sha256
& s
)
590 void lua_skein_update(skein::hash
& s
, const char* ptr
, size_t size
)
592 s
.write(reinterpret_cast<const uint8_t*>(ptr
), size
);
595 std::string
lua_skein_read(skein::hash
& s
)
599 return hex::b_to(buf
, 32, false);
602 template<bool extended
>
603 int hash_region(lua::state
& L
, lua::parameters
& P
)
606 return hash_core
<sha256
, lua_sha256_update
, lua_sha256_read
, extended
>(h
, L
, P
);
609 int hash_region_skein(lua::state
& L
, lua::parameters
& P
)
611 skein::hash
h(skein::hash::PIPE_512
, 256);
612 return hash_core
<skein::hash
, lua_skein_update
, lua_skein_read
, true>(h
, L
, P
);
616 int copy_to_host(lua::state
& L
, lua::parameters
& P
)
618 uint64_t addr
, daddr
, size
, low
, high
;
619 uint64_t stride
= 0, rows
= 1;
620 bool equals
= true, mappable
= true;
622 addr
= lua_get_read_address(P
);
623 P(daddr
, size
, P
.optional(rows
, 1));
627 rpair(low
, high
) = memoryspace_row_bounds(addr
, size
, rows
, stride
);
628 if(low
> high
|| high
- low
+ 1 == 0)
630 if(rows
&& (size_t)(size
* rows
) / rows
!= size
)
631 throw std::runtime_error("Size to copy too large");
632 if((size_t)(daddr
+ rows
* size
) < daddr
)
633 throw std::runtime_error("Size to copy too large");
635 auto& h
= movb
.get_mfile().host_memory
;
636 if(daddr
+ rows
* size
> h
.size()) {
638 h
.resize(daddr
+ rows
* size
);
641 char* pbuffer
= mappable
? lsnes_memory
.get_physical_mapping(low
, high
- low
+ 1) : NULL
;
645 uint64_t offset
= addr
- low
;
646 for(uint64_t i
= 0; i
< rows
; i
++) {
647 bool eq
= (cmp
&& !memcmp(&h
[daddr
+ i
* size
], pbuffer
+ offset
, size
));
649 memcpy(&h
[daddr
+ i
* size
], pbuffer
+ offset
, size
);
655 for(uint64_t i
= 0; i
< rows
; i
++) {
656 uint64_t addr1
= addr
+ i
* stride
;
657 uint64_t addr2
= daddr
+ i
* size
;
658 for(uint64_t j
= 0; j
< size
; j
++) {
659 uint8_t byte
= lsnes_memory
.read
<uint8_t>(addr1
+ j
);
660 bool eq
= (cmp
&& h
[addr2
+ j
] == (char)byte
);
668 L
.pushboolean(equals
);
672 int readregion(lua::state
& L
, lua::parameters
& P
)
676 addr
= lua_get_read_address(P
);
680 char buffer
[BLOCKSIZE
];
683 size_t rsize
= min(size
, static_cast<uint64_t>(BLOCKSIZE
));
684 lsnes_memory
.read_range(addr
, buffer
, rsize
);
685 for(size_t i
= 0; i
< rsize
; i
++) {
687 L
.pushnumber(static_cast<unsigned char>(buffer
[i
]));
696 int writeregion(lua::state
& L
, lua::parameters
& P
)
701 addr
= lua_get_read_address(P
);
702 P(size
, P
.table(ltbl
));
704 char buffer
[BLOCKSIZE
];
707 size_t rsize
= min(size
, static_cast<uint64_t>(BLOCKSIZE
));
708 for(size_t i
= 0; i
< rsize
; i
++) {
711 buffer
[i
] = L
.tointeger(-1);
714 lsnes_memory
.write_range(addr
, buffer
, rsize
);
721 lua::functions
memoryfuncs(lua_func_misc
, "memory", {
722 {"vma_count", vma_count
},
724 {"setxmask", setxmask
},
725 {"read_vma", read_vma
},
726 {"find_vma", find_vma
},
727 {"hash_state", hash_state
},
728 {"hash_region", hash_region
<false>},
729 {"hash_region2", hash_region
<true>},
730 {"hash_region_skein", hash_region_skein
},
731 {"store", copy_to_host
<false>},
732 {"storecmp", copy_to_host
<true>},
733 {"readregion", readregion
},
734 {"writeregion", readregion
},
735 {"read_sg", memory_scattergather
<false, false>},
736 {"sread_sg", memory_scattergather
<false, true>},
737 {"write_sg", memory_scattergather
<true, false>},
738 {"readbyte", lua_read_memory
<uint8_t, &memory_space::read
<uint8_t>>},
739 {"readsbyte", lua_read_memory
<int8_t, &memory_space::read
<int8_t>>},
740 {"readword", lua_read_memory
<uint16_t, &memory_space::read
<uint16_t>>},
741 {"readsword", lua_read_memory
<int16_t, &memory_space::read
<int16_t>>},
742 {"readhword", lua_read_memory
<ss_uint24_t
, &memory_space::read
<ss_uint24_t
>>},
743 {"readshword", lua_read_memory
<ss_int24_t
, &memory_space::read
<ss_int24_t
>>},
744 {"readdword", lua_read_memory
<uint32_t, &memory_space::read
<uint32_t>>},
745 {"readsdword", lua_read_memory
<int32_t, &memory_space::read
<int32_t>>},
746 {"readqword", lua_read_memory
<uint64_t, &memory_space::read
<uint64_t>>},
747 {"readsqword", lua_read_memory
<int64_t, &memory_space::read
<int64_t>>},
748 {"readfloat", lua_read_memory
<float, &memory_space::read
<float>>},
749 {"readdouble", lua_read_memory
<double, &memory_space::read
<double>>},
750 {"writebyte", lua_write_memory
<uint8_t, &memory_space::write
<uint8_t>>},
751 {"writeword", lua_write_memory
<uint16_t, &memory_space::write
<uint16_t>>},
752 {"writehword", lua_write_memory
<ss_uint24_t
, &memory_space::write
<ss_uint24_t
>>},
753 {"writedword", lua_write_memory
<uint32_t, &memory_space::write
<uint32_t>>},
754 {"writeqword", lua_write_memory
<uint64_t, &memory_space::write
<uint64_t>>},
755 {"writefloat", lua_write_memory
<float, &memory_space::write
<float>>},
756 {"writedouble", lua_write_memory
<double, &memory_space::write
<double>>},
757 {"mapbyte", lua_mmap_memory
<uint8_t, &memory_space::read
<uint8_t>, &memory_space::write
<uint8_t>>},
758 {"mapsbyte", lua_mmap_memory
<int8_t, &memory_space::read
<int8_t>, &memory_space::write
<int8_t>>},
759 {"mapword", lua_mmap_memory
<uint16_t, &memory_space::read
<uint16_t>, &memory_space::write
<uint16_t>>},
760 {"mapsword", lua_mmap_memory
<int16_t, &memory_space::read
<int16_t>, &memory_space::write
<int16_t>>},
761 {"maphword", lua_mmap_memory
<ss_uint24_t
, &memory_space::read
<ss_uint24_t
>,
762 &memory_space::write
<ss_uint24_t
>>},
763 {"mapshword", lua_mmap_memory
<ss_int24_t
, &memory_space::read
<ss_int24_t
>,
764 &memory_space::write
<ss_int24_t
>>},
765 {"mapdword", lua_mmap_memory
<uint32_t, &memory_space::read
<uint32_t>,
766 &memory_space::write
<uint32_t>>},
767 {"mapsdword", lua_mmap_memory
<int32_t, &memory_space::read
<int32_t>, &memory_space::write
<int32_t>>},
768 {"mapqword", lua_mmap_memory
<uint64_t, &memory_space::read
<uint64_t>,
769 &memory_space::write
<uint64_t>>},
770 {"mapsqword", lua_mmap_memory
<int64_t, &memory_space::read
<int64_t>, &memory_space::write
<int64_t>>},
771 {"mapfloat", lua_mmap_memory
<float, &memory_space::read
<float>, &memory_space::write
<float>>},
772 {"mapdouble", lua_mmap_memory
<double, &memory_space::read
<double>, &memory_space::write
<double>>},
773 {"registerread", lua_registerX
<DEBUG_READ
, true>},
774 {"unregisterread", lua_registerX
<DEBUG_READ
, false>},
775 {"registerwrite", lua_registerX
<DEBUG_WRITE
, true>},
776 {"unregisterwrite", lua_registerX
<DEBUG_WRITE
, false>},
777 {"registerexec", lua_registerX
<DEBUG_EXEC
, true>},
778 {"unregisterexec", lua_registerX
<DEBUG_EXEC
, false>},
779 {"registertrace", lua_registerX
<DEBUG_TRACE
, true>},
780 {"unregistertrace", lua_registerX
<DEBUG_TRACE
, false>},
783 lua::_class
<lua_mmap_struct
> class_mmap_struct(lua_class_memory
, "MMAP_STRUCT", {
784 {"new", &lua_mmap_struct::create
},
786 {"__index", &lua_mmap_struct::index
},
787 {"__newindex", &lua_mmap_struct::newindex
},
788 {"__call", &lua_mmap_struct::map
},
789 }, &lua_mmap_struct::print
);
792 int lua_mmap_struct::map(lua::state
& L
, lua::parameters
& P
)
794 std::string name
, type
;
797 P(P
.skipped(), name
);
798 addr
= lua_get_read_address(P
);
802 mappings
[name
] = mapping(addr
, do_rw
<uint8_t, &memory_space::read
<uint8_t>,
803 &memory_space::write
<uint8_t>>);
804 else if(type
== "sbyte")
805 mappings
[name
] = mapping(addr
, do_rw
<int8_t, &memory_space::read
<int8_t>,
806 &memory_space::write
<int8_t>>);
807 else if(type
== "word")
808 mappings
[name
] = mapping(addr
, do_rw
<uint16_t, &memory_space::read
<uint16_t>,
809 &memory_space::write
<uint16_t>>);
810 else if(type
== "sword")
811 mappings
[name
] = mapping(addr
, do_rw
<int16_t, &memory_space::read
<int16_t>,
812 &memory_space::write
<int16_t>>);
813 else if(type
== "hword")
814 mappings
[name
] = mapping(addr
, do_rw
<ss_uint24_t
, &memory_space::read
<ss_uint24_t
>,
815 &memory_space::write
<ss_uint24_t
>>);
816 else if(type
== "shword")
817 mappings
[name
] = mapping(addr
, do_rw
<ss_int24_t
, &memory_space::read
<ss_int24_t
>,
818 &memory_space::write
<ss_int24_t
>>);
819 else if(type
== "dword")
820 mappings
[name
] = mapping(addr
, do_rw
<uint32_t, &memory_space::read
<uint32_t>,
821 &memory_space::write
<uint32_t>>);
822 else if(type
== "sdword")
823 mappings
[name
] = mapping(addr
, do_rw
<int32_t, &memory_space::read
<int32_t>,
824 &memory_space::write
<int32_t>>);
825 else if(type
== "qword")
826 mappings
[name
] = mapping(addr
, do_rw
<uint64_t, &memory_space::read
<uint64_t>,
827 &memory_space::write
<uint64_t>>);
828 else if(type
== "sqword")
829 mappings
[name
] = mapping(addr
, do_rw
<int64_t, &memory_space::read
<int64_t>,
830 &memory_space::write
<int64_t>>);
831 else if(type
== "float")
832 mappings
[name
] = mapping(addr
, do_rw
<float, &memory_space::read
<float>,
833 &memory_space::write
<float>>);
834 else if(type
== "double")
835 mappings
[name
] = mapping(addr
, do_rw
<double, &memory_space::read
<double>,
836 &memory_space::write
<double>>);
838 (stringfmt() << P
.get_fname() << ": Bad type").throwex();
842 lua_mmap_struct::lua_mmap_struct(lua::state
& L
)