1 #include "lua/internal.hpp"
2 #include "core/memorymanip.hpp"
3 #include "core/memorywatch.hpp"
4 #include "core/moviedata.hpp"
5 #include "core/moviefile.hpp"
6 #include "core/rom.hpp"
7 #include "library/sha256.hpp"
8 #include "library/string.hpp"
9 #include "library/serialization.hpp"
10 #include "library/minmax.hpp"
11 #include "library/int24.hpp"
15 int handle_push_vma(lua_state
& L
, memory_region
& r
)
19 L
.pushlstring(r
.name
.c_str(), r
.name
.size());
21 L
.pushstring("address");
28 L
.pushnumber(r
.last_address());
30 L
.pushstring("readonly");
31 L
.pushboolean(r
.readonly
);
33 L
.pushstring("special");
34 L
.pushboolean(r
.special
);
36 L
.pushstring("endian");
37 L
.pushnumber(r
.endian
);
42 template<typename T
> T
bswap(T val
)
45 serialization::swap_endian(val2
);
52 lua_vma(lua_state
& L
, memory_region
* r
);
53 int info(lua_state
& L
, const std::string
& fname
);
54 template<class T
, bool _bswap
> int rw(lua_state
& L
, const std::string
& fname
);
55 template<bool write
, bool sign
> int scattergather(lua_state
& L
, const std::string
& fname
);
70 lua_vma_list(lua_state
& L
);
71 int index(lua_state
& L
, const std::string
& fname
);
72 int newindex(lua_state
& L
, const std::string
& fname
);
73 int call(lua_state
& L
, const std::string
& fname
);
80 lua_class
<lua_vma
> class_vma("VMA");
81 lua_class
<lua_vma_list
> class_vmalist("VMALIST");
83 lua_vma::lua_vma(lua_state
& L
, memory_region
* r
)
85 objclass
<lua_vma
>().bind_multi(L
, {
86 {"info", &lua_vma::info
},
87 {"read", &lua_vma::scattergather
<false, false>},
88 {"sread", &lua_vma::scattergather
<false, true>},
89 {"write", &lua_vma::scattergather
<true, false>},
90 {"sbyte", &lua_vma::rw
<int8_t, false>},
91 {"byte", &lua_vma::rw
<uint8_t, false>},
92 {"sword", &lua_vma::rw
<int16_t, false>},
93 {"word", &lua_vma::rw
<uint16_t, false>},
94 {"shword", &lua_vma::rw
<ss_int24_t
, false>},
95 {"hword", &lua_vma::rw
<ss_uint24_t
, false>},
96 {"sdword", &lua_vma::rw
<int32_t, false>},
97 {"dword", &lua_vma::rw
<uint32_t, false>},
98 {"sqword", &lua_vma::rw
<int64_t, false>},
99 {"qword", &lua_vma::rw
<uint64_t, false>},
100 {"float", &lua_vma::rw
<float, false>},
101 {"double", &lua_vma::rw
<double, false>},
102 {"isbyte", &lua_vma::rw
<int8_t, true>},
103 {"ibyte", &lua_vma::rw
<uint8_t, true>},
104 {"isword", &lua_vma::rw
<int16_t, true>},
105 {"iword", &lua_vma::rw
<uint16_t, true>},
106 {"ishword", &lua_vma::rw
<ss_int24_t
, true>},
107 {"ihword", &lua_vma::rw
<ss_uint24_t
, true>},
108 {"isdword", &lua_vma::rw
<int32_t, true>},
109 {"idword", &lua_vma::rw
<uint32_t, true>},
110 {"isqword", &lua_vma::rw
<int64_t, true>},
111 {"iqword", &lua_vma::rw
<uint64_t, true>},
112 {"ifloat", &lua_vma::rw
<float, true>},
113 {"idouble", &lua_vma::rw
<double, true>},
121 int lua_vma::info(lua_state
& L
, const std::string
& fname
)
123 for(auto i
: lsnes_memory
.get_regions())
125 return handle_push_vma(L
, *i
);
126 (stringfmt() << fname
<< ": Stale region").throwex();
129 template<class T
, bool _bswap
> int lua_vma::rw(lua_state
& L
, const std::string
& fname
)
131 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(2, fname
.c_str());
132 if(addr
> vmasize
|| addr
> vmasize
- sizeof(T
))
133 throw std::runtime_error("VMA::rw<T>: Address outside VMA bounds");
134 if(L
.type(3) == LUA_TNIL
|| L
.type(3) == LUA_TNONE
) {
136 T val
= lsnes_memory
.read
<T
>(addr
+ vmabase
);
137 if(_bswap
) val
= bswap(val
);
140 } else if(L
.type(3) == LUA_TNUMBER
) {
143 (stringfmt() << fname
<< ": VMA is read-only").throwex();
144 T val
= L
.get_numeric_argument
<T
>(3, "VMA::rw<T>");
145 if(_bswap
) val
= bswap(val
);
146 lsnes_memory
.write
<T
>(addr
+ vmabase
, val
);
149 (stringfmt() << fname
<< ": Parameter #3 must be integer if present").throwex();
152 template<bool write
, bool sign
> int lua_vma::scattergather(lua_state
& L
, const std::string
& fname
)
159 val
= L
.get_numeric_argument
<uint64_t>(ptr
++, fname
.c_str());
160 while(L
.type(ptr
) != LUA_TNIL
&& L
.type(ptr
) != LUA_TNONE
) {
161 if(L
.type(ptr
) == LUA_TBOOLEAN
) {
162 if(L
.toboolean(ptr
++))
167 addr
= L
.get_numeric_argument
<uint64_t>(ptr
++, fname
.c_str());
169 lsnes_memory
.write
<uint8_t>(addr
+ vmabase
, val
>> shift
);
171 val
= val
+ ((uint64_t)lsnes_memory
.read
<uint8_t>(addr
+ vmabase
) << shift
);
176 if(val
>= (1ULL << (shift
- 1))) sval
-= (1ULL << shift
);
177 if(sign
) L
.pushnumber(sval
); else L
.pushnumber(val
);
179 return write
? 0 : 1;
182 lua_vma_list::lua_vma_list(lua_state
& L
)
184 objclass
<lua_vma_list
>().bind_multi(L
, {
185 {"__index", &lua_vma_list::index
},
186 {"__newindex", &lua_vma_list::newindex
},
187 {"__call", &lua_vma_list::call
},
191 int lua_vma_list::call(lua_state
& L
, const std::string
& fname
)
195 for(auto i
: lsnes_memory
.get_regions()) {
197 L
.pushlstring(i
->name
);
203 int lua_vma_list::index(lua_state
& L
, const std::string
& fname
)
205 std::string vma
= L
.get_string(2, fname
.c_str());
206 auto l
= lsnes_memory
.get_regions();
208 std::list
<memory_region
*>::iterator i
;
209 for(i
= l
.begin(), j
= 0; i
!= l
.end(); i
++, j
++)
210 if((*i
)->name
== vma
) {
211 lua_class
<lua_vma
>::create(L
, *i
);
214 (stringfmt() << fname
<< ": No such VMA").throwex();
217 int lua_vma_list::newindex(lua_state
& L
, const std::string
& fname
)
219 throw std::runtime_error("Writing is not allowed");
222 function_ptr_luafun
memory2(lua_func_misc
, "memory2", [](lua_state
& L
, const std::string
& fname
) ->
224 lua_class
<lua_vma_list
>::create(L
);