Remove DFusion plugin and script system

It's been four years since meaningful updates, and in that time
alternatives have emerged to almost everything.  Any remaining
functionality to replace is on the issue tracker.

Simpler is better, for users and developers, and removing a legacy
system makes it easier to understand how DFHack works.
develop
PeridexisErrant 2015-11-17 10:49:19 +09:30
parent 928bcb6d95
commit 80e4b8d3df
32 changed files with 4 additions and 3948 deletions

@ -36,6 +36,10 @@ Fixes
-----
- confirm haul-delete: Fixed issue preventing deletion of stop conditions or using "x" in route names
Removed
-------
- DFusion: legacy script system, obsolete or replaced by better alternatives
DFHack 0.40.24-r4
=================

@ -1,11 +1,5 @@
INCLUDE(Plugins.cmake)
# Dfusion plugin
OPTION(BUILD_DFUSION "Build DFusion." ON)
if(BUILD_DFUSION)
add_subdirectory (Dfusion)
endif()
OPTION(BUILD_STONESENSE "Build stonesense (needs a checkout first)." OFF)
if(BUILD_STONESENSE)
add_subdirectory (stonesense)

@ -1,11 +0,0 @@
include_directories(include)
FILE(GLOB DFUSION_CPPS src/*.c*)
set(
DFUSION_CPPS_ALL
dfusion.cpp
${DFUSION_CPPS}
)
FILE(GLOB DFUSION_HS include/*)
SET_SOURCE_FILES_PROPERTIES( ${DFUSION_HS} PROPERTIES HEADER_FILE_ONLY TRUE )
DFHACK_PLUGIN(dfusion ${DFUSION_CPPS_ALL} ${DFUSION_HS} LINK_LIBRARIES lua dfhack-tinythread)

@ -1,88 +0,0 @@
#include "Core.h"
#include "Export.h"
#include "PluginManager.h"
#include "MemAccess.h"
#include "MiscUtils.h"
#include <vector>
#include <string>
#include "luamain.h"
#include "lua_Process.h"
#include "lua_Hexsearch.h"
#include "lua_Misc.h"
#include "DataDefs.h"
#include "LuaTools.h"
using std::vector;
using std::string;
using namespace DFHack;
DFHACK_PLUGIN("dfusion")
static int loadObjectFile(lua_State* L)
{
std::string path;
path=luaL_checkstring(L,1);
OutFile::File f(path);
lua_newtable(L);
int table_pos=lua_gettop(L);
size_t size=f.GetTextSize();
Lua::Push(L,size);
lua_setfield(L,table_pos,"data_size");
char* buf=new char[size];
f.GetText(buf);
//Lua::PushDFObject(L,DFHack::,buf);
//Lua::Push(L,buf);
lua_pushlightuserdata(L,buf);
lua_setfield(L,table_pos,"data");
const OutFile::vSymbol &symbols=f.GetSymbols();
lua_newtable(L);
for(size_t i=0;i<symbols.size();i++)
{
Lua::Push(L,i);
lua_newtable(L);
Lua::Push(L,symbols[i].name);
lua_setfield(L,-2,"name");
Lua::Push(L,symbols[i].pos);
lua_setfield(L,-2,"pos");
lua_settable(L,-3);
}
lua_setfield(L,table_pos,"symbols");
return 1;
}
static int markAsExecutable(lua_State* L)
{
unsigned addr=luaL_checkunsigned(L,1);
std::vector<DFHack::t_memrange> ranges;
DFHack::Core::getInstance().p->getMemRanges(ranges);
for(size_t i=0;i<ranges.size();i++)
{
if(ranges[i].isInRange((void*)addr))
{
DFHack::t_memrange newperm=ranges[i];
newperm.execute=true;
DFHack::Core::getInstance().p->setPermisions(ranges[i],newperm);
return 0;
}
}
lua_pushlstring(L,"Memory range not found",23);
lua_error(L);
return 0;
}
DFHACK_PLUGIN_LUA_COMMANDS {
DFHACK_LUA_COMMAND(loadObjectFile),
DFHACK_LUA_COMMAND(markAsExecutable),
DFHACK_LUA_END
};
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
return CR_OK;
}

@ -1,126 +0,0 @@
#ifndef OUTFILE_H
#define OUTFILE_H
#include <string>
#include <fstream>
#include <iostream>
#include <map>
#include <vector>
namespace OutFile
{
struct Header
{
unsigned short machinetype;
unsigned short sectioncount;
unsigned long time;
unsigned long symbolptr;
unsigned long symbolcount;
unsigned short opthead;
unsigned short flags;
void PrintData()
{
std::cout<<"Symbol start:"<<symbolptr<<"\n";
}
};
struct Section
{
char name[8];
unsigned long Vsize;
unsigned long Vstart;
unsigned long size;
unsigned long start;
unsigned long ptrRel;
unsigned long ptrLine;
unsigned short numRel;
unsigned short numLine;
unsigned long flags;
void PrintData()
{
std::cout<<name<<" size:"<<size<<" start:"<<start<<"\n";
}
};
struct Symbol
{
std::string name;
unsigned long pos;
unsigned short sectnumb;
unsigned short type;
unsigned char storageclass;
unsigned char auxsymbs;
//char unk2[6];
void Read(std::iostream &s,unsigned long strptr)
{
union
{
char buf[8];
struct
{
unsigned long zeros;
unsigned long strptr;
};
}data;
s.read((char*)&data,8);
s.read((char*)&pos,4);
s.read((char*)&sectnumb,2);
s.read((char*)&type,2);
s.read((char*)&storageclass,1);
s.read((char*)&auxsymbs,1);
if(data.zeros!=0)
{
name=data.buf;
name=name.substr(0,8);
}
else
{
//name="";
//std::cout<<"Name in symbol table\n";
char buf[256];
s.seekg(strptr+data.strptr);
s.get(buf,256,'\0');
name=buf;
}
//s.seekp(6,std::ios::cur);
}
void PrintData()
{
std::cout<<name<<" section:"<<sectnumb<<" pos:"<<pos<<"\n";
}
};
struct Relocation
{
unsigned long ptr;
unsigned long tblIndex;
unsigned short type;
};
typedef std::vector<Symbol> vSymbol;
class File
{
public:
File(std::string path);
virtual ~File();
void GetText(char *ptr);
size_t GetTextSize();
void LoadSymbols();
const vSymbol& GetSymbols(){LoadSymbols();return symbols;};
void PrintSymbols();
void PrintRelocations();
protected:
private:
typedef std::map<std::string,Section> secMap;
secMap sections;
vSymbol symbols;
Section &GetSection(std::string name);
std::fstream mystream;
Header myhead;
// Section Text;
//Section Data;
// Section Bss;
};
}
#endif // OUTFILE_H

@ -1,37 +0,0 @@
#ifndef HEXSEARCH_H
#define HEXSEARCH_H
#include <vector>
#include "Core.h" //for some reason process.h needs core
#include "MemAccess.h"
//(not yet)implemented using Boyer-Moore algorithm
class Hexsearch
{
public:
typedef std::vector<int> SearchArgType;
enum SearchConst //TODO add more
{
ANYBYTE=0x101,DWORD_,ANYDWORD,ADDRESS
};
Hexsearch(const SearchArgType &args,char * startpos,char * endpos);
~Hexsearch();
void Reset(){pos_=startpos_;};
void SetStart(char * pos){pos_=pos;};
void * FindNext();
std::vector<void *> FindAll();
private:
bool Compare(int a,int b);
void ReparseArgs();
SearchArgType args_;
char * pos_,* startpos_,* endpos_;
std::vector<int> BadCharShifts,GoodSuffixShift;
void PrepareGoodSuffixTable();
void PrepareBadCharShift();
};
#endif

@ -1,33 +0,0 @@
#ifndef LUA_HEXSEARCH_H
#define LUA_HEXSEARCH_H
#include "hexsearch.h"
#include "luamain.h"
namespace lua
{
class Hexsearch
{
int tblid;
::Hexsearch *p;
public:
Hexsearch(lua_State *L,int id);
~Hexsearch();
int GetTableId(){return tblid;};
int find(lua_State *L);
int findall(lua_State *L);
int reset(lua_State *L);
DEF_LUNE(Hexsearch);
};
void RegisterHexsearch(lua::state &st);
}
#endif

@ -1,46 +0,0 @@
#ifndef LUA_MISC_H
#define LUA_MISC_H
#include <map>
#include "Core.h"
#include <MemAccess.h>
#include "luamain.h"
#include "OutFile.h"
#include "LuaTools.h"
namespace lua
{
typedef std::map<std::string,void *> mapPlugs;
class PlugManager
{
public:
mapPlugs GetList(){return plugs;};
uint32_t AddNewPlug(std::string name,uint32_t size,uint32_t loc=0);
uint32_t FindPlugin(std::string name);
static PlugManager &GetInst()
{
void *p;
p=DFHack::Core::getInstance().GetData("dfusion_manager");
if(p==0)
{
p=new PlugManager;
DFHack::Core::getInstance().RegisterData(p,"dfusion_manager");
}
return *static_cast<PlugManager*>(p);
};
protected:
private:
PlugManager(){};
mapPlugs plugs;
};
void RegisterMisc(lua::state &st);
}
#endif

@ -1,13 +0,0 @@
#ifndef LUA_PROCESS_H
#define LUA_PROCESS_H
#include "Core.h"
#include <MemAccess.h>
#include "luamain.h"
namespace lua
{
void RegisterProcess(lua::state &st);
}
#endif

@ -1,40 +0,0 @@
#ifndef LUAMAIN_H
#define LUAMAIN_H
#include <string>
using std::string;
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "lune.h"
#include "luaxx.hpp"
namespace lua
{
//global lua state singleton
class glua
{
public:
static state &Get();
private:
glua();
static glua *ptr;
state mystate;
};
//registers basic lua commands
void RegBasics(lua::state &L);
//dumps lua function trace, useless unless called from lua.
string DebugDump(lua::state &L);
//register functions, first registers into global scope, second into current table
void RegFunctions(lua::state &L,luaL_Reg const *arr);
void RegFunctionsLocal(lua::state &L,luaL_Reg const *arr);
}
#endif // LUAMAIN_H

@ -1,530 +0,0 @@
/* vim: set et sw=3 tw=0 fo=croqlaw cino=t0:
*
* Luaxx, the C++ Lua wrapper library.
* Copyright (c) 2006-2008 Matthew Nicholson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef LUAXX_H
#define LUAXX_H
#define lua_Integer_long 1
#define lua_Integer_int 1
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <string>
#include <vector>
#include <new>
#include <exception>
/** @file
* Luaxx header file.
*/
/** @mainpage Luaxx
*
* Luaxx is a thin wrapper around the Lua C API. The wrapper adds some
* convenience functions and integrates well with modern C++.
*
* Luaxx is not designed like toLua, instead Luaxx is more of a 1 to 1
* logical mapping of the lua API in C++. For example: in C you would write
* 'lua_pushnumber(L, 3)', in C++ with Luaxx you would write
* 'L.push(3)'.
*
* Every thing is contained in the 'lua' namespace and exceptions are thrown
* when a lua API function returns an error. Most of the functionality is
* contained in the lua::state class, which can be passed directly to lua C API
* functions (the compiler will automatically use the internal lua_State
* pointer). See the documentation for that class for more information.
*/
namespace lua
{
void StackDump(lua_State *L);
/** A generic lua exception.
*/
class exception : public std::exception {
public:
/// Constructor.
exception() : std::exception() { }
/// Constructor.
explicit exception(const char* desc) : std::exception(), description(desc) { }
virtual ~exception() throw() { }
/** Get a description of the error.
* @returns a C-string describing the error
*/
virtual const char* what() const throw() {
return description.c_str();
}
private:
std::string description;
};
/** A lua runtime error.
* This is thrown when there was an error executing some lua code.
* @note This is not an std::runtime error.
*/
class runtime_error : public exception {
public:
/// Constructor.
runtime_error() : exception() { }
/// Constructor.
explicit runtime_error(const char* desc) : exception(desc) { }
virtual ~runtime_error() throw() { }
};
/** A syntax error.
*/
class syntax_error : public exception {
public:
/// Constructor.
syntax_error() : exception() { }
/// Constructor.
explicit syntax_error(const char* desc) : exception(desc) { }
virtual ~syntax_error() throw() { }
};
/** An error loading a lua file.
* This is thrown when a call to lua::loadfile failed because the file could
* not be opened or read.
*/
class file_error : public exception {
public:
/// Constructor.
file_error() : exception() { }
/// Constructor.
explicit file_error(const char* desc) : exception(desc) { }
virtual ~file_error() throw() { }
};
/** A memory allocation error.
*/
class bad_alloc : public exception, std::bad_alloc {
public:
/// Constructor.
bad_alloc() : lua::exception(), std::bad_alloc() { }
/// Constructor.
explicit bad_alloc(const char* desc) : lua::exception(desc), std::bad_alloc() { }
virtual ~bad_alloc() throw() { }
};
/** An error converting a lua type.
*/
class bad_conversion : public exception {
public:
/// Constructor.
bad_conversion() : exception() { }
/// Constructor.
explicit bad_conversion(const char* desc) : exception(desc) { }
virtual ~bad_conversion() throw() { }
};
/// A Lua table (this class does not have any data).
class table { };
/// A Lua nil (this class does not have any data).
class nil { };
/// A lua function (not a cfunction).
class function { };
/// A lua userdatum
class userdata { };
/// A lua light userdatum
class lightuserdata { };
typedef lua_CFunction cfunction; ///< A cfunction on the lua statck
typedef lua_Integer integer; ///< The default lua integer type
typedef lua_Number number; ///< The default lua number type
typedef lua_Reader reader; ///< The type of function used by lua_load
const int multiret = LUA_MULTRET; ///< LUA_MULTIRET
/** This is the Luaxx equivalent of lua_State.
* The functions provided by this class, closely resemble those of the Lua C
* API.
*/
void StackDump(lua_State *L);
class state {
public:
state();
state(lua_State* L);
state(const state& t)
{
managed=false;
L=t.L;
}
state& operator = (const state& t);
~state();
operator lua_State*();
state& push();
state& push(nil);
state& push(bool boolean);
template<typename T> state& push(T number);
state& push(const char* s, size_t length);
state& push(const char* s);
state& push(const std::string& s);
state& push(cfunction f);
state& push(table);
state& push(void* p);
template<typename T> state& pushlightuserdata(T p);
template<typename T> state& to(T& number, int index = -1);
template<typename T> state& touserdata(T& p, int index = -1);
template<typename T> T as(T default_value, int index = -1);
template<typename T> T as(int index = -1);
template<typename T> T vpop()
{
T ret;
ret=as<T>();
pop();
return ret;
}
template<typename T> bool is(int index = -1);
state& check(int narg);
#ifndef lua_Integer_int
state& check(int& i, int narg);
#endif
state& check(integer& i, int narg);
#ifndef lua_Integer_long
state& check(long& l, int narg);
#endif
state& check(std::string& s, int narg);
state& check(number& n, int narg);
template<typename msg_t> void error(msg_t message);
#if 0
template<> void error(const std::string& message);
#endif
state& pcall(int nargs = 0, int nresults = 0, int on_error = 0);
state& call(int nargs = 0, int nresults = 0);
state& checkstack(int size);
state& settop(int index);
int gettop();
int size();
bool empty();
state& insert(int index);
state& replace(int index);
state& remove(int index);
state& pop(int elements = 1);
state& pushvalue(int index);
state& newtable();
bool newmetatable(const std::string& tname);
template<typename userdata_t> userdata_t* newuserdata();
void* newuserdata(size_t nbytes);
state& gettable(int index = -2);
state& getfield(const std::string& k, int index = -1);
state& settable(int index = -3);
state& setfield(const std::string& k, int index = -2);
state& getmetatable(const std::string& tname);
bool getmetatable(int index);
bool next(int index = -2);
state& getglobal(const std::string& name);
state& setglobal(const std::string& name);
state& loadfile(const std::string& filename);
state& loadstring(const std::string& s);
template<typename iterator_t> state& load(iterator_t begin, iterator_t end);
size_t objlen(int index = -1);
private:
lua_State* L;
bool managed;
int throw_error(int code);
};
// template functions
/** Push a number onto the stack.
* @tparam T the numeric type to push (should be automatically determined,
* if there is no specialization for the desired type, lua_pushnumber() will
* be used, and may fail)
* @param number the number to push
* @returns a reference to this lua::state
*/
template<typename T>
state& state::push(T number) {
lua_pushnumber(L, number);
return *this;
}
/** Push a light userdatum on to the stack.
* @tparam T the type of data to push (should be automatically determined)
* @param p the pointer to push
* @returns a reference to this lua::state
*/
template<typename T>
state& state::pushlightuserdata(T p) {
lua_pushlightuserdata(L, p);
return *this;
}
/** Check if the given index is of the given type (defaults to using
* lua_isnumber()).
* @tparam T the type to check for (the default, if no specializations
* match, does lua_isnumber())
* @param index the index to check
* @note the default version (used if no specialization is matched) will
* check if the given value is a number
* @returns whether the value at the given index is a nil
*/
template<typename T>
bool state::is(int index) {
return lua_isnumber(L, index);
}
/** Get the value at index as the given numeric type.
* @tparam T they numeric type to static_cast<T>() the numeric value on the
* stack to
* @param number where to store the value
* @param index the index to get
* @note This function does \em not pop the value from the stack.
* @todo Instead of throwing an exception here, we may just return an
* error code.
* @throws lua::bad_conversion if the value on the stack could not be
* converted to the indicated type
* @returns a reference to this lua::state
*/
template<typename T>
state& state::to(T& number, int index) {
if (lua_isnumber(L, index))
number = static_cast<T>(lua_tonumber(L, index));
else
throw bad_conversion("Cannot convert non 'number' value to number");
return *this;
}
/** Get the value at index as (light) userdata.
* @tparam T the type of data pointed to (pointer is returned as
* reinterpret_cast<T>())
* @param p the pointer to store the value in
* @param index the index to get
* @note This function does \em not pop the value from the stack.
* @todo Instead of throwing an exception here, we may just return an
* error code.
* @throws lua::bad_conversion if the value on the stack could not be
* converted to the indicated type
* @returns a reference to this lua::state
*/
template<typename T>
state& state::touserdata(T& p, int index) {
if (lua_isuserdata(L, index))
p = reinterpret_cast<T>(lua_touserdata(L, index));
else
throw bad_conversion("Cannot convert non 'userdata' or 'lightuserdata' value to userdata");
return *this;
}
/** Get the value at index as the given type.
* @tparam T the type to retrieve the value on the stack as (the default
* template function uses lua_tonumber(), specializations may cause
* different behavior)
* @param default_value this value is returned if the conversion fails
* @param index the index to get
* @note This function does \em not pop the value from the stack.
* @returns the indicated value from the stack or the default value if
* the conversion fails
*/
template<typename T>
T state::as(T default_value, int index) {
if (lua_isnumber(L, index))
return static_cast<T>(lua_tonumber(L, index));
else
return default_value;
}
/** Get the value at index as the given type.
* @tparam T the expected type of the value
* @param index the index to get
*
* @note This function does \em not pop the value from the stack.
* @note The default version of this function uses lua_tonumber() but
* specializations may cause different behavior.
*
* @todo Instead of throwing an exception here, we may just return an
* error code.
*
* @throws lua::bad_conversion if the value on the stack could not be
* converted to the indicated type
*
* This function will return the value on the stack as the given type. If
* the value is not of the given type <em>no conversion will be
* performed</em> and lua::bad_conversion will be thrown. There are some
* exceptions to this rule, for example, numbers will be converted to
* strings and vice-versa (conversion is only performed if the matching
* lua_is*() function returns true). The state::to() function should be
* used to perform automatic conversion.
*
* @returns the indicated value as the given type if possible
*/
template<typename T>
T state::as(int index) {
if (lua_isnumber(L, index))
return static_cast<T>(lua_tonumber(L, index));
else
throw bad_conversion("Cannot convert non 'number' value to number");
}
/** Create a new userdatum on the stack.
* @tparam userdata_t the type of the userdata (will be passed to sizeof())
*
* This function creates a new userdatum on the stack the size of
* userdata_t and return a pointer to it.
* @returns a pointer to the new userdatum
*/
template<typename userdata_t>
userdata_t* state::newuserdata() {
return reinterpret_cast<userdata_t*>(lua_newuserdata(L, sizeof(userdata_t)));
}
/** Generate a Lua error.
* @tparam msg_t the type of error message data (should be automatically
* determined)
* @param message the error message/value
* @note This function is used to raise errors from lua::cfunctions.
* @note This function never returns, instead it throws an exception
* caught by the intepreter.
*/
template<typename msg_t>
void state::error(msg_t message) {
push(message);
lua_error(L);
}
/** Load a sequence of data as a Lua chunk.
* @tparam iterator_t the type of iterator to use (should be automatically
* determined)
* @param begin an iterator to the start of the sequence
* @param end an iterator to the end of the sequence (one past the
* end)
*
* This function takes a sequence of data and attempts to convert it
* into a Lua chunk. The type of data passed must be able to be
* converted into an 8-bit char.
*
* @note This function should automatically detect if the data is text
* or binary.
*
* @returns a reference to this lua::state
*/
template<typename iterator_t>
state& state::load(iterator_t begin, iterator_t end) {
// convert the data to characters
std::vector<char> chunk(begin, end);
// Here we use the address of the first element of our vector.
// This works because the data in std::vectors is contiguous.
throw_error(luaL_loadbuffer(L, &(*chunk.begin()), chunk.size(), NULL));
return *this;
}
// template specializations
template<> state& state::to(bool& boolean, int index);
template<> state& state::to(std::string& string, int index);
template<> bool state::as(bool default_value, int index);
template<> std::string state::as(std::string default_value, int index);
template<> bool state::as(int index);
template<> std::string state::as(int index);
template<> bool state::is<nil>(int index);
template<> bool state::is<bool>(int index);
template<> bool state::is<std::string>(int index);
template<> bool state::is<table>(int index);
template<> bool state::is<cfunction>(int index);
template<> bool state::is<function>(int index);
template<> bool state::is<userdata>(int index);
template<> bool state::is<lightuserdata>(int index);
// inline functions
/** Convert a lua::state to a lua_State*.
* This operator allows lua::state to behave like a lua_State
* pointer.
*
* @note This should be used as a last result to interoperate with C
* code. This may be removed in future versions of Luaxx.
*/
inline state::operator lua_State*() {
return L;
}
/** Throws exceptions for error return codes.
* @param code the return code
*
* This function throws an exception based on the error it was passed.
* If it is passed a 0 it will not throw anything.
*
* @todo In the future this function may check an exception mask
* before throwing an error.
*
* @returns the code it was passed
*/
inline int state::throw_error(int code) {
std::string error;
// below, we package lua errors into exceptions
switch (code) {
case 0:
break;
case LUA_ERRSYNTAX:
to(error).pop();
throw syntax_error(error.c_str());
case LUA_ERRMEM:
to(error).pop();
throw bad_alloc(error.c_str());
case LUA_ERRRUN:
to(error).pop();
throw runtime_error(error.c_str());
case LUA_ERRFILE:
to(error).pop();
throw file_error(error.c_str());
default:
to(error).pop();
throw exception(error.c_str());
}
return code;
}
}
#endif

@ -1,360 +0,0 @@
#ifndef LUNE_H
#define LUNE_H
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "luaxx.hpp"
#include <string>
namespace lua
{
class object
{
state &myst;
int myref;
public:
object(state &myst):myst(myst)
{
myref=luaL_ref(myst,LUA_REGISTRYINDEX);
}
~object()
{
luaL_unref(myst,LUA_REGISTRYINDEX,myref);
}
void Get()
{
lua_rawgeti(myst,LUA_REGISTRYINDEX,myref);
}
state &GetState(){return myst;};
};
class local_object
{
state myst;
int myref;
static object *mytbl;
public:
local_object(lua_State *L)
{
myst=state(L);
//LOG<<"Creating local object...\n";
//StackDump(L);
if(!mytbl)
{
//LOG<<" Metable...\n";
myst.newtable(); //2
if(myst.newmetatable("WEAKTABLE"))//3
{
//StackDump(L);
myst.push("kv"); //4
myst.setfield("__mode");//3
//LOG<<" Setting Metable...\n";
//StackDump(L);
}
//LOG<<" Attaching to holder...\n";
//myst.setfield("__metatable");//2
lua_setmetatable(myst,-1);
mytbl=new object(myst);
//StackDump(L);
//LOG<<" Done Metatable...\n";
}
//StackDump(L);
mytbl->Get();
//LOG<<" Got my table...\n";
//StackDump(L);
myst.insert(-2);
myref=luaL_ref(myst,-2);
//LOG<<"Before pop:";
//StackDump(L);
myst.pop(1);
GetTable();
//LOG<<"========Done...\n"<<"Ref="<<myref<<"\n";
//mytbl->Get();
//StackDump(L);
//LOG<<"===========================\n";
}
~local_object()
{
//LOG<<"Deleting local object...\n";
ReleaseTable();
}
void ReleaseTable()
{
mytbl->Get();
int pos=myst.gettop();
luaL_unref(myst,pos,myref);
myst.remove(pos);
}
state GetState(){return myst;}
void GetTable()
{
//LOG<<"Getting ref="<<myref<<"\n";
//StackDump(myst);
//LOG<<"Tbl preget\n";
mytbl->Get();
int pos=myst.gettop();
//StackDump(myst);
//LOG<<"Tbl get\n";
//int pos=myst.gettop();
lua_rawgeti(myst,pos,myref);
//StackDump(myst);
//LOG<<"Done\n";
myst.remove(pos);
}
protected:
};
};
template <typename T,bool GC=true>
class Lune
{
public:
typedef struct
{
T *pT;
int tableref;
} userdataType;
typedef int (T::*mfp)(lua_State *L);
typedef struct
{
const char *name;
mfp mfunc;
} RegType;
static void Register(lua_State *L)
{
lua_newtable(L);
int methods = lua_gettop(L);
luaL_newmetatable(L, T::className);
int metatable = lua_gettop(L);
// store method table in globals so that
// scripts can add functions written in Lua.
lua_pushvalue(L, methods);
lua_setglobal(L, T::className);
lua_pushliteral(L, "__metatable");
lua_pushvalue(L, methods);
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
lua_pushliteral(L, "__index");
lua_pushcfunction(L, index_T);
lua_settable(L, metatable);
//lua_pushliteral(L, "__name");
//lua_pushstring(L, T::className);
//lua_settable(L, metatable);
lua_pushliteral(L, "__newindex");
lua_pushcfunction(L, newindex_T);
lua_settable(L, metatable);
lua_pushliteral(L, "__instances");
lua_newtable(L);
lua_settable(L, metatable);
if(GC)
{
lua_pushliteral(L, "__gc");
lua_pushcfunction(L, gc_T);
lua_settable(L, metatable);
}
lua_newtable(L); // metatable for method table
int mt = lua_gettop(L);
lua_pushliteral(L, "__call");
lua_pushcfunction(L, new_T);
lua_pushliteral(L, "new");
lua_pushvalue(L, -2); // dup new_T function
lua_settable(L, methods); // add new_T to method table
lua_settable(L, mt); // mt.__call = new_T
lua_setmetatable(L, methods);
//LOG<<"lune: registered class \""<<T::className<<"\"\n";
// fill method table with methods from class T
for (RegType *l = T::methods; l->name; l++)
{
/* edited by Snaily: shouldn't it be const RegType *l ... ? */
lua_pushstring(L, l->name);
lua_pushlightuserdata(L, (void*)l);
lua_pushcclosure(L, thunk, 1);
lua_settable(L, methods);
//LOG<<"lune: method \""<<l->name<<"\"\n";
}
lua_pop(L, 2); // drop metatable and method table
};
static void GetTable(lua_State *L,T *p)
{
GetTableEx(L,p->GetTableId());
}
static void GetTableEx(lua_State *L,int id)
{
lua::state s(L);
s.getmetatable(T::className);
s.getfield("__instances");
int ins=s.gettop();
lua_rawgeti(L, ins, id);
s.insert(-3);
s.pop(2);
}
static T *check(lua_State *L, int narg)
{
userdataType *ud =
static_cast<userdataType*>(luaL_checkudata(L, narg, T::className)); //TODO FIX THIs..
//(lua_touserdata(L, narg));//
if(!ud) luaL_error(L, "Bad argument %d: expected type %s", narg, T::className);
return ud->pT; // pointer to T object
}
protected:
private:
static int RegTable(lua_State *L)
{
// LOG<<"Regging....\n";
//lua::StackDump(L);
lua::state s(L);
int ssize=s.gettop();
//s.getglobal(T::className);
s.getmetatable(T::className);
s.getfield("__instances");
int ins=s.gettop();
s.newtable();
int id=luaL_ref(L,ins);
//LOG<<"After reg:\n";
//lua::StackDump(L);
s.settop(ssize);
return id;
}
static void UnregTable(lua_State *L,int id)
{
lua::state s(L);
s.getmetatable(T::className);
s.getfield("__instances");
int ins=s.gettop();
//LOG<<"Unreg table id:"<<id<<"stack dump:\n";
//lua::StackDump(L);
luaL_unref(L,ins,id);
}
static int index_T(lua_State *L) // calls with (table, key), return value
{
lua::state st(L);
std::string key=st.as<std::string>(-1);
T *p=check(L,1);
GetTable(L,p);
st.insert(-2);
//LOG<<"Index:\n";
//lua::StackDump(L);
lua_rawget(L,-2); //try getting from normal table
if(st.is<lua::nil>()) //failed
{
st.pop(2);
st.getglobal(T::className); //try class tables then
st.push(key);
st.gettable();
}
return 1;
}
static int newindex_T(lua_State *L)
{
//LOG<<"New index....\n";
//lua::StackDump(L);
lua::state st(L);
T *p=check(L,1);
GetTable(L,p);
//st.insert(-3);
//LOG<<"Before set:\n";
st.insert(-3);
//lua::StackDump(L);
lua_rawset(L,-3);
return 0;
}
static int thunk(lua_State *L)
{
//LOG<<"Size of stack:"<<lua_gettop(L)<<"\n";
//lua::StackDump(L);
if(lua_gettop(L)<1)
luaL_error(L,"Member function called without 'self'");
//LOG<<"Size of stack after:"<<lua_gettop(L)<<"\n";
// stack has userdata, followed by method args
T *obj = check(L, 1); // get 'self', or if you prefer, 'this'
//T *obj=static_cast<userdataType*>(lua_touserdata(L,1))->pT;
lua_remove(L, 1); // remove self so member function args start at index 1
// get member function from upvalue
RegType *l = static_cast<RegType*>(lua_touserdata(L, lua_upvalueindex(1)));
return (obj->*(l->mfunc))(L); // call member function
}
static int gc_T(lua_State *L)
{
//lua_getfield(L,,"__ud");
//LOG<<"Garbage collecting.\n";
//lua::StackDump(L);
userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, 1));
T *obj = ud->pT;
delete obj; // call destructor for T objects
UnregTable(L,ud->tableref);
return 0;
}
static int new_T(lua_State *L)
{
//LOG<<"Pre build:"<<lua_gettop(L)<<"\n";
//lua::StackDump(L);
lua_remove(L, 1); // use classname:new(), instead of classname.new()
//lua_newtable(L);
int id=RegTable(L);
//LOG<<"Registred as:"<<id<<"\n";
//int ssize=lua_gettop(L);
T *obj = new T(L,id); // call constructor for T objects
lua_settop(L,0); //no need for parameters later.
//LOG<<"Post build:"<<lua_gettop(L)<<"\t";
//lua::StackDump(L);
//LOG<<"TSOP\n";
userdataType *ud =
static_cast<userdataType*>(lua_newuserdata(L, sizeof(userdataType)));
//lua::StackDump(L);
luaL_getmetatable(L, T::className); // lookup metatable in Lua registry
lua_setmetatable(L,-2);
//LOG<<"metatable set\n";
//lua::StackDump(L);
GetTable(L,obj);
lua_pushliteral(L,"__obj");
lua_pushvalue(L,-3);
lua_settable(L,-3);
lua_pop(L,1);
//LOG<<"Object referenced\n";
//lua::StackDump(L);
//T *p = new(ud) T(L); // call constructor for T objects
//lua::StackDump(L);
ud->pT = obj; // store pointer to object in userdata
ud->tableref=id;
//luaL_getmetatable(L, T::className); // lookup metatable in Lua registry
//lua_setmetatable(L, tableindex);
//lua::StackDump(L);
//LOG<<"Push done\n";
return 1; // userdata containing pointer to T object
}
Lune() {}; //non constructable...
};
#define method(class, name) {#name, &class::name}
#define DEF_LUNE(class) static const char className[];\
static Lune<class>::RegType methods[];
#define DEF_LUNE_NOGC(class) static const char className[];\
static Lune<class,false>::RegType methods[];
#define IMP_LUNE(class,lua_name) const char class::className[]=#lua_name;
#define LUNE_METHODS_START(class) Lune<class>::RegType class::methods[] = {
#define LUNE_METHODS_START_NOGC(class) Lune<class,false>::RegType class::methods[] = {
#define LUNE_METHODS_END() {0,0}}
#endif // LUNE_H

@ -1,12 +0,0 @@
Dfusion plugin offers four DFhack commands: 'dfusion', 'dfuse' and 'lua', 'runlua'.
lua:
Runs an interactive lua console. For more on lua commands see [http://www.lua.org/manual/5.1/manual.html Lua reference manual] or google "lua". Also this command could be ran with filepath as an argument. Then it runs that file as a lua script file. E.g. ''lua dfusion/temp.lua'' runs a file <your df path>/dfusion/temp.lua.
runlua:
Similar to ''lua <filename>'' but not interactive, to be used with hotkeys
dfusion:
First this command runs all plugins' init.lua part then show a menu. Type number to run specified plugin.
dfuse:
Similar to dfusion but not interactive. To be used with hotkeys (later will have command support).
Also dfuse/dfusion runs an init script located at 'save directory/dfusion/init.lua'. And 'initcustom.lua' if it exists
More info http://dwarffortresswiki.org/index.php/Utility:DFusion

@ -1,102 +0,0 @@
#include "OutFile.h"
#include <stdexcept>
using namespace OutFile;
File::File(std::string path)
{
//mystream.exceptions ( std::fstream::eofbit | std::fstream::failbit | std::fstream::badbit );
mystream.open(path.c_str(),std::fstream::binary|std::ios::in|std::ios::out);
if(mystream)
{
mystream.read((char*)&myhead,sizeof(myhead));
for(unsigned i=0;i<myhead.sectioncount;i++)
{
Section x;
mystream.read((char*)&x,sizeof(Section));
sections[x.name]=x;
}
//std::cout<<"Sizeof:"<<sizeof(Section)<<"\n";
/*myhead.PrintData();
for(auto it=sections.begin();it!=sections.end();it++)
{
it->second.PrintData();
}*/
}
else
{
throw std::runtime_error("Error opening file!");
}
}
Section &File::GetSection(std::string name)
{
return sections[name];
}
void File::GetText(char *ptr)
{
Section &s=GetSection(".text");
mystream.seekg(s.start);
mystream.read(ptr,s.size);
}
size_t File::GetTextSize()
{
Section &s=GetSection(".text");
return s.size;
}
void File::PrintRelocations()
{
for(auto it=sections.begin();it!=sections.end();it++)
{
std::cout<<it->first<<":\n";
for(unsigned i=0;i<it->second.numRel;i++)
{
Relocation r;
mystream.seekg(it->second.ptrRel+10*i);
mystream.read((char*)&r,10);
std::cout<<r.ptr<<" -- "<<r.tblIndex<<":"<</*symbols[r.tblIndex].name<<*/" type:"<<r.type<<"\n";
}
}
}
void File::PrintSymbols()
{
std::cout<<"Sizeof symbol:"<<sizeof(Symbol)<<std::endl;
std::cout<<"Symbol count:"<<myhead.symbolcount<<std::endl;
for(unsigned i=0;i<myhead.symbolcount;i++)
{
mystream.seekg(myhead.symbolptr+i*18);
Symbol s;
std::cout<<i<<"\t";
s.Read(mystream,myhead.symbolptr+18*myhead.symbolcount);
//mystream.read((char*)&s,sizeof(Symbol));
s.PrintData();
symbols.push_back(s);
if(s.auxsymbs>0)
{
i+=s.auxsymbs;
}
}
}
void File::LoadSymbols()
{
symbols.clear();
for(unsigned i=0;i<myhead.symbolcount;i++)
{
mystream.seekg(myhead.symbolptr+i*18);
Symbol s;
s.Read(mystream,myhead.symbolptr+18*myhead.symbolcount);
symbols.push_back(s);
if(s.auxsymbs>0)
{
i+=s.auxsymbs;
}
}
}
File::~File()
{
}

@ -1,116 +0,0 @@
#include "hexsearch.h"
Hexsearch::Hexsearch(const SearchArgType &args,char * startpos,char * endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos)
{
ReparseArgs();
}
Hexsearch::~Hexsearch()
{
}
inline bool Hexsearch::Compare(int a,int b)
{
if(b==Hexsearch::ANYBYTE)
return true;
if(a==b)
return true;
return false;
}
void Hexsearch::ReparseArgs()
{
union
{
uint32_t val;
uint8_t bytes[4];
}B;
SearchArgType targ;
targ=args_;
args_.clear();
for(size_t i=0;i<targ.size();)
{
if(targ[i]==DWORD_)
{
i++;
B.val=targ[i];
for(int j=0;j<4;j++)
{
args_.push_back(B.bytes[j]);
}
i++;
}
else if (targ[i]==ANYDWORD)
{
i++;
for(int j=0;j<4;j++)
args_.push_back(ANYBYTE);
}
else
{
args_.push_back(targ[i]);
i++;
}
}
}
void * Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm
{
DFHack::Core &inst=DFHack::Core::getInstance();
DFHack::Process *p=inst.p;
uint8_t *buf;
buf=new uint8_t[args_.size()];
while(pos_<endpos_)
{
bool found=true;
p->readByte(pos_,buf[0]);
if(Compare(buf[0],args_[0]))
{
p->read(pos_,args_.size(),buf);
for(size_t i=0;i<args_.size();i++)
{
if(!Compare(buf[i],args_[i]))
{
pos_+=i;
found=false;
break;
}
}
if(found)
{
pos_+=args_.size();
delete [] buf;
return pos_-args_.size();
}
}
pos_ = pos_ + 1;
}
delete [] buf;
return 0;
}
std::vector<void *> Hexsearch::FindAll()
{
std::vector<void *> ret;
void * cpos=pos_;
while(cpos!=0)
{
cpos=FindNext();
if(cpos!=0)
ret.push_back(cpos);
}
return ret;
}
void Hexsearch::PrepareBadCharShift()
{
BadCharShifts.resize(256,-1);
int i=0;
for(SearchArgType::reverse_iterator it=args_.rbegin();it!=args_.rend();it++)
{
BadCharShifts[*it]=i;
i++;
}
}
void Hexsearch::PrepareGoodSuffixTable()
{
GoodSuffixShift.resize(args_.size()+1,0);
}

@ -1,61 +0,0 @@
#include "lua_Hexsearch.h"
int lua::Hexsearch::find(lua_State *L)
{
lua::state st(L);
void * pos=p->FindNext();
st.push(reinterpret_cast<size_t>(pos));
return 1;
}
int lua::Hexsearch::findall(lua_State *L)
{
lua::state st(L);
std::vector<void *> pos=p->FindAll();
st.newtable();
for(unsigned i=0;i<pos.size();i++)
{
st.push(i+1);
st.push(reinterpret_cast<size_t>(pos[i]));
st.settable();
}
return 1;
}
lua::Hexsearch::Hexsearch(lua_State *L,int id):tblid(id)
{
lua::state st(L);
char * start,* end;
::Hexsearch::SearchArgType args;
start= (char *)st.as<uint32_t>(1);
end=(char *)st.as<uint32_t>(2);
for(int i=3;i<=st.gettop();i++)
{
args.push_back(st.as<int>(i));
}
p=new ::Hexsearch(args,start,end);
}
lua::Hexsearch::~Hexsearch()
{
delete p;
}
int lua::Hexsearch::reset(lua_State *L)
{
lua::state st(L);
p->Reset();
return 0;
}
IMP_LUNE(lua::Hexsearch,hexsearch);
LUNE_METHODS_START(lua::Hexsearch)
method(lua::Hexsearch,find),
method(lua::Hexsearch,findall),
method(lua::Hexsearch,reset),
LUNE_METHODS_END();
#define __ADDCONST(name) st.push(::Hexsearch:: name); st.setglobal(#name)
void lua::RegisterHexsearch(lua::state &st)
{
Lune<lua::Hexsearch>::Register(st);
__ADDCONST(ANYBYTE);
__ADDCONST(ANYDWORD);
__ADDCONST(DWORD_);
}
#undef __ADDCONST

@ -1,154 +0,0 @@
#include "lua_Misc.h"
uint32_t lua::PlugManager::AddNewPlug(std::string name,uint32_t size,uint32_t loc)
{
void *p;
if(size!=0)
p=new unsigned char[size];
else
p=(void*)loc;
plugs[name]=p;
return (uint32_t)p;
}
uint32_t lua::PlugManager::FindPlugin(std::string name)
{
mapPlugs::iterator it=plugs.find(name);
if(it!=plugs.end())
return (uint32_t)it->second;
else
return 0;
}
static int LoadMod(lua_State *L)
{
lua::state st(L);
std::string modfile=st.as<std::string>(1);
std::string modname=st.as<std::string>(2);
uint32_t size_add=st.as<uint32_t>(0,3);
OutFile::File f(modfile);
uint32_t size=f.GetTextSize();
uint32_t pos=lua::PlugManager::GetInst().AddNewPlug(modname,size+size_add);
char *buf;
buf=new char[size];
f.GetText(buf);
//std::cout<<"poking @:"<<std::hex<<pos<<"size :"<<size<<std::endl;
DFHack::Core::getInstance().p->write((void *) pos,size,(uint8_t*)buf);
delete [] buf;
st.push(pos);
st.push(size);
return 2;
}
static int LoadObj(lua_State *L)
{
lua::state st(L);
std::string modfile=st.as<std::string>(1);
OutFile::File f(modfile);
size_t s=f.GetTextSize();
void *p=st.newuserdata(s); //TODO does it leak memory??
f.GetText((char*)p);
st.push(s);
return 2;
}
static int FindMarker(lua_State *L) // marker, void ptr, size, start
{
lua::state st(L);
union
{
unsigned char bytes[4];
size_t mark;
}M;
M.mark=st.as<size_t>(1);
unsigned char *p=(unsigned char *)lua_touserdata(L, 2);//st.as<lua::userdata>(2);
size_t size=st.as<size_t>(3);
size_t start=st.as<size_t>(4);
for(size_t i=start;i<size;i++)
{
bool ok;
ok=true;
if(p[i]==M.bytes[0])
{
for(size_t j=0;j<4;j++)
{
if(p[i+j]!=M.bytes[j])
{
ok=false;
break;
}
}
if(ok)
{
st.push(i);
return 1;
}
}
}
return 0;
}
static int LoadObjSymbols(lua_State *L)
{
lua::state st(L);
std::string modfile=st.as<std::string>(1);
OutFile::File f(modfile);
OutFile::vSymbol vec=f.GetSymbols();
OutFile::Symbol S;
st.newtable();
for(size_t i=0;i<vec.size();i++)
{
st.push(i);
S=vec[i];
st.newtable();
st.push(S.name);
st.setfield("name");
st.push(S.pos);
st.setfield("pos");
st.settable();
}
return 1;
}
static int NewMod(lua_State *L)
{
lua::state st(L);
std::string modname=st.as<std::string>(1);
size_t size=st.as<size_t>(2);
size_t loc=st.as<size_t>(3,0);
uint32_t pos=lua::PlugManager::GetInst().AddNewPlug(modname,size,loc);
st.push(pos);
return 1;
}
static int GetMod(lua_State *L)
{
lua::state st(L);
std::string modname=st.as<std::string>(1);
uint32_t pos=lua::PlugManager::GetInst().FindPlugin(modname);
if(pos==0)
st.push();
else
st.push(pos);
return 1;
}
const luaL_Reg lua_misc_func[]=
{
{"loadmod",LoadMod},
{"getmod",GetMod},
{"loadobj",LoadObj},
{"loadobjsymbols",LoadObjSymbols},
{"findmarker",FindMarker},
{"newmod",NewMod},
{NULL,NULL}
};
void lua::RegisterMisc(lua::state &st)
{
st.getglobal("engine");
if(st.is<lua::nil>())
{
st.pop();
st.newtable();
}
lua::RegFunctionsLocal(st, lua_misc_func);
st.setglobal("engine");
}

@ -1,269 +0,0 @@
#include "lua_Process.h"
static DFHack::Process* GetProcessPtr(lua::state &st)
{
return DFHack::Core::getInstance().p;
}
static int lua_Process_readDWord(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint32_t ret=c->readDWord( (void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
}
static int lua_Process_writeDWord(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->writeDWord((void *) st.as<uint32_t>(1),st.as<uint32_t>(2));
return 0;
}
static int lua_Process_readFloat(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
float ret=c->readFloat((void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
}
static int lua_Process_readWord(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint16_t ret=c->readWord((void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
}
static int lua_Process_writeWord(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->writeWord((void *) st.as<uint32_t>(1),st.as<uint16_t>(2));
return 0;
}
static int lua_Process_readByte(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint8_t ret=c->readByte((void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
}
static int lua_Process_writeByte(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->writeByte((void *) st.as<uint32_t>(1),st.as<uint8_t>(2));
return 0;
}
static int lua_Process_read(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
size_t len=st.as<uint32_t>(2);
uint8_t* buf;
if(!st.is<lua::nil>(3))
buf=(uint8_t*)lua_touserdata(st,3);
else
buf=new uint8_t[len];
c->read((void *) st.as<uint32_t>(1),len,buf);
st.pushlightuserdata(buf);
return 1;
}
static int lua_Process_write(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c-> write((void *) st.as<uint32_t>(1),st.as<uint32_t>(2),static_cast<uint8_t*>(lua_touserdata(st,3)));
return 0;
}
static int lua_Process_readSTLString (lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->readSTLString((void *) st.as<uint32_t>(1));
st.push(r);
return 1;
}
static int lua_Process_writeSTLString(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->writeSTLString((void *) st.as<uint32_t>(1),st.as<std::string>(2));
return 0;
}
static int lua_Process_copySTLString(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->copySTLString((void *) st.as<uint32_t>(1),st.as<uint32_t>(2));
return 0;
}
static int lua_Process_doReadClassName(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->doReadClassName((void*)st.as<size_t>(1));
st.push(r);
return 1;
}
static int lua_Process_readClassName(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->readClassName((void*)st.as<size_t>(1));
st.push(r);
return 1;
}
static int lua_Process_readCString (lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->readCString((void *) st.as<uint32_t>(1));
st.push(r);
return 1;
}
static int lua_Process_isSuspended(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
st.push(c->isSuspended());
return 1;
}
static int lua_Process_isIdentified(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
st.push(c->isIdentified());
return 1;
}
static int lua_Process_getMemRanges(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::vector<DFHack::t_memrange> ranges;
c->getMemRanges(ranges);
st.newtable();
for(size_t i=0;i<ranges.size();i++)
{
st.push(i);
st.newtable();
st.push((uint32_t)ranges[i].start); // WARNING!! lua has only 32bit numbers, possible loss of data!!
st.setfield("start");
st.push((uint32_t)ranges[i].end);
st.setfield("end");
st.push(std::string(ranges[i].name));
st.setfield("name");
st.push(ranges[i].read);
st.setfield("read");
st.push(ranges[i].write);
st.setfield("write");
st.push(ranges[i].execute);
st.setfield("execute");
st.push(ranges[i].shared);
st.setfield("shared");
st.push(ranges[i].valid);
st.setfield("valid");
st.settable();
}
return 1;
}
static int lua_Process_getBase(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint32_t base=c->getBase();
st.push(base);
return 1;
}
/*static int lua_Process_getPID(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
int ret=c->getPID();
st.push(ret);
return 1;
}*/
static int lua_Process_getPath(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string ret=c->getPath();
st.push(ret);
return 1;
}
static int lua_Process_setPermisions(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
DFHack::t_memrange range,trange;
st.getfield("start",1);
range.start= (void *)st.as<uint64_t>();
st.pop();
st.getfield("end",1);
range.end= (void *)st.as<uint64_t>();
st.pop();
st.getfield("read",2);
trange.read=st.as<bool>();
st.pop();
st.getfield("write",2);
trange.write=st.as<bool>();
st.pop();
st.getfield("execute",2);
trange.execute=st.as<bool>();
st.pop();
c->setPermisions(range,trange);
return 0;
}
#define PROC_FUNC(name) {#name,lua_Process_ ## name}
const luaL_Reg lua_process_func[]=
{
PROC_FUNC(readDWord),
PROC_FUNC(writeDWord),
PROC_FUNC(readFloat),
PROC_FUNC(readWord),
PROC_FUNC(writeWord),
PROC_FUNC(readByte),
PROC_FUNC(writeByte),
PROC_FUNC(read),
PROC_FUNC(write),
PROC_FUNC(readSTLString),
PROC_FUNC(writeSTLString),
PROC_FUNC(copySTLString),
PROC_FUNC(doReadClassName),
PROC_FUNC(readClassName),
PROC_FUNC(readCString ),
PROC_FUNC(isSuspended),
PROC_FUNC(isIdentified),
PROC_FUNC(getMemRanges),
PROC_FUNC(getBase),
//PROC_FUNC(getPID), //not implemented
PROC_FUNC(getPath),
PROC_FUNC(setPermisions),
{NULL,NULL}
};
#undef PROC_FUNC
void lua::RegisterProcess(lua::state &st)
{
st.getglobal("Process");
if(st.is<lua::nil>())
{
st.pop();
st.newtable();
}
lua::RegFunctionsLocal(st, lua_process_func);
st.setglobal("Process");
}

@ -1,69 +0,0 @@
#include "luamain.h"
#include <vector>
lua::glua* lua::glua::ptr=0;
lua::glua::glua()
{
RegBasics(mystate);
}
lua::state &lua::glua::Get()
{
if(!glua::ptr)
glua::ptr=new glua();
return glua::ptr->mystate;
}
int lua_Ver_Lua(lua_State *L)
{
lua::state st(L);
st.push(LUA_RELEASE);
return 1;
}
static const struct luaL_Reg lua_basic_lib [] =
{
{"getluaver", lua_Ver_Lua},
{NULL, NULL} /* sentinel */
};
void lua::RegBasics(lua::state &L)
{
luaL_openlibs(L);
RegFunctions(L,lua_basic_lib);
}
void lua::RegFunctions(lua::state &L,luaL_Reg const*arr)
{
luaL_Reg const *cur=arr;
while(cur->name!=NULL)
{
lua_pushcfunction(L, cur->func);
lua_setglobal(L, cur->name);
cur++;
}
}
void lua::RegFunctionsLocal(lua::state &L,luaL_Reg const*arr)
{
luaL_Reg const *cur=arr;
while(cur->name!=NULL)
{
lua_pushcfunction(L, cur->func);
//lua_setglobal(L, cur->name);
L.setfield(cur->name);
cur++;
}
}
string lua::DebugDump(lua::state &L)
{
L.getglobal("debug");
L.getfield("traceback");
L.call(0,1);
string ret=L.as<string>();
//cout<<"StackTrace:"<<ret<<endl;
L.settop(0);
return ret;
}

@ -1,836 +0,0 @@
/* vim: set et sw=3 tw=0 fo=croqlaw cino=t0:
*
* Luaxx, the C++ Lua wrapper library.
* Copyright (c) 2006-2008 Matthew Nicholson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <luaxx.hpp>
#include <iostream>
#define LOG std::cout
/** @file
* Luaxx implementation file.
*/
namespace lua
{
void StackDump(lua_State *L)
{
int i;
int top = lua_gettop(L);
for (i = 1; i <= top; i++) /* repeat for each level */
{
int t = lua_type(L, i);
LOG<<i<<":";
switch (t)
{
case LUA_TSTRING: /* strings */
LOG<<"str ="<<lua_tostring(L, i)<<"\n";
break;
case LUA_TBOOLEAN: /* booleans */
LOG<<"bool="<<(lua_toboolean(L, i) ? "true" : "false")<<"\n";
break;
case LUA_TNUMBER: /* numbers */
LOG<<"num ="<<lua_tonumber(L, i)<<"\n";
break;
case LUA_TTABLE:
LOG<<lua_typename(L, t);
{
//LOG<<"PRE TOP:"<< lua_gettop(L)<<"\n";
lua_getglobal(L,"PrintTable");
//lua_insert(L,-2);
lua_pushvalue(L,i);
lua_pcall(L,1,0,0);
//LOG<<"POST TOP:"<< lua_gettop(L)<<"\n";
}
break;
default: /* other values */
LOG<<lua_typename(L, t);
{
//LOG<<"PRE TOP:"<< lua_gettop(L)<<"\n";
lua_getglobal(L,"tostring");
//lua_insert(L,-2);
lua_pushvalue(L,i);
lua_pcall(L,1,1,0);
LOG<<"=";
LOG<<lua_tostring(L,-1)<<"\n";
lua_pop(L,1);
//LOG<<"POST TOP:"<< lua_gettop(L)<<"\n";
}
break;
}
}
LOG<<"\n"; /* end the listing */
LOG<<"==============================\n";
}
#undef LOG
/// Construct our lua environment.
state::state() : L(luaL_newstate()), managed(true) {
if (L == NULL)
throw bad_alloc("Error creating lua state");
}
/** Construct our lua environment from an existing lua_State.
* @param L the existing state to use.
*
* This function differs from the normal constructor as it sets a flag
* that prevents lua_close() from being called when this class is
* destroyed.
*/
state::state(lua_State* L) :
L(L), managed(false) {
}
state& state::operator = (const state& t)
{
if(managed)
lua_close(L);
managed=false;
L=t.L;
return *this;
}
/// Destroy our lua environment.
state::~state() {
if (managed)
lua_close(L);
}
/** Push a nil onto the stack.
* @returns a reference to this lua::state
*/
state& state::push() {
lua_pushnil(L);
return *this;
}
/** Push a nil onto the stack.
* @returns a reference to this lua::state
*/
state& state::push(nil) {
lua_pushnil(L);
return *this;
}
/** Push a boolean onto the stack.
* @param boolean the value to push
* @returns a reference to this lua::state
*/
state& state::push(bool boolean) {
lua_pushboolean(L, boolean);
return *this;
}
/** Push a C-style string onto the stack.
* @param s the string to push
* @param length the length of the string
* @returns a reference to this lua::state
*/
state& state::push(const char* s, size_t length) {
lua_pushlstring(L, s, length);
return *this;
}
/** Push a C-style string onto the stack.
* @param s the string to push
* @note This must be a '0' terminated string.
* @returns a reference to this lua::state
*/
state& state::push(const char* s) {
lua_pushstring(L, s);
return *this;
}
/** Push an std::string onto the stack.
* @param s the string to push
* @returns a reference to this lua::state
*/
state& state::push(const std::string& s) {
lua_pushlstring(L, s.c_str(), s.size());
return *this;
}
/** Push an C function onto the stack.
* @param f the function to push
* @returns a reference to this lua::state
*/
state& state::push(cfunction f) {
lua_pushcfunction(L, f);
return *this;
}
/** Create a new table on to the stack.
* @see state::newtable()
* @returns a reference to this lua::state
*/
state& state::push(table) {
lua_newtable(L);
return *this;
}
/** Push a light userdatum on to the stack.
* @param p the pointer to push
* @returns a reference to this lua::state
*/
state& state::push(void* p) {
lua_pushlightuserdata(L, p);
return *this;
}
/** Get the value at index as a string.
* @param default_value this value is returned if the conversion fails
* @param index the index to get
* @note This function does \em not pop the value from the stack.
*
* @note lua::state::as(std::string()) will convert the value at the
* indicated index to a string <em>on the stack</em>. This can
* confuse lua::state::next();
*
* @returns the indicated value from the stack or the default value if the
* conversion fails
*/
template<>
std::string state::as(std::string default_value, int index) {
if (lua_isstring(L, index))
{
size_t len;
const char *str = lua_tolstring(L, index, &len);
return std::string(str, len);
}
else
return default_value;
}
/** Check an argument of the current function.
* @param narg the argument number to check
*
* This function will throw a lua error if there is no argument at the
* given position.
*
* @note This function is meant to be called from with in a lua::cfunction.
* The error throw is internal to the lua interpreter. When compiled as
* C++, a C++ exception is thrown, so the stack is properly unwound. This
* exception is not meant to be caught.
*/
state& state::check(int narg) {
luaL_checkany(L, narg);
return *this;
}
#ifndef lua_Integer_int
/** Check an argument of the current function.
* @param i the int to hold the returned value
* @param narg the argument number to check
*
* This function checks if the given argument number is an int.
*
* @note This function is meant to be called from with in a
* lua::cfunction. The error throw is internal to the lua intrepeter.
* When compiled as C++, a C++ exception is thrown, so the stack is
* properly unwound. This exception is not meant to be caught.
*/
state& state::check(int& i, int narg) {
i = luaL_checkint(L, narg);
return *this;
}
#endif
/** Check an argument of the current function.
* @param i the lua::integer (lua_Integer) to hold the returned value
* @param narg the argument number to check
*
* This function checks if the given argument number is an integer.
*
* @note This is different from lua::check(int(), ...). It returns a
* lua::integer (lua_Integer), which may not be an int.
*
* @note This function is meant to be called from with in a
* lua::cfunction. The error throw is internal to the lua intrepeter.
* When compiled as C++, a C++ exception is thrown, so the stack is
* properly unwound. This exception is not meant to be caught.
*/
state& state::check(integer& i, int narg) {
i = luaL_checkinteger(L, narg);
return *this;
}
#ifndef lua_Integer_long
/** Check an argument of the current function.
* @param l the long to hold the returned value
* @param narg the argument number to check
*
* This function checks if the given argument number is a long.
*
* @note This function is meant to be called from with in a
* lua::cfunction. The error throw is internal to the lua intrepeter.
* When compiled as C++, a C++ exception is thrown, so the stack is
* properly unwound. This exception is not meant to be caught.
*/
state& state::check(long& l, int narg) {
l = luaL_checklong(L, narg);
return *this;
}
#endif
/** Check an argument of the current function.
* @param s the string to hold the returned value
* @param narg the argument number to check
*
* This function checks if the given argument number is a string.
*
* @note This function is meant to be called from with in a
* lua::cfunction. The error throw is internal to the lua intrepeter.
* When compiled as C++, a C++ exception is thrown, so the stack is
* properly unwound. This exception is not meant to be caught.
*/
state& state::check(std::string& s, int narg) {
const char* c;
size_t l;
c = luaL_checklstring(L, narg, &l);
s.assign(c, l);
return *this;
}
/** Check an argument of the current function.
* @param n the lua::number (lua_Number) to hold the returned value
* @param narg the argument number to check
*
* This function checks if the given argument number is a lua::number
* (lua_Number, a double by default).
*
* @note This function is meant to be called from with in a lua::cfunction.
* The error throw is internal to the lua interpreter. When compiled as
* C++, a C++ exception is thrown, so the stack is properly unwound. This
* exception is not meant to be caught.
*/
state& state::check(number& n, int narg) {
n = luaL_checknumber(L, narg);
return *this;
}
#if 0
/** [specialization] Generate a Lua error (T = std::string).
*/
template<>
void state::error(const std::string& message) {
push(message);
lua_error(L);
}
#endif
/** Call a lua function.
* @param nargs the number of args to pass to the function
* @param nresults the number of values to return from the function
* @param on_error A stack index where the error handling function is
* stored.
* @note The error handling function must be pushed in the stack
* before the function to be called and its arguments.
* @returns a reference to this lua::state
*/
state& state::pcall(int nargs, int nresults, int on_error) {
throw_error(lua_pcall(L, nargs, nresults, on_error));
return *this;
}
/** Call a lua function in unprotected mode.
* @param nargs the number of args to pass to the function
* @param nresults the number of values to return from the function
* stored.
* @note If there is an error in the call the program will terminate.
* @returns a reference to this lua::state
*/
state& state::call(int nargs, int nresults) {
lua_call(L, nargs, nresults);
return *this;
}
/** Ensure the stack is at least the given size.
* @param size the size to use
*
* If the stack is smaller than the given size, it will grow to the
* specified size.
*
* @exception lua::exception Thrown if the operation fails.
* @returns a reference to this lua::state
*/
state& state::checkstack(int size) {
if (!lua_checkstack(L, size))
throw lua::exception("Error growing the stack");
return *this;
}
/** Set a new index as the top of the stack.
* @param index the index to use as the new top
* @note If the previous top was higher than the new one, top values
* are discarded. Otherwise this function pushs nils on to the stack
* to get the proper size.
* @returns a reference to this lua::state
*/
state& state::settop(int index) {
lua_settop(L, index);
return *this;
}
/** Get the number of elements in the stack.
* @note This value is also the index of the top element.
* @returns the number of elements in the stack
*/
int state::gettop() {
return lua_gettop(L);
}
/** Get the number of elements in the stack.
* @note This value is also the index of the top element.
* @returns the number of elements in the stack
*/
int state::size() {
return lua_gettop(L);
}
/** Check if the stack is empty.
* @returns true if the stack is empty, false otherwise
*/
bool state::empty() {
return !lua_gettop(L);
}
/** Move the top element to the given index.
* @param index the index to insert at
* @note All elements on top of the given index are shifted up to open
* space for this element.
* @returns a reference to this lua::state
*/
state& state::insert(int index) {
lua_insert(L, index);
return *this;
}
/** Replace the given index with the top element.
* @param index the index to replae
* @returns a reference to this lua::state
*/
state& state::replace(int index) {
lua_replace(L, index);
return *this;
}
/** Remove the given index from the stack.
* @param index the index to remove
* @note Elements are shifted down to fill in the empty spot.
* @returns a reference to this lua::state
*/
state& state::remove(int index) {
lua_remove(L, index);
return *this;
}
/** Remove the given number of elemens from the stack.
* @param elements the number of elements to remove
* @returns a reference to this lua::state
*/
state& state::pop(int elements) {
lua_pop(L, elements);
return *this;
}
/** Push a copy of the element at the given index to the top of the
* stack.
* @param index the index of the element to copy
* @returns a reference to this lua::state
*/
state& state::pushvalue(int index) {
lua_pushvalue(L, index);
return *this;
}
/** Create a new table on the stack.
* @returns a reference to this lua::state
*/
state& state::newtable() {
lua_newtable(L);
return *this;
}
/** Create a new metatable and add it to the registry.
* @param tname the name to use for the new metatable in the registry
*
* This function creates a new metatable and adds it to the registry
* with the given key. This function also pushes the new metatable
* onto the stack.
*
* @note Regardless of the return value, the new metatable is always pushed
* on to the stack.
*
* @return true if a new metatable was created, false if the registry
* alread has a key with the given name.
*/
bool state::newmetatable(const std::string& tname) {
return luaL_newmetatable(L, tname.c_str());
}
/** Create a new userdatum on the stack.
* @param nbytes the size of the new userdatum
* @return a pointer to the new userdatum
*/
void* state::newuserdata(size_t nbytes) {
return lua_newuserdata(L, nbytes);
}
/** Get a value from a table on the stack.
* @param index the index the table is stored at
*
* This function gets a value from the table at the given index and
* pushes it onto the stack.
*
* @note You should have already pushed the key used to reference this
* value onto the stack before calling this function.
*
* @returns a reference to this lua::state
*/
state& state::gettable(int index) {
lua_gettable(L, index);
return *this;
}
/** Get a value from a table on the stack.
* @param k the key
* @param index the index the table is stored at
*
* This function gets a value from the table at the given index and
* pushes it onto the stack.
*
* @returns a reference to this lua::state
*/
state& state::getfield(const std::string& k, int index) {
lua_getfield(L, index, k.c_str());
return *this;
}
/** Set a value in a table.
* @param index the index the table is stored at
*
* This function sets a value in a table stored at the given index.
*
* @note The key and value to be used should have already been pushed
* on the stack in that order.
*
* @returns a reference to this lua::state
*/
state& state::settable(int index) {
lua_settable(L, index);
return *this;
}
/** Set a field in a table.
* @param k the key
* @param index the index the table is stored at
*
* This function sets a value in a table stored at the given index.
*
* @note The value to be used should be on the top of the stack.
*
* @returns a reference to this lua::state
*/
state& state::setfield(const std::string& k, int index) {
lua_setfield(L, index, k.c_str());
return *this;
}
/** Get the metatable associated with the given registry entry.
* @param tname the name in the registry
*
* This function gets the metatable associated with the given key in
* the registry. The resulting metatable is pushed onto the stack.
*
* @note This function uses luaL_getmetatable() internally.
*
* @returns a reference to this lua::state
*/
state& state::getmetatable(const std::string& tname) {
luaL_getmetatable(L, tname.c_str());
return *this;
}
/** Get the metatable of the value at the given index.
* @param index the index the value is stored at
*
* This function pushes on to the stack the metatabe of the value at
* the given index.
*
* @note This function uses lua_getmetatable() internally.
*
* @returns false if the value at the given index does not have a
* metatable or if the index is not valid
*/
bool state::getmetatable(int index) {
return lua_getmetatable(L, index);
}
/** Get the next key value pair from a table on the stack.
* @param index the stack index the table is at
*
* This function pops a key from the stack and pushes the next key
* value pair to the stack. The key will be stored at index -2 and
* the value will be at index -1. The key is expected to be on the
* top of the stack.
*
* @note While traversing a table, do not call
* lua::state::to(std::string()) directly on a key, unless you know
* that the key is actually a string. lua::state::to(std::string())
* changes the value at the given index; this confuses the next call
* to lua::state::next().
*
* <strong>While Loop Example:</strong>
* @code
* while(L.next() != 0) {
* // do stuff
* L.pop();
* }
* @endcode
*
* <strong>For Loop Example:</strong>
* @code
* for(L.push(lua::nil()); L.next(); L.pop()) {
* // do stuff
* }
* @endcode
*
* @returns true as long as there are remaining items in the table
*/
bool state::next(int index) {
return lua_next(L, index);
}
/** Load a global symbol onto the stack.
* @param name the name of the global to load
*
* This function loads a global symbol onto the stack from the lua
* state.
*
* @returns a reference to this lua::state
*/
state& state::getglobal(const std::string& name) {
lua_getglobal(L, name.c_str());
return *this;
}
/** Set a global symbol.
* @param name the name of the global to set
*
* This function sets/creates a global symbol from the value above it
* on the stack.
*
* @note You should have pushed the value of the symbol onto the stack
* before calling this function.
*
* @returns a reference to this lua::state
*/
state& state::setglobal(const std::string& name) {
lua_setglobal(L, name.c_str());
return *this;
}
/** Load a file as a Lua chunk.
* @param filename the name of the file to load
* @returns a reference to this lua::state
*/
state& state::loadfile(const std::string& filename) {
throw_error(luaL_loadfile(L, filename.c_str()));
return *this;
}
/** Load a string as a Lua chunk.
* @param s the string to load
* @returns a reference to this lua::state
*/
state& state::loadstring(const std::string& s) {
throw_error(luaL_loadstring(L, s.c_str()));
return *this;
}
/** Get the length of a value on the stack.
* @param index the index the value is stored at
* @returns the length of the indicated value
*/
size_t state::objlen(int index) {
return lua_rawlen(L, index);
}
/** Get the value at index as a bool.
* @param boolean where to store the value
* @param index the index to get
* @note This function does \em not pop the value from the stack.
* @todo Instead of throwing an exception here, we may just return an
* error code.
* @throws lua::bad_conversion if the value on the stack could not be
* converted to the indicated type
* @returns a reference to this lua::state
*/
template<>
state& state::to(bool& boolean, int index) {
if (lua_isboolean(L, index))
boolean = lua_toboolean(L, index);
else
throw bad_conversion("Cannot convert non 'boolean' value to bool");
return *this;
}
/** Get the value at index as a string.
* @param string where to store the value
* @param index the index to get
* @note This function does \em not pop the value from the stack.
* @todo Instead of throwing an exception here, we may just return an
* error code.
*
* @note lua::state::to(std::string()) will convert the value at the
* indicated index to a string <em>on the stack</em>. This can
* confuse lua::state::next();
*
* @throws lua::bad_conversion if the value on the stack could not be
* converted to the indicated type
* @returns a reference to this lua::state
*/
template<>
state& state::to(std::string& string, int index) {
if (lua_isstring(L, index))
{
size_t len;
const char *str = lua_tolstring(L, index, &len);
string.replace(0, std::string::npos, str, len);
}
else
throw bad_conversion("Cannot convert value to string");
return *this;
}
/** Get the value at index as a bool.
* @param default_value this value is returned if the conversion fails
* @param index the index to get
* @note This function does \em not pop the value from the stack.
* @returns the indicated value from the stack or the default value if the
* conversion fails
*/
template<>
bool state::as(bool default_value, int index) {
if (lua_isboolean(L, index))
return lua_toboolean(L, index);
else
return default_value;
}
/** [specialization] Get the value at index as a bool (T = bool).
*/
template<>
bool state::as(int index) {
if (lua_isboolean(L, index))
return lua_toboolean(L, index);
else
throw bad_conversion("Cannot convert non 'boolean' value to bool");
}
/** [specialization] Get the value at index as a string (T = std::string).
* @note lua::state::as(std::string()) will convert the value at the
* indicated index to a string <em>on the stack</em>. This can confuse
* lua::state::next();
*/
template<>
std::string state::as(int index) {
if (lua_isstring(L, index))
{
size_t len;
const char *str = lua_tolstring(L, index, &len);
return std::string(str, len);
}
else
throw bad_conversion("Cannot convert value to string");
}
/** [specialization] Check if the given index is a nil (T = lua::nil).
*/
template<>
bool state::is<nil>(int index) {
return lua_isnil(L, index);
}
/** [specialization] Check if the given index is a boolean (T = bool).
*/
template<>
bool state::is<bool>(int index) {
return lua_isboolean(L, index);
}
/** [specialization] Check if the given index is a string (T = std::string).
*/
template<>
bool state::is<std::string>(int index) {
return lua_isstring(L, index);
}
/** [specialization] Check if the given index is a table (T = lua::table).
*/
template<>
bool state::is<table>(int index) {
return lua_istable(L, index);
}
/** [specialization] Check if the given index is a C function (T =
* lua::cfunction).
*/
template<>
bool state::is<cfunction>(int index) {
return lua_iscfunction(L, index);
}
/** [specialization] Check if the given index is a function (T =
* lua::function).
*/
template<>
bool state::is<function>(int index) {
return lua_isfunction(L, index);
}
/** [specialization] Check if the given index is userdata (T =
* lua::userdata).
*/
template<>
bool state::is<userdata>(int index) {
return lua_isuserdata(L, index);
}
/** [specialization] Check if the given index is light userdata (T =
* lua::lightuserdata).
*/
template<>
bool state::is<lightuserdata>(int index) {
return lua_islightuserdata(L, index);
}
}

@ -1,2 +0,0 @@
#include "lune.h"
lua::object *lua::local_object::mytbl=0;

@ -1,241 +0,0 @@
-- Stuff used by dfusion
local _ENV = mkmodule('plugins.dfusion')
local ms=require("memscan")
local marker={0xDE,0xAD,0xBE,0xEF}
--utility functions
function dwordToTable(dword)
local b={bit32.extract(dword,0,8),bit32.extract(dword,8,8),bit32.extract(dword,16,8),bit32.extract(dword,24,8)}
return b
end
function concatTables(t1,t2)
for k,v in pairs(t2) do
table.insert(t1,v)
end
end
function makeCall(from,to)
local ret={0xe8}
concatTables(ret,dwordToTable(to-from-5))
return ret
end
-- A reversable binary patch
patches={}
BinaryPatch=defclass(BinaryPatch)
BinaryPatch.ATTRS {pre_data=DEFAULT_NIL,data=DEFAULT_NIL,address=DEFAULT_NIL,name=DEFAULT_NIL}
function BinaryPatch:init(args)
self.is_applied=false
if args.pre_data==nil or args.data==nil or args.address==nil or args.name==nil then
error("Invalid parameters to binary patch")
end
if patches[self.name]~=nil then
error("Patch already exist")
end
for k,v in ipairs(args.data) do
if args.pre_data[k]==nil then
error("can't edit without revert data")
end
end
end
function BinaryPatch:postinit(args)
patches[args.name]=self
end
function BinaryPatch:test()
local arr=ms.CheckedArray.new('uint8_t',self.address,self.address+#self.pre_data)
for k,v in ipairs(self.pre_data) do
if arr[k-1]~=v then
return false
end
end
return true
end
function BinaryPatch:apply()
if not self:test() then
error(string.format("pre-data for binary patch does not match expected"))
end
local post_buf=df.new('uint8_t',#self.pre_data)
for k,v in ipairs(self.pre_data) do
if self.data[k]==nil then
post_buf[k-1]=v
else
post_buf[k-1]=self.data[k]
end
end
local ret=dfhack.with_finalize(function() post_buf:delete() end,dfhack.internal.patchMemory,self.address,post_buf,#self.pre_data)
if not ret then
error("Patch application failed!")
end
self.is_applied=true
end
function BinaryPatch:repatch(newdata)
if newdata==nil then newdata=self.data end
self:remove()
self.data=newdata
self:apply()
end
function BinaryPatch:remove(delete)
if delete==nil then
delete=true
end
if not self.is_applied then
error("can't remove BinaryPatch, not applied.")
end
local arr=ms.CheckedArray.new('uint8_t',self.address,self.address+#self.pre_data)
local post_buf=df.new('uint8_t',#self.pre_data)
for k,v in pairs(self.pre_data) do
post_buf[k-1]=v
end
local ret=dfhack.with_finalize(function() post_buf:delete() end,dfhack.internal.patchMemory,self.address,post_buf,#self.pre_data)
if not ret then
error("Patch remove failed!")
end
self.is_applied=false
if delete then
patches[self.name]=nil
end
end
function BinaryPatch:__gc()
if self.is_applied then
self:remove()
end
end
-- A binary hack (obj file) loader/manager
-- has to have: a way to get offsets for marked areas (for post load modification) or some way to do that pre-load
-- page managing (including excecute/write flags for DEP and the like)
-- TODO plugin state enum, a way to modify post install (could include repatching code...)
plugins=plugins or {}
BinaryPlugin=defclass(BinaryPlugin)
BinaryPlugin.ATTRS {filename=DEFAULT_NIL,reloc_table={},name=DEFAULT_NIL}
function BinaryPlugin:init(args)
end
function BinaryPlugin:postinit(args)
if self.name==nil then error("Not a valid plugin name!") end
if plugins[args.name]==nil then
plugins[self.name]=self
else
error("Trying to create a same plugin")
end
self.allocated_object={}
self:load()
end
function BinaryPlugin:get_or_alloc(name,typename,arrsize)
if self.allocated_object[name]~=nil then
return self.allocated_object[name]
else
return self:allocate(name,typename,arrsize)
end
end
function BinaryPlugin:allocate(name,typename,arrsize)
local trg
if df[typename]==nil then
trg=df.new(typename,arrsize)
self.allocated_object[name]=trg
else
trg=df[typename]:new(arrsize)
self.allocated_object[name]=trg
end
return trg
end
function BinaryPlugin:load()
local obj=loadObjectFile(self.filename)
self.data=df.reinterpret_cast("uint8_t",obj.data)
self.size=obj.data_size
for _,v in pairs(obj.symbols) do
if string.sub(v.name,1,5)=="mark_" then
local new_pos=self:find_marker(v.pos)
self.reloc_table[string.sub(v.name,6)]=new_pos
end
end
end
function BinaryPlugin:find_marker(start_pos)
local matched=0
for i=start_pos,self.size do
if self.data[i]==marker[4-matched] then
matched=matched+1
if matched == 4 then
return i-4
end
end
end
end
function BinaryPlugin:set_marker_dword(marker,dword) -- i hope Toady does not make a 64bit version...
if self.reloc_table[marker]==nil then
error("marker ".. marker.. " not found")
end
local b=dwordToTable(dword)
local off=self.reloc_table[marker]
for k,v in ipairs(b) do
self.data[off+k]=b[k]
end
end
function BinaryPlugin:move_to_df()
local _,addr=df.sizeof(self.data)
markAsExecutable(addr)
return addr
end
function BinaryPlugin:print_data()
local out=""
for i=0,self.size do
out=out..string.format(" %02x",self.data[i])
if math.modf(i,16)==15 then
print(out)
out=""
end
end
print(out)
end
function BinaryPlugin:status()
return "invalid, base class only!"
end
function BinaryPlugin:__gc()
for k,v in pairs(self.allocated_object) do
df.delete(v)
end
if self.unload then
self:unload()
end
self.data:delete()
end
-- a Menu for some stuff. Maybe add a posibility of it working as a gui, or a gui adaptor?
-- Todo add hints, and parse them to make a "smart" choice of parameters to pass
SimpleMenu=defclass(SimpleMenu)
SimpleMenu.ATTRS{title=DEFAULT_NIL}
function SimpleMenu:init(args)
self.items={}
end
function SimpleMenu:add(name,entry,hints)
table.insert(self.items,{entry,name,hints})
end
function SimpleMenu:display()
print("Select choice (q exits):")
for p,c in pairs(self.items) do
print(string.format("%3d).%s",p,c[2]))
end
local ans
repeat
local r
r=dfhack.lineedit()
if r==nil then return end
if r=='q' then return end
ans=tonumber(r)
if ans==nil or not(ans<=#self.items and ans>0) then
print("Invalid choice.")
end
until ans~=nil and (ans<=#self.items and ans>0)
if type(self.items[ans][1])=="function" then
self.items[ans][1]()
else
self.items[ans][1]:display()
end
end
return _ENV

@ -1,172 +0,0 @@
local _ENV = mkmodule('plugins.dfusion.adv_tools')
local dfu=require("plugins.dfusion")
local tools=require("plugins.dfusion.tools")
menu=dfu.SimpleMenu()
function Reincarnate(trg_unit,swap_soul) --only for adventurer i guess
if swap_soul==nil then
swap_soul=true
end
local adv=trg_unit or df.global.world.units.active[0]
if adv.flags1.dead==false then
qerror("You are not dead (yet)!")
end
local hist_fig=dfhack.units.getNemesis(adv).figure
if hist_fig==nil then
qerror("No historical figure for adventurer...")
end
local events=df.global.world.history.events
local trg_hist_fig
for i=#events-1,0,-1 do -- reverse search because almost always it will be last entry
if df.history_event_hist_figure_diedst:is_instance(events[i]) then
--print("is instance:"..i)
if events[i].victim_hf==hist_fig.id then
--print("Is same id:"..i)
trg_hist_fig=events[i].slayer_hf
if trg_hist_fig then
trg_hist_fig=df.historical_figure.find(trg_hist_fig)
end
break
end
end
end
if trg_hist_fig ==nil then
qerror("Slayer not found")
end
local trg_unit=trg_hist_fig.unit_id
if trg_unit==nil then
qerror("Unit id not found!")
end
local trg_unit_final=df.unit.find(trg_unit)
change_adv(trg_unit_final)
if swap_soul then --actually add a soul...
t_soul=adv.status.current_soul
adv.status.current_soul=df.NULL
adv.status.souls:resize(0)
trg_unit_final.status.current_soul=t_soul
trg_unit_final.status.souls:insert(#trg_unit_final.status.souls,t_soul)
end
end
menu:add("Reincarnate",Reincarnate,{{df.unit,"optional"}})-- bool, optional
function change_adv(unit,nemesis)
if nemesis==nil then
nemesis=true --default value is nemesis switch too.
end
if unit==nil then
unit=dfhack.gui.getSelectedUnit()--getCreatureAtPointer()
end
if unit==nil then
error("Invalid unit!")
end
local other=df.global.world.units.active
local unit_indx
for k,v in pairs(other) do
if v==unit then
unit_indx=k
break
end
end
if unit_indx==nil then
error("Unit not found in array?!") --should not happen
end
other[unit_indx]=other[0]
other[0]=unit
if nemesis then --basicly copied from advtools plugin...
local nem=dfhack.units.getNemesis(unit)
local other_nem=dfhack.units.getNemesis(other[unit_indx])
if other_nem then
other_nem.flags[0]=false
other_nem.flags[1]=true
end
if nem then
nem.flags[0]=true
nem.flags[2]=true
for k,v in pairs(df.global.world.nemesis.all) do
if v.id==nem.id then
df.global.ui_advmode.player_id=k
end
end
else
qerror("Current unit does not have nemesis record, further working not guaranteed")
end
end
end
menu:add("Change adventurer",change_adv)
function log_pos()
local adv=df.global.world.units.active[0]
local wmap=df.global.world.map
local sub_pos={x=adv.pos.x,y=adv.pos.y,z=adv.pos.z}
local region_pos={x=wmap.region_x,y=wmap.region_y,z=wmap.region_z}
local pos={x=sub_pos.x+region_pos.x*48,y=sub_pos.y+region_pos.y*48,z=sub_pos.z+region_pos.z}
local state
if adv.flags1.dead then
state="dead"
else
state="live n kicking"
end
local message=string.format("%s %s at pos={%d,%d,%d} region={%d,%d,%d}",dfhack.TranslateName(adv.name),state,pos.x,pos.y,pos.z,region_pos.x,region_pos.y,region_pos.z)
print(message)
local path="deaths_"..df.global.world.cur_savegame.save_dir..".txt"
local f=io.open(path,"a")
f:write(message)
f:close()
end
menu:add("Log adventurers position",log_pos)
function addSite(x,y,rgn_max_x,rgn_min_x,rgn_max_y,rgn_min_y,civ_id,name,sitetype)
if x==nil or y==nil then
x=(df.global.world.map.region_x+1)/16
y=(df.global.world.map.region_y+1)/16
end
if name==nil then
name=dfhack.lineedit("Site name:")or "Hacked site"
end
if sitetype==nil then
sitetype=tonumber(dfhack.lineedit("Site type (numeric):")) or 7
end
rgn_max_x=rgn_max_x or (df.global.world.map.region_x+1)%16
rgn_max_y=rgn_max_y or (df.global.world.map.region_y+1)%16
rgn_min_y=rgn_min_y or rgn_max_y
rgn_min_x=rgn_min_x or rgn_max_x
print("Region:",rgn_max_x,rgn_min_x,rgn_max_y,rgn_min_y)
--[=[
<angavrilov> global = pos*16 + rgn
<angavrilov> BUT
<angavrilov> for cities global is usually 17x17, i.e. max size
<angavrilov> while rgn designates a small bit in the middle
<angavrilov> for stuff like forts that formula holds exactly
]=]--
local wd=df.global.world.world_data
local nsite=df.world_site:new()
nsite.name.first_name=name
nsite.name.has_name=true
nsite.pos:assign{x=x,y=y}
nsite.rgn_max_x=rgn_max_x
nsite.rgn_min_x=rgn_min_x
nsite.rgn_min_y=rgn_min_y
nsite.rgn_max_y=rgn_max_y
nsite.global_max_x=nsite.pos.x*16+nsite.rgn_max_x
nsite.global_min_x=nsite.pos.x*16+nsite.rgn_min_x
nsite.global_max_y=nsite.pos.y*16+nsite.rgn_max_y
nsite.global_min_y=nsite.pos.y*16+nsite.rgn_min_y
nsite.id=wd.next_site_id
nsite.civ_id=civ_id or -1
nsite.cur_owner_id=civ_id or -1
nsite.type=sitetype --lair = 7
nsite.flags:resize(23)
--nsite.flags[4]=true
--nsite.flags[5]=true
--nsite.flags[6]=true
nsite.index=#wd.sites+1
wd.sites:insert("#",nsite)
wd.next_site_id=wd.next_site_id+1
--might not be needed...
--[[local unk130=df.world_site_unk130:new()
unk130.index=#wd.site_unk130+1
wd.site_unk130:insert("#",unk130)
--wd.next_site_unk136_id=wd.next_site_unk136_id+1--]]
return nsite
end
menu:add("Create site at current location",addSite)
return _ENV

@ -1,124 +0,0 @@
local _ENV = mkmodule('plugins.dfusion.embark')
local dfu=require("plugins.dfusion")
local ms=require("memscan")
local MAX_RACES=100
CustomEmbark=defclass(CustomEmbark,dfu.BinaryPlugin)
local myos=dfhack.getOSType()
if myos=="windows" then
CustomEmbark.ATTRS{filename="hack/lua/plugins/dfusion/embark.o",name="CustomEmbark",race_caste_data=DEFAULT_NIL}
function CustomEmbark:parseRaces(races)
if #races<7 then
error("caste and race count must be bigger than 6")
end
if #races>MAX_RACES then
error("caste and race count must be less then "..MAX_RACES)
end
local n_to_id=require("plugins.dfusion.tools").build_race_names()
local ids={}
for k,v in pairs(races) do
local race=v[1] or v
ids[k]={}
ids[k][1]=n_to_id[race]
if ids[k][1]==nil then qerror(race.." not found!") end
ids[k][2]=v[2] or -1
end
self.race_caste_data=ids
end
function CustomEmbark:install(race_caste_data)
local stoff=dfhack.internal.getAddress('start_dwarf_count')
if race_caste_data~=nil then
self:parseRaces(race_caste_data)
end
if stoff==nil then
error("address for start_dwarf_count not found!")
end
local _,race_id_offset=df.sizeof(df.global.ui:_field("race_id"))
print(string.format("start=%08x",stoff))
local needle={0x0f,0xb7,0x0d} --movzx eax,dword ptr [race_id]
local tmp_table=dfu.dwordToTable(race_id_offset)
for k,v in ipairs(tmp_table) do
table.insert(needle,v)
end
local mem=ms.get_code_segment()
print(mem.uint8_t:addr2idx(stoff))
print(mem.uint8_t:find(needle,mem.uint8_t:addr2idx(stoff)))
local _,trg_offset=mem.uint8_t:find(needle,mem.uint8_t:addr2idx(stoff),nil)--maybe endoff=stoff+bignumber
if trg_offset==nil then
error("address for race_load not found")
end
local call_data={0x90,0x90}
local _,data_offset=df.sizeof(self.data)
dfu.concatTables(call_data,dfu.makeCall(trg_offset+2,data_offset))
self.call_patch=self.call_patch or dfu.BinaryPatch{pre_data=needle,data=call_data,address=trg_offset,name="custom_embark_call_patch"}
needle={0x83,0xc8,0xff} -- or eax, 0xFF
local _,caste_offset=mem.uint8_t:find(needle,mem.uint8_t:addr2idx(trg_offset),nil)
if caste_offset==nil or caste_offset-stoff>1000 then
error("Caste change code not found or found too far!")
end
self.disable_castes=self.disable_castes or dfu.BinaryPatch{pre_data={0x83,0xc8,0xff},data={0x90,0x90,0x90},address=caste_offset,name="custom_embark_caste_disable"}
self.disable_castes:apply()
self:setEmbarkParty(self.race_caste_data)
local caste_array=self:get_or_alloc("caste_array","uint16_t",MAX_RACES)
local race_array=self:get_or_alloc("race_array","uint16_t",MAX_RACES)
local race_array_off,caste_array_off
local _
_,race_array_off=df.sizeof(race_array)
_,caste_array_off=df.sizeof(caste_array)
self:set_marker_dword("race",caste_array_off) --hehe... mixed them up i guess...
self:set_marker_dword("caste",race_array_off)
self:move_to_df()
self.call_patch:apply()
self.installed=true
end
function CustomEmbark:setEmbarkParty(racesAndCastes)
local stoff=dfhack.internal.getAddress('start_dwarf_count')
if self.dwarfcount== nil then
self.dwarfcount=dfu.BinaryPatch{pre_data=dfu.dwordToTable(7),data=dfu.dwordToTable(#self.race_caste_data),address=stoff,name="custom_embark_embarkcount"}
self.dwarfcount:apply()
else
self.dwarfcount:repatch(dfu.dwordToTable(#self.race_caste_data))
end
local caste_array=self:get_or_alloc("caste_array","uint16_t",MAX_RACES)
local race_array=self:get_or_alloc("race_array","uint16_t",MAX_RACES)
for k,v in ipairs(self.race_caste_data) do
caste_array[k-1]=v[2] or -1
race_array[k-1]=v[1]
end
end
function CustomEmbark:status()
if self.installed then
return "valid, installed"
else
return "valid, not installed"
end
end
function CustomEmbark:uninstall()
if self.installed then
self.call_patch:remove()
self.disable_castes:remove()
self.dwarfcount:remove()
end
end
function CustomEmbark:unload()
self:uninstall()
if Embark~=nil then
Embark=nil
end
end
Embark=Embark or CustomEmbark()
else
CustomEmbark.status=function() return"invalid, os not supported" end
end
return _ENV

Binary file not shown.

@ -1,121 +0,0 @@
local _ENV = mkmodule('plugins.dfusion.friendship')
local dfu=require("plugins.dfusion")
local ms=require("memscan")
local MAX_RACES=100
local MAX_CODE_DIST=250
FriendshipRainbow=defclass(FriendshipRainbow,dfu.BinaryPlugin)
FriendshipRainbow.name="FriendshipRainbow"
-- os independant... I think...
FriendshipRainbow.ATTRS{filename="hack/lua/plugins/dfusion/friendship.o",name="FriendshipRainbow",race_data=DEFAULT_NIL}
FriendshipRainbow.class_status="valid, not installed"
function FriendshipRainbow:findall_needles(codesg,needle) -- todo move to memscan.lua
local cidx,caddr=codesg.uint8_t:find(needle)
local ret={}
while cidx~=nil do
table.insert(ret,{cidx,caddr})
cidx,caddr=codesg.uint8_t:find(needle,cidx+1)
end
return ret
end
function FriendshipRainbow:find_one(codesg,needle,crace)
dfu.concatTables(needle,dfu.dwordToTable(crace))
return self:findall_needles(codesg,needle)
end
function FriendshipRainbow:find_all()
local code=ms.get_code_segment()
local locations={}
local _,crace=df.sizeof(df.global.ui:_field("race_id"))
dfu.concatTables(locations,self:find_one(code,{0x66,0xa1},crace)) --mov ax,[ptr]
dfu.concatTables(locations,self:find_one(code,{0xa1},crace)) --mov ax,[ptr]
local registers=
{0x05, -- (e)ax
0x1d, --ebx
0x0d, --ecx
0x15, --edx
0x35, --esi
0x3d, --edi
--0x25, --esp not used?
--0x2d, --ebp not used?
}
for k,reg in ipairs(registers) do
dfu.concatTables(locations,self:find_one(code,{0x0f,0xbf,reg},crace)) --movsx reg,[ptr]
dfu.concatTables(locations,self:find_one(code,{0x66,0x8b,reg},crace)) --mov reg,[ptr]
end
return self:filter_locations(code,locations)
end
function FriendshipRainbow:filter_locations(codesg,locations)
local ret={}
local registers={0x80,0x83,0x81,0x82,0x86,0x87,
0x98,0x9b,0x99,0x9a,0x9e,0x9f,
0x88,0x8b,0x89,0x8a,0x8e,0x8f,
0x90,0x93,0x91,0x92,0x96,0x97,
0xb0,0xb3,0xb1,0xb2,0xb6,0xb7,
0xb8,0xbb,0xb9,0xba,0xbe,0xbf}
for _,entry in ipairs(locations) do
for _,r in ipairs(registers) do
local idx,addr=codesg.uint8_t:find({0x39,r,0x8c,0x00,0x00,0x00},
codesg.uint8_t:addr2idx(entry[2]),codesg.uint8_t:addr2idx(entry[2])+MAX_CODE_DIST)
if addr then
table.insert(ret,{addr,r})
break
end
idx,addr=codesg.uint8_t:find({0x3b,r,0x8c,0x00,0x00,0x00},
codesg.uint8_t:addr2idx(entry[2]),codesg.uint8_t:addr2idx(entry[2])+MAX_CODE_DIST)
if addr then
table.insert(ret,{addr,r})
break
end
end
end
return ret
end
function FriendshipRainbow:patchCalls(target)
local addrs=self:find_all()
local swaps={}
for k,adr in ipairs(addrs) do
local newval=dfu.makeCall(adr[1],target)
table.insert(newval,adr[2])
for t,val in ipairs(newval) do
swaps[adr[1]+t-1]=val
end
end
dfhack.internal.patchBytes(swaps)
end
function FriendshipRainbow:set_races(arr)
local n_to_id=require("plugins.dfusion.tools").build_race_names()
local ids={}
for k,v in ipairs(self.race_data) do -- to check if all races are valid.
ids[k]=n_to_id[v]
end
for k,v in ipairs(ids) do
arr[k-1]=ids[k]
end
end
function FriendshipRainbow:install(races)
self.race_data=races or self.race_data
if #self.race_data<1 then
error("race count must be bigger than 0")
end
if #self.race_data>MAX_RACES then
error("race count must be less then "..MAX_RACES)
end
local rarr=self:allocate("race_array",'uint16_t',MAX_RACES)
local _,rarr_offset=df.sizeof(rarr)
self:set_marker_dword("racepointer",rarr_offset)
self:set_races(rarr)
self:set_marker_dword("racecount",#self.race_data)
local safe_loc=self:allocate("safe_loc",'uint32_t',1)
local _1,safe_loc_offset=df.sizeof(safe_loc)
self:set_marker_dword("safeloc1",safe_loc_offset)
self:set_marker_dword("safeloc2",safe_loc_offset)
local addr=self:move_to_df()
self:patchCalls(addr)
self.installed=true
end
Friendship=Friendship or FriendshipRainbow()
return _ENV

Binary file not shown.

@ -1 +0,0 @@
as -anl --32 -o friendship.o friendship.asm

@ -1,7 +0,0 @@
.intel_syntax
mov eax , [esp+0x1C] # loop counter
mark_caste:
movsx ecx, word ptr[eax*2+0xdeadbeef]
mark_race:
movzx eax,word ptr [eax*2+0xDEADBEEF]
ret

@ -1,106 +0,0 @@
.intel_syntax
push eax
mov eax,[esp+0x04]
push ebx
pushfd
mov eax,[eax] # get a byte after the call this procedure to analyze what register holds cr ptr
jmptbl:
cmp al,0x81
jz regC
cmp al,0x82
jz regD
cmp al,0x83
jz regB
cmp al,0x85
jz regBP
cmp al,0x86
jz regESI
cmp al,0x87
jz regEDI
cmp al,0x88
jz regA
cmp al,0x8A
jz regD
cmp al,0x8B
jz regB
cmp al,0x8D
jz regBP
cmp al,0x8E
jz regESI
cmp al,0x8F
jz regEDI
cmp al,0x90
jz regA
cmp al,0x91
jz regC
cmp al,0x93
jz regB
cmp al,0x95
jz regBP
cmp al,0x96
jz regESI
cmp al,0x97
jz regEDI
jmp fail
regA:
mov eax, [esp+0x8]
mov eax, [eax+0x8c]
jmp compare
regC:
mov eax, [ecx+0x8c]
jmp compare
regB:
mov eax, [ebx+0x8c]
jmp compare
regD:
mov eax, [edx+0x8c]
jmp compare
regBP:
mov eax, [ebp+0x8c]
jmp compare
regESI:
mov eax, [esi+0x8c]
jmp compare
regEDI:
mov eax, [edi+0x8c]
#jmp compare
compare:
push ecx
mark_racepointer:
mov ebx,0xDEADBEEF #write a pointer to the list of allowed races
mark_racecount:
mov ecx,0xDEADBEEF #write a number of allowed races
loop1:
cmp word[ebx+ecx*2],ax
jz endok
dec ecx
cmp ecx ,-1
jnz loop1
pop ecx
popfd
jmp fail
endok:
pop ecx
popfd
cmp eax,eax
jmp endfinal
fail:
xor ebx,ebx
xor eax,eax
inc eax
cmp eax,ebx
endfinal:
pop ebx
pop eax
mark_safeloc1:
mov [0xDEADBEEF],eax #write a pointer to safe location (usually after this)
pop eax
pushfd
inc eax #skip one instruction
popfd
push eax
mark_safeloc2:
mov eax,[0xDEADBEEF] #write a pointer to safe location (same as above)
ret

@ -1,243 +0,0 @@
local _ENV = mkmodule('plugins.dfusion.tools')
local dfu=require("plugins.dfusion")
local ms=require "memscan"
menu=dfu.SimpleMenu()
RaceNames={}
function build_race_names()
if #RaceNames~=0 then
return RaceNames
else
for k,v in pairs(df.global.world.raws.creatures.all) do
RaceNames[v.creature_id]=k
end
dfhack.onStateChange.invalidate_races=function(change_id) --todo does this work?
if change_id==SC_WORLD_UNLOADED then
dfhack.onStateChange.invalidate_races=nil
RaceNames={}
end
end
return RaceNames
end
end
function setrace(name)
local RaceTable=build_race_names()
print("Your current race is:"..df.global.world.raws.creatures.all[df.global.ui.race_id].creature_id)
local id
if name == nil then
print("Type new race's token name in full caps (q to quit):")
repeat
local entry=dfhack.lineedit()
if entry=="q" then
return
end
id=RaceTable[entry]
until id~=nil
else
id=RaceTable[name]
if id==nil then
error("Name not found!")
end
end
df.global.ui.race_id=id
end
menu:add("Set current race",setrace)
function GiveSentience(names)
local RaceTable=build_race_names() --slow.If loaded don't load again
local id,ids
if names ==nil then
ids={}
print("Type race's token name in full caps to give sentience to:")
repeat
id=dfhack.lineedit()
id=RaceTable[entry]
if id~=nil then
table.insert(ids,id)
end
until id==nil
else
ids={}
for _,name in pairs(names) do
id=RaceTable[name]
table.insert(ids,id)
end
end
for _,id in pairs(ids) do
local races=df.global.world.raws.creatures.all
local castes=races[id].caste
print(string.format("Caste count:%i",#castes))
for i =0,#castes-1 do
print("Caste name:"..castes[i].caste_id.."...")
local flags=castes[i].flags
--print(string.format("%x",flagoffset))
if flags.CAN_SPEAK then
print("\tis sentient.")
else
print("\tnon sentient. Allocating IQ...")
flags.CAN_SPEAK=true
end
end
end
end
menu:add("Give Sentience",GiveSentience)
function MakeFollow(unit,trgunit)
if unit == nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit== nil then
error("Invalid creature")
end
if trgunit==nil then
trgunit=df.global.world.units.active[0]
end
unit.relations.group_leader_id=trgunit.id
local u_nem=dfhack.units.getNemesis(unit)
local t_nem=dfhack.units.getNemesis(trgunit)
if u_nem then
u_nem.group_leader_id=t_nem.id
end
if t_nem and u_nem then
t_nem.companions:insert(#t_nem.companions,u_nem.id)
end
end
menu:add("Make creature follow",MakeFollow)
function project(unit,trg) --TODO add to menu?
if unit==nil then
unit=getCreatureAtPointer()
end
if unit==nil then
error("Failed to project unit. Unit not selected/valid")
end
-- todo: add projectile to world, point to unit, add flag to unit, add gen-ref to projectile.
local p=df.proj_unitst:new()
local startpos={x=unit.pos.x,y=unit.pos.y,z=unit.pos.z}
p.origin_pos=startpos
p.target_pos=trg
p.cur_pos=startpos
p.prev_pos=startpos
p.unit=unit
--- wtf stuff
p.unk14=100
p.unk16=-1
p.unk23=-1
p.fall_delay=5
p.fall_counter=5
p.collided=true
-- end wtf
local citem=df.global.world.proj_list
local maxid=1
local newlink=df.proj_list_link:new()
newlink.item=p
while citem.item~= nil do
if citem.item.id>maxid then maxid=citem.item.id end
if citem.next ~= nil then
citem=citem.next
else
break
end
end
p.id=maxid+1
newlink.prev=citem
citem.next=newlink
local proj_ref=df.general_ref_projectile:new()
proj_ref.projectile_id=p.id
unit.general_refs:insert(#unit.general_refs,proj_ref)
unit.flags1.projectile=true
end
function empregnate(unit)
if unit==nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit==nil then
error("Failed to empregnate. Unit not selected/valid")
end
if unit.curse then
unit.curse.add_tags2.STERILE=false
end
local genes = unit.appearance.genes
if unit.relations.pregnancy_genes == nil then
print("creating preg ptr.")
if false then
print(string.format("%x %x",df.sizeof(unit.relations:_field("pregnancy_genes"))))
return
end
unit.relations.pregnancy_genes = { new = true, assign = genes }
end
local ngenes = unit.relations.pregnancy_genes
if #ngenes.appearance ~= #genes.appearance or #ngenes.colors ~= #genes.colors then
print("Array sizes incorrect, fixing.")
ngenes:assign(genes);
end
print("Setting preg timer.")
unit.relations.pregnancy_timer=10
unit.relations.pregnancy_caste=1
end
menu:add("Empregnate",empregnate)
function healunit(unit)
if unit==nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit==nil then
error("Failed to Heal unit. Unit not selected/valid")
end
unit.body.wounds:resize(0) -- memory leak here :/
unit.body.blood_count=unit.body.blood_max
--set flags for standing and grasping...
unit.status2.limbs_stand_max=4
unit.status2.limbs_stand_count=4
unit.status2.limbs_grasp_max=4
unit.status2.limbs_grasp_count=4
--should also set temperatures, and flags for breath etc...
unit.flags1.dead=false
unit.flags2.calculated_bodyparts=false
unit.flags2.calculated_nerves=false
unit.flags2.circulatory_spray=false
unit.flags2.vision_good=true
unit.flags2.vision_damaged=false
unit.flags2.vision_missing=false
unit.counters.winded=0
unit.counters.unconscious=0
for k,v in pairs(unit.body.components) do
for kk,vv in pairs(v) do
if k == 'body_part_status' then v[kk].whole = 0 else v[kk] = 0 end
end
end
end
menu:add("Heal unit",healunit)
function powerup(unit,labor_rating,military_rating,skills)
if unit==nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit==nil then
error("Failed to power up unit. Unit not selected/valid")
end
if unit.status.current_soul== nil then
error("Failed to power up unit. Unit has no soul")
end
local utils = require 'utils'
labor_rating = labor_rating or 15
military_rating = military_rating or 70
skill =skill or { 0,2,3,4,5,6,7,8,9,10,11,12,13,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,41,42,43,44,45,46,47,48,49,54,55,57,58,59,60,61,62,63,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,95,96,97,98,99,100,101,102,103,104,105,109,110,111,112,113,114,115 }
local military = { 38,39,41,42,43,44,45,46,54,99,100,101,102,103,104,105 }
for sk,sv in ipairs(skill) do
local new_rating = labor_rating
for _,v in ipairs(military) do
if v == sv then
local new_rating = military_rating
end
end
utils.insert_or_update(unit.status.current_soul.skills, { new = true, id = sv, rating = new_rating, experience = (new_rating * 500) + (new_rating * (new_rating - 1)) * 50}, 'id')
end
end
menu:add("Power up",powerup)
return _ENV

@ -1,22 +0,0 @@
-- a collection of misc lua scripts
--[[=begin
dfusion
=======
Interface to a lecacy script system.
=end]]
local dfu=require("plugins.dfusion")
local myos=dfhack.getOSType()
args={...}
mainmenu=dfu.SimpleMenu()
function runsave()
local path=string.format("data/save/%s/dfhack.lua",df.global.world.cur_savegame.save_dir)
print("doing file:"..path)
loadfile(path)()
end
mainmenu:add("Run save script",runsave)
mainmenu:add("Adventurer tools",require("plugins.dfusion.adv_tools").menu)
mainmenu:add("Misc tools",require("plugins.dfusion.tools").menu)
mainmenu:display()