1 #include "cmdhelp/lua.hpp"
2 #include "core/command.hpp"
3 #include "core/debug.hpp"
4 #include "core/instance.hpp"
5 #include "core/memorymanip.hpp"
6 #include "core/memorywatch.hpp"
7 #include "core/messages.hpp"
8 #include "core/moviedata.hpp"
9 #include "core/moviefile.hpp"
10 #include "core/rom.hpp"
11 #include "lua/address.hpp"
12 #include "lua/internal.hpp"
13 #include "library/sha256.hpp"
14 #include "library/string.hpp"
15 #include "library/skein.hpp"
16 #include "library/memoryspace.hpp"
17 #include "library/minmax.hpp"
18 #include "library/hex.hpp"
19 #include "library/int24.hpp"
23 template<typename T
, T (memory_space::*rfun
)(uint64_t addr
),
24 bool (memory_space::*wfun
)(uint64_t addr
, T value
)>
25 void do_rw(lua::state
& L
, uint64_t addr
, bool wrflag
)
29 T value
= L
.get_numeric_argument
<T
>(3, "aperture(write)");
30 (core
.memory
->*wfun
)(addr
, value
);
32 L
.pushnumber(static_cast<T
>((core
.memory
->*rfun
)(addr
)));
35 template<typename T
, T (memory_space::*rfun
)(uint64_t addr
)>
36 int lua_read_memory(lua::state
& L
, lua::parameters
& P
)
38 auto addr
= lua_get_read_address(P
);
39 L
.pushnumber(static_cast<T
>((CORE().memory
->*rfun
)(addr
)));
43 template<typename T
, bool (memory_space::*wfun
)(uint64_t addr
, T value
)>
44 int lua_write_memory(lua::state
& L
, lua::parameters
& P
)
46 auto addr
= lua_get_read_address(P
);
48 (CORE().memory
->*wfun
)(addr
, value
);
56 lua_mmap_struct(lua::state
& L
);
57 static size_t overcommit() { return 0; }
63 int index(lua::state
& L
, lua::parameters
& P
)
65 const char* c
= L
.tostring(2);
71 if(!mappings
.count(c2
)) {
75 auto& x
= mappings
[c2
];
76 x
.rw(L
, x
.addr
, false);
79 int newindex(lua::state
& L
, lua::parameters
& P
)
81 const char* c
= L
.tostring(2);
85 if(!mappings
.count(c2
))
87 auto& x
= mappings
[c2
];
88 x
.rw(L
, x
.addr
, true);
91 static int create(lua::state
& L
, lua::parameters
& P
)
93 lua::_class
<lua_mmap_struct
>::create(L
);
96 int map(lua::state
& L
, lua::parameters
& P
);
99 size_t s
= mappings
.size();
100 return (stringfmt() << s
<< " " << ((s
!= 1) ? "mappings" : "mapping")).str();
106 mapping(uint64_t _addr
, void (*_rw
)(lua::state
& L
, uint64_t addr
, bool wrflag
))
107 : addr(_addr
), rw(_rw
)
111 void (*rw
)(lua::state
& L
, uint64_t addr
, bool wrflag
);
113 std::map
<std::string
, mapping
> mappings
;
118 template<typename T
, T (memory_space::*rfun
)(uint64_t addr
)>
119 int aperture_read_fun(lua_State
* _L
)
121 lua::state
& mL
= *reinterpret_cast<lua::state
*>(lua_touserdata(_L
, lua_upvalueindex(3)));
122 lua::state
L(mL
, _L
);
124 uint64_t base
= L
.tonumber(lua_upvalueindex(1));
125 uint64_t size
= 0xFFFFFFFFFFFFFFFFULL
;
126 if(L
.type(lua_upvalueindex(2)) == LUA_TNUMBER
)
127 size
= L
.tonumber(lua_upvalueindex(2));
128 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(2, "aperture(read)");
129 if(addr
> size
|| addr
+ base
< addr
) {
134 L
.pushnumber(static_cast<T
>((CORE().memory
->*rfun
)(addr
)));
138 template<typename T
, bool (memory_space::*wfun
)(uint64_t addr
, T value
)>
139 int aperture_write_fun(lua_State
* _L
)
141 lua::state
& mL
= *reinterpret_cast<lua::state
*>(lua_touserdata(_L
, lua_upvalueindex(3)));
142 lua::state
L(mL
, _L
);
144 uint64_t base
= L
.tonumber(lua_upvalueindex(1));
145 uint64_t size
= 0xFFFFFFFFFFFFFFFFULL
;
146 if(L
.type(lua_upvalueindex(2)) == LUA_TNUMBER
)
147 size
= L
.tonumber(lua_upvalueindex(2));
148 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(2, "aperture(write)");
149 if(addr
> size
|| addr
+ base
< addr
)
152 T value
= L
.get_numeric_argument
<T
>(3, "aperture(write)");
153 (CORE().memory
->*wfun
)(addr
, value
);
157 template<typename T
, T (memory_space::*rfun
)(uint64_t addr
), bool (memory_space::*wfun
)(uint64_t addr
,
159 void aperture_make_fun(lua::state
& L
, uint64_t base
, uint64_t size
)
163 L
.pushstring( "__index");
169 L
.pushlightuserdata(&L
);
170 L
.pushcclosure(aperture_read_fun
<T
, rfun
>, 3);
172 L
.pushstring("__newindex");
178 L
.pushlightuserdata(&L
);
179 L
.pushcclosure(aperture_write_fun
<T
, wfun
>, 3);
184 void do_lua_error(lua::state
& L
, int ret
)
189 messages
<< "Error in Lua memory callback: " << L
.get_string(-1, "errhnd") << std::endl
;
193 messages
<< "Error in Lua memory callback (Out of memory)" << std::endl
;
196 messages
<< "Error in Lua memory callback (Double fault)" << std::endl
;
199 messages
<< "Error in Lua memory callback (\?\?\?)" << std::endl
;
204 char CONST_lua_cb_list_key
= 0;
206 struct lua_debug_callback2
: public debug_context::callback_base
210 debug_context::etype type
;
213 ~lua_debug_callback2();
215 void set_lua_fn(int slot
);
217 void callback(const debug_context::params
& p
);
218 void killed(uint64_t addr
, debug_context::etype type
);
219 static int on_lua_gc(lua_State
* L
);
220 lua_debug_callback2
* prev
;
221 lua_debug_callback2
* next
;
224 struct lua_debug_callback_dict
226 ~lua_debug_callback_dict();
227 std::map
<std::pair
<debug_context::etype
, uint64_t>, lua_debug_callback2
*> cblist
;
228 static int on_lua_gc(lua_State
* L
);
231 lua_debug_callback2::~lua_debug_callback2()
234 L
->pushlightuserdata(&CONST_lua_cb_list_key
);
235 L
->rawget(LUA_REGISTRYINDEX
);
237 lua_debug_callback_dict
* dc
= (lua_debug_callback_dict
*)L
->touserdata(-1);
238 std::pair
<debug_context::etype
, uint64_t> key
= std::make_pair(type
, addr
);
239 if(dc
->cblist
.count(key
)) {
240 dc
->cblist
[key
] = next
;
242 dc
->cblist
.erase(key
);
248 if(prev
) prev
->next
= next
;
249 if(next
) next
->prev
= prev
;
253 void lua_debug_callback2::link_to_list()
256 L
->pushlightuserdata(&CONST_lua_cb_list_key
);
257 L
->rawget(LUA_REGISTRYINDEX
);
259 //No existing dict, create one.
261 L
->pushlightuserdata(&CONST_lua_cb_list_key
);
262 lua_debug_callback_dict
* D
= (lua_debug_callback_dict
*)
263 L
->newuserdata(sizeof(lua_debug_callback_dict
));
264 new(D
) lua_debug_callback_dict
;
266 L
->pushstring("__gc");
267 L
->pushcclosure(&lua_debug_callback_dict::on_lua_gc
, 0);
270 L
->rawset(LUA_REGISTRYINDEX
);
272 L
->pushlightuserdata(&CONST_lua_cb_list_key
);
273 L
->rawget(LUA_REGISTRYINDEX
);
274 lua_debug_callback2
* was
= NULL
;
275 lua_debug_callback_dict
* dc
= (lua_debug_callback_dict
*)L
->touserdata(-1);
276 std::pair
<debug_context::etype
, uint64_t> key
= std::make_pair(type
, addr
);
277 if(dc
->cblist
.count(key
))
278 was
= dc
->cblist
[key
];
279 dc
->cblist
[key
] = this;
285 void lua_debug_callback2::set_lua_fn(int slot
)
287 //Convert to absolute slot.
289 slot
= L
->gettop() + slot
;
290 //Write the function.
291 L
->pushlightuserdata((char*)this + 1);
293 L
->rawset(LUA_REGISTRYINDEX
);
294 lua_fn
= L
->topointer(slot
);
297 void lua_debug_callback2::unregister()
300 CORE().dbg
->remove_callback(addr
, type
, *this);
302 //Delink from Lua, prompting Lua to GC this.
303 L
->pushlightuserdata(this);
305 L
->rawset(LUA_REGISTRYINDEX
);
306 L
->pushlightuserdata((char*)this + 1);
308 L
->rawset(LUA_REGISTRYINDEX
);
311 void lua_debug_callback2::callback(const debug_context::params
& p
)
313 L
->pushlightuserdata((char*)this + 1);
314 L
->rawget(LUA_REGISTRYINDEX
);
316 case debug_context::DEBUG_READ
:
317 case debug_context::DEBUG_WRITE
:
318 case debug_context::DEBUG_EXEC
:
319 L
->pushnumber(p
.rwx
.addr
);
320 L
->pushnumber(p
.rwx
.value
);
321 do_lua_error(*L
, L
->pcall(2, 0, 0));
323 case debug_context::DEBUG_TRACE
:
324 L
->pushnumber(p
.trace
.cpu
);
325 L
->pushstring(p
.trace
.decoded_insn
);
326 L
->pushboolean(p
.trace
.true_insn
);
327 do_lua_error(*L
, L
->pcall(3, 0, 0));
329 case debug_context::DEBUG_FRAME
:
330 L
->pushnumber(p
.frame
.frame
);
331 L
->pushboolean(p
.frame
.loadstated
);
332 do_lua_error(*L
, L
->pcall(2, 0, 0));
335 //Remove the junk from stack.
341 void lua_debug_callback2::killed(uint64_t addr
, debug_context::etype type
)
343 //Assume this has been unregistered.
345 //Delink from Lua, lua will GC this.
346 L
->pushlightuserdata(this);
348 L
->rawset(LUA_REGISTRYINDEX
);
349 L
->pushlightuserdata((char*)this + 1);
351 L
->rawset(LUA_REGISTRYINDEX
);
354 int lua_debug_callback2::on_lua_gc(lua_State
* _L
)
356 //We need to destroy the object.
357 lua_debug_callback2
* D
= (lua_debug_callback2
*)lua_touserdata(_L
, 1);
360 CORE().dbg
->remove_callback(D
->addr
, D
->type
, *D
);
363 D
->~lua_debug_callback2();
367 lua_debug_callback_dict::~lua_debug_callback_dict()
371 int lua_debug_callback_dict::on_lua_gc(lua_State
* _L
)
373 lua_pushlightuserdata(_L
, &CONST_lua_cb_list_key
);
375 lua_rawset(_L
, LUA_REGISTRYINDEX
);
376 lua_debug_callback_dict
* D
= (lua_debug_callback_dict
*)lua_touserdata(_L
, 1);
377 D
->~lua_debug_callback_dict();
382 template<debug_context::etype type
>
383 void handle_registerX(lua::state
& L
, uint64_t addr
, int lfn
)
385 //Put the context in userdata so it can be gc'd when Lua context is terminated.
386 lua_debug_callback2
* D
= (lua_debug_callback2
*)L
.newuserdata(sizeof(lua_debug_callback2
));
387 new(D
) lua_debug_callback2
;
389 L
.pushstring("__gc");
390 L
.pushcclosure(&lua_debug_callback2::on_lua_gc
, 0);
393 L
.pushlightuserdata(D
);
395 L
.rawset(LUA_REGISTRYINDEX
);
396 L
.pop(1); //Pop the copy of object.
398 D
->L
= &L
.get_master();
405 CORE().dbg
->add_callback(addr
, type
, *D
);
408 template<debug_context::etype type
>
409 void handle_unregisterX(lua::state
& L
, uint64_t addr
, int lfn
)
411 lua_debug_callback_dict
* Dx
;
412 lua_debug_callback2
* D
= NULL
;
413 L
.pushlightuserdata(&CONST_lua_cb_list_key
);
414 L
.rawget(LUA_REGISTRYINDEX
);
416 Dx
= (lua_debug_callback_dict
*)L
.touserdata(-1);
417 auto key
= std::make_pair(type
, addr
);
418 if(Dx
->cblist
.count(key
))
422 if(D
->dead
|| D
->type
!= type
|| D
->addr
!= addr
|| L
.topointer(lfn
) != D
->lua_fn
) {
435 typedef void(*dummy1_t
)(lua::state
& L
, uint64_t addr
, int lfn
);
436 dummy1_t dummy_628963286932869328692386963
[] = {
437 handle_registerX
<debug_context::DEBUG_READ
>,
438 handle_registerX
<debug_context::DEBUG_WRITE
>,
439 handle_registerX
<debug_context::DEBUG_EXEC
>,
440 handle_unregisterX
<debug_context::DEBUG_READ
>,
441 handle_unregisterX
<debug_context::DEBUG_WRITE
>,
442 handle_unregisterX
<debug_context::DEBUG_EXEC
>,
447 template<debug_context::etype type
, bool reg
>
448 int lua_registerX(lua::state
& L
, lua::parameters
& P
)
452 if(P
.is_nil() && type
!= debug_context::DEBUG_TRACE
) {
453 addr
= 0xFFFFFFFFFFFFFFFFULL
;
455 } else if(type
!= debug_context::DEBUG_TRACE
)
456 addr
= lua_get_read_address(P
);
462 handle_registerX
<type
>(L
, addr
, lfn
);
466 handle_unregisterX
<type
>(L
, addr
, lfn
);
471 command::fnptr
<> CMD_callbacks_show_lua(lsnes_cmds
, CLUA::scb
,
472 []() throw(std::bad_alloc
, std::runtime_error
) {
474 lua::state
& L
= *core
.lua
;
475 lua_debug_callback2
* D
;
476 lua_debug_callback_dict
* Dx
;
477 L
.pushlightuserdata(&CONST_lua_cb_list_key
);
478 L
.rawget(LUA_REGISTRYINDEX
);
480 Dx
= (lua_debug_callback_dict
*)L
.touserdata(-1);
481 for(auto Dy
: Dx
->cblist
) {
484 messages
<< "addr=" << core
.memory
->address_to_textual(D
->addr
)
485 << " type=" << D
->type
<< " handle=" << D
<< " dead=" << D
->dead
486 << " lua_fn=" << D
->lua_fn
<< std::endl
;
494 template<typename T
, T (memory_space::*rfun
)(uint64_t addr
), bool (memory_space::*wfun
)(uint64_t addr
,
496 int lua_mmap_memory(lua::state
& L
, lua::parameters
& P
)
499 static char deprecation
;
500 if(L
.do_once(&deprecation
))
501 messages
<< P
.get_fname() << ": Mapping entiere space is deprecated." << std::endl
;
502 aperture_make_fun
<T
, rfun
, wfun
>(L
.get_master(), 0, 0xFFFFFFFFFFFFFFFFULL
);
505 auto addr
= lua_get_read_address(P
);
506 auto size
= P
.arg
<uint64_t>();
508 throw std::runtime_error("Aperture with zero size is not valid");
509 aperture_make_fun
<T
, rfun
, wfun
>(L
.get_master(), addr
, size
- 1);
513 int handle_push_vma(lua::state
& L
, memory_space::region
& r
)
516 L
.pushstring("region_name");
517 L
.pushlstring(r
.name
.c_str(), r
.name
.size());
519 L
.pushstring("baseaddr");
520 L
.pushnumber(r
.base
);
522 L
.pushstring("size");
523 L
.pushnumber(r
.size
);
525 L
.pushstring("lastaddr");
526 L
.pushnumber(r
.last_address());
528 L
.pushstring("readonly");
529 L
.pushboolean(r
.readonly
);
531 L
.pushstring("iospace");
532 L
.pushboolean(r
.special
);
534 L
.pushstring("native_endian");
535 L
.pushboolean(r
.endian
== 0);
537 L
.pushstring("endian");
538 L
.pushnumber(r
.endian
);
543 template<bool write
, bool sign
> int memory_scattergather(lua::state
& L
, lua::parameters
& P
)
546 static char deprecation
;
550 uint64_t vmabase
= 0;
551 bool have_vmabase
= false;
553 val
= P
.arg
<uint64_t>();
560 } else if(P
.is
<lua_address
>()) {
561 auto laddr
= P
.arg
<lua_address
*>();
562 vmabase
= lua_get_vmabase(laddr
->get_vma());
564 addr
= laddr
->get_offset();
565 //No continue, fall through.
566 } else if(P
.is_string()) {
567 vmabase
= lua_get_vmabase(P
.arg
<std::string
>());
571 addr
= P
.arg
<uint64_t>();
572 if(!have_vmabase
&& L
.do_once(&deprecation
))
573 messages
<< P
.get_fname() << ": Global memory form is deprecated." << std::endl
;
575 core
.memory
->write
<uint8_t>(addr
+ vmabase
, val
>> shift
);
577 val
= val
+ ((uint64_t)core
.memory
->read
<uint8_t>(addr
+ vmabase
) << shift
);
582 if(val
>= (1ULL << (shift
- 1))) sval
-= (1ULL << shift
);
583 if(sign
) L
.pushnumber(sval
); else L
.pushnumber(val
);
585 return write
? 0 : 1;
588 #define BLOCKSIZE 256
590 int vma_count(lua::state
& L
, lua::parameters
& P
)
592 L
.pushnumber(CORE().memory
->get_regions().size());
596 int cheat(lua::state
& L
, lua::parameters
& P
)
599 uint64_t addr
, value
;
601 addr
= lua_get_read_address(P
);
604 core
.dbg
->clear_cheat(addr
);
607 core
.dbg
->set_cheat(addr
, value
);
612 int setxmask(lua::state
& L
, lua::parameters
& P
)
614 auto value
= P
.arg
<uint64_t>();
615 CORE().dbg
->setxmask(value
);
619 int read_vma(lua::state
& L
, lua::parameters
& P
)
625 std::list
<memory_space::region
*> regions
= CORE().memory
->get_regions();
627 for(auto i
= regions
.begin(); i
!= regions
.end(); i
++, j
++)
629 return handle_push_vma(L
, **i
);
634 int find_vma(lua::state
& L
, lua::parameters
& P
)
640 auto r
= CORE().memory
->lookup(addr
);
642 return handle_push_vma(L
, *r
.first
);
647 int hash_state(lua::state
& L
, lua::parameters
& P
)
650 auto x
= core
.rom
->save_core_state();
651 size_t offset
= x
.size() - 32;
652 L
.pushlstring(hex::b_to((uint8_t*)&x
[offset
], 32));
656 template<typename H
, void(*update
)(H
& state
, const char* mem
, size_t memsize
),
657 std::string(*read
)(H
& state
), bool extra
>
658 int hash_core(H
& state
, lua::state
& L
, lua::parameters
& P
)
662 uint64_t addr
, size
, low
, high
;
663 uint64_t stride
= 0, rows
= 1;
664 bool mappable
= true;
665 char buffer
[BLOCKSIZE
];
667 addr
= lua_get_read_address(P
);
670 P(P
.optional(rows
, 1));
675 rpair(low
, high
) = memoryspace_row_bounds(addr
, size
, rows
, stride
);
676 if(low
> high
|| high
- low
+ 1 == 0)
679 char* pbuffer
= mappable
? core
.memory
->get_physical_mapping(low
, high
- low
+ 1) : NULL
;
682 uint64_t offset
= addr
- low
;
683 for(uint64_t i
= 0; i
< rows
; i
++) {
684 update(state
, pbuffer
+ offset
, size
);
688 uint64_t offset
= addr
;
689 for(uint64_t i
= 0; i
< rows
; i
++) {
692 size_t ssz
= min(sz
, static_cast<size_t>(BLOCKSIZE
));
693 for(size_t i
= 0; i
< ssz
; i
++)
694 buffer
[i
] = core
.memory
->read
<uint8_t>(offset
+ i
);
697 update(state
, buffer
, ssz
);
699 offset
+= (stride
- size
);
707 void lua_sha256_update(sha256
& s
, const char* ptr
, size_t size
)
712 std::string
lua_sha256_read(sha256
& s
)
717 void lua_skein_update(skein::hash
& s
, const char* ptr
, size_t size
)
719 s
.write(reinterpret_cast<const uint8_t*>(ptr
), size
);
722 std::string
lua_skein_read(skein::hash
& s
)
726 return hex::b_to(buf
, 32, false);
729 template<bool extended
>
730 int hash_region(lua::state
& L
, lua::parameters
& P
)
733 return hash_core
<sha256
, lua_sha256_update
, lua_sha256_read
, extended
>(h
, L
, P
);
736 int hash_region_skein(lua::state
& L
, lua::parameters
& P
)
738 skein::hash
h(skein::hash::PIPE_512
, 256);
739 return hash_core
<skein::hash
, lua_skein_update
, lua_skein_read
, true>(h
, L
, P
);
743 int copy_to_host(lua::state
& L
, lua::parameters
& P
)
746 uint64_t addr
, daddr
, size
, low
, high
;
747 uint64_t stride
= 0, rows
= 1;
748 bool equals
= true, mappable
= true;
750 addr
= lua_get_read_address(P
);
751 P(daddr
, size
, P
.optional(rows
, 1));
755 rpair(low
, high
) = memoryspace_row_bounds(addr
, size
, rows
, stride
);
756 if(low
> high
|| high
- low
+ 1 == 0)
758 if(rows
&& (size_t)(size
* rows
) / rows
!= size
)
759 throw std::runtime_error("Size to copy too large");
760 if((size_t)(daddr
+ rows
* size
) < daddr
)
761 throw std::runtime_error("Size to copy too large");
763 auto& h
= core
.mlogic
->get_mfile().host_memory
;
764 if(daddr
+ rows
* size
> h
.size()) {
766 h
.resize(daddr
+ rows
* size
);
769 char* pbuffer
= mappable
? core
.memory
->get_physical_mapping(low
, high
- low
+ 1) : NULL
;
773 uint64_t offset
= addr
- low
;
774 for(uint64_t i
= 0; i
< rows
; i
++) {
775 bool eq
= (cmp
&& !memcmp(&h
[daddr
+ i
* size
], pbuffer
+ offset
, size
));
777 memcpy(&h
[daddr
+ i
* size
], pbuffer
+ offset
, size
);
783 for(uint64_t i
= 0; i
< rows
; i
++) {
784 uint64_t addr1
= addr
+ i
* stride
;
785 uint64_t addr2
= daddr
+ i
* size
;
786 for(uint64_t j
= 0; j
< size
; j
++) {
787 uint8_t byte
= core
.memory
->read
<uint8_t>(addr1
+ j
);
788 bool eq
= (cmp
&& h
[addr2
+ j
] == (char)byte
);
796 L
.pushboolean(equals
);
800 int readregion(lua::state
& L
, lua::parameters
& P
)
805 addr
= lua_get_read_address(P
);
809 char buffer
[BLOCKSIZE
];
812 size_t rsize
= min(size
, static_cast<uint64_t>(BLOCKSIZE
));
813 core
.memory
->read_range(addr
, buffer
, rsize
);
814 for(size_t i
= 0; i
< rsize
; i
++) {
816 L
.pushnumber(static_cast<unsigned char>(buffer
[i
]));
825 int writeregion(lua::state
& L
, lua::parameters
& P
)
831 addr
= lua_get_read_address(P
);
832 P(size
, P
.table(ltbl
));
834 char buffer
[BLOCKSIZE
];
837 size_t rsize
= min(size
, static_cast<uint64_t>(BLOCKSIZE
));
838 for(size_t i
= 0; i
< rsize
; i
++) {
841 buffer
[i
] = L
.tointeger(-1);
844 core
.memory
->write_range(addr
, buffer
, rsize
);
851 lua::functions
LUA_memory_fns(lua_func_misc
, "memory", {
852 {"vma_count", vma_count
},
854 {"setxmask", setxmask
},
855 {"read_vma", read_vma
},
856 {"find_vma", find_vma
},
857 {"hash_state", hash_state
},
858 {"hash_region", hash_region
<false>},
859 {"hash_region2", hash_region
<true>},
860 {"hash_region_skein", hash_region_skein
},
861 {"store", copy_to_host
<false>},
862 {"storecmp", copy_to_host
<true>},
863 {"readregion", readregion
},
864 {"writeregion", writeregion
},
865 {"read_sg", memory_scattergather
<false, false>},
866 {"sread_sg", memory_scattergather
<false, true>},
867 {"write_sg", memory_scattergather
<true, false>},
868 {"readbyte", lua_read_memory
<uint8_t, &memory_space::read
<uint8_t>>},
869 {"readsbyte", lua_read_memory
<int8_t, &memory_space::read
<int8_t>>},
870 {"readword", lua_read_memory
<uint16_t, &memory_space::read
<uint16_t>>},
871 {"readsword", lua_read_memory
<int16_t, &memory_space::read
<int16_t>>},
872 {"readhword", lua_read_memory
<ss_uint24_t
, &memory_space::read
<ss_uint24_t
>>},
873 {"readshword", lua_read_memory
<ss_int24_t
, &memory_space::read
<ss_int24_t
>>},
874 {"readdword", lua_read_memory
<uint32_t, &memory_space::read
<uint32_t>>},
875 {"readsdword", lua_read_memory
<int32_t, &memory_space::read
<int32_t>>},
876 {"readqword", lua_read_memory
<uint64_t, &memory_space::read
<uint64_t>>},
877 {"readsqword", lua_read_memory
<int64_t, &memory_space::read
<int64_t>>},
878 {"readfloat", lua_read_memory
<float, &memory_space::read
<float>>},
879 {"readdouble", lua_read_memory
<double, &memory_space::read
<double>>},
880 {"writebyte", lua_write_memory
<uint8_t, &memory_space::write
<uint8_t>>},
881 {"writeword", lua_write_memory
<uint16_t, &memory_space::write
<uint16_t>>},
882 {"writehword", lua_write_memory
<ss_uint24_t
, &memory_space::write
<ss_uint24_t
>>},
883 {"writedword", lua_write_memory
<uint32_t, &memory_space::write
<uint32_t>>},
884 {"writeqword", lua_write_memory
<uint64_t, &memory_space::write
<uint64_t>>},
885 {"writefloat", lua_write_memory
<float, &memory_space::write
<float>>},
886 {"writedouble", lua_write_memory
<double, &memory_space::write
<double>>},
887 {"mapbyte", lua_mmap_memory
<uint8_t, &memory_space::read
<uint8_t>, &memory_space::write
<uint8_t>>},
888 {"mapsbyte", lua_mmap_memory
<int8_t, &memory_space::read
<int8_t>, &memory_space::write
<int8_t>>},
889 {"mapword", lua_mmap_memory
<uint16_t, &memory_space::read
<uint16_t>, &memory_space::write
<uint16_t>>},
890 {"mapsword", lua_mmap_memory
<int16_t, &memory_space::read
<int16_t>, &memory_space::write
<int16_t>>},
891 {"maphword", lua_mmap_memory
<ss_uint24_t
, &memory_space::read
<ss_uint24_t
>,
892 &memory_space::write
<ss_uint24_t
>>},
893 {"mapshword", lua_mmap_memory
<ss_int24_t
, &memory_space::read
<ss_int24_t
>,
894 &memory_space::write
<ss_int24_t
>>},
895 {"mapdword", lua_mmap_memory
<uint32_t, &memory_space::read
<uint32_t>,
896 &memory_space::write
<uint32_t>>},
897 {"mapsdword", lua_mmap_memory
<int32_t, &memory_space::read
<int32_t>, &memory_space::write
<int32_t>>},
898 {"mapqword", lua_mmap_memory
<uint64_t, &memory_space::read
<uint64_t>,
899 &memory_space::write
<uint64_t>>},
900 {"mapsqword", lua_mmap_memory
<int64_t, &memory_space::read
<int64_t>, &memory_space::write
<int64_t>>},
901 {"mapfloat", lua_mmap_memory
<float, &memory_space::read
<float>, &memory_space::write
<float>>},
902 {"mapdouble", lua_mmap_memory
<double, &memory_space::read
<double>, &memory_space::write
<double>>},
903 {"registerread", lua_registerX
<debug_context::DEBUG_READ
, true>},
904 {"unregisterread", lua_registerX
<debug_context::DEBUG_READ
, false>},
905 {"registerwrite", lua_registerX
<debug_context::DEBUG_WRITE
, true>},
906 {"unregisterwrite", lua_registerX
<debug_context::DEBUG_WRITE
, false>},
907 {"registerexec", lua_registerX
<debug_context::DEBUG_EXEC
, true>},
908 {"unregisterexec", lua_registerX
<debug_context::DEBUG_EXEC
, false>},
909 {"registertrace", lua_registerX
<debug_context::DEBUG_TRACE
, true>},
910 {"unregistertrace", lua_registerX
<debug_context::DEBUG_TRACE
, false>},
913 lua::_class
<lua_mmap_struct
> LUA_class_mmap_struct(lua_class_memory
, "MMAP_STRUCT", {
914 {"new", &lua_mmap_struct::create
},
916 {"__index", &lua_mmap_struct::index
},
917 {"__newindex", &lua_mmap_struct::newindex
},
918 {"__call", &lua_mmap_struct::map
},
919 }, &lua_mmap_struct::print
);
922 int lua_mmap_struct::map(lua::state
& L
, lua::parameters
& P
)
924 std::string name
, type
;
927 P(P
.skipped(), name
);
928 addr
= lua_get_read_address(P
);
932 mappings
[name
] = mapping(addr
, do_rw
<uint8_t, &memory_space::read
<uint8_t>,
933 &memory_space::write
<uint8_t>>);
934 else if(type
== "sbyte")
935 mappings
[name
] = mapping(addr
, do_rw
<int8_t, &memory_space::read
<int8_t>,
936 &memory_space::write
<int8_t>>);
937 else if(type
== "word")
938 mappings
[name
] = mapping(addr
, do_rw
<uint16_t, &memory_space::read
<uint16_t>,
939 &memory_space::write
<uint16_t>>);
940 else if(type
== "sword")
941 mappings
[name
] = mapping(addr
, do_rw
<int16_t, &memory_space::read
<int16_t>,
942 &memory_space::write
<int16_t>>);
943 else if(type
== "hword")
944 mappings
[name
] = mapping(addr
, do_rw
<ss_uint24_t
, &memory_space::read
<ss_uint24_t
>,
945 &memory_space::write
<ss_uint24_t
>>);
946 else if(type
== "shword")
947 mappings
[name
] = mapping(addr
, do_rw
<ss_int24_t
, &memory_space::read
<ss_int24_t
>,
948 &memory_space::write
<ss_int24_t
>>);
949 else if(type
== "dword")
950 mappings
[name
] = mapping(addr
, do_rw
<uint32_t, &memory_space::read
<uint32_t>,
951 &memory_space::write
<uint32_t>>);
952 else if(type
== "sdword")
953 mappings
[name
] = mapping(addr
, do_rw
<int32_t, &memory_space::read
<int32_t>,
954 &memory_space::write
<int32_t>>);
955 else if(type
== "qword")
956 mappings
[name
] = mapping(addr
, do_rw
<uint64_t, &memory_space::read
<uint64_t>,
957 &memory_space::write
<uint64_t>>);
958 else if(type
== "sqword")
959 mappings
[name
] = mapping(addr
, do_rw
<int64_t, &memory_space::read
<int64_t>,
960 &memory_space::write
<int64_t>>);
961 else if(type
== "float")
962 mappings
[name
] = mapping(addr
, do_rw
<float, &memory_space::read
<float>,
963 &memory_space::write
<float>>);
964 else if(type
== "double")
965 mappings
[name
] = mapping(addr
, do_rw
<double, &memory_space::read
<double>,
966 &memory_space::write
<double>>);
968 (stringfmt() << P
.get_fname() << ": Bad type").throwex();
972 lua_mmap_struct::lua_mmap_struct(lua::state
& L
)