Lua: COMPARE_OBJ: Check strided memory block for modifications
This commit is contained in:
parent
b53979bcd1
commit
ef1f61a6e7
6 changed files with 173 additions and 23 deletions
|
@ -38,4 +38,6 @@ extern uint64_t lua_timer_hook_time;
|
||||||
extern void* synchronous_paint_ctx;
|
extern void* synchronous_paint_ctx;
|
||||||
void lua_renderq_run(lua_render_context* ctx, void* synchronous_paint_ctx);
|
void lua_renderq_run(lua_render_context* ctx, void* synchronous_paint_ctx);
|
||||||
|
|
||||||
|
void lua_accessed_range(uint64_t base, uint64_t size, uint64_t rows, uint64_t stride, uint64_t& m, uint64_t& M);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
28
lua.lyx
28
lua.lyx
|
@ -6788,6 +6788,34 @@ Set the global execute hook mask to <mask>.
|
||||||
CPU.
|
CPU.
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Subsection
|
||||||
|
memory.compare_new: Create memory compare object.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
Syntax: COMPARE_OBJ memory.compare_new([string marea], number size, [number
|
||||||
|
rows, number stride])
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Standard
|
||||||
|
Create memory compare object of <rows> blocks of <size> bytes starting from
|
||||||
|
address <base> (relative to <marea>).
|
||||||
|
The blocks are offset by <stride> from one another.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Subsection
|
||||||
|
COMPARE_OBJ(): Region changed?
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
Syntax: bool COMPARE_OBJ()
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Standard
|
||||||
|
Returns true if region has changed, false if it is still is way it is during
|
||||||
|
last call (creation counts).
|
||||||
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Subsection
|
\begin_layout Subsection
|
||||||
memory.mmap: Class MMAP_STRUCT
|
memory.mmap: Class MMAP_STRUCT
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
BIN
lua.pdf
BIN
lua.pdf
Binary file not shown.
119
src/lua/memory-compare.cpp
Normal file
119
src/lua/memory-compare.cpp
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
#include "lua/internal.hpp"
|
||||||
|
#include "core/memorymanip.hpp"
|
||||||
|
#include "library/minmax.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
uint64_t get_vmabase(const std::string& vma)
|
||||||
|
{
|
||||||
|
for(auto i : lsnes_memory.get_regions())
|
||||||
|
if(i->name == vma)
|
||||||
|
return i->base;
|
||||||
|
throw std::runtime_error("No such VMA");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t get_read_address(lua::parameters& P)
|
||||||
|
{
|
||||||
|
uint64_t vmabase = 0;
|
||||||
|
if(P.is_string())
|
||||||
|
vmabase = get_vmabase(P.arg<std::string>());
|
||||||
|
auto addr = P.arg<uint64_t>();
|
||||||
|
return addr + vmabase;
|
||||||
|
}
|
||||||
|
|
||||||
|
class compare_obj
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
compare_obj(lua::state& L, uint64_t addr, uint64_t size, uint64_t rows, uint64_t stride);
|
||||||
|
static int create(lua::state& L, lua::parameters& P);
|
||||||
|
int call(lua::state& L, lua::parameters& P);
|
||||||
|
private:
|
||||||
|
std::vector<uint8_t> prev;
|
||||||
|
bool try_map;
|
||||||
|
uint64_t addr;
|
||||||
|
uint64_t minaddr;
|
||||||
|
uint64_t maxaddr;
|
||||||
|
uint64_t rows;
|
||||||
|
uint64_t size;
|
||||||
|
uint64_t stride;
|
||||||
|
};
|
||||||
|
|
||||||
|
compare_obj::compare_obj(lua::state& L, uint64_t _addr, uint64_t _size, uint64_t _rows, uint64_t _stride)
|
||||||
|
{
|
||||||
|
if(!_size || !_rows) {
|
||||||
|
//Empty.
|
||||||
|
try_map = false;
|
||||||
|
addr = 0;
|
||||||
|
minaddr = 0;
|
||||||
|
maxaddr = 0;
|
||||||
|
rows = 0;
|
||||||
|
size = 1;
|
||||||
|
stride = 0;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
addr = _addr;
|
||||||
|
size = _size;
|
||||||
|
rows = _rows;
|
||||||
|
stride = _stride;
|
||||||
|
lua_accessed_range(addr, size, rows, stride, minaddr, maxaddr);
|
||||||
|
try_map = (minaddr <= maxaddr && (maxaddr - minaddr + 1));
|
||||||
|
if((size_t)(size * rows) / rows != size)
|
||||||
|
throw std::runtime_error("Size to monitor too large");
|
||||||
|
prev.resize(size * rows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int compare_obj::create(lua::state& L, lua::parameters& P)
|
||||||
|
{
|
||||||
|
uint64_t addr, daddr, size;
|
||||||
|
uint64_t stride = 0, rows = 1;
|
||||||
|
|
||||||
|
addr = get_read_address(P);
|
||||||
|
P(daddr, size, P.optional(rows, 1));
|
||||||
|
if(rows > 1)
|
||||||
|
P(stride);
|
||||||
|
|
||||||
|
compare_obj* o = lua::_class<compare_obj>::create(L, addr, size, rows, stride);
|
||||||
|
o->call(L, P);
|
||||||
|
L.pop(1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int compare_obj::call(lua::state& L, lua::parameters& P)
|
||||||
|
{
|
||||||
|
bool equals = true;
|
||||||
|
char* pbuffer = try_map ? lsnes_memory.get_physical_mapping(minaddr, maxaddr - minaddr + 1) : NULL;
|
||||||
|
if(pbuffer) {
|
||||||
|
//Mapable.
|
||||||
|
uint64_t offset = addr - minaddr;
|
||||||
|
for(uint64_t i = 0; i < rows; i++) {
|
||||||
|
bool eq = !memcmp(&prev[i * size], pbuffer + offset, size);
|
||||||
|
if(!eq)
|
||||||
|
memcpy(&prev[i * size], pbuffer + offset, size);
|
||||||
|
equals &= eq;
|
||||||
|
offset += stride;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Not mapable.
|
||||||
|
for(uint64_t i = 0; i < rows; i++) {
|
||||||
|
uint64_t addr1 = addr + i * stride;
|
||||||
|
uint64_t addr2 = i * size;
|
||||||
|
for(uint64_t j = 0; j < size; j++) {
|
||||||
|
uint8_t byte = lsnes_memory.read<uint8_t>(addr1 + j);
|
||||||
|
bool eq = prev[addr2 + j] == (char)byte;
|
||||||
|
if(!eq)
|
||||||
|
prev[addr2 + j] = byte;
|
||||||
|
equals &= eq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
L.pushboolean(!equals);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua::_class<compare_obj> class_vmalist(lua_class_memory, "COMPARE_OBJ", {
|
||||||
|
{"new", compare_obj::create},
|
||||||
|
}, {
|
||||||
|
{"__call", &compare_obj::call},
|
||||||
|
});
|
||||||
|
}
|
|
@ -320,6 +320,27 @@ void handle_unregisterX(lua::state& L, uint64_t addr, int lfn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lua_accessed_range(uint64_t base, uint64_t size, uint64_t rows, uint64_t stride, uint64_t& m, uint64_t& M)
|
||||||
|
{
|
||||||
|
m = 0xFFFFFFFFFFFFFFFFULL;
|
||||||
|
M = 0;
|
||||||
|
if(!rows || !size)
|
||||||
|
return;
|
||||||
|
for(uint64_t i = 0; i < rows; i++) {
|
||||||
|
if(base + size > base) {
|
||||||
|
m = min(m, base);
|
||||||
|
M = max(M, base + size - 1);
|
||||||
|
} else if(base + size == 0) {
|
||||||
|
m = min(m, base);
|
||||||
|
M = 0xFFFFFFFFFFFFFFFFULL;
|
||||||
|
} else {
|
||||||
|
m = 0;
|
||||||
|
M = 0xFFFFFFFFFFFFFFFFULL;
|
||||||
|
}
|
||||||
|
base += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typedef void(*dummy1_t)(lua::state& L, uint64_t addr, int lfn);
|
typedef void(*dummy1_t)(lua::state& L, uint64_t addr, int lfn);
|
||||||
dummy1_t dummy_628963286932869328692386963[] = {
|
dummy1_t dummy_628963286932869328692386963[] = {
|
||||||
handle_registerX<DEBUG_READ>,
|
handle_registerX<DEBUG_READ>,
|
||||||
|
@ -513,27 +534,6 @@ namespace
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void accessed_range(uint64_t base, uint64_t size, uint64_t rows, uint64_t stride, uint64_t& m, uint64_t& M)
|
|
||||||
{
|
|
||||||
m = 0xFFFFFFFFFFFFFFFFULL;
|
|
||||||
M = 0;
|
|
||||||
if(!rows || !size)
|
|
||||||
return;
|
|
||||||
for(uint64_t i = 0; i < rows; i++) {
|
|
||||||
if(base + size > base) {
|
|
||||||
m = min(m, base);
|
|
||||||
M = max(M, base + size - 1);
|
|
||||||
} else if(base + size == 0) {
|
|
||||||
m = min(m, base);
|
|
||||||
M = 0xFFFFFFFFFFFFFFFFULL;
|
|
||||||
} else {
|
|
||||||
m = 0;
|
|
||||||
M = 0xFFFFFFFFFFFFFFFFULL;
|
|
||||||
}
|
|
||||||
base += stride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename H, void(*update)(H& state, const char* mem, size_t memsize),
|
template<typename H, void(*update)(H& state, const char* mem, size_t memsize),
|
||||||
std::string(*read)(H& state), bool extra>
|
std::string(*read)(H& state), bool extra>
|
||||||
int hash_core(H& state, lua::state& L, lua::parameters& P)
|
int hash_core(H& state, lua::state& L, lua::parameters& P)
|
||||||
|
@ -552,7 +552,7 @@ namespace
|
||||||
P(stride);
|
P(stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
accessed_range(addr, size, rows, stride, low, high);
|
lua_accessed_range(addr, size, rows, stride, low, high);
|
||||||
if(low > high || high - low + 1 == 0)
|
if(low > high || high - low + 1 == 0)
|
||||||
mappable = false;
|
mappable = false;
|
||||||
|
|
||||||
|
@ -631,7 +631,7 @@ namespace
|
||||||
if(rows > 1)
|
if(rows > 1)
|
||||||
P(stride);
|
P(stride);
|
||||||
|
|
||||||
accessed_range(addr, size, rows, stride, low, high);
|
lua_accessed_range(addr, size, rows, stride, low, high);
|
||||||
if(low > high || high - low + 1 == 0)
|
if(low > high || high - low + 1 == 0)
|
||||||
mappable = false;
|
mappable = false;
|
||||||
if(rows && (size_t)(size * rows) / rows != size)
|
if(rows && (size_t)(size * rows) / rows != size)
|
||||||
|
|
|
@ -69,6 +69,7 @@ filereader = classes.FILEREADER;
|
||||||
memory2=classes.VMALIST.new();
|
memory2=classes.VMALIST.new();
|
||||||
callback=classes.CALLBACKS_LIST.new();
|
callback=classes.CALLBACKS_LIST.new();
|
||||||
memory.map_structure=classes.MMAP_STRUCT.new;
|
memory.map_structure=classes.MMAP_STRUCT.new;
|
||||||
|
memory.compare_new=classes.COMPARE_OBJ.new;
|
||||||
zip.create=classes.ZIPWRITER.new;
|
zip.create=classes.ZIPWRITER.new;
|
||||||
gui.tilemap=classes.TILEMAP.new;
|
gui.tilemap=classes.TILEMAP.new;
|
||||||
gui.renderq_new=classes.RENDERCTX.new;
|
gui.renderq_new=classes.RENDERCTX.new;
|
||||||
|
|
Loading…
Add table
Reference in a new issue