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
, lua::parameters
& P
);
54 template<class T
, bool _bswap
> int rw(lua::state
& L
, lua::parameters
& P
);
55 template<bool write
, bool sign
> int scattergather(lua::state
& L
, lua::parameters
& P
);
70 lua_vma_list(lua::state
& L
);
71 static int create(lua::state
& L
, lua::parameters
& P
);
72 int index(lua::state
& L
, lua::parameters
& P
);
73 int newindex(lua::state
& L
, lua::parameters
& P
);
74 int call(lua::state
& L
, lua::parameters
& P
);
81 lua::_class
<lua_vma
> class_vma(lua_class_memory
, "VMA", {}, {
82 {"info", &lua_vma::info
},
83 {"read", &lua_vma::scattergather
<false, false>},
84 {"sread", &lua_vma::scattergather
<false, true>},
85 {"write", &lua_vma::scattergather
<true, false>},
86 {"sbyte", &lua_vma::rw
<int8_t, false>},
87 {"byte", &lua_vma::rw
<uint8_t, false>},
88 {"sword", &lua_vma::rw
<int16_t, false>},
89 {"word", &lua_vma::rw
<uint16_t, false>},
90 {"shword", &lua_vma::rw
<ss_int24_t
, false>},
91 {"hword", &lua_vma::rw
<ss_uint24_t
, false>},
92 {"sdword", &lua_vma::rw
<int32_t, false>},
93 {"dword", &lua_vma::rw
<uint32_t, false>},
94 {"sqword", &lua_vma::rw
<int64_t, false>},
95 {"qword", &lua_vma::rw
<uint64_t, false>},
96 {"float", &lua_vma::rw
<float, false>},
97 {"double", &lua_vma::rw
<double, false>},
98 {"isbyte", &lua_vma::rw
<int8_t, true>},
99 {"ibyte", &lua_vma::rw
<uint8_t, true>},
100 {"isword", &lua_vma::rw
<int16_t, true>},
101 {"iword", &lua_vma::rw
<uint16_t, true>},
102 {"ishword", &lua_vma::rw
<ss_int24_t
, true>},
103 {"ihword", &lua_vma::rw
<ss_uint24_t
, true>},
104 {"isdword", &lua_vma::rw
<int32_t, true>},
105 {"idword", &lua_vma::rw
<uint32_t, true>},
106 {"isqword", &lua_vma::rw
<int64_t, true>},
107 {"iqword", &lua_vma::rw
<uint64_t, true>},
108 {"ifloat", &lua_vma::rw
<float, true>},
109 {"idouble", &lua_vma::rw
<double, true>},
112 lua::_class
<lua_vma_list
> class_vmalist(lua_class_memory
, "VMALIST", {
113 {"new", lua_vma_list::create
},
115 {"__index", &lua_vma_list::index
},
116 {"__newindex", &lua_vma_list::newindex
},
117 {"__call", &lua_vma_list::call
},
120 lua_vma::lua_vma(lua::state
& L
, memory_region
* r
)
128 int lua_vma::info(lua::state
& L
, lua::parameters
& P
)
130 for(auto i
: lsnes_memory
.get_regions())
132 return handle_push_vma(L
, *i
);
133 (stringfmt() << P
.get_fname() << ": Stale region").throwex();
136 template<class T
, bool _bswap
> int lua_vma::rw(lua::state
& L
, lua::parameters
& P
)
141 P(P
.skipped(), addr
);
143 if(addr
> vmasize
|| addr
> vmasize
- sizeof(T
))
144 throw std::runtime_error("VMA::rw<T>: Address outside VMA bounds");
147 T val
= lsnes_memory
.read
<T
>(addr
+ vmabase
);
148 if(_bswap
) val
= bswap(val
);
151 } else if(P
.is_number()) {
154 (stringfmt() << P
.get_fname() << ": VMA is read-only").throwex();
156 if(_bswap
) val
= bswap(val
);
157 lsnes_memory
.write
<T
>(addr
+ vmabase
, val
);
160 P
.expected("number or nil");
163 template<bool write
, bool sign
> int lua_vma::scattergather(lua::state
& L
, lua::parameters
& P
)
173 while(!P
.is_novalue()) {
180 addr
= P
.arg
<uint64_t>();
182 lsnes_memory
.write
<uint8_t>(addr
+ vmabase
, val
>> shift
);
184 val
= val
+ ((uint64_t)lsnes_memory
.read
<uint8_t>(addr
+ vmabase
) << shift
);
189 if(val
>= (1ULL << (shift
- 1))) sval
-= (1ULL << shift
);
190 if(sign
) L
.pushnumber(sval
); else L
.pushnumber(val
);
192 return write
? 0 : 1;
195 lua_vma_list::lua_vma_list(lua::state
& L
)
199 int lua_vma_list::create(lua::state
& L
, lua::parameters
& P
)
201 lua::_class
<lua_vma_list
>::create(L
);
205 int lua_vma_list::call(lua::state
& L
, lua::parameters
& P
)
209 for(auto i
: lsnes_memory
.get_regions()) {
211 L
.pushlstring(i
->name
);
217 int lua_vma_list::index(lua::state
& L
, lua::parameters
& P
)
223 auto l
= lsnes_memory
.get_regions();
225 std::list
<memory_region
*>::iterator i
;
226 for(i
= l
.begin(), j
= 0; i
!= l
.end(); i
++, j
++)
227 if((*i
)->name
== vma
) {
228 lua::_class
<lua_vma
>::create(L
, *i
);
231 (stringfmt() << P
.get_fname() << ": No such VMA").throwex();
234 int lua_vma_list::newindex(lua::state
& L
, lua::parameters
& P
)
236 throw std::runtime_error("Writing is not allowed");