Merge branch 'master' of git://github.com/peterix/dfhack

develop
Warmist 2012-01-06 10:24:46 +02:00
commit 3115fb17c7
191 changed files with 3956 additions and 11454 deletions

3
.gitmodules vendored

@ -4,3 +4,6 @@
[submodule "plugins/df2mc"]
path = plugins/df2mc
url = git://github.com/peterix/DF2MC.git
[submodule "library/xml"]
path = library/xml
url = git://github.com/peterix/df-structures.git

@ -19,8 +19,8 @@ a 64-bit distribution like Arch, you'll need the multilib development tools and
Before you can build anything, you'll also need ``cmake``. It is advisable to also get
``ccmake`` on distributions that split the cmake package into multiple parts.
For the code generation parts, you need perl and the XML::LibXML perl package.
You should be able to find them in your distro repositories (on Arch linux 'perl-xml-libxml').
For the code generation parts, you need perl and the XML::LibXML and XML::LibXSLT perl packages.
You should be able to find them in your distro repositories (on Arch linux 'perl-xml-libxml' and 'perl-xml-libxslt').
Build
=====
@ -58,9 +58,11 @@ You'll need a copy of Microsoft Visual C++ 2010. The Express version is sufficie
Grab it from Microsoft's site.
For the code generation parts, you'll need perl and XML::LibXML. You can install them like this:
* download and install strawberry perl from http://strawberryperl.com/
* reboot so that the system can pick up the new binary path
* open a cmd.exe window and run "cpan XML::LibXML" (obviously without the quotes). This can take a while to complete.
* Same with "cpan XML::LibXSLT".
Build
=====

@ -351,8 +351,8 @@ ul.auto-toc {
a 64-bit distribution like Arch, you'll need the multilib development tools and libraries.</p>
<p>Before you can build anything, you'll also need <tt class="docutils literal">cmake</tt>. It is advisable to also get
<tt class="docutils literal">ccmake</tt> on distributions that split the cmake package into multiple parts.</p>
<p>For the code generation parts, you need perl and the XML::LibXML perl package.
You should be able to find them in your distro repositories (on Arch linux 'perl-xml-libxml').</p>
<p>For the code generation parts, you need perl and the XML::LibXML and XML::LibXSLT perl packages.
You should be able to find them in your distro repositories (on Arch linux 'perl-xml-libxml' and 'perl-xml-libxslt').</p>
</div>
<div class="section" id="build">
<h2><a class="toc-backref" href="#id4">Build</a></h2>
@ -384,10 +384,13 @@ site: <a class="reference external" href="http://www.cmake.org/cmake/resources/s
to your binary search PATH so the tool can be later run from anywhere.</p>
<p>You'll need a copy of Microsoft Visual C++ 2010. The Express version is sufficient.
Grab it from Microsoft's site.</p>
<p>For the code generation parts, you'll need perl and XML::LibXML. You can install them like this:
* download and install strawberry perl from http://strawberryperl.com/
* reboot so that the system can pick up the new binary path
* open a cmd.exe window and run &quot;cpan XML::LibXML&quot; (obviously without the quotes). This can take a while to complete.</p>
<p>For the code generation parts, you'll need perl and XML::LibXML. You can install them like this:</p>
<ul class="simple">
<li>download and install strawberry perl from <a class="reference external" href="http://strawberryperl.com/">http://strawberryperl.com/</a></li>
<li>reboot so that the system can pick up the new binary path</li>
<li>open a cmd.exe window and run &quot;cpan XML::LibXML&quot; (obviously without the quotes). This can take a while to complete.</li>
<li>Same with &quot;cpan XML::LibXSLT&quot;.</li>
</ul>
<div class="section" id="id1">
<h2><a class="toc-backref" href="#id6">Build</a></h2>
<p>Open the <tt class="docutils literal">build</tt> folder and double click the batch script there. This will eventually open

@ -1078,12 +1078,23 @@
<Group name="Notes" description="In-game notes">
<Address name="vector"/>
</Group>
<Group name='vtable'>
</Group>
<Group name='global'>
<Address name='cursor'/>
<Address name='selection_rect'/>
<Address name='world'/>
<Address name='ui'/>
<Address name='gview'/>
<Address name='init'/>
<Address name='d_init'/>
<Address name='ui_sidebar_menus'/>
<Address name='ui_build_selector'/>
<Address name='ui_look_list'/>
<Address name='ui_look_cursor'/>
<Address name='ui_workshop_job_cursor'/>
<Address name='ui_workshop_in_add'/>
<Address name='job_next_id'/>
</Group>
</Offsets>
</Base>
@ -2316,12 +2327,27 @@
<Group name="World">
<Address name="save_folder" value="0x1847A40" />
</Group>
<Group name='vtable'>
</Group>
<Group name='global'>
<!-- .data -->
<Address name='cursor' value='0xb347f0'/>
<Address name='selection_rect' value='0xb347fc'/>
<!-- .bss -->
<Address name='world' value='0x16b0a58'/>
<Address name='ui' value='0x14ee7e0'/>
<Address name='gview' value='0x14f6070'/>
<Address name='init' value='0x184ae58'/>
<Address name='d_init' value='0x1848350'/>
<Address name='ui_sidebar_menus' value='0x1848648'/>
<Address name='ui_build_selector' value='0x1849e88'/>
<Address name='ui_look_list' value='0x185c104'/>
<Address name='ui_look_cursor' value='0xedeb98'/>
<Address name='ui_workshop_job_cursor' value='0x14ec79c'/>
<Address name='ui_workshop_in_add' value='0xeb0992'/>
<Address name='job_next_id' value='0xe18290'/>
</Group>
</Offsets>
cmake
@ -3188,12 +3214,27 @@
<Group name="Notes">
<Address name="vector" value="0x93f635c"/>
</Group>
<Group name='vtable'>
</Group>
<Group name='global'>
<!-- .data -->
<Address name='cursor' value='0x8c3de60'/>
<Address name='selection_rect' value='0x8c3de70'/>
<!-- .bss -->
<Address name='world' value='0x93f77a0'/>
<Address name='ui' value='0x93f0780'/>
<Address name='gview' value='0x8c3e900'/>
<Address name='init' value='0x959c2a0'/>
<Address name='d_init' value='0x959d340'/>
<Address name='ui_sidebar_menus' value='0x958aa40'/>
<Address name='ui_build_selector' value='0x8df9b20'/>
<Address name='ui_look_list' value='0x961d840'/>
<!--<Address name='ui_look_cursor' value=''/>-->
<Address name='ui_workshop_job_cursor' value='0x93f0644'/>
<Address name='ui_workshop_in_add' value='0x93f0651'/>
<Address name='job_next_id' value='0x961d940'/>
</Group>
</Offsets>
</Version>

3
build/.gitignore vendored

@ -1 +1,2 @@
build-real
VC2010
DF_PATH.txt

@ -0,0 +1,4 @@
call "%VS100COMNTOOLS%vsvars32.bat"
cd VC2010
msbuild /m /p:Platform=Win32 /p:Configuration=RelWithDebInfo ALL_BUILD.vcxproj
cd ..

@ -0,0 +1,5 @@
call "%VS100COMNTOOLS%vsvars32.bat"
cd VC2010
msbuild /m /p:Platform=Win32 /p:Configuration=Release ALL_BUILD.vcxproj
cd ..
pause

@ -1,5 +0,0 @@
mkdir VC2010
cd VC2010
echo Pre-generating a build folder
cmake ..\.. -G"Visual Studio 10"
cmake-gui .

@ -0,0 +1,6 @@
IF EXIST DF_PATH.txt SET /P _DF_PATH=<DF_PATH.txt
IF NOT EXIST DF_PATH.txt SET _DF_PATH=%CD%\DF
mkdir VC2010
cd VC2010
echo generating a build folder
cmake ..\.. -G"Visual Studio 10" -DCMAKE_INSTALL_PREFIX=%_DF_PATH% -DBUILD_DEVEL=1 -DBUILD_DEV_PLUGINS=1 -DBUILD_DF2MC=1 -DBUILD_DFUSION=1 -DBUILD_STONESENSE=1 -DBUILD_SERVER=1

@ -0,0 +1,7 @@
IF EXIST DF_PATH.txt SET /P _DF_PATH=<DF_PATH.txt
IF NOT EXIST DF_PATH.txt SET _DF_PATH=%CD%\DF
mkdir VC2010
cd VC2010
echo Pre-generating a build folder
cmake ..\.. -G"Visual Studio 10" -DCMAKE_INSTALL_PREFIX=%_DF_PATH%
cmake-gui .

@ -0,0 +1,6 @@
IF EXIST DF_PATH.txt SET /P _DF_PATH=<DF_PATH.txt
IF NOT EXIST DF_PATH.txt SET _DF_PATH=%CD%\DF
mkdir VC2010
cd VC2010
echo generating a build folder
cmake ..\.. -G"Visual Studio 10" -DCMAKE_INSTALL_PREFIX=%_DF_PATH% -DBUILD_DEVEL=0 -DBUILD_DEV_PLUGINS=0 -DBUILD_DF2MC=0 -DBUILD_DFUSION=0 -DBUILD_STONESENSE=0 -DBUILD_SERVER=0

@ -0,0 +1,4 @@
call "%VS100COMNTOOLS%vsvars32.bat"
cd VC2010
msbuild /m /p:Platform=Win32 /p:Configuration=RelWithDebInfo INSTALL.vcxproj
cd ..

@ -0,0 +1,4 @@
call "%VS100COMNTOOLS%vsvars32.bat"
cd VC2010
msbuild /m /p:Platform=Win32 /p:Configuration=Release INSTALL.vcxproj
cd ..

@ -0,0 +1,4 @@
call "%VS100COMNTOOLS%vsvars32.bat"
cd VC2010
msbuild /m /p:Platform=Win32 /p:Configuration=RelWithDebInfo PACKAGE.vcxproj
cd ..

@ -0,0 +1,4 @@
call "%VS100COMNTOOLS%vsvars32.bat"
cd VC2010
msbuild /m /p:Platform=Win32 /p:Configuration=Release PACKAGE.vcxproj
cd ..

@ -0,0 +1,32 @@
Option Explicit
Const BIF_returnonlyfsdirs = &H0001
Dim wsh, objDlg, objF, fso, spoFile
Set objDlg = WScript.CreateObject("Shell.Application")
Set objF = objDlg.BrowseForFolder (&H0,"Select your DF folder", BIF_returnonlyfsdirs)
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists("DF_PATH.txt") Then
fso.DeleteFile "DF_PATH.txt", True
End If
If IsValue(objF) Then
If InStr(1, TypeName(objF), "Folder") > 0 Then
Set spoFile = fso.CreateTextFile("DF_PATH.txt", True)
spoFile.WriteLine(objF.Self.Path)
End If
End If
Function IsValue(obj)
' Check whether the value has been returned.
Dim tmp
On Error Resume Next
tmp = " " & obj
If Err <> 0 Then
IsValue = False
Else
IsValue = True
End If
On Error GoTo 0
End Function

@ -13,60 +13,59 @@ include_directories (include)
include_directories (depends/md5)
include_directories (depends/tinyxml)
include_directories (depends/tthread)
include_directories (private)
execute_process(COMMAND perl xml/list.pl xml include/dfhack/df ";"
execute_process(COMMAND perl xml/list.pl xml include/df ";"
WORKING_DIRECTORY ${dfapi_SOURCE_DIR}
OUTPUT_VARIABLE GENERATED_HDRS)
SET(PROJECT_HDRS_INTERNAL
private/ContextShared.h
private/Internal.h
private/wdirent.h
)
SET(PROJECT_HDRS
include/Internal.h
include/DFHack.h
include/dfhack/Console.h
include/dfhack/Core.h
include/dfhack/DataDefs.h
include/dfhack/Error.h
include/dfhack/Export.h
include/dfhack/FakeSDL.h
include/dfhack/MiscUtils.h
include/dfhack/Module.h
include/dfhack/Pragma.h
include/dfhack/Process.h
include/dfhack/TileTypes.h
include/dfhack/Types.h
include/dfhack/Vector.h
include/dfhack/VersionInfo.h
include/dfhack/VersionInfoFactory.h
include/dfhack/Virtual.h
include/dfhack/extra/MapExtras.h
include/dfhack/extra/stopwatch.h
include/dfhack/extra/termutil.h
include/dfhack/modules/Buildings.h
include/dfhack/modules/Constructions.h
include/dfhack/modules/Units.h
include/dfhack/modules/Engravings.h
include/dfhack/modules/Gui.h
include/dfhack/modules/Items.h
include/dfhack/modules/kitchen.h
include/dfhack/modules/Maps.h
include/dfhack/modules/Materials.h
include/dfhack/modules/Notes.h
include/dfhack/modules/Translation.h
include/dfhack/modules/Vegetation.h
include/dfhack/modules/Vermin.h
include/dfhack/modules/World.h
include/dfhack/modules/Graphic.h
include/Console.h
include/Core.h
include/DataDefs.h
include/Error.h
include/Export.h
include/Hooks.h
include/MiscUtils.h
include/Module.h
include/Pragma.h
include/MemAccess.h
include/SDL_events.h
include/SDL_keyboard.h
include/SDL_keysym.h
include/TileTypes.h
include/Types.h
include/VersionInfo.h
include/VersionInfoFactory.h
include/Virtual.h
include/modules/Buildings.h
include/modules/Constructions.h
include/modules/Units.h
include/modules/Engravings.h
include/modules/Gui.h
include/modules/Items.h
include/modules/kitchen.h
include/modules/Maps.h
include/modules/MapCache.h
include/modules/Materials.h
include/modules/Notes.h
include/modules/Translation.h
include/modules/Vegetation.h
include/modules/Vermin.h
include/modules/World.h
include/modules/Graphic.h
)
SET(PROJECT_SRCS
Core.cpp
DataDefs.cpp
DataStatics.cpp
DataStaticsCtor.cpp
MiscUtils.cpp
PluginManager.cpp
TileTypes.cpp
VersionInfo.cpp
@ -104,17 +103,18 @@ SET(PROJECT_HDRS_LINUX
)
SET(PROJECT_HDRS_WINDOWS
include/wdirent.h
)
SET(PROJECT_SRCS_LINUX
Console-linux.cpp
FakeSDL-linux.cpp
Hooks-linux.cpp
Process-linux.cpp
)
SET(PROJECT_SRCS_WINDOWS
Console-windows.cpp
FakeSDL-windows.cpp
Hooks-windows.cpp
Process-windows.cpp
)
@ -134,17 +134,18 @@ LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS})
SET_SOURCE_FILES_PROPERTIES(${GENERATED_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE GENERATED TRUE)
FILE(GLOB GENERATE_INPUT_SCRIPTS ${dfapi_SOURCE_DIR}/xml/*.pm ${dfapi_SOURCE_DIR}/xml/*.xslt)
FILE(GLOB GENERATE_INPUT_XMLS ${dfapi_SOURCE_DIR}/xml/*.xml)
ADD_CUSTOM_COMMAND(
OUTPUT ${dfapi_SOURCE_DIR}/include/dfhack/df/static.inc
COMMAND perl xml/codegen.pl xml include/dfhack/df
OUTPUT ${dfapi_SOURCE_DIR}/include/df/static.inc
COMMAND perl xml/codegen.pl xml include/df
WORKING_DIRECTORY ${dfapi_SOURCE_DIR}
MAIN_DEPENDENCY ${dfapi_SOURCE_DIR}/xml/codegen.pl
DEPENDS ${GENERATE_INPUT_XMLS}
DEPENDS ${GENERATE_INPUT_XMLS} ${GENERATE_INPUT_SCRIPTS}
)
ADD_CUSTOM_TARGET(generate_headers DEPENDS ${dfapi_SOURCE_DIR}/include/dfhack/df/static.inc)
ADD_CUSTOM_TARGET(generate_headers DEPENDS ${dfapi_SOURCE_DIR}/include/df/static.inc)
# Compilation

@ -61,8 +61,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <errno.h>
#include <deque>
#include "dfhack/Console.h"
#include "dfhack/FakeSDL.h"
#include "Console.h"
#include "Hooks.h"
using namespace DFHack;
#include "tinythread.h"

@ -50,8 +50,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include <istream>
#include <string>
#include "dfhack/Console.h"
#include "dfhack/FakeSDL.h"
#include "Console.h"
#include "Hooks.h"
#include <cstdio>
#include <cstdlib>
#include <sstream>

@ -34,30 +34,37 @@ distribution.
#include <sstream>
using namespace std;
#include "dfhack/Error.h"
#include "dfhack/Process.h"
#include "dfhack/Core.h"
#include "dfhack/DataDefs.h"
#include "dfhack/Console.h"
#include "dfhack/Module.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/PluginManager.h"
#include "Error.h"
#include "MemAccess.h"
#include "Core.h"
#include "DataDefs.h"
#include "Console.h"
#include "Module.h"
#include "VersionInfoFactory.h"
#include "VersionInfo.h"
#include "PluginManager.h"
#include "ModuleFactory.h"
#include "dfhack/modules/Gui.h"
#include "dfhack/modules/World.h"
#include "dfhack/modules/Graphic.h"
#include "modules/Gui.h"
#include "modules/World.h"
#include "modules/Graphic.h"
using namespace DFHack;
#include "dfhack/SDL_fakes/events.h"
#include "SDL_events.h"
#include "df/ui.h"
#include "df/world.h"
#include "df/world_data.h"
#include "df/interface.h"
#include "df/viewscreen_dwarfmodest.h"
#include <stdio.h>
#include <iomanip>
#include <stdlib.h>
#include <fstream>
#include "tinythread.h"
using namespace tthread;
using namespace tthread;
using namespace df::enums;
struct Core::Cond
{
@ -91,9 +98,35 @@ struct Core::Cond
void cheap_tokenise(string const& input, vector<string> &output)
{
istringstream str(input);
istream_iterator<string> cur(str), end;
output.assign(cur, end);
string *cur = NULL;
for (unsigned i = 0; i < input.size(); i++) {
char c = input[i];
if (isspace(c)) {
cur = NULL;
} else {
if (!cur) {
output.push_back("");
cur = &output.back();
}
if (c == '"') {
for (i++; i < input.size(); i++) {
c = input[i];
if (c == '"')
break;
else if (c == '\\') {
if (++i < input.size())
cur->push_back(input[i]);
}
else
cur->push_back(c);
}
} else {
cur->push_back(c);
}
}
}
}
struct IODATA
@ -119,8 +152,17 @@ void fHKthread(void * iodata)
std::string stuff = core->getHotkeyCmd(); // waits on mutex!
if(!stuff.empty())
{
vector <string> crap;
command_result cr = plug_mgr->InvokeCommand(stuff, crap, false);
vector <string> args;
cheap_tokenise(stuff, args);
if (args.empty()) {
core->con.printerr("Empty hotkey command.\n");
continue;
}
string first = args[0];
args.erase(args.begin());
command_result cr = plug_mgr->InvokeCommand(first, args, false);
if(cr == CR_WOULD_BREAK)
{
core->con.printerr("It isn't possible to run an interactive command outside the console.\n");
@ -129,53 +171,25 @@ void fHKthread(void * iodata)
}
}
// A thread function... for the interactive console.
void fIOthread(void * iodata)
static void runInteractiveCommand(Core *core, PluginManager *plug_mgr, int &clueless_counter, const string &command)
{
IODATA * iod = ((IODATA*) iodata);
Core * core = iod->core;
PluginManager * plug_mgr = ((IODATA*) iodata)->plug_mgr;
CommandHistory main_history;
main_history.load("dfhack.history");
Console & con = core->con;
if(plug_mgr == 0 || core == 0)
{
con.printerr("Something horrible happened in Core's constructor...\n");
return;
}
con.print("DFHack is ready. Have a nice day!\n"
"Type in '?' or 'help' for general help, 'ls' to see all commands.\n");
int clueless_counter = 0;
while (true)
if (!command.empty())
{
string command = "";
int ret = con.lineedit("[DFHack]# ",command, main_history);
if(ret == -2)
{
cerr << "Console is shutting down properly." << endl;
return;
}
else if(ret == -1)
{
cerr << "Console caught an unspecified error." << endl;
continue;
}
else if(ret)
{
// a proper, non-empty command was entered
main_history.add(command);
main_history.save("dfhack.history");
}
// cut the input into parts
vector <string> parts;
cheap_tokenise(command,parts);
if(parts.size() == 0)
{
clueless_counter ++;
continue;
return;
}
string first = parts[0];
parts.erase(parts.begin());
if (first[0] == '#') return;
cerr << "Invoking: " << command << endl;
// let's see what we actually got
@ -194,6 +208,7 @@ void fIOthread(void * iodata)
" cls - Clear the console.\n"
" fpause - Force DF to pause.\n"
" die - Force DF to close immediately\n"
" keybinding - Modify bindings of commands to keys\n"
"Plugin management (useful for developers):\n"
//" belongs COMMAND - Tell which plugin a command belongs to.\n"
" plug [PLUGIN|v] - List plugin state and description.\n"
@ -202,6 +217,27 @@ void fIOthread(void * iodata)
" reload PLUGIN|all - Reload a plugin or all loaded plugins.\n"
);
}
else if (parts.size() == 1)
{
Plugin *plug = plug_mgr->getPluginByCommand(parts[0]);
if (plug) {
for (int j = 0; j < plug->size();j++)
{
const PluginCommand & pcmd = (plug->operator[](j));
if (pcmd.name != parts[0])
continue;
if (pcmd.isHotkeyCommand())
con.color(Console::COLOR_CYAN);
con.print("%s: %s\n",pcmd.name.c_str(), pcmd.description.c_str());
con.reset_color();
if (!pcmd.usage.empty())
con << "Usage:\n" << pcmd.usage << flush;
return;
}
}
con.printerr("Unknown command: %s\n", parts[0].c_str());
}
else
{
con.printerr("not implemented yet\n");
@ -301,7 +337,10 @@ void fIOthread(void * iodata)
else for (int j = 0; j < plug->size();j++)
{
const PluginCommand & pcmd = (plug->operator[](j));
if (pcmd.isHotkeyCommand())
con.color(Console::COLOR_CYAN);
con.print(" %-22s - %s\n",pcmd.name.c_str(), pcmd.description.c_str());
con.reset_color();
}
}
else
@ -329,7 +368,10 @@ void fIOthread(void * iodata)
for (int j = 0; j < plug->size();j++)
{
const PluginCommand & pcmd = (plug->operator[](j));
if (pcmd.isHotkeyCommand())
con.color(Console::COLOR_CYAN);
con.print(" %-22s- %s\n",pcmd.name.c_str(), pcmd.description.c_str());
con.reset_color();
}
}
}
@ -344,6 +386,49 @@ void fIOthread(void * iodata)
con.print("%s\n", plug->getName().c_str());
}
}
else if(first == "keybinding")
{
if (parts.size() >= 3 && (parts[0] == "set" || parts[0] == "add"))
{
std::string keystr = parts[1];
if (parts[0] == "set")
core->ClearKeyBindings(keystr);
for (int i = parts.size()-1; i >= 2; i--)
{
if (!core->AddKeyBinding(keystr, parts[i])) {
con.printerr("Invalid key spec: %s\n", keystr.c_str());
break;
}
}
}
else if (parts.size() >= 2 && parts[0] == "clear")
{
for (unsigned i = 1; i < parts.size(); i++)
{
if (!core->ClearKeyBindings(parts[i])) {
con.printerr("Invalid key spec: %s\n", parts[i].c_str());
break;
}
}
}
else if (parts.size() == 2 && parts[0] == "list")
{
std::vector<std::string> list = core->ListKeyBindings(parts[1]);
if (list.empty())
con << "No bindings." << endl;
for (unsigned i = 0; i < list.size(); i++)
con << " " << list[i] << endl;
}
else
{
con << "Usage:" << endl
<< " keybinding list <key>" << endl
<< " keybinding clear <key> <key>..." << endl
<< " keybinding set <key> \"cmdline\" \"cmdline\"..." << endl
<< " keybinding add <key> \"cmdline\" \"cmdline\"..." << endl
<< "Later adds, and earlier items within one command have priority." << endl;
}
}
else if(first == "fpause")
{
World * w = core->getWorld();
@ -384,6 +469,70 @@ void fIOthread(void * iodata)
*/
}
}
}
}
static void loadInitFile(Core *core, PluginManager *plug_mgr, string fname)
{
ifstream init(fname);
if (init.bad())
return;
int tmp = 0;
string command;
while (getline(init, command))
{
if (!command.empty())
runInteractiveCommand(core, plug_mgr, tmp, command);
}
}
// A thread function... for the interactive console.
void fIOthread(void * iodata)
{
IODATA * iod = ((IODATA*) iodata);
Core * core = iod->core;
PluginManager * plug_mgr = ((IODATA*) iodata)->plug_mgr;
CommandHistory main_history;
main_history.load("dfhack.history");
Console & con = core->con;
if(plug_mgr == 0 || core == 0)
{
con.printerr("Something horrible happened in Core's constructor...\n");
return;
}
loadInitFile(core, plug_mgr, "dfhack.init");
con.print("DFHack is ready. Have a nice day!\n"
"Type in '?' or 'help' for general help, 'ls' to see all commands.\n");
int clueless_counter = 0;
while (true)
{
string command = "";
int ret = con.lineedit("[DFHack]# ",command, main_history);
if(ret == -2)
{
cerr << "Console is shutting down properly." << endl;
return;
}
else if(ret == -1)
{
cerr << "Console caught an unspecified error." << endl;
continue;
}
else if(ret)
{
// a proper, non-empty command was entered
main_history.add(command);
main_history.save("dfhack.history");
}
runInteractiveCommand(core, plug_mgr, clueless_counter, command);
if(clueless_counter == 3)
{
con.print("Do 'help' or '?' for the list of available commands.\n");
@ -408,11 +557,12 @@ Core::Core()
StackMutex = 0;
core_cond = 0;
// set up hotkey capture
memset(hotkey_states,0,sizeof(hotkey_states));
hotkey_set = false;
HotkeyMutex = 0;
HotkeyCond = 0;
misc_data_mutex=0;
last_world_data_ptr = NULL;
top_viewscreen = NULL;
};
void Core::fatal (std::string output, bool deactivate)
@ -497,7 +647,7 @@ bool Core::Init()
}
// initialize data defs
virtual_identity::Init();
virtual_identity::Init(this);
InitDataDefGlobals(this);
// create mutex for syncing with interactive tasks
@ -605,8 +755,36 @@ int Core::Update()
if(errorstate)
return -1;
// detect if the game was loaded or unloaded in the meantime
void *new_wdata = NULL;
if (df::global::world) {
df::world_data *wdata = df::global::world->world_data;
// when the game is unloaded, world_data isn't deleted, but its contents are
if (wdata && !wdata->sites.empty())
new_wdata = wdata;
}
if (new_wdata != last_world_data_ptr) {
last_world_data_ptr = new_wdata;
plug_mgr->OnStateChange(new_wdata ? SC_GAME_LOADED : SC_GAME_UNLOADED);
}
// detect if the viewscreen changed
if (df::global::gview)
{
df::viewscreen *screen = &df::global::gview->view;
while (screen->child)
screen = screen->child;
if (screen != top_viewscreen)
{
top_viewscreen = screen;
plug_mgr->OnStateChange(SC_VIEWSCREEN_CHANGED);
}
}
// notify all the plugins that a game tick is finished
plug_mgr->OnUpdate();
// wake waiting tools
// do not allow more tools to join in while we process stuff here
StackMutex->lock();
@ -695,39 +873,168 @@ int Core::SDL_Event(SDL::Event* ev, int orig_return)
if(ev && ev->type == SDL::ET_KEYDOWN || ev->type == SDL::ET_KEYUP)
{
SDL::KeyboardEvent * ke = (SDL::KeyboardEvent *)ev;
bool shift = ke->ksym.mod & SDL::KMOD_SHIFT;
// consuming F1 .. F8
int idx = ke->ksym.sym - SDL::K_F1;
if(idx < 0 || idx > 7)
return orig_return;
idx += 8*shift;
// now we have the real index...
if(ke->state == SDL::BTN_PRESSED && !hotkey_states[idx])
if(ke->state == SDL::BTN_PRESSED && !hotkey_states[ke->ksym.sym])
{
hotkey_states[idx] = 1;
Gui * g = getGui();
if(g->hotkeys && g->df_interface && g->df_menu_state)
{
t_viewscreen * ws = g->GetCurrentScreen();
// FIXME: put hardcoded values into memory.xml
if(ws->getClassName() == "viewscreen_dwarfmodest" && *g->df_menu_state == 0x23)
return orig_return;
else
{
t_hotkey & hotkey = (*g->hotkeys)[idx];
setHotkeyCmd(hotkey.name);
}
}
hotkey_states[ke->ksym.sym] = true;
int mod = 0;
if (ke->ksym.mod & SDL::KMOD_SHIFT) mod |= 1;
if (ke->ksym.mod & SDL::KMOD_CTRL) mod |= 2;
if (ke->ksym.mod & SDL::KMOD_ALT) mod |= 4;
SelectHotkey(ke->ksym.sym, mod);
}
else if(ke->state == SDL::BTN_RELEASED)
{
hotkey_states[idx] = 0;
hotkey_states[ke->ksym.sym] = false;
}
}
return orig_return;
// do stuff with the events...
}
bool Core::SelectHotkey(int sym, int modifiers)
{
// Find the topmost viewscreen
if (!df::global::gview || !df::global::ui)
return false;
df::viewscreen *screen = &df::global::gview->view;
while (screen->child)
screen = screen->child;
std::string cmd;
{
tthread::lock_guard<tthread::mutex> lock(*HotkeyMutex);
// Check the internal keybindings
std::vector<KeyBinding> &bindings = key_bindings[sym];
for (int i = bindings.size()-1; i >= 0; --i) {
if (bindings[i].modifiers != modifiers)
continue;
if (!plug_mgr->CanInvokeHotkey(bindings[i].command[0], screen))
continue;
cmd = bindings[i].cmdline;
break;
}
if (cmd.empty()) {
// Check the hotkey keybindings
int idx = sym - SDL::K_F1;
if(idx >= 0 && idx < 8)
{
if (modifiers & 1)
idx += 8;
if (strict_virtual_cast<df::viewscreen_dwarfmodest>(screen) &&
df::global::ui->main.mode != ui_sidebar_mode::Hotkeys)
{
cmd = df::global::ui->main.hotkeys[idx].name;
}
}
}
}
if (!cmd.empty()) {
setHotkeyCmd(cmd);
return true;
}
else
return false;
}
static bool parseKeySpec(std::string keyspec, int *psym, int *pmod)
{
*pmod = 0;
// ugh, ugly
for (;;) {
if (keyspec.size() > 6 && keyspec.substr(0, 6) == "Shift-") {
*pmod |= 1;
keyspec = keyspec.substr(6);
} else if (keyspec.size() > 5 && keyspec.substr(0, 5) == "Ctrl-") {
*pmod |= 2;
keyspec = keyspec.substr(5);
} else if (keyspec.size() > 4 && keyspec.substr(0, 4) == "Alt-") {
*pmod |= 4;
keyspec = keyspec.substr(4);
} else
break;
}
if (keyspec.size() == 1 && keyspec[0] >= 'A' && keyspec[0] <= 'Z') {
*psym = SDL::K_a + (keyspec[0]-'A');
return true;
} else if (keyspec.size() == 2 && keyspec[0] == 'F' && keyspec[1] >= '1' && keyspec[1] <= '9') {
*psym = SDL::K_F1 + (keyspec[1]-'1');
return true;
} else
return false;
}
bool Core::ClearKeyBindings(std::string keyspec)
{
int sym, mod;
if (!parseKeySpec(keyspec, &sym, &mod))
return false;
tthread::lock_guard<tthread::mutex> lock(*HotkeyMutex);
std::vector<KeyBinding> &bindings = key_bindings[sym];
for (int i = bindings.size()-1; i >= 0; --i) {
if (bindings[i].modifiers == mod)
bindings.erase(bindings.begin()+i);
}
return true;
}
bool Core::AddKeyBinding(std::string keyspec, std::string cmdline)
{
int sym;
KeyBinding binding;
if (!parseKeySpec(keyspec, &sym, &binding.modifiers))
return false;
cheap_tokenise(cmdline, binding.command);
if (binding.command.empty())
return false;
tthread::lock_guard<tthread::mutex> lock(*HotkeyMutex);
// Don't add duplicates
std::vector<KeyBinding> &bindings = key_bindings[sym];
for (int i = bindings.size()-1; i >= 0; --i) {
if (bindings[i].modifiers == binding.modifiers &&
bindings[i].cmdline == cmdline)
return true;
}
binding.cmdline = cmdline;
bindings.push_back(binding);
return true;
}
std::vector<std::string> Core::ListKeyBindings(std::string keyspec)
{
int sym, mod;
std::vector<std::string> rv;
if (!parseKeySpec(keyspec, &sym, &mod))
return rv;
tthread::lock_guard<tthread::mutex> lock(*HotkeyMutex);
std::vector<KeyBinding> &bindings = key_bindings[sym];
for (int i = bindings.size()-1; i >= 0; --i) {
if (bindings[i].modifiers == mod)
rv.push_back(bindings[i].cmdline);
}
return rv;
}
////////////////
// ClassNamCheck
////////////////

@ -28,12 +28,14 @@ distribution.
#include <vector>
#include <map>
#include "dfhack/Process.h"
#include "dfhack/Core.h"
#include "dfhack/VersionInfo.h"
#include "MemAccess.h"
#include "Core.h"
#include "VersionInfo.h"
#include "tinythread.h"
// must be last due to MS stupidity
#include "dfhack/DataDefs.h"
#include "DataDefs.h"
#include "MiscUtils.h"
using namespace DFHack;
@ -78,31 +80,62 @@ virtual_identity *virtual_identity::get(virtual_ptr instance_ptr)
for (virtual_identity *p = list; p; p = p->next) {
if (strcmp(name.c_str(), p->getOriginalName()) != 0) continue;
if (p->vtable_ptr && p->vtable_ptr != vtable) {
std::cerr << "Conflicting vtable ptr for class '" << p->getName()
<< "': found 0x" << std::hex << unsigned(vtable)
<< ", previous 0x" << unsigned(p->vtable_ptr) << std::dec << std::endl;
abort();
} else if (!p->vtable_ptr) {
std::cerr << "class '" << p->getName() << "': vtable = 0x"
<< std::hex << unsigned(vtable) << std::dec << std::endl;
}
known[vtable] = p;
p->vtable_ptr = vtable;
return p;
}
std::cerr << "UNKNOWN CLASS '" << name << "': vtable = 0x"
<< std::hex << unsigned(vtable) << std::dec << std::endl;
known[vtable] = NULL;
return NULL;
}
bool virtual_identity::check_instance(virtual_ptr instance_ptr, bool allow_subclasses)
bool virtual_identity::is_subclass(virtual_identity *actual)
{
virtual_identity *actual = get(instance_ptr);
if (actual == this) return true;
if (!allow_subclasses || !actual) return false;
do {
actual = actual->parent;
for (; actual; actual = actual->parent)
if (actual == this) return true;
} while (actual);
return false;
}
void virtual_identity::Init()
void virtual_identity::adjust_vtable(virtual_ptr obj, virtual_identity *main)
{
if (vtable_ptr) {
*(void**)obj = vtable_ptr;
return;
}
if (main && main != this && is_subclass(main))
return;
std::cerr << "Attempt to create class '" << getName() << "' without known vtable." << std::endl;
abort();
}
virtual_ptr virtual_identity::clone(virtual_ptr obj)
{
virtual_identity *id = get(obj);
if (!id) return NULL;
virtual_ptr copy = id->instantiate();
if (!copy) return NULL;
id->do_copy(copy, obj);
return copy;
}
void virtual_identity::Init(Core *core)
{
if (!known_mutex)
known_mutex = new tthread::mutex();
@ -119,19 +152,66 @@ void virtual_identity::Init()
p->parent->has_children = true;
}
}
// Read pre-filled vtable ptrs
OffsetGroup *ptr_table = core->vinfo->getGroup("vtable");
for (virtual_identity *p = list; p; p = p->next) {
void * tmp;
if (ptr_table->getSafeAddress(p->getName(),tmp))
p->vtable_ptr = tmp;
}
}
std::string DFHack::bitfieldToString(const void *p, int size, const bitfield_item_info *items)
{
std::string res;
const char *data = (const char*)p;
for (int i = 0; i < size*8; i++) {
unsigned v;
if (items[i].size > 1) {
unsigned pdv = *(unsigned*)&data[i/8];
v = (pdv >> (i%8)) & ((1 << items[i].size)-1);
} else {
v = (data[i/8]>>(i%8)) & 1;
}
if (v) {
if (!res.empty())
res += ' ';
if (items[i].name)
res += items[i].name;
else
res += stl_sprintf("UNK_%d", i);
if (items[i].size > 1)
res += stl_sprintf("=%u", v);
}
if (items[i].size > 1)
i += items[i].size-1;
}
return res;
}
#define GLOBAL(name,tname) \
df::tname *df::global::name = NULL;
#define SIMPLE_GLOBAL(name,tname) \
tname *df::global::name = NULL;
#define GLOBAL(name,tname) SIMPLE_GLOBAL(name,df::tname)
DF_KNOWN_GLOBALS
#undef GLOBAL
#undef SIMPLE_GLOBAL
void DFHack::InitDataDefGlobals(Core *core) {
OffsetGroup *global_table = core->vinfo->getGroup("global");
uint32_t tmp;
void * tmp;
#define GLOBAL(name,tname) \
if (global_table->getSafeAddress(#name,tmp)) df::global::name = (df::tname*)tmp;
#define SIMPLE_GLOBAL(name,tname) \
if (global_table->getSafeAddress(#name,tmp)) df::global::name = (tname*)tmp;
#define GLOBAL(name,tname) SIMPLE_GLOBAL(name,df::tname)
DF_KNOWN_GLOBALS
#undef GLOBAL
#undef SIMPLE_GLOBAL
}

@ -1,10 +1,10 @@
#include "Internal.h"
#include "dfhack/DataDefs.h"
#include "dfhack/MiscUtils.h"
#include "DataDefs.h"
#include "MiscUtils.h"
#include "dfhack/df/world.h"
#include "dfhack/df/world_data.h"
#include "dfhack/df/ui.h"
#include "df/world.h"
#include "df/world_data.h"
#include "df/ui.h"
namespace {
template<class T>
@ -14,4 +14,5 @@ namespace {
}
// Instantiate all the static objects
#include "dfhack/df/static.inc"
#include "df/static.inc"
#include "df/static.enums.inc"

@ -0,0 +1,6 @@
#include "Internal.h"
#include "DataDefs.h"
#include "MiscUtils.h"
// Object constructors
#include "df/static.ctors.inc"

@ -39,8 +39,8 @@ distribution.
#include <map>
#include "DFHack.h"
#include "dfhack/Core.h"
#include "dfhack/FakeSDL.h"
#include "Core.h"
#include "Hooks.h"
#include <iostream>
/*

@ -28,12 +28,12 @@ distribution.
#include <stdint.h>
#include <vector>
#include <string>
#include "dfhack/Core.h"
#include "dfhack/FakeSDL.h"
#include "Core.h"
#include "Hooks.h"
#include <stdio.h>
#include "tinythread.h"
#include "dfhack/modules/Graphic.h"
#include "modules/Graphic.h"
/*
* Plugin loading functions

@ -0,0 +1,97 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include "Export.h"
#include "Core.h"
#include "MiscUtils.h"
#ifndef LINUX_BUILD
#include <Windows.h>
#else
#include <sys/time.h>
#include <ctime>
#endif
#include <stdarg.h>
std::string stl_sprintf(const char *fmt, ...) {
va_list lst;
va_start(lst, fmt);
std::string rv = stl_vsprintf(fmt, lst);
va_end(lst);
return rv;
}
std::string stl_vsprintf(const char *fmt, va_list args) {
std::vector<char> buf;
buf.resize(4096);
for (;;) {
int rsz = vsnprintf(&buf[0], buf.size(), fmt, args);
if (rsz < 0)
buf.resize(buf.size()*2);
else if (unsigned(rsz) > buf.size())
buf.resize(rsz+1);
else
return std::string(&buf[0], rsz);
}
}
#ifdef LINUX_BUILD // Linux
uint64_t GetTimeMs64()
{
struct timeval tv;
gettimeofday(&tv, NULL);
uint64_t ret = tv.tv_usec;
// Convert from micro seconds (10^-6) to milliseconds (10^-3)
ret /= 1000;
// Adds the seconds (10^0) after converting them to milliseconds (10^-3)
ret += (tv.tv_sec * 1000);
return ret;
}
#else // Windows
uint64_t GetTimeMs64()
{
FILETIME ft;
LARGE_INTEGER li;
// Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC)
// and copy it to a LARGE_INTEGER structure.
GetSystemTimeAsFileTime(&ft);
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
uint64_t ret = li.QuadPart;
// Convert from file time to UNIX epoch time.
ret -= 116444736000000000LL;
// From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals
ret /= 10000;
return ret;
}
#endif

@ -23,10 +23,13 @@ distribution.
*/
#include "Internal.h"
#include "dfhack/Core.h"
#include "dfhack/Process.h"
#include "dfhack/PluginManager.h"
#include "dfhack/Console.h"
#include "Core.h"
#include "MemAccess.h"
#include "PluginManager.h"
#include "Console.h"
#include "DataDefs.h"
using namespace DFHack;
#include <string>
@ -135,6 +138,7 @@ Plugin::Plugin(Core * core, const std::string & filepath, const std::string & _f
plugin_shutdown = 0;
plugin_status = 0;
plugin_onupdate = 0;
plugin_onstatechange = 0;
state = PS_UNLOADED;
access = new RefLock();
}
@ -192,6 +196,7 @@ bool Plugin::load()
plugin_status = (command_result (*)(Core *, std::string &)) LookupPlugin(plug, "plugin_status");
plugin_onupdate = (command_result (*)(Core *)) LookupPlugin(plug, "plugin_onupdate");
plugin_shutdown = (command_result (*)(Core *)) LookupPlugin(plug, "plugin_shutdown");
plugin_onstatechange = (command_result (*)(Core *, state_change_event)) LookupPlugin(plug, "plugin_onstatechange");
//name = _PlugName();
plugin_lib = plug;
if(plugin_init(&c,commands) == CR_OK)
@ -232,7 +237,7 @@ bool Plugin::unload()
ClosePlugin(plugin_lib);
state = PS_UNLOADED;
access->unlock();
return false;
return true;
}
else
{
@ -271,13 +276,63 @@ command_result Plugin::invoke( std::string & command, std::vector <std::string>
{
for (int i = 0; i < commands.size();i++)
{
if(commands[i].name == command)
PluginCommand &cmd = commands[i];
if(cmd.name == command)
{
// running interactive things from some other source than the console would break it
if(!interactive_ && commands[i].interactive)
if(!interactive_ && cmd.interactive)
cr = CR_WOULD_BREAK;
else if (cmd.guard)
{
// Execute hotkey commands in a way where they can
// expect their guard conditions to be matched,
// so as to avoid duplicating checks.
// This means suspending the core beforehand.
CoreSuspender suspend(&c);
df::viewscreen *top = c.getTopViewscreen();
if (!cmd.guard(&c, top))
{
c.con.printerr("Could not invoke %s: unsuitable UI state.\n", command.c_str());
cr = CR_WRONG_USAGE;
}
else
{
cr = cmd.function(&c, parameters);
}
}
else
cr = commands[i].function(&c, parameters);
{
cr = cmd.function(&c, parameters);
}
if (cr == CR_WRONG_USAGE && !cmd.usage.empty())
c.con << "Usage:\n" << cmd.usage << flush;
break;
}
}
}
access->lock_sub();
return cr;
}
bool Plugin::can_invoke_hotkey( std::string & command, df::viewscreen *top )
{
Core & c = Core::getInstance();
bool cr = false;
access->lock_add();
if(state == PS_LOADED)
{
for (int i = 0; i < commands.size();i++)
{
PluginCommand &cmd = commands[i];
if(cmd.name == command)
{
if (cmd.interactive)
cr = false;
else if (cmd.guard)
cr = cmd.guard(&c, top);
else
cr = default_hotkey(&c, top);
break;
}
}
@ -299,6 +354,19 @@ command_result Plugin::on_update()
return cr;
}
command_result Plugin::on_state_change(state_change_event event)
{
Core & c = Core::getInstance();
command_result cr = CR_NOT_IMPLEMENTED;
access->lock_add();
if(state == PS_LOADED && plugin_onstatechange)
{
cr = plugin_onstatechange(&c, event);
}
access->lock_sub();
return cr;
}
Plugin::plugin_state Plugin::getState() const
{
return state;
@ -348,19 +416,27 @@ Plugin *PluginManager::getPluginByName (const std::string & name)
return 0;
}
Plugin *PluginManager::getPluginByCommand(const std::string &command)
{
tthread::lock_guard<tthread::mutex> lock(*cmdlist_mutex);
map <string, Plugin *>::iterator iter = belongs.find(command);
if (iter != belongs.end())
return iter->second;
else
return NULL;
}
// FIXME: handle name collisions...
command_result PluginManager::InvokeCommand( std::string & command, std::vector <std::string> & parameters, bool interactive)
{
command_result cr = CR_NOT_IMPLEMENTED;
Core * c = &Core::getInstance();
cmdlist_mutex->lock();
map <string, Plugin *>::iterator iter = belongs.find(command);
if(iter != belongs.end())
{
cr = iter->second->invoke(command, parameters, interactive);
}
cmdlist_mutex->unlock();
return cr;
Plugin *plugin = getPluginByCommand(command);
return plugin ? plugin->invoke(command, parameters, interactive) : CR_NOT_IMPLEMENTED;
}
bool PluginManager::CanInvokeHotkey(std::string &command, df::viewscreen *top)
{
Plugin *plugin = getPluginByCommand(command);
return plugin ? plugin->can_invoke_hotkey(command, top) : false;
}
void PluginManager::OnUpdate( void )
@ -370,6 +446,15 @@ void PluginManager::OnUpdate( void )
all_plugins[i]->on_update();
}
}
void PluginManager::OnStateChange( state_change_event event )
{
for(int i = 0; i < all_plugins.size(); i++)
{
all_plugins[i]->on_state_change(event);
}
}
// FIXME: doesn't check name collisions!
void PluginManager::registerCommands( Plugin * p )
{

@ -36,10 +36,10 @@ distribution.
using namespace std;
#include <md5wrapper.h>
#include "dfhack/Process.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Error.h"
#include "MemAccess.h"
#include "VersionInfoFactory.h"
#include "VersionInfo.h"
#include "Error.h"
#include <string.h>
using namespace DFHack;
@ -111,8 +111,8 @@ Process::~Process()
string Process::doReadClassName (void * vptr)
{
//FIXME: BAD!!!!!
int typeinfo = Process::readDWord((uint32_t)vptr - 0x4);
int typestring = Process::readDWord(typeinfo + 0x4);
char * typeinfo = Process::readPtr(((char *)vptr - 0x4));
char * typestring = Process::readPtr(typeinfo + 0x4);
string raw = readCString(typestring);
size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers
size_t end = raw.length();
@ -138,8 +138,8 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
(char*)&permissions,
&offset, &device1, &device2, &node,
(char*)&temp.name);
temp.start = start;
temp.end = end;
temp.start = (void *) start;
temp.end = (void *) end;
temp.read = permissions[0] == 'r';
temp.write = permissions[1] == 'w';
temp.execute = permissions[2] == 'x';
@ -214,7 +214,7 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange)
if(trgrange.read)protect|=PROT_READ;
if(trgrange.write)protect|=PROT_WRITE;
if(trgrange.execute)protect|=PROT_EXEC;
result=mprotect((void *)range.start, range.end-range.start,protect);
result=mprotect((void *)range.start, (size_t)range.end-(size_t)range.start,protect);
return result==0;
}

@ -91,10 +91,10 @@ extern "C" __declspec(dllimport) NTSTATUS __stdcall RtlDestroyQueryDebugBuffer(
#include <map>
using namespace std;
#include "dfhack/VersionInfo.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/Error.h"
#include "dfhack/Process.h"
#include "VersionInfo.h"
#include "VersionInfoFactory.h"
#include "Error.h"
#include "MemAccess.h"
using namespace DFHack;
namespace DFHack
{
@ -112,7 +112,7 @@ namespace DFHack
uint32_t my_pid;
IMAGE_NT_HEADERS pe_header;
IMAGE_SECTION_HEADER * sections;
uint32_t base;
char * base;
};
}
Process::Process(VersionInfoFactory * factory)
@ -134,7 +134,7 @@ Process::Process(VersionInfoFactory * factory)
}
// got base ;)
d->base = (uint32_t)hmod;
d->base = (char *)hmod;
// read from this process
try
@ -161,7 +161,7 @@ Process::Process(VersionInfoFactory * factory)
identified = true;
// give the process a data model and memory layout fixed for the base of first module
my_descriptor = new VersionInfo(*vinfo);
my_descriptor->RebaseAll(d->base);
my_descriptor->RebaseAll((uint32_t)d->base);
// keep track of created memory_info object so we can destroy it later
my_descriptor->setParentProcess(this);
for(size_t i = 0; i < threads_ids.size();i++)
@ -236,7 +236,7 @@ struct HeapBlock
ULONG reserved;
};
*/
void HeapNodes(DWORD pid, map<uint64_t, unsigned int> & heaps)
void HeapNodes(DWORD pid, map<char *, unsigned int> & heaps)
{
// Create debug buffer
PDEBUG_BUFFER db = RtlCreateQueryDebugBuffer(0, FALSE);
@ -247,7 +247,7 @@ void HeapNodes(DWORD pid, map<uint64_t, unsigned int> & heaps)
// Go through each of the heap nodes and dispaly the information
for (unsigned int i = 0; i < heapNodeCount; i++)
{
heaps[heapInfo[i].Base] = i;
heaps[(char *)heapInfo[i].Base] = i;
}
// Clean up the buffer
RtlDestroyQueryDebugBuffer( db );
@ -257,9 +257,9 @@ void HeapNodes(DWORD pid, map<uint64_t, unsigned int> & heaps)
void Process::getMemRanges( vector<t_memrange> & ranges )
{
MEMORY_BASIC_INFORMATION MBI;
map<uint64_t, unsigned int> heaps;
map<char *, unsigned int> heaps;
uint64_t movingStart = 0;
map <uint64_t, string> nameMap;
map <char *, string> nameMap;
// get page size
SYSTEM_INFO si;
@ -277,18 +277,18 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
if( !(MBI.State & MEM_COMMIT) /*|| !(MBI.Type & MEM_PRIVATE)*/ )
continue;
t_memrange temp;
temp.start = (uint64_t) MBI.BaseAddress;
temp.end = ((uint64_t)MBI.BaseAddress + (uint64_t)MBI.RegionSize);
temp.start = (char *) MBI.BaseAddress;
temp.end = ((char *)MBI.BaseAddress + (uint64_t)MBI.RegionSize);
temp.read = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READONLY || MBI.Protect & PAGE_READWRITE;
temp.write = MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READWRITE;
temp.execute = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_EXECUTE;
temp.valid = true;
if(!GetModuleBaseName(d->my_handle, (HMODULE) temp.start, temp.name, 1024))
{
if(nameMap.count(temp.start))
if(nameMap.count((char *)temp.start))
{
// potential buffer overflow...
strcpy(temp.name, nameMap[temp.start].c_str());
strcpy(temp.name, nameMap[(char *)temp.start].c_str());
}
else
{
@ -298,9 +298,9 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
else
{
// could be a heap?
if(heaps.count(temp.start))
if(heaps.count((char *)temp.start))
{
sprintf(temp.name,"HEAP %d",heaps[temp.start]);
sprintf(temp.name,"HEAP %d",heaps[(char*)temp.start]);
}
else temp.name[0]=0;
}
@ -320,7 +320,7 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
nm.append(temp.name);
nm.append(" : ");
nm.append(sectionName);
nameMap[temp.start + d->sections[i].VirtualAddress] = nm;
nameMap[(char *)temp.start + d->sections[i].VirtualAddress] = nm;
}
}
else
@ -333,14 +333,14 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
uint32_t Process::getBase()
{
if(d)
return d->base;
return (uint32_t) d->base;
return 0x400000;
}
string Process::doReadClassName (void * vptr)
{
int rtti = readDWord((uint32_t)vptr - 0x4);
int typeinfo = readDWord(rtti + 0xC);
char * rtti = readPtr((char *)vptr - 0x4);
char * typeinfo = readPtr(rtti + 0xC);
string raw = readCString(typeinfo + 0xC); // skips the .?AV
raw.resize(raw.length() - 2);// trim @@ from end
return raw;
@ -367,7 +367,7 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange)
if(trgrange.read && trgrange.write && trgrange.execute)newprotect=PAGE_EXECUTE_READWRITE;
DWORD oldprotect=0;
bool result;
result=VirtualProtect((LPVOID)range.start,range.end-range.start,newprotect,&oldprotect);
result=VirtualProtect((LPVOID)range.start,(char *)range.end-(char *)range.start,newprotect,&oldprotect);
return result;
}

@ -23,8 +23,8 @@ distribution.
*/
#include "Internal.h"
#include "dfhack/TileTypes.h"
#include "dfhack/Export.h"
#include "TileTypes.h"
#include "Export.h"
namespace DFHack
{

@ -31,9 +31,9 @@ distribution.
#include <map>
using namespace std;
#include "dfhack/VersionInfo.h"
#include "dfhack/Error.h"
#include "dfhack/Process.h"
#include "VersionInfo.h"
#include "Error.h"
#include "MemAccess.h"
using namespace DFHack;
//Inital amount of space in levels vector (since we usually know the number, efficient!)
@ -158,6 +158,8 @@ namespace DFHack
{
typedef pair <INVAL_TYPE, uint32_t> nullableUint32;
typedef map <string, nullableUint32 >::iterator uint32_Iter;
typedef pair <INVAL_TYPE, char *> nullableBytePtr;
typedef map <string, nullableBytePtr >::iterator byteptr_Iter;
typedef pair <INVAL_TYPE, int32_t> nullableInt32;
typedef map <string, nullableInt32 >::iterator int32_Iter;
typedef pair <INVAL_TYPE, string> nullableString;
@ -166,7 +168,7 @@ namespace DFHack
class OffsetGroupPrivate
{
public:
map <string, nullableUint32 > addresses;
map <string, nullableBytePtr > addresses;
map <string, nullableUint32 > hexvals;
map <string, nullableInt32 > offsets;
map <string, nullableString > strings;
@ -183,7 +185,7 @@ void OffsetGroup::createOffset(const string & key)
void OffsetGroup::createAddress(const string & key)
{
OGd->addresses[key] = nullableUint32(NOT_SET, 0);
OGd->addresses[key] = nullableBytePtr(NOT_SET, (char*) 0);
}
void OffsetGroup::createHexValue(const string & key)
@ -227,10 +229,10 @@ void OffsetGroup::setOffsetValidity (const string & key, const INVAL_TYPE inval)
void OffsetGroup::setAddress (const string & key, const string & value, const INVAL_TYPE inval)
{
uint32_Iter it = OGd->addresses.find(key);
byteptr_Iter it = OGd->addresses.find(key);
if(it != OGd->addresses.end())
{
uint32_t address = strtol(value.c_str(), NULL, 16);
char * address = (char *) strtol(value.c_str(), NULL, 16);
if((*it).second.second == address)
std::cout << "Pointless address setting: " << this->getFullName() + key << endl;
(*it).second.second = address;
@ -244,7 +246,7 @@ void OffsetGroup::setAddressValidity (const string & key, const INVAL_TYPE inval
{
if(inval != NOT_SET)
{
uint32_Iter it = OGd->addresses.find(key);
byteptr_Iter it = OGd->addresses.find(key);
if(it != OGd->addresses.end())
{
(*it).second.first = inval;
@ -305,9 +307,9 @@ void OffsetGroup::setStringValidity (const string & key, const INVAL_TYPE inval)
}
// Get named address
uint32_t OffsetGroup::getAddress (const string & key)
char * OffsetGroup::getAddress (const string & key)
{
uint32_Iter iter = OGd->addresses.find(key);
byteptr_Iter iter = OGd->addresses.find(key);
if(iter != OGd->addresses.end())
{
@ -321,9 +323,9 @@ uint32_t OffsetGroup::getAddress (const string & key)
}
// Get named offset, return bool instead of throwing exceptions
bool OffsetGroup::getSafeAddress (const string & key, uint32_t & out)
bool OffsetGroup::getSafeAddress (const string & key, void * & out)
{
uint32_Iter iter = OGd->addresses.find(key);
byteptr_Iter iter = OGd->addresses.find(key);
if(iter != OGd->addresses.end() && (*iter).second.first == IS_VALID)
{
out = (*iter).second.second;
@ -410,7 +412,7 @@ OffsetGroup * OffsetGroup::createGroup(const std::string &name)
void OffsetGroup::RebaseAddresses(int32_t offset)
{
for(uint32_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
for(byteptr_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
{
if(iter->second.first)
OGd->addresses[iter->first].second = iter->second.second + offset;
@ -470,18 +472,19 @@ std::string OffsetGroup::getFullName()
std::string OffsetGroup::PrintOffsets(int indentation)
{
byteptr_Iter addriter;
uint32_Iter iter;
ostringstream ss;
indentr i(indentation);
typedef pair <uint32_t, pair< string, nullableUint32 > > horrible;
typedef pair <void *, pair< string, nullableBytePtr > > horrible;
vector < horrible > addrsorter;
for(iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
for(addriter = OGd->addresses.begin(); addriter != OGd->addresses.end(); addriter++)
{
if(!(*iter).second.first)
addrsorter.push_back( make_pair( 0, *iter ) );
if(!(*addriter).second.first)
addrsorter.push_back( make_pair( (void *)0, *addriter ) );
else
{
addrsorter.push_back( make_pair( (*iter).second.second, *iter ) );
addrsorter.push_back( make_pair( (*addriter).second.second, *addriter ) );
}
}
std::sort(addrsorter.begin(), addrsorter.end(), compare_pair_first<>());
@ -569,7 +572,7 @@ void OffsetGroup::setInvalid(INVAL_TYPE invalidity)
if(invalidity == NOT_SET)
return;
uint32_Iter iter;
byteptr_Iter iter;
for(iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
{
if((*iter).second.first)
@ -581,17 +584,18 @@ void OffsetGroup::setInvalid(INVAL_TYPE invalidity)
if((*iter2).second.first)
(*iter2).second.first = invalidity;
}
for(iter = OGd->hexvals.begin(); iter != OGd->hexvals.end(); iter++)
{
if((*iter).second.first)
(*iter).second.first = invalidity;
}
strings_Iter iter3;
for(iter3 = OGd->strings.begin(); iter3 != OGd->strings.end(); iter3++)
uint32_Iter iter3;
for(iter3 = OGd->hexvals.begin(); iter3 != OGd->hexvals.end(); iter3++)
{
if((*iter3).second.first)
(*iter3).second.first = invalidity;
}
strings_Iter iter5;
for(iter5 = OGd->strings.begin(); iter5 != OGd->strings.end(); iter5++)
{
if((*iter5).second.first)
(*iter5).second.first = invalidity;
}
groups_Iter iter4;
for(iter4 = OGd->groups.begin(); iter4 != OGd->groups.end(); iter4++)
{
@ -603,7 +607,7 @@ std::vector<OffsetKey> OffsetGroup::getKeys() const
std::vector<OffsetKey> ret;
OffsetKey K;
K.keytype=IS_ADDRESS;
for(uint32_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
for(byteptr_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
{
K.key=iter->first;
K.inval=iter->second.first;
@ -1015,7 +1019,7 @@ void VersionInfo::setClassChild (t_class * parent, const char * name, const char
// FIXME: This in now DEPRECATED!
bool VersionInfo::resolveObjectToClassID(const uint32_t address, int32_t & classid)
bool VersionInfo::resolveObjectToClassID(const char * address, int32_t & classid)
{
uint32_t vtable = d->p->readDWord(address);
// try to find the vtable in our cache
@ -1205,7 +1209,7 @@ string VersionInfo::getTrait (const uint32_t traitIdx, const uint32_t traitValue
if(d->traits.size() > traitIdx)
{
int diff = absolute(traitValue-50);
if(diff < 10)
if(diff <= 10)
{
return string("");
}
@ -1294,4 +1298,4 @@ std::string VersionInfo::PrintOffsets()
ss << i << "</Version>" << endl;
ss << endl;
return ss.str();
}
}

@ -31,9 +31,9 @@ distribution.
#include <iostream>
using namespace std;
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Error.h"
#include "VersionInfoFactory.h"
#include "VersionInfo.h"
#include "Error.h"
using namespace DFHack;
#include <tinyxml.h>

@ -4,9 +4,9 @@
#include <vector>
#include <map>
#include "dfhack/Process.h"
#include "dfhack/Core.h"
#include "dfhack/Virtual.h"
#include "MemAccess.h"
#include "Core.h"
#include "Virtual.h"
using namespace DFHack;
std::string t_virtual::getClassName() const

@ -23,8 +23,8 @@ distribution.
*/
#pragma once
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "Pragma.h"
#include "Export.h"
#include <stdint.h>
#include <string.h>
#include <sstream>

@ -23,8 +23,8 @@ distribution.
*/
#pragma once
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "Pragma.h"
#include "Export.h"
#include <deque>
#include <fstream>
#include <assert.h>

@ -24,15 +24,15 @@ distribution.
#pragma once
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "dfhack/FakeSDL.h"
#include "Pragma.h"
#include "Export.h"
#include "Hooks.h"
#include <vector>
#include <stack>
#include <map>
#include <stdint.h>
#include "dfhack/Console.h"
#include "dfhack/modules/Graphic.h"
#include "Console.h"
#include "modules/Graphic.h"
struct WINDOW;
@ -43,6 +43,11 @@ namespace tthread
class thread;
}
namespace df
{
struct viewscreen;
}
namespace DFHack
{
class Process;
@ -134,6 +139,13 @@ namespace DFHack
/// returns a named pointer.
void *GetData(std::string key);
bool ClearKeyBindings(std::string keyspec);
bool AddKeyBinding(std::string keyspec, std::string cmdline);
std::vector<std::string> ListKeyBindings(std::string keyspec);
bool isWorldLoaded() { return (last_world_data_ptr != NULL); }
df::viewscreen *getTopViewscreen() { return top_viewscreen; }
DFHack::Process * p;
DFHack::VersionInfo * vinfo;
DFHack::Console con;
@ -178,12 +190,25 @@ namespace DFHack
} s_mods;
std::vector <Module *> allModules;
DFHack::PluginManager * plug_mgr;
// hotkey-related stuff
int hotkey_states[16];
struct KeyBinding {
int modifiers;
std::vector<std::string> command;
std::string cmdline;
};
std::map<int, std::vector<KeyBinding> > key_bindings;
std::map<int, bool> hotkey_states;
std::string hotkey_cmd;
bool hotkey_set;
tthread::mutex * HotkeyMutex;
tthread::condition_variable * HotkeyCond;
bool SelectHotkey(int key, int modifiers);
void *last_world_data_ptr; // for state change tracking
df::viewscreen *top_viewscreen;
// Very important!
bool started;

@ -47,34 +47,34 @@ distribution.
#include <stdint.h>
// DFHack core classes and types
#include "dfhack/Error.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include "dfhack/Types.h"
#include "Error.h"
#include "VersionInfo.h"
#include "MemAccess.h"
#include "Types.h"
// DFHack modules
#include "dfhack/modules/Buildings.h"
#include "dfhack/modules/Engravings.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/modules/Constructions.h"
#include "dfhack/modules/Units.h"
#include "dfhack/modules/Translation.h"
#include "dfhack/modules/World.h"
#include "dfhack/modules/Items.h"
#include "dfhack/modules/Vegetation.h"
#include "dfhack/modules/Maps.h"
#include "dfhack/modules/Gui.h"
#include "modules/Buildings.h"
#include "modules/Engravings.h"
#include "modules/Materials.h"
#include "modules/Constructions.h"
#include "modules/Units.h"
#include "modules/Translation.h"
#include "modules/World.h"
#include "modules/Items.h"
#include "modules/Vegetation.h"
#include "modules/Maps.h"
#include "modules/Gui.h"
/*
* This is a header full of ugly, volatile things.
* Only for use of official DFHack tools!
*/
#ifdef DFHACK_WANT_MISCUTILS
#include "dfhack/MiscUtils.h"
#include "MiscUtils.h"
#endif
// define this to get the static tiletype->properties mapping
#ifdef DFHACK_WANT_TILETYPES
#include "dfhack/TileTypes.h"
#include "TileTypes.h"
#endif
#endif

@ -28,8 +28,8 @@ distribution.
#include <vector>
#include <map>
#include "dfhack/Core.h"
#include "dfhack/BitArray.h"
#include "Core.h"
#include "BitArray.h"
// Stop some MS stupidity
#ifdef interface
@ -62,8 +62,6 @@ namespace DFHack
protected:
virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent);
bool check_instance(virtual_ptr instance_ptr, bool allow_subclasses);
static void *get_vtable(virtual_ptr instance_ptr) { return *(void**)instance_ptr; }
public:
@ -73,8 +71,10 @@ namespace DFHack
virtual_identity *getParent() { return parent; }
const std::vector<virtual_identity*> &getChildren() { return children; }
public:
static virtual_identity *get(virtual_ptr instance_ptr);
bool is_subclass(virtual_identity *subtype);
bool is_instance(virtual_ptr instance_ptr) {
if (!instance_ptr) return false;
if (vtable_ptr) {
@ -82,16 +82,28 @@ namespace DFHack
if (vtable == vtable_ptr) return true;
if (!has_children) return false;
}
return check_instance(instance_ptr, true);
return is_subclass(get(instance_ptr));
}
bool is_direct_instance(virtual_ptr instance_ptr) {
if (!instance_ptr) return false;
return vtable_ptr ? (vtable_ptr == get_vtable(instance_ptr))
: check_instance(instance_ptr, false);
: (this == get(instance_ptr));
}
static void Init();
public:
bool can_instantiate() { return (vtable_ptr != NULL); }
virtual_ptr instantiate() { return can_instantiate() ? do_instantiate() : NULL; }
static virtual_ptr clone(virtual_ptr obj);
protected:
virtual virtual_ptr do_instantiate() = 0;
virtual void do_copy(virtual_ptr tgt, virtual_ptr src) = 0;
public:
static void Init(Core *core);
// Strictly for use in virtual class constructors
void adjust_vtable(virtual_ptr obj, virtual_identity *main);
};
template<class T>
@ -99,27 +111,59 @@ namespace DFHack
return T::_identity.is_instance(ptr) ? static_cast<T*>(ptr) : NULL;
}
#define VIRTUAL_CAST_VAR(var,type,input) type *var = virtual_cast<type>(input)
template<class T>
inline T *strict_virtual_cast(virtual_ptr ptr) {
return T::_identity.is_direct_instance(ptr) ? static_cast<T*>(ptr) : NULL;
}
#define STRICT_VIRTUAL_CAST_VAR(var,type,input) type *var = strict_virtual_cast<type>(input)
void InitDataDefGlobals(Core *core);
template<class T>
T *ifnull(T *a, T *b) { return a ? a : b; }
template<class T, T start, bool (*isvalid)(T)>
inline T next_enum_item_(T v) {
v = T(int(v) + 1);
return isvalid(v) ? v : start;
}
struct bitfield_item_info {
const char *name;
int size;
};
DFHACK_EXPORT std::string bitfieldToString(const void *p, int size, const bitfield_item_info *items);
template<class T>
inline std::string bitfieldToString(const T &val) {
return bitfieldToString(&val.whole, sizeof(val.whole), val.get_items());
}
}
namespace df
{
using DFHack::virtual_ptr;
using DFHack::virtual_identity;
using DFHack::virtual_class;
using DFHack::bitfield_item_info;
using DFHack::BitArray;
template<class T>
class class_virtual_identity : public DFHack::virtual_identity {
class class_virtual_identity : public virtual_identity {
public:
class_virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent)
: virtual_identity(dfhack_name, original_name, parent) {};
T *instantiate() { return static_cast<T*>(virtual_identity::instantiate()); }
T *clone(T* obj) { return static_cast<T*>(virtual_identity::clone(obj)); }
protected:
virtual virtual_ptr do_instantiate() { return new T(); }
virtual void do_copy(virtual_ptr tgt, virtual_ptr src) { *static_cast<T*>(tgt) = *static_cast<T*>(src); }
};
template<class EnumType, class IntType = int32_t>
@ -146,17 +190,33 @@ namespace df
#define ENUM_FIRST_ITEM(enum) (df::enums::enum::_first_item_of_##enum)
#define ENUM_LAST_ITEM(enum) (df::enums::enum::_last_item_of_##enum)
#define ENUM_NEXT_ITEM(enum,val) \
(DFHack::next_enum_item_<df::enum,ENUM_FIRST_ITEM(enum),df::enums::enum::is_valid>(val))
#define FOR_ENUM_ITEMS(enum,iter) \
for(df::enum iter = ENUM_FIRST_ITEM(enum); iter < ENUM_LAST_ITEM(enum); iter = df::enum(1+int(iter)))
namespace df {
#define DF_KNOWN_GLOBALS \
GLOBAL(cursor,cursor) \
GLOBAL(selection_rect,selection_rect) \
GLOBAL(world,world) \
GLOBAL(ui,ui) \
GLOBAL(gview,interface) \
GLOBAL(init,init) \
GLOBAL(d_init,d_init)
#define GLOBAL(name,tname) \
struct tname; \
GLOBAL(d_init,d_init) \
SIMPLE_GLOBAL(job_next_id,int) \
SIMPLE_GLOBAL(ui_look_cursor,int) \
SIMPLE_GLOBAL(ui_workshop_job_cursor,int) \
SIMPLE_GLOBAL(ui_workshop_in_add,bool) \
GLOBAL(ui_sidebar_menus,ui_sidebar_menus) \
GLOBAL(ui_build_selector,ui_build_selector) \
GLOBAL(ui_look_list,ui_look_list)
#define SIMPLE_GLOBAL(name,tname) \
namespace global { extern DFHACK_EXPORT tname *name; }
#define GLOBAL(name,tname) \
struct tname; SIMPLE_GLOBAL(name,tname)
DF_KNOWN_GLOBALS
#undef GLOBAL
#undef SIMPLE_GLOBAL
}

@ -27,8 +27,8 @@ distribution.
#ifndef ERROR_H_INCLUDED
#define ERROR_H_INCLUDED
#include "dfhack/Export.h"
#include "dfhack/Pragma.h"
#include "Export.h"
#include "Pragma.h"
#include <string>
#include <sstream>
#include <exception>

@ -28,39 +28,20 @@ distribution.
* Some much needed SDL fakery.
*/
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "Pragma.h"
#include "Export.h"
#include <string>
#include <stdint.h>
// function and variable pointer... we don't try to understand what SDL does here
typedef void * fPtr;
typedef void * vPtr;
struct WINDOW;
namespace SDL
{
union Event;
//struct Thread;
//struct Mutex;
//struct Cond;
//struct Library;
}
/*
// mutex stuff
DFhackCExport SDL::Mutex * SDL_CreateMutex(void);
DFhackCExport int SDL_mutexP(SDL::Mutex *);
DFhackCExport int SDL_mutexV(SDL::Mutex *);
DFhackCExport void SDL_DestroyMutex(SDL::Mutex *);
// thread stuff
DFhackCExport SDL::Thread *SDL_CreateThread(int (*fn)(void *), void *data);
DFhackCExport uint32_t SDL_ThreadID();
// condition variables
DFhackCExport SDL::Cond *SDL_CreateCond(void);
DFhackCExport void SDL_DestroyCond(SDL::Cond *cond);
DFhackCExport int SDL_CondSignal(SDL::Cond *cond);
DFhackCExport int SDL_CondWait(SDL::Cond *cond, SDL::Mutex * mut);
*/
// these functions are here because they call into DFHack::Core and therefore need to
// be declared as friend functions/known
DFhackCExport int SDL_NumJoysticks(void);
@ -69,4 +50,3 @@ DFhackCExport int SDL_PollEvent(SDL::Event* event);
DFhackCExport int SDL_Init(uint32_t flags);
DFhackCExport int wgetch(WINDOW * win);
// Other crud is in the OS-specific core files.

@ -24,9 +24,6 @@ distribution.
#pragma once
#ifndef DFCOMMONINTERNAL_H_INCLUDED
#define DFCOMMONINTERNAL_H_INCLUDED
// this makes everything that includes this file export symbols when using DFHACK_EXPORT (see DFExport.h)
#ifndef BUILD_DFHACK_LIB
#define BUILD_DFHACK_LIB
@ -38,10 +35,7 @@ distribution.
#endif
// one file for telling the MSVC compiler where it can shove its pointless warnings
#include "dfhack/Pragma.h"
#include "Pragma.h"
// C99 integer types
#include <stdint.h>
#endif // DFCOMMONINTERNAL_H_INCLUDED

@ -28,8 +28,8 @@ distribution.
#ifndef PROCESS_H_INCLUDED
#define PROCESS_H_INCLUDED
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "Pragma.h"
#include "Export.h"
#include <iostream>
#include <cstring>
#include <map>
@ -72,8 +72,8 @@ namespace DFHack
*/
struct DFHACK_EXPORT t_memrange
{
uint64_t start;
uint64_t end;
void * start;
void * end;
// memory range name (if any)
char name[1024];
// permission to read
@ -84,7 +84,7 @@ namespace DFHack
bool execute : 1;
// is a shared region
bool shared : 1;
inline bool isInRange( uint64_t address)
inline bool isInRange( void * address)
{
if (address >= start && address < end) return true;
return false;
@ -104,99 +104,110 @@ namespace DFHack
Process(VersionInfoFactory * known_versions);
~Process();
/// read a 8-byte integer
uint64_t readQuad(const uint32_t address)
uint64_t readQuad(const void * address)
{
return *(uint64_t *)address;
}
/// read a 8-byte integer
void readQuad(const uint32_t address, uint64_t & value)
void readQuad(const void * address, uint64_t & value)
{
value = *(uint64_t *)address;
};
/// write a 8-byte integer
void writeQuad(const uint32_t address, const uint64_t value)
void writeQuad(const void * address, const uint64_t value)
{
(*(uint64_t *)address) = value;
};
/// read a 4-byte integer
uint32_t readDWord(const uint32_t address)
uint32_t readDWord(const void * address)
{
return *(uint32_t *)address;
}
/// read a 4-byte integer
void readDWord(const uint32_t address, uint32_t & value)
void readDWord(const void * address, uint32_t & value)
{
value = *(uint32_t *)address;
};
/// write a 4-byte integer
void writeDWord(const uint32_t address, const uint32_t value)
void writeDWord(const void * address, const uint32_t value)
{
(*(uint32_t *)address) = value;
};
/// read a pointer
char * readPtr(const void * address)
{
return *(char **)address;
}
/// read a pointer
void readPtr(const void * address, char * & value)
{
value = *(char **)address;
};
/// read a float
float readFloat(const uint32_t address)
float readFloat(const void * address)
{
return *(float*)address;
}
/// write a float
void readFloat(const uint32_t address, float & value)
void readFloat(const void * address, float & value)
{
value = *(float*)address;
};
/// read a 2-byte integer
uint16_t readWord(const uint32_t address)
uint16_t readWord(const void * address)
{
return *(uint16_t *)address;
}
/// read a 2-byte integer
void readWord(const uint32_t address, uint16_t & value)
void readWord(const void * address, uint16_t & value)
{
value = *(uint16_t *)address;
};
/// write a 2-byte integer
void writeWord(const uint32_t address, const uint16_t value)
void writeWord(const void * address, const uint16_t value)
{
(*(uint16_t *)address) = value;
};
/// read a byte
uint8_t readByte(const uint32_t address)
uint8_t readByte(const void * address)
{
return *(uint8_t *)address;
}
/// read a byte
void readByte(const uint32_t address, uint8_t & value)
void readByte(const void * address, uint8_t & value)
{
value = *(uint8_t *)address;
};
/// write a byte
void writeByte(const uint32_t address, const uint8_t value)
void writeByte(const void * address, const uint8_t value)
{
(*(uint8_t *)address) = value;
};
/// read an arbitrary amount of bytes
void read( uint32_t address, uint32_t length, uint8_t* buffer)
void read(void * address, uint32_t length, uint8_t* buffer)
{
memcpy(buffer, (void *) address, length);
};
/// write an arbitrary amount of bytes
void write(uint32_t address, uint32_t length, uint8_t* buffer)
void write(void * address, uint32_t length, uint8_t* buffer)
{
memcpy((void *) address, buffer, length);
};
/// read an STL string
const std::string readSTLString (uint32_t offset)
const std::string readSTLString (void * offset)
{
std::string * str = (std::string *) offset;
return *str;
};
/// read an STL string
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
size_t readSTLString (void * offset, char * buffer, size_t bufcapacity)
{
if(!bufcapacity || bufcapacity == 1)
return 0;
@ -209,7 +220,7 @@ namespace DFHack
* write an STL string
* @return length written
*/
size_t writeSTLString(const uint32_t address, const std::string writeString)
size_t writeSTLString(const void * address, const std::string writeString)
{
std::string * str = (std::string *) address;
str->assign(writeString);
@ -219,7 +230,7 @@ namespace DFHack
* attempt to copy a string from source address to target address. may truncate or leak, depending on platform
* @return length copied
*/
size_t copySTLString(const uint32_t address, const uint32_t target)
size_t copySTLString(const void * address, const uint32_t target)
{
std::string * strsrc = (std::string *) address;
std::string * str = (std::string *) target;
@ -239,7 +250,7 @@ namespace DFHack
}
/// read a null-terminated C string
const std::string readCString (uint32_t offset)
const std::string readCString (void * offset)
{
return std::string((char *) offset);
};

@ -0,0 +1,228 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#include "Export.h"
#include <iostream>
#include <iomanip>
#include <climits>
#include <stdint.h>
#include <vector>
#include <sstream>
#include <cstdio>
using namespace std;
template <typename T>
void print_bits ( T val, DFHack::Console& out )
{
stringstream strs;
T n_bits = sizeof ( val ) * CHAR_BIT;
int cnt;
for ( unsigned i = 0; i < n_bits; ++i )
{
cnt = i/10;
strs << cnt << " ";
}
strs << endl;
for ( unsigned i = 0; i < n_bits; ++i )
{
cnt = i%10;
strs << cnt << " ";
}
strs << endl;
for ( unsigned i = 0; i < n_bits; ++i )
{
strs << "--";
}
strs << endl;
for ( unsigned i = 0; i < n_bits; ++i )
{
strs<< !!( val & 1 ) << " ";
val >>= 1;
}
strs << endl;
out.print(strs.str().c_str());
}
/*
* Binary search in vectors.
*/
template <typename FT>
int linear_index(const std::vector<FT> &vec, FT key)
{
for (unsigned i = 0; i < vec.size(); i++)
if (vec[i] == key)
return i;
return -1;
}
template <typename FT>
int linear_index(const std::vector<FT*> &vec, const FT &key)
{
for (unsigned i = 0; i < vec.size(); i++)
if (vec[i] && *vec[i] == key)
return i;
return -1;
}
template <typename FT>
int binsearch_index(const std::vector<FT> &vec, FT key, bool exact = true)
{
// Returns the index of the value >= the key
int min = -1, max = (int)vec.size();
const FT *p = vec.data();
for (;;)
{
int mid = (min + max)>>1;
if (mid == min)
return exact ? -1 : max;
FT midv = p[mid];
if (midv == key)
return mid;
else if (midv < key)
min = mid;
else
max = mid;
}
}
template <typename CT, typename FT>
int linear_index(const std::vector<CT*> &vec, FT CT::*field, FT key)
{
for (unsigned i = 0; i < vec.size(); i++)
if (vec[i]->*field == key)
return i;
return -1;
}
template <typename CT, typename FT>
int binsearch_index(const std::vector<CT*> &vec, FT CT::*field, FT key, bool exact = true)
{
// Returns the index of the value >= the key
int min = -1, max = (int)vec.size();
CT *const *p = vec.data();
for (;;)
{
int mid = (min + max)>>1;
if (mid == min)
return exact ? -1 : max;
FT midv = p[mid]->*field;
if (midv == key)
return mid;
else if (midv < key)
min = mid;
else
max = mid;
}
}
template <typename CT>
inline int binsearch_index(const std::vector<CT*> &vec, typename CT::key_field_type key, bool exact = true)
{
return CT::binsearch_index(vec, key, exact);
}
template <typename CT>
inline int binsearch_index(const std::vector<CT*> &vec, typename CT::key_pointer_type key, bool exact = true)
{
return CT::binsearch_index(vec, key, exact);
}
template<typename FT, typename KT>
inline bool vector_contains(const std::vector<FT> &vec, KT key)
{
return binsearch_index(vec, key) >= 0;
}
template<typename CT, typename FT>
inline bool vector_contains(const std::vector<CT*> &vec, FT CT::*field, FT key)
{
return binsearch_index(vec, field, key) >= 0;
}
template<typename FT>
unsigned insert_into_vector(std::vector<FT> &vec, FT key, bool *inserted = NULL)
{
unsigned pos = (unsigned)binsearch_index(vec, key, false);
bool to_ins = (pos >= vec.size() || vec[pos] != key);
if (inserted) *inserted = to_ins;
if (to_ins)
vec.insert(vec.begin()+pos,key);
return pos;
}
template<typename CT, typename FT>
unsigned insert_into_vector(std::vector<CT*> &vec, FT CT::*field, CT *obj, bool *inserted = NULL)
{
unsigned pos = (unsigned)binsearch_index(vec, field, obj->*field, false);
bool to_ins = (pos >= vec.size() || vec[pos] != obj);
if (inserted) *inserted = to_ins;
if (to_ins)
vec.insert(vec.begin()+pos,obj);
return pos;
}
template <typename CT, typename KT>
CT *binsearch_in_vector(const std::vector<CT*> &vec, KT value)
{
int idx = binsearch_index(vec, value);
return idx < 0 ? NULL : vec[idx];
}
template <typename CT, typename FT>
CT *binsearch_in_vector(const std::vector<CT*> &vec, FT CT::*field, FT value)
{
int idx = binsearch_index(vec, field, value);
return idx < 0 ? NULL : vec[idx];
}
/*
* List
*/
template<typename Link>
Link *linked_list_append(Link *head, Link *tail)
{
while (head->next)
head = head->next;
head->next = tail;
tail->prev = head;
return tail;
}
/*
* MISC
*/
/**
* Returns the amount of milliseconds elapsed since the UNIX epoch.
* Works on both windows and linux.
* source: http://stackoverflow.com/questions/1861294/how-to-calculate-execution-time-of-a-code-snippet-in-c
*/
DFHACK_EXPORT uint64_t GetTimeMs64();
DFHACK_EXPORT std::string stl_sprintf(const char *fmt, ...);
DFHACK_EXPORT std::string stl_vsprintf(const char *fmt, va_list args);

@ -27,7 +27,7 @@ distribution.
#ifndef MODULE_H_INCLUDED
#define MODULE_H_INCLUDED
#include "dfhack/Export.h"
#include "Export.h"
namespace DFHack
{
/**

@ -24,55 +24,80 @@ distribution.
#pragma once
#include "dfhack/Export.h"
#include "Export.h"
#include "Hooks.h"
#include <map>
#include <string>
#include <vector>
#include "FakeSDL.h"
struct DFLibrary;
namespace tthread
{
class mutex;
class condition_variable;
}
namespace df
{
struct viewscreen;
}
namespace DFHack
{
class Core;
class PluginManager;
struct virtual_identity;
enum command_result
{
CR_WOULD_BREAK = -2,
CR_NOT_IMPLEMENTED = -1,
CR_FAILURE = 0,
CR_OK = 1
CR_OK = 1,
CR_WRONG_USAGE = 2
};
struct PluginCommand
enum state_change_event
{
SC_GAME_LOADED,
SC_GAME_UNLOADED,
SC_VIEWSCREEN_CHANGED
};
struct DFHACK_EXPORT PluginCommand
{
typedef command_result (*command_function)(Core *, std::vector <std::string> &);
typedef bool (*command_hotkey_guard)(Core *, df::viewscreen *);
/// create a command with a name, description, function pointer to its code
/// and saying if it needs an interactive terminal
/// Most commands shouldn't require an interactive terminal!
PluginCommand(const char * _name,
const char * _description,
command_result (*function_)(Core *, std::vector <std::string> &),
bool interactive_ = false
command_function function_,
bool interactive_ = false,
const char * usage_ = ""
)
: name(_name), description(_description),
function(function_), interactive(interactive_),
guard(NULL), usage(usage_)
{
name = _name;
description = _description;
function = function_;
interactive = interactive_;
}
PluginCommand (const PluginCommand & rhs)
PluginCommand(const char * _name,
const char * _description,
command_function function_,
command_hotkey_guard guard_,
const char * usage_ = "")
: name(_name), description(_description),
function(function_), interactive(false),
guard(guard_), usage(usage_)
{
name = rhs.name;
description = rhs.description;
function = rhs.function;
interactive = rhs.interactive;
}
bool isHotkeyCommand() const { return guard != NULL; }
std::string name;
std::string description;
command_result (*function)(Core *, std::vector <std::string> &);
command_function function;
bool interactive;
command_hotkey_guard guard;
std::string usage;
};
class Plugin
{
@ -87,11 +112,13 @@ namespace DFHack
Plugin(DFHack::Core* core, const std::string& filepath, const std::string& filename, PluginManager * pm);
~Plugin();
command_result on_update();
command_result on_state_change(state_change_event event);
public:
bool load();
bool unload();
bool reload();
command_result invoke( std::string & command, std::vector <std::string> & parameters, bool interactive );
bool can_invoke_hotkey( std::string & command, df::viewscreen *top );
plugin_state getState () const;
const PluginCommand& operator[] (std::size_t index) const
{
@ -117,6 +144,7 @@ namespace DFHack
command_result (*plugin_status)(Core *, std::string &);
command_result (*plugin_shutdown)(Core *);
command_result (*plugin_onupdate)(Core *);
command_result (*plugin_onstatechange)(Core *, state_change_event);
};
class DFHACK_EXPORT PluginManager
{
@ -126,12 +154,15 @@ namespace DFHack
PluginManager(Core * core);
~PluginManager();
void OnUpdate( void );
void OnStateChange( state_change_event event );
void registerCommands( Plugin * p );
void unregisterCommands( Plugin * p );
// PUBLIC METHODS
public:
Plugin *getPluginByName (const std::string & name);
Plugin *getPluginByCommand (const std::string &command);
command_result InvokeCommand( std::string & command, std::vector <std::string> & parameters, bool interactive = true );
bool CanInvokeHotkey(std::string &command, df::viewscreen *top);
Plugin* operator[] (std::size_t index)
{
if(index >= all_plugins.size())
@ -149,5 +180,10 @@ namespace DFHack
std::vector <Plugin *> all_plugins;
std::string plugin_path;
};
// Predefined hotkey guards
DFHACK_EXPORT bool default_hotkey(Core *, df::viewscreen *);
DFHACK_EXPORT bool dwarfmode_hotkey(Core *, df::viewscreen *);
DFHACK_EXPORT bool cursor_hotkey(Core *, df::viewscreen *);
}

@ -24,7 +24,7 @@
// Needed for processing its event types without polluting our namespaces with C garbage
#pragma once
#include "keyboard.h"
#include "SDL_keyboard.h"
namespace SDL
{

@ -24,7 +24,7 @@
// Needed for processing its event types without polluting our namespaces with C garbage
#pragma once
#include "keysym.h"
#include "SDL_keysym.h"
#include <stdint.h>
namespace SDL

@ -27,8 +27,8 @@ distribution.
#ifndef TILETYPES_H_INCLUDED
#define TILETYPES_H_INCLUDED
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "Pragma.h"
#include "Export.h"
namespace DFHack
{

@ -25,8 +25,8 @@ distribution.
#pragma once
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "Pragma.h"
#include "Export.h"
namespace DFHack
{

@ -28,9 +28,9 @@ distribution.
#ifndef MEMINFO_H_INCLUDED
#define MEMINFO_H_INCLUDED
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "dfhack/Types.h"
#include "Pragma.h"
#include "Export.h"
#include "Types.h"
#include <map>
#include <sys/types.h>
#include <vector>
@ -88,13 +88,13 @@ namespace DFHack
OffsetGroup * createGroup ( const std::string & name );
int32_t getOffset (const std::string & key);
uint32_t getAddress (const std::string & key);
char * getAddress (const std::string & key);
uint32_t getHexValue (const std::string & key);
std::string getString (const std::string & key);
OffsetGroup * getGroup ( const std::string & name );
bool getSafeOffset (const std::string & key, int32_t & out);
bool getSafeAddress (const std::string & key, uint32_t & out);
bool getSafeAddress (const std::string & key, void * & out);
void setOffset (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID);
void setOffsetValidity(const std::string& key, const DFHack::INVAL_TYPE inval = IS_VALID);
@ -189,7 +189,7 @@ namespace DFHack
* uses memory reading directly, needs suspend. input = address of the object
* fails if it's unable to read from memory
*/
bool resolveObjectToClassID (const uint32_t address, int32_t & classID);
bool resolveObjectToClassID (const char * address, int32_t & classID);
/**
* Get a ClassID when you know the classname. can fail if the class is not in the cache

@ -28,8 +28,8 @@ distribution.
#ifndef MEMINFO_MANAGER_H_INCLUDED
#define MEMINFO_MANAGER_H_INCLUDED
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "Pragma.h"
#include "Export.h"
class TiXmlElement;
namespace DFHack

@ -1,269 +0,0 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#include <iostream>
#include <iomanip>
#include <climits>
#include <stdint.h>
#include <vector>
#include <sstream>
#include <ctime>
#include <cstdio>
using namespace std;
/*
#include <dfhack/Process.h>
#include <dfhack/VersionInfo.h>
#include <dfhack/Vector.h>
void DumpObjStr0Vector (const char * name, DFHack::Process *p, uint32_t addr)
{
cout << "----==== " << name << " ====----" << endl;
DFHack::DfVector <uint32_t> vect(p,addr);
for(uint32_t i = 0; i < vect.size();i++)
{
uint32_t addr = vect[i];
cout << p->readSTLString(addr) << endl;
}
cout << endl;
}
void DumpObjVtables (const char * name, DFHack::Process *p, uint32_t addr)
{
cout << "----==== " << name << " ====----" << endl;
DFHack::DfVector <uint32_t> vect(p,addr);
for(uint32_t i = 0; i < vect.size();i++)
{
uint32_t addr = vect[i];
uint32_t vptr = p->readDWord(addr);
cout << p->readClassName(vptr) << endl;
}
cout << endl;
}
void DumpDWordVector (const char * name, DFHack::Process *p, uint32_t addr)
{
cout << "----==== " << name << " ====----" << endl;
DFHack::DfVector <uint32_t> vect(p,addr);
for(uint32_t i = 0; i < vect.size();i++)
{
uint32_t number = vect[i];
cout << number << endl;
}
cout << endl;
}
*/
/*
address = absolute address of dump start
length = length in lines. 1 line = 16 bytes
*/
/*
void hexdump (DFHack::Context *DF, uint32_t address, uint32_t length)
{
char *buf = new char[length];
DF->ReadRaw(address, length, (uint8_t *) buf);
uint32_t i = 0;
while (i < length)
{
// leading offset
if(i%16 == 0)
cout << "0x" << hex << setw(8) << address + i << "| ";
// bytes
for(int k = 0; k < 4; k++)
{
cout << hex << setw(2) << int(static_cast<unsigned char>(buf[i])) << " ";
i++;
if(i == length) break;
}
if(i%16 == 0 || i>= length)
{
cout << endl;
}
else if(i%4 == 0)
{
cout << " ";
}
}
delete buf;
}
void interleave_hex (DFHack::Context* DF, vector < uint32_t > & addresses, uint32_t length)
{
vector <char * > bufs;
for(uint32_t counter = 0; counter < addresses.size(); counter ++)
{
char * buf = new char[length * 16];
DF->ReadRaw(addresses[counter], length * 16, (uint8_t *) buf);
bufs.push_back(buf);
}
cout << setfill('0');
// output a header
cout << "line offset ";
for (uint32_t obj = 0; obj < addresses.size(); obj++)
{
cout << "0x" << hex << setw(9) << addresses[obj] << " ";
}
cout << endl;
for(uint32_t offs = 0 ; offs < length * 16; offs += 4)
{
if((!(offs % 16)) && offs != 0)
{
cout << endl;
}
cout << setfill(' ');
cout << dec << setw(4) << offs/4 << " ";
cout << setfill('0');
cout << "0x" << hex << setw(4) << offs << " ";
for (uint32_t object = 0; object < bufs.size(); object++)
{
// bytes
for(int k = 0; k < 4; k++)
{
uint8_t data = bufs[object][offs + k];
cout << hex << setw(2) << int(static_cast<unsigned char>(data)) << " ";
}
cout << " ";
}
cout << endl;
}
for(uint32_t counter = 0; counter < addresses.size(); counter ++)
{
delete bufs[counter];
}
}
*/
template <typename T>
void print_bits ( T val, DFHack::Console& out )
{
stringstream strs;
T n_bits = sizeof ( val ) * CHAR_BIT;
int cnt;
for ( unsigned i = 0; i < n_bits; ++i )
{
cnt = i/10;
strs << cnt << " ";
}
strs << endl;
for ( unsigned i = 0; i < n_bits; ++i )
{
cnt = i%10;
strs << cnt << " ";
}
strs << endl;
for ( unsigned i = 0; i < n_bits; ++i )
{
strs << "--";
}
strs << endl;
for ( unsigned i = 0; i < n_bits; ++i )
{
strs<< !!( val & 1 ) << " ";
val >>= 1;
}
strs << endl;
out.print(strs.str().c_str());
}
/*
// this is probably completely bogus
std::string PrintSplatterType (int16_t mat1, int32_t mat2, vector<DFHack::t_matgloss> &creature_types)
{
std::string ret;
switch (mat1)
{
case 0:
return "Rock";
case 1:
return "Amber";
case 2:
return "Coral";
case 3:
return "Green Glass";
case 4:
return "Clear Glass";
case 5:
return "Crystal Glass";
case 6:
return "Water";
case 7:
return "Coal";
case 8:
return "Potash";
case 9:
return "Ash";
case 10:
return "Pearlash";
case 11:
return "Lye";
case 12:
return "Mud";
case 13:
return "Vomit";
case 14:
return "Salt";
case 15:
return "Filth";
case 16:
return "Frozen? Filth";
case 18:
return "Grime";
case 0xF2:
return "Very Specific Blood (references a named creature)";
case 0x2A:
case 0x2B:
if(mat2 != -1)
{
ret += creature_types[mat2].id;
ret += " ";
}
ret += "Blood";
return ret;
default:
return "Unknown";
}
}
*/
//FIXME: Error 8 error C4519: default template arguments are only allowed on a class template
template <typename CT, typename FT, typename AT/* = FT*/>
CT *binsearch_in_vector(std::vector<CT*> &vec, FT CT::*field, AT value) {
int min = -1, max = (int)vec.size();
CT **p = vec.data();
FT key = (FT)value;
for (;;) {
int mid = (min + max)>>1;
if (mid == min)
return NULL;
FT midv = p[mid]->*field;
if (midv == key)
return p[mid];
else if (midv < key)
min = mid;
else
max = mid;
}
}

@ -1,96 +0,0 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#ifndef DFVECTOR_H_INCLUDED
#define DFVECTOR_H_INCLUDED
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include <string.h>
#include <vector>
namespace DFHack
{
template <class T>
class DFHACK_EXPORT DfVector
{
private:
std::vector<T> * real_vec;
public:
DfVector(uint32_t address)
{
real_vec = (std::vector<T> *) address;
};
~DfVector()
{
};
// get offset of the specified index
inline const T& operator[] (uint32_t index)
{
// FIXME: vector out of bounds exception
//assert(index < size);
return real_vec->at(index);
};
// get offset of the specified index
inline const T& at (uint32_t index)
{
//assert(index < size);
return real_vec->at(index);
};
// update value at index
bool set(uint32_t index, T value)
{
if (index >= real_vec->size())
return false;
real_vec->at(index) = value;
return true;
}
// remove value
bool remove(uint32_t index)
{
if (index >= real_vec->size())
return false;
// Remove the item
real_vec->erase(real_vec->begin() + index);
return true;
}
// get vector size
inline uint32_t size ()
{
return real_vec->size();
};
// get vector start
inline const T * start ()
{
return real_vec->data();
};
};
}
#endif // DFVECTOR_H_INCLUDED

@ -1,47 +0,0 @@
// Returns the amount of milliseconds elapsed since the UNIX epoch.
// Works on both windows and linux.
// source: http://stackoverflow.com/questions/1861294/how-to-calculate-execution-time-of-a-code-snippet-in-c
#ifndef LINUX_BUILD
#include <Windows.h>
#else
#include <sys/time.h>
#include <ctime>
#endif
#ifdef LINUX_BUILD // Linux
uint64_t GetTimeMs64()
{
struct timeval tv;
gettimeofday(&tv, NULL);
uint64_t ret = tv.tv_usec;
// Convert from micro seconds (10^-6) to milliseconds (10^-3)
ret /= 1000;
// Adds the seconds (10^0) after converting them to milliseconds (10^-3)
ret += (tv.tv_sec * 1000);
return ret;
}
#else // Windows
uint64_t GetTimeMs64()
{
FILETIME ft;
LARGE_INTEGER li;
// Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC)
// and copy it to a LARGE_INTEGER structure.
GetSystemTimeAsFileTime(&ft);
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
uint64_t ret = li.QuadPart;
// Convert from file time to UNIX epoch time.
ret -= 116444736000000000LL;
// From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals
ret /= 10000;
return ret;
}
#endif

@ -1,54 +0,0 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#ifndef TERMUTIL_H
#define TERMUTIL_H
#ifdef LINUX_BUILD
// FIXME: is this ever true?
bool TemporaryTerminal ()
{
return false;
}
#else
#include <windows.h>
#include <stdio.h>
#include <conio.h>
bool TemporaryTerminal ()
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
HANDLE hStdOutput;
hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
if (!GetConsoleScreenBufferInfo(hStdOutput, &csbi))
{
printf("GetConsoleScreenBufferInfo failed: %d\n", GetLastError());
return false;
}
return ((!csbi.dwCursorPosition.X) && (!csbi.dwCursorPosition.Y));
};
#endif // LINUX_BUILD
#endif

@ -29,8 +29,8 @@ distribution.
* \defgroup grp_buildings Building module parts - also includes zones and stockpiles
* @ingroup grp_modules
*/
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "Export.h"
#include "Module.h"
#ifdef __cplusplus
namespace DFHack
@ -42,8 +42,6 @@ namespace DFHack
*/
struct t_building
{
uint32_t origin;
uint32_t vtable;
uint32_t x1;
uint32_t y1;
uint32_t x2;
@ -51,7 +49,8 @@ namespace DFHack
uint32_t z;
t_matglossPair material;
uint32_t type;
// FIXME: not complete, we need building presence bitmaps for stuff like farm plots and stockpiles, orientation (N,E,S,W) and state (open/closed)
int32_t custom_type;
void * origin;
};
#ifdef __cplusplus
@ -70,10 +69,9 @@ namespace DFHack
bool Read (const uint32_t index, t_building & building);
bool Finish();
// read a vector of names
// read mapping from custom_type value to building RAW name
// custom_type of -1 implies ordinary building
bool ReadCustomWorkshopTypes(std::map <uint32_t, std::string> & btypes);
// returns -1 on error, >= 0 for real value
int32_t GetCustomWorkshopType(t_building & building);
private:
struct Private;

@ -28,8 +28,8 @@ distribution.
/*
* DF constructions
*/
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "Export.h"
#include "Module.h"
/**
* \defgroup grp_constructions Construction module parts
@ -74,7 +74,7 @@ namespace DFHack
uint32_t unk6;
/// Address of the read object in DF memory. Added by DFHack.
uint32_t origin;
t_construction * origin;
};
#pragma pack (pop)
class DFContextShared;

@ -28,8 +28,8 @@ distribution.
/*
* DF engravings
*/
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "Export.h"
#include "Module.h"
/**
* \defgroup grp_engraving Engraving module parts
@ -97,7 +97,7 @@ namespace DFHack
struct dfh_engraving
{
t_engraving s;
uint32_t origin;
t_engraving * origin;
};
/**
* The Engravings module - allows reading engravings :D

@ -1,6 +1,6 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
Copyright (c) 2009-2011 Petr Mr<EFBFBD>zek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@ -31,8 +31,8 @@ distribution.
#define CL_MOD_GRAPHIC
#include <stdint.h>
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "Export.h"
#include "Module.h"
namespace DFHack
{

@ -26,10 +26,10 @@ distribution.
#ifndef CL_MOD_GUI
#define CL_MOD_GUI
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/Virtual.h"
#include "dfhack/BitArray.h"
#include "Export.h"
#include "Module.h"
#include "Virtual.h"
#include "BitArray.h"
#include <string>
/**

@ -26,12 +26,12 @@ distribution.
/*
* Items!
*/
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/Types.h"
#include "dfhack/Virtual.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/Process.h"
#include "Export.h"
#include "Module.h"
#include "Types.h"
#include "Virtual.h"
#include "modules/Materials.h"
#include "MemAccess.h"
/**
* \defgroup grp_items Items module and its types
* @ingroup grp_modules

@ -26,8 +26,8 @@ distribution.
#ifndef MAPEXTRAS_H
#define MAPEXTRAS_H
#include "dfhack/modules/Maps.h"
#include "dfhack/TileTypes.h"
#include "modules/Maps.h"
#include "TileTypes.h"
#include <stdint.h>
#include <cstring>
namespace MapExtras

@ -30,12 +30,12 @@ distribution.
#ifndef CL_MOD_MAPS
#define CL_MOD_MAPS
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/modules/Vegetation.h"
#include "Export.h"
#include "Module.h"
#include "modules/Vegetation.h"
#include <vector>
#include "dfhack/Virtual.h"
#include "dfhack/BitArray.h"
#include "Virtual.h"
#include "BitArray.h"
#include "Materials.h"
/**
@ -149,7 +149,7 @@ namespace DFHack
/// placeholder
bool discovered;
/// this is NOT part of the DF feature, but an address of the feature as seen by DFhack.
uint32_t origin;
void * origin;
};

@ -29,16 +29,105 @@ distribution.
* \defgroup grp_materials Materials module - used for reading raws mostly
* @ingroup grp_modules
*/
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/Types.h"
#include "dfhack/BitArray.h"
#include "Export.h"
#include "Module.h"
#include "Types.h"
#include "BitArray.h"
#include "DataDefs.h"
#include "df/material.h"
#include <vector>
#include <string>
namespace df
{
struct item;
struct inorganic_raw;
struct plant_raw;
struct creature_raw;
struct historical_figure;
struct material_vec_ref;
struct job_item;
union job_material_category;
union job_item_flags1;
union job_item_flags2;
union job_item_flags3;
}
namespace DFHack
{
struct DFHACK_EXPORT MaterialInfo {
static const int NUM_BUILTIN = 19;
static const int GROUP_SIZE = 200;
static const int CREATURE_BASE = NUM_BUILTIN;
static const int FIGURE_BASE = NUM_BUILTIN + GROUP_SIZE;
static const int PLANT_BASE = NUM_BUILTIN + GROUP_SIZE*2;
static const int END_BASE = NUM_BUILTIN + GROUP_SIZE*3;
int16_t type;
int32_t index;
df::material *material;
enum Mode {
Builtin,
Inorganic,
Creature,
Plant
};
Mode mode;
int16_t subtype;
df::inorganic_raw *inorganic;
df::creature_raw *creature;
df::plant_raw *plant;
df::historical_figure *figure;
public:
MaterialInfo(int16_t type = -1, int32_t index = -1) { decode(type, index); }
template<class T> MaterialInfo(T *ptr) { decode(ptr); }
bool isValid() const { return material != NULL; }
bool decode(int16_t type, int32_t index = -1);
bool decode(df::item *item);
bool decode(const df::material_vec_ref &vr, int idx);
template<class T> bool decode(T *ptr) {
// Assume and exploit a certain naming convention
return ptr ? decode(ptr->mat_type, ptr->mat_index) : decode(-1);
}
bool find(const std::string &token, const std::string &subtoken = std::string());
bool findBuiltin(const std::string &token);
bool findInorganic(const std::string &token);
bool findPlant(const std::string &token, const std::string &subtoken);
bool findCreature(const std::string &token, const std::string &subtoken);
std::string toString(uint16_t temp = 10015, bool named = true);
bool isAnyCloth();
void getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &mask);
void getMatchBits(df::job_item_flags2 &ok, df::job_item_flags2 &mask);
void getMatchBits(df::job_item_flags3 &ok, df::job_item_flags3 &mask);
df::craft_material_class getCraftClass();
bool matches(const df::job_material_category &cat);
bool matches(const df::job_item &item);
};
inline bool operator== (const MaterialInfo &a, const MaterialInfo &b) {
return a.type == b.type && a.index == b.index;
}
inline bool operator!= (const MaterialInfo &a, const MaterialInfo &b) {
return a.type != b.type || a.index != b.index;
}
typedef int32_t t_materialIndex;
typedef int16_t t_materialType, t_itemType, t_itemSubtype;

@ -5,8 +5,8 @@
* \defgroup grp_notes In game notes (and routes)
* @ingroup grp_notes
*/
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "Export.h"
#include "Module.h"
#include <vector>
#include <string>

@ -30,9 +30,9 @@ distribution.
* @ingroup grp_modules
*/
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/Types.h"
#include "Export.h"
#include "Module.h"
#include "Types.h"
namespace DFHack
{

@ -28,9 +28,9 @@ distribution.
/*
* Creatures
*/
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/modules/Items.h"
#include "Export.h"
#include "Module.h"
#include "modules/Items.h"
/**
* \defgroup grp_units Unit module parts
* @ingroup grp_modules

@ -30,9 +30,9 @@ distribution.
* @ingroup grp_modules
*/
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/Types.h"
#include "Export.h"
#include "Module.h"
#include "Types.h"
namespace DFHack
{
/**

@ -5,8 +5,8 @@
* \defgroup grp_vermin Wild vermin (ants, bees, etc)
* @ingroup grp_vermin
*/
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "Export.h"
#include "Module.h"
#ifdef __cplusplus
namespace DFHack
@ -18,7 +18,7 @@ namespace DFHack
*/
struct t_spawnPoint
{
uint32_t origin;
void * origin;
int16_t race;
uint16_t type;
uint16_t x;
@ -76,7 +76,7 @@ namespace DFHack
private:
Vermin* v;
std::vector <void*> * p_sp;
std::vector <char*> * p_sp;
friend class Vermin;
};

@ -31,8 +31,8 @@ distribution.
* @ingroup grp_modules
*/
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "Export.h"
#include "Module.h"
#include <ostream>
namespace DFHack

@ -26,13 +26,13 @@ distribution.
/*
* kitchen settings
*/
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/Types.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/modules/Items.h"
#include <dfhack/Core.h>
#include "Export.h"
#include "Module.h"
#include "Types.h"
#include "VersionInfo.h"
#include "modules/Materials.h"
#include "modules/Items.h"
#include "Core.h"
/**
* \defgroup grp_kitchen Kitchen settings
* @ingroup grp_modules

@ -30,16 +30,26 @@ distribution.
#include <map>
using namespace std;
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/Types.h"
#include "dfhack/Error.h"
#include "dfhack/modules/Buildings.h"
#include "VersionInfo.h"
#include "MemAccess.h"
#include "Types.h"
#include "Error.h"
#include "modules/Buildings.h"
#include "ModuleFactory.h"
#include "dfhack/Core.h"
#include "Core.h"
using namespace DFHack;
#include "DataDefs.h"
#include "df/world.h"
#include "df/world_raws.h"
#include "df/building_def.h"
#include "df/building.h"
#include "df/building_workshopst.h"
using namespace df::enums;
using df::global::world;
using df::building_def;
//raw
struct t_building_df40d
{
@ -58,17 +68,10 @@ struct t_building_df40d
struct Buildings::Private
{
uint32_t buildings_vector;
uint32_t custom_workshop_vector;
uint32_t building_custom_workshop_type;
uint32_t custom_workshop_type;
uint32_t custom_workshop_name;
int32_t custom_workshop_id;
DfVector <uint32_t> * p_bld;
Process * owner;
bool Inited;
bool hasCustomWorkshops;
bool Started;
int32_t custom_workshop_id;
};
Module* DFHack::createBuildings()
@ -80,37 +83,10 @@ Buildings::Buildings()
{
Core & c = Core::getInstance();
d = new Private;
d->p_bld = NULL;
d->Inited = d->Started = d->hasCustomWorkshops = false;
VersionInfo * mem = c.vinfo;
d->Started = false;
d->owner = c.p;
OffsetGroup * OG_build = mem->getGroup("Buildings");
d->Inited = true;
try
{
d->buildings_vector = OG_build->getAddress ("buildings_vector");
}
catch(DFHack::Error::AllMemdef &e)
{
cerr << "Buildings not available... " << e.what() << endl;
d->Inited = false;
}
if(d->Inited)
{
try
{
d->custom_workshop_vector = OG_build->getAddress("custom_workshop_vector");
d->building_custom_workshop_type = OG_build->getOffset("building_custom_workshop_type");
d->custom_workshop_type = OG_build->getOffset("custom_workshop_type");
d->custom_workshop_name = OG_build->getOffset("custom_workshop_name");
mem->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id);
d->hasCustomWorkshops = true;
}
catch(DFHack::Error::AllMemdef &e)
{
cerr << "Custom workshops not available. Memory Definition: " << e.what() << endl;
}
}
c.vinfo->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id);
}
Buildings::~Buildings()
@ -124,8 +100,7 @@ bool Buildings::Start(uint32_t & numbuildings)
{
if(!d->Inited)
return false;
d->p_bld = new DfVector <uint32_t> (d->buildings_vector);
numbuildings = d->p_bld->size();
numbuildings = world->buildings.all.size();
d->Started = true;
return true;
}
@ -134,37 +109,26 @@ bool Buildings::Read (const uint32_t index, t_building & building)
{
if(!d->Started)
return false;
t_building_df40d bld_40d;
// read pointer from vector at position
uint32_t temp = d->p_bld->at (index);
//d->p_bld->read(index,(uint8_t *)&temp);
//read building from memory
d->owner->read (temp, sizeof (t_building_df40d), (uint8_t *) &bld_40d);
df::building *bld_40d = world->buildings.all[index];
// transform
int32_t type = -1;
d->owner->getDescriptor()->resolveObjectToClassID (temp, type);
building.origin = temp;
building.vtable = bld_40d.vtable;
building.x1 = bld_40d.x1;
building.x2 = bld_40d.x2;
building.y1 = bld_40d.y1;
building.y2 = bld_40d.y2;
building.z = bld_40d.z;
building.material = bld_40d.material;
d->owner->getDescriptor()->resolveObjectToClassID ( (char *)bld_40d, type);
building.x1 = bld_40d->x1;
building.x2 = bld_40d->x2;
building.y1 = bld_40d->y1;
building.y2 = bld_40d->y2;
building.z = bld_40d->z;
building.material.index = bld_40d->mat_index;
building.material.type = bld_40d->mat_type;
building.type = type;
building.custom_type = bld_40d->getCustomType();
building.origin = (void *) &bld_40d;
return true;
}
bool Buildings::Finish()
{
if(d->p_bld)
{
delete d->p_bld;
d->p_bld = NULL;
}
d->Started = false;
return true;
}
@ -173,39 +137,20 @@ bool Buildings::ReadCustomWorkshopTypes(map <uint32_t, string> & btypes)
{
if(!d->Inited)
return false;
if(!d->hasCustomWorkshops)
return false;
Core & c = Core::getInstance();
Process * p = d->owner;
DfVector <uint32_t> p_matgloss (d->custom_workshop_vector);
uint32_t size = p_matgloss.size();
vector <building_def *> & bld_def = world->raws.buildings.all;
uint32_t size = bld_def.size();
btypes.clear();
for (uint32_t i = 0; i < size;i++)
c.con.print("Probing vector at 0x%x for custom workshops.\n", &bld_def);
for (auto iter = bld_def.begin(); iter != bld_def.end();iter++)
{
string out = p->readSTLString (p_matgloss[i] + d->custom_workshop_name);
uint32_t type = p->readDWord (p_matgloss[i] + d->custom_workshop_type);
#ifdef DEBUG
cout << out << ": " << type << endl;
#endif
btypes[type] = out;
building_def * temp = *iter;
btypes[temp->id] = temp->code;
c.con.print("%d : %s\n",temp->id, temp->code.c_str());
}
return true;
}
int32_t Buildings::GetCustomWorkshopType(t_building & building)
{
if(!d->Inited)
return false;
if(!d->hasCustomWorkshops)
return false;
int32_t type = (int32_t)building.type;
int32_t ret = -1;
if(type != -1 && type == d->custom_workshop_id)
{
// read the custom workshop subtype
ret = (int32_t) d->owner->readDWord(building.origin + d->building_custom_workshop_type);
}
return ret;
}

@ -31,22 +31,18 @@ distribution.
using namespace std;
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/Types.h"
#include "dfhack/modules/Constructions.h"
#include "VersionInfo.h"
#include "MemAccess.h"
#include "Types.h"
#include "modules/Constructions.h"
#include "ModuleFactory.h"
#include "dfhack/Core.h"
#include "Core.h"
using namespace DFHack;
struct Constructions::Private
{
uint32_t construction_vector;
// translation
DfVector <uint32_t> * p_cons;
vector <t_construction *> * p_cons;
Process * owner;
bool Inited;
bool Started;
@ -62,10 +58,9 @@ Constructions::Constructions()
Core & c = Core::getInstance();
d = new Private;
d->owner = c.p;
d->p_cons = 0;
d->Inited = d->Started = false;
VersionInfo * mem = c.vinfo;
d->construction_vector = mem->getGroup("Constructions")->getAddress ("vector");
d->p_cons = (decltype(d->p_cons)) mem->getGroup("Constructions")->getAddress ("vector");
d->Inited = true;
}
@ -78,7 +73,6 @@ Constructions::~Constructions()
bool Constructions::Start(uint32_t & numconstructions)
{
d->p_cons = new DfVector <uint32_t> (d->construction_vector);
numconstructions = d->p_cons->size();
d->Started = true;
return true;
@ -89,24 +83,14 @@ bool Constructions::Read (const uint32_t index, t_construction & construction)
{
if(!d->Started) return false;
// read pointer from vector at position
uint32_t temp = d->p_cons->at (index);
//read construction from memory
d->owner->read (temp, sizeof (t_construction), (uint8_t *) &construction);
// transform
construction.origin = temp;
t_construction * orig = d->p_cons->at(index);
construction = *orig;
construction.origin = orig;
return true;
}
bool Constructions::Finish()
{
if(d->p_cons)
{
delete d->p_cons;
d->p_cons = NULL;
}
d->Started = false;
return true;
}

@ -30,21 +30,19 @@ distribution.
#include <map>
using namespace std;
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/Types.h"
#include "dfhack/modules/Engravings.h"
#include "VersionInfo.h"
#include "MemAccess.h"
#include "Types.h"
#include "modules/Engravings.h"
#include "ModuleFactory.h"
#include "dfhack/Core.h"
#include "Core.h"
using namespace DFHack;
struct Engravings::Private
{
uint32_t engraving_vector;
// translation
DfVector <uint32_t> * p_engr;
vector <t_engraving *> * p_engr;
Process * owner;
bool Inited;
@ -61,9 +59,8 @@ Engravings::Engravings()
Core & c = Core::getInstance();
d = new Private;
d->owner = c.p;
d->p_engr = 0;
d->Inited = d->Started = false;
d->engraving_vector = c.vinfo->getGroup("Engravings")->getAddress ("vector");
d->p_engr = (decltype(d->p_engr)) c.vinfo->getGroup("Engravings")->getAddress ("vector");
d->Inited = true;
}
@ -76,7 +73,8 @@ Engravings::~Engravings()
bool Engravings::Start(uint32_t & numengravings)
{
d->p_engr = new DfVector <uint32_t> (d->engraving_vector);
if(!d->Inited)
return false;
numengravings = d->p_engr->size();
d->Started = true;
return true;
@ -88,13 +86,10 @@ bool Engravings::Read (const uint32_t index, dfh_engraving & engraving)
if(!d->Started) return false;
// read pointer from vector at position
uint32_t temp = d->p_engr->at (index);
//read construction from memory
d->owner->read (temp, sizeof (t_engraving), (uint8_t *) &(engraving.s));
engraving.s = *d->p_engr->at (index);
// transform
engraving.origin = temp;
engraving.origin = d->p_engr->at (index);
return true;
}
@ -108,11 +103,6 @@ bool Engravings::Write (const dfh_engraving & engraving)
bool Engravings::Finish()
{
if(d->p_engr)
{
delete d->p_engr;
d->p_engr = NULL;
}
d->Started = false;
return true;
}

@ -1,6 +1,6 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
Copyright (c) 2009-2011 Petr Mr<EFBFBD>zek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@ -33,13 +33,12 @@ distribution.
#include <cstdlib>
using namespace std;
#include "dfhack/modules/Graphic.h"
#include "dfhack/Error.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "modules/Graphic.h"
#include "Error.h"
#include "VersionInfo.h"
#include "MemAccess.h"
#include "ModuleFactory.h"
#include <dfhack/Core.h>
#include "Core.h"
using namespace DFHack;

@ -30,15 +30,51 @@ distribution.
#include <map>
using namespace std;
#include "dfhack/modules/Gui.h"
#include "dfhack/Process.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Types.h"
#include "dfhack/Error.h"
#include "modules/Gui.h"
#include "MemAccess.h"
#include "VersionInfo.h"
#include "Types.h"
#include "Error.h"
#include "ModuleFactory.h"
#include "dfhack/Core.h"
#include "Core.h"
#include "PluginManager.h"
using namespace DFHack;
#include "DataDefs.h"
#include "df/cursor.h"
#include "df/viewscreen_dwarfmodest.h"
// Predefined common guard functions
bool DFHack::default_hotkey(Core *, df::viewscreen *top)
{
// Default hotkey guard function
for (;top ;top = top->parent)
if (strict_virtual_cast<df::viewscreen_dwarfmodest>(top))
return true;
return false;
}
bool DFHack::dwarfmode_hotkey(Core *, df::viewscreen *top)
{
// Require the main dwarf mode screen
return !!strict_virtual_cast<df::viewscreen_dwarfmodest>(top);
}
bool DFHack::cursor_hotkey(Core *c, df::viewscreen *top)
{
if (!dwarfmode_hotkey(c, top))
return false;
// Also require the cursor.
if (!df::global::cursor || df::global::cursor->x == -30000)
return false;
return true;
}
//
Module* DFHack::createGui()
{
return new Gui();
@ -55,16 +91,23 @@ struct Gui::Private
}
bool Started;
uint32_t window_x_offset;
uint32_t window_y_offset;
uint32_t window_z_offset;
uint32_t cursor_xyz_offset;
uint32_t designation_xyz_offset;
uint32_t mouse_xy_offset;
uint32_t window_dims_offset;
int32_t * window_x_offset;
int32_t * window_y_offset;
int32_t * window_z_offset;
struct xyz
{
int32_t x;
int32_t y;
int32_t z;
} * cursor_xyz_offset, * designation_xyz_offset;
struct xy
{
int32_t x;
int32_t y;
} * mouse_xy_offset, * window_dims_offset;
bool StartedScreen;
uint32_t screen_tiles_ptr_offset;
void * screen_tiles_ptr_offset;
Process * owner;
};
@ -121,19 +164,33 @@ Gui::Gui()
try
{
OG_Position = mem->getGroup("Position");
d->window_x_offset = OG_Position->getAddress ("window_x");
d->window_y_offset = OG_Position->getAddress ("window_y");
d->window_z_offset = OG_Position->getAddress ("window_z");
d->cursor_xyz_offset = OG_Position->getAddress ("cursor_xyz");
d->window_dims_offset = OG_Position->getAddress ("window_dims");
d->window_x_offset = (int32_t *) OG_Position->getAddress ("window_x");
d->window_y_offset = (int32_t *) OG_Position->getAddress ("window_y");
d->window_z_offset = (int32_t *) OG_Position->getAddress ("window_z");
d->cursor_xyz_offset = (Private::xyz *) OG_Position->getAddress ("cursor_xyz");
d->window_dims_offset = (Private::xy *) OG_Position->getAddress ("window_dims");
d->Started = true;
}
catch(Error::All &){};
OG_Position->getSafeAddress("mouse_xy", d->mouse_xy_offset);
OG_Position->getSafeAddress("designation_xyz", d->designation_xyz_offset);
try
{
d->screen_tiles_ptr_offset = OG_Position->getAddress ("screen_tiles_pointer");
d->mouse_xy_offset = (Private::xy *) OG_Position->getAddress ("mouse_xy");
}
catch(Error::All &)
{
d->mouse_xy_offset = 0;
};
try
{
d->designation_xyz_offset = (Private::xyz *) OG_Position->getAddress ("designation_xyz");
}
catch(Error::All &)
{
d->designation_xyz_offset = 0;
};
try
{
d->screen_tiles_ptr_offset = (void *) OG_Position->getAddress ("screen_tiles_pointer");
d->StartedScreen = true;
}
catch(Error::All &){};
@ -263,10 +320,10 @@ bool Gui::getScreenTiles (int32_t width, int32_t height, t_screen screen[])
{
if(!d->StartedScreen) return false;
uint32_t screen_addr = d->owner->readDWord(d->screen_tiles_ptr_offset);
void * screen_addr = (void *) d->owner->readDWord(d->screen_tiles_ptr_offset);
uint8_t* tiles = new uint8_t[width*height*4/* + 80 + width*height*4*/];
d->owner->read (screen_addr, (width*height*4/* + 80 + width*height*4*/), (uint8_t *) tiles);
d->owner->read (screen_addr, (width*height*4/* + 80 + width*height*4*/), tiles);
for(int32_t iy=0; iy<height; iy++)
{

@ -33,16 +33,15 @@ distribution.
#include <set>
using namespace std;
#include "dfhack/Types.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/modules/Items.h"
#include "dfhack/modules/Units.h"
#include "Types.h"
#include "VersionInfo.h"
#include "MemAccess.h"
#include "modules/Materials.h"
#include "modules/Items.h"
#include "modules/Units.h"
#include "ModuleFactory.h"
#include <dfhack/Core.h>
#include <dfhack/Virtual.h>
#include "Core.h"
#include "Virtual.h"
using namespace DFHack;
@ -58,7 +57,7 @@ class Items::Private
std::map<int32_t, df_item *> idLookupTable;
uint32_t refVectorOffset;
uint32_t idFieldOffset;
uint32_t itemVectorAddress;
void * itemVectorAddress;
ClassNameCheck isOwnerRefClass;
ClassNameCheck isContainerRefClass;

@ -33,13 +33,12 @@ distribution.
#include <cstdlib>
using namespace std;
#include "dfhack/modules/Maps.h"
#include "dfhack/Error.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "modules/Maps.h"
#include "Error.h"
#include "VersionInfo.h"
#include "MemAccess.h"
#include "ModuleFactory.h"
#include <dfhack/Core.h>
#include "Core.h"
#define MAPS_GUARD if(!d->Started) throw DFHack::Error::ModuleNotInitialized();
@ -96,7 +95,7 @@ struct Maps::Private
FEATURES
*/
// FIXME: replace with a struct pointer, eventually. needs to be mapped out first
uint32_t world_data;
char * world_data;
uint32_t local_f_start; // offset from world_data
// FIXME: replace by virtual function call
uint32_t local_material;
@ -122,7 +121,7 @@ struct Maps::Private
set <uint32_t> unknown_veins;
// map between feature address and the read object
map <uint32_t, t_feature> local_feature_store;
map <void *, t_feature> local_feature_store;
map <DFCoord, vector <t_feature *> > m_local_feature;
vector <t_feature> v_global_feature;
@ -508,13 +507,13 @@ bool Maps::StartFeatures()
Process * p = d->owner;
Private::t_offsets &off = d->offsets;
uint32_t base = 0;
uint32_t global_feature_vector = 0;
char * base = 0;
char * global_feature_vector = 0;
uint32_t world = p->readDWord(off.world_data);
char * world = p->readPtr( (void *) off.world_data);
if(!world) return false;
base = p->readDWord(world + off.local_f_start);
global_feature_vector = p->readDWord(off.world_data) + off.global_vector;
base = p->readPtr(world + off.local_f_start);
global_feature_vector = p->readPtr(off.world_data) + off.global_vector;
// deref pointer to the humongo-structure
if(!base)
@ -549,22 +548,21 @@ bool Maps::StartFeatures()
// base = pointer to local feature structure (inside world data struct)
// bigregion is 16x16 regions. for each bigregion in X dimension:
uint32_t mega_column = p->readDWord(base + bigregion_x * 4);
char * mega_column = p->readPtr(base + bigregion_x * 4);
// 16B structs, second DWORD of the struct is a pointer
uint32_t loc_f_array16x16 = p->readDWord(mega_column + offset_elem + (sizeof_elem * bigregion_y));
char * loc_f_array16x16 = p->readPtr(mega_column + offset_elem + (sizeof_elem * bigregion_y));
if(loc_f_array16x16)
{
uint32_t feat_vector = loc_f_array16x16 + sizeof_16vec * sub_x + sizeof_vec * sub_y;
DfVector<uint32_t> p_features(feat_vector);
uint32_t size = p_features.size();
vector <char *> * p_features = (vector <char *> *) (loc_f_array16x16 + sizeof_16vec * sub_x + sizeof_vec * sub_y);
uint32_t size = p_features->size();
DFCoord pc(blockX,blockY);
std::vector<t_feature *> tempvec;
for(uint32_t i = 0; i < size; i++)
{
uint32_t cur_ptr = p_features[i];
char * cur_ptr = p_features->at(i);
map <uint32_t, t_feature>::iterator it;
map <void *, t_feature>::iterator it;
it = d->local_feature_store.find(cur_ptr);
// do we already have the feature?
if(it != d->local_feature_store.end())
@ -579,7 +577,7 @@ bool Maps::StartFeatures()
// create, add to store
t_feature tftemp;
tftemp.discovered = false; //= p->readDWord(cur_ptr + 4);
tftemp.origin = cur_ptr;
tftemp.origin = (t_feature *) cur_ptr;
string name = p->readClassName((void *)p->readDWord( cur_ptr ));
if(name == "feature_init_deep_special_tubest")
{
@ -611,17 +609,15 @@ bool Maps::StartFeatures()
const uint32_t global_feature_funcptr = off.global_funcptr;
const uint32_t glob_main_mat_offset = off.global_material;
const uint32_t glob_sub_mat_offset = off.global_submaterial;
DfVector<uint32_t> p_features (global_feature_vector);
vector <char *> * p_features = (vector <char *> *) global_feature_vector;
d->v_global_feature.clear();
uint32_t size = p_features.size();
uint32_t size = p_features->size();
d->v_global_feature.reserve(size);
for(uint32_t i = 0; i < size; i++)
{
t_feature temp;
uint32_t feat_ptr = p->readDWord(p_features[i] + global_feature_funcptr );
char * feat_ptr = p->readPtr(p_features->at(i) + global_feature_funcptr );
temp.origin = feat_ptr;
//temp.discovered = p->readDWord( feat_ptr + 4 ); // maybe, placeholder
temp.discovered = false;
// FIXME: use the memory_info cache mechanisms
@ -887,8 +883,8 @@ bool Maps::RemoveBlockEvent(uint32_t x, uint32_t y, uint32_t z, t_virtual * whic
}
/*
* Layer geology
*/
* Layer geology
*/
bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
{
MAPS_GUARD
@ -896,17 +892,18 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
Process *p = d->owner;
// get needed addresses and offsets. Now this is what I call crazy.
uint16_t worldSizeX, worldSizeY;
uint32_t regions, geoblocks_vector_addr;
char *regions;
char *geoblocks_vector_addr;
Private::t_offsets &off = d->offsets;
// get world size
uint32_t world = p->readDWord(off.world_data);
char * world = p->readPtr(off.world_data);
p->readWord (world + off.world_size_x, worldSizeX);
p->readWord (world + off.world_size_y, worldSizeY);
regions = p->readDWord ( world + off.world_regions); // ptr2_region_array
regions = p->readPtr ( world + off.world_regions); // ptr2_region_array
geoblocks_vector_addr = world + off.world_geoblocks_vector;
// read the geoblock vector
DfVector <uint32_t> geoblocks (geoblocks_vector_addr);
vector <char *> & geoblocks = *(vector <char *> *)(geoblocks_vector_addr);
// iterate over 8 surrounding regions + local region
for (int i = eNorthWest; i < eBiomeCount; i++)
@ -925,8 +922,8 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
/// regions are a 2d array. consists of pointers to arrays of regions
/// regions are of region_size size
// get pointer to column of regions
uint32_t geoX;
p->readDWord (regions + bioRX*4, geoX);
char * geoX;
p->readPtr (regions + bioRX*4, geoX);
// get index into geoblock vector
uint16_t geoindex;
@ -935,11 +932,11 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
/// geology blocks are assigned to regions from a vector
// get the geoblock from the geoblock vector using the geoindex
// read the matgloss pointer from the vector into temp
uint32_t geoblock_off = geoblocks[geoindex];
char * geoblock_off = geoblocks[geoindex];
/// geology blocks have a vector of layer descriptors
// get the vector with pointer to layers
DfVector <uint32_t> geolayers (geoblock_off + off.geolayer_geoblock_offset); // let's hope
vector <char *> & geolayers = *(vector <char *> *)(geoblock_off + off.geolayer_geoblock_offset);
// make sure we don't load crap
assert (geolayers.size() > 0 && geolayers.size() <= 16);
@ -949,7 +946,7 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
for (uint32_t j = 0;j < geolayers.size();j++)
{
// read pointer to a layer
uint32_t geol_offset = geolayers[j];
char * geol_offset = geolayers[j];
// read word at pointer + 2, store in our geology vectors
d->v_geology[i].push_back (p->readWord (geol_offset + off.type_inside_geolayer));
}

@ -31,16 +31,367 @@ distribution.
#include <cstring>
using namespace std;
#include "dfhack/Types.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include <dfhack/Error.h>
#include "Types.h"
#include "modules/Materials.h"
#include "VersionInfo.h"
#include "MemAccess.h"
#include "Error.h"
#include "ModuleFactory.h"
#include <dfhack/Core.h>
#include "Core.h"
#include "MiscUtils.h"
#include "df/world.h"
#include "df/ui.h"
#include "df/item.h"
#include "df/inorganic_raw.h"
#include "df/plant_raw.h"
#include "df/plant_raw_flags.h"
#include "df/creature_raw.h"
#include "df/historical_figure.h"
#include "df/job_item.h"
#include "df/job_material_category.h"
#include "df/matter_state.h"
#include "df/material_vec_ref.h"
using namespace DFHack;
using namespace df::enums;
bool MaterialInfo::decode(df::item *item)
{
if (!item)
return decode(-1);
else
return decode(item->getActualMaterial(), item->getActualMaterialIndex());
}
bool MaterialInfo::decode(const df::material_vec_ref &vr, int idx)
{
if (idx < 0 || idx >= vr.mat_type.size() || idx >= vr.mat_index.size())
return decode(-1);
else
return decode(vr.mat_type[idx], vr.mat_index[idx]);
}
bool MaterialInfo::decode(int16_t type, int32_t index)
{
this->type = type;
this->index = index;
material = NULL;
mode = Builtin; subtype = 0;
inorganic = NULL; plant = NULL; creature = NULL;
figure = NULL;
df::world_raws &raws = df::global::world->raws;
if (type < 0 || type >= sizeof(raws.mat_table.builtin)/sizeof(void*))
return false;
if (index < 0)
{
material = raws.mat_table.builtin[type];
}
else if (type == 0)
{
mode = Inorganic;
inorganic = df::inorganic_raw::find(index);
if (!inorganic)
return false;
material = &inorganic->material;
}
else if (type < CREATURE_BASE)
{
material = raws.mat_table.builtin[type];
}
else if (type < FIGURE_BASE)
{
mode = Creature;
subtype = type-CREATURE_BASE;
creature = df::creature_raw::find(index);
if (!creature || subtype >= creature->material.size())
return false;
material = creature->material[subtype];
}
else if (type < PLANT_BASE)
{
mode = Creature;
subtype = type-FIGURE_BASE;
figure = df::historical_figure::find(index);
if (!figure)
return false;
creature = df::creature_raw::find(figure->race);
if (!creature || subtype >= creature->material.size())
return false;
material = creature->material[subtype];
}
else if (type < END_BASE)
{
mode = Plant;
subtype = type-PLANT_BASE;
plant = df::plant_raw::find(index);
if (!plant || subtype >= plant->material.size())
return false;
material = plant->material[subtype];
}
else
{
material = raws.mat_table.builtin[type];
}
return (material != NULL);
}
bool MaterialInfo::find(const std::string &token, const std::string &subtoken)
{
if (findBuiltin(token))
return true;
if (subtoken.empty())
{
if (findInorganic(token))
return true;
}
else
{
if (findPlant(token, subtoken))
return true;
if (findCreature(token, subtoken))
return true;
}
return false;
}
bool MaterialInfo::findBuiltin(const std::string &token)
{
df::world_raws &raws = df::global::world->raws;
for (int i = 1; i < NUM_BUILTIN; i++)
if (raws.mat_table.builtin[i]->id == token)
return decode(i, -1);
return decode(-1);
}
bool MaterialInfo::findInorganic(const std::string &token)
{
df::world_raws &raws = df::global::world->raws;
for (unsigned i = 0; i < raws.inorganics.size(); i++)
{
df::inorganic_raw *p = raws.inorganics[i];
if (p->id == token)
return decode(0, i);
}
return decode(-1);
}
bool MaterialInfo::findPlant(const std::string &token, const std::string &subtoken)
{
df::world_raws &raws = df::global::world->raws;
for (unsigned i = 0; i < raws.plants.all.size(); i++)
{
df::plant_raw *p = raws.plants.all[i];
if (p->id != token)
continue;
for (unsigned j = 0; j < p->material.size(); j++)
if (p->material[j]->id == subtoken)
return decode(PLANT_BASE+j, i);
break;
}
return decode(-1);
}
bool MaterialInfo::findCreature(const std::string &token, const std::string &subtoken)
{
df::world_raws &raws = df::global::world->raws;
for (unsigned i = 0; i < raws.creatures.all.size(); i++)
{
df::creature_raw *p = raws.creatures.all[i];
if (p->creature_id != token)
continue;
for (unsigned j = 0; j < p->material.size(); j++)
if (p->material[j]->id == subtoken)
return decode(CREATURE_BASE+j, i);
break;
}
return decode(-1);
}
std::string MaterialInfo::toString(uint16_t temp, bool named)
{
if (type == -1)
return "NONE";
if (!material)
return stl_sprintf("INVALID %d:%d", type, index);
df::matter_state state = matter_state::Solid;
if (temp >= material->heat.melting_point)
state = matter_state::Liquid;
if (temp >= material->heat.boiling_point)
state = matter_state::Gas;
std::string name = material->state_name[state];
if (!material->prefix.empty())
name = material->prefix + " " + name;
if (named && figure)
name += stl_sprintf(" of HF %d", index);
return name;
}
df::craft_material_class MaterialInfo::getCraftClass()
{
if (!material)
return craft_material_class::None;
if (type == 0 && index == -1)
return craft_material_class::Stone;
FOR_ENUM_ITEMS(material_flags, i)
{
df::craft_material_class ccv = ENUM_ATTR(material_flags, type, i);
if (ccv == craft_material_class::None)
continue;
if (material->flags.is_set(i))
return ccv;
}
return craft_material_class::None;
}
bool MaterialInfo::isAnyCloth()
{
using namespace df::enums::material_flags;
return material && (
material->flags.is_set(THREAD_PLANT) ||
material->flags.is_set(SILK) ||
material->flags.is_set(YARN)
);
}
bool MaterialInfo::matches(const df::job_material_category &cat)
{
if (!material)
return false;
using namespace df::enums::material_flags;
#define TEST(bit,flag) if (cat.bits.bit && material->flags.is_set(flag)) return true;
TEST(plant, STRUCTURAL_PLANT_MAT);
TEST(wood, WOOD);
TEST(cloth, THREAD_PLANT);
TEST(silk, SILK);
TEST(leather, LEATHER);
TEST(bone, BONE);
TEST(shell, SHELL);
TEST(wood2, WOOD);
TEST(soap, SOAP);
TEST(tooth, TOOTH);
TEST(horn, HORN);
TEST(pearl, PEARL);
TEST(yarn, YARN);
#undef TEST
return false;
}
bool MaterialInfo::matches(const df::job_item &item)
{
if (!isValid()) return false;
df::job_item_flags1 ok1, mask1;
getMatchBits(ok1, mask1);
df::job_item_flags2 ok2, mask2;
getMatchBits(ok2, mask2);
df::job_item_flags3 ok3, mask3;
getMatchBits(ok3, mask3);
return ((item.flags1.whole & mask1.whole) == (item.flags1.whole & ok1.whole)) &&
((item.flags2.whole & mask2.whole) == (item.flags2.whole & ok2.whole)) &&
((item.flags3.whole & mask3.whole) == (item.flags3.whole & ok3.whole));
}
void MaterialInfo::getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &mask)
{
ok.whole = mask.whole = 0;
if (!isValid()) return;
#define MAT_FLAG(name) material->flags.is_set(df::enums::material_flags::name)
#define FLAG(field, name) (field && field->flags.is_set(name))
#define TEST(bit, check) \
mask.bits.bit = true; ok.bits.bit = !!(check);
bool structural = MAT_FLAG(STRUCTURAL_PLANT_MAT);
TEST(millable, structural && FLAG(plant, plant_raw_flags::MILL));
TEST(sharpenable, MAT_FLAG(IS_STONE));
TEST(distillable, structural && FLAG(plant, plant_raw_flags::DRINK));
TEST(processable, structural && FLAG(plant, plant_raw_flags::THREAD));
TEST(bag, isAnyCloth());
TEST(cookable, MAT_FLAG(EDIBLE_COOKED));
TEST(extract_bearing_plant, structural && FLAG(plant, plant_raw_flags::EXTRACT_STILL_VIAL));
TEST(extract_bearing_fish, false);
TEST(extract_bearing_vermin, false);
TEST(processable_to_vial, structural && FLAG(plant, plant_raw_flags::EXTRACT_VIAL));
TEST(processable_to_bag, structural && FLAG(plant, plant_raw_flags::LEAVES));
TEST(processable_to_barrel, structural && FLAG(plant, plant_raw_flags::EXTRACT_BARREL));
TEST(solid, !(MAT_FLAG(ALCOHOL_PLANT) ||
MAT_FLAG(ALCOHOL_CREATURE) ||
MAT_FLAG(LIQUID_MISC_PLANT) ||
MAT_FLAG(LIQUID_MISC_CREATURE) ||
MAT_FLAG(LIQUID_MISC_OTHER)));
TEST(tameable_vermin, false);
TEST(sharpenable, MAT_FLAG(IS_GLASS));
TEST(milk, linear_index(material->reaction_product.id, std::string("CHEESE_MAT")) >= 0);
//04000000 - "milkable" - vtable[107],1,1
}
void MaterialInfo::getMatchBits(df::job_item_flags2 &ok, df::job_item_flags2 &mask)
{
ok.whole = mask.whole = 0;
if (!isValid()) return;
bool is_cloth = isAnyCloth();
TEST(dye, MAT_FLAG(IS_DYE));
TEST(dyeable, is_cloth);
TEST(dyed, is_cloth);
TEST(sewn_imageless, is_cloth);
TEST(glass_making, MAT_FLAG(CRYSTAL_GLASSABLE));
TEST(fire_safe, material->heat.melting_point > 11000);
TEST(magma_safe, material->heat.melting_point > 12000);
TEST(deep_material, FLAG(inorganic, df::enums::inorganic_flags::DEEP_ANY));
TEST(non_economic, inorganic && !(df::global::ui && df::global::ui->economic_stone[index]));
TEST(plant, plant);
TEST(silk, MAT_FLAG(SILK));
TEST(leather, MAT_FLAG(LEATHER));
TEST(bone, MAT_FLAG(BONE));
TEST(shell, MAT_FLAG(SHELL));
TEST(totemable, false);
TEST(horn, MAT_FLAG(HORN));
TEST(pearl, MAT_FLAG(PEARL));
TEST(soap, MAT_FLAG(SOAP));
TEST(ivory_tooth, MAT_FLAG(TOOTH));
//TEST(hair_wool, MAT_FLAG(YARN));
TEST(yarn, MAT_FLAG(YARN));
}
void MaterialInfo::getMatchBits(df::job_item_flags3 &ok, df::job_item_flags3 &mask)
{
ok.whole = mask.whole = 0;
if (!isValid()) return;
TEST(hard, MAT_FLAG(ITEMS_HARD));
}
#undef MAT_FLAG
#undef FLAG
#undef TEST
Module* DFHack::createMaterials()
{
@ -52,8 +403,8 @@ class Materials::Private
public:
Process * owner;
OffsetGroup * OG_Materials;
uint32_t vector_races;
uint32_t vector_other;
void * vector_races;
void * vector_other;
};
Materials::Materials()
@ -67,10 +418,10 @@ Materials::Materials()
df_inorganic = 0;
OffsetGroup *OG_Materials = d->OG_Materials = c.vinfo->getGroup("Materials");
{
OG_Materials->getSafeAddress("inorganics",(uint32_t &)df_inorganic);
OG_Materials->getSafeAddress("organics_all",(uint32_t &)df_organic);
OG_Materials->getSafeAddress("organics_plants",(uint32_t &)df_plants);
OG_Materials->getSafeAddress("organics_trees",(uint32_t &)df_trees);
OG_Materials->getSafeAddress("inorganics",(void * &)df_inorganic);
OG_Materials->getSafeAddress("organics_all",(void * &)df_organic);
OG_Materials->getSafeAddress("organics_plants",(void * &)df_plants);
OG_Materials->getSafeAddress("organics_trees",(void * &)df_trees);
d->vector_races = OG_Materials->getAddress("creature_type_vector");
}
}
@ -111,16 +462,16 @@ bool t_matglossInorganic::isGem()
}
// good for now
inline bool ReadNamesOnly(Process* p, uint32_t address, vector<t_matgloss> & names)
inline bool ReadNamesOnly(Process* p, void * address, vector<t_matgloss> & names)
{
DfVector <uint32_t> p_matgloss (address);
uint32_t size = p_matgloss.size();
vector <string *> * p_names = (vector <string *> *) address;
uint32_t size = p_names->size();
names.clear();
names.reserve (size);
for (uint32_t i = 0; i < size;i++)
{
t_matgloss mat;
mat.id = *(std::string *)p_matgloss[i];
mat.id = *p_names->at(i);
names.push_back(mat);
}
return true;
@ -159,21 +510,21 @@ bool Materials::CopyInorganicMaterials (std::vector<t_matglossInorganic> & inorg
bool Materials::CopyOrganicMaterials (std::vector<t_matgloss> & organic)
{
if(df_organic)
return ReadNamesOnly(d->owner, (uint32_t) df_organic, organic );
return ReadNamesOnly(d->owner, (void *) df_organic, organic );
else return false;
}
bool Materials::CopyWoodMaterials (std::vector<t_matgloss> & tree)
{
if(df_trees)
return ReadNamesOnly(d->owner, (uint32_t) df_trees, tree );
return ReadNamesOnly(d->owner, (void *) df_trees, tree );
else return false;
}
bool Materials::CopyPlantMaterials (std::vector<t_matgloss> & plant)
{
if(df_plants)
return ReadNamesOnly(d->owner, (uint32_t) df_plants, plant );
return ReadNamesOnly(d->owner, (void *) df_plants, plant );
else return false;
}
@ -185,7 +536,7 @@ bool Materials::ReadCreatureTypes (void)
bool Materials::ReadOthers(void)
{
Process * p = d->owner;
uint32_t matBase = d->OG_Materials->getAddress ("other");
char * matBase = d->OG_Materials->getAddress ("other");
uint32_t i = 0;
std::string * ptr;
@ -194,7 +545,7 @@ bool Materials::ReadOthers(void)
while(1)
{
t_matglossOther mat;
ptr = (std::string *) p->readDWord(matBase + i*4);
ptr = (std::string *) p->readPtr(matBase + i*4);
if(ptr==0)
break;
mat.id = *ptr;
@ -208,7 +559,7 @@ bool Materials::ReadDescriptorColors (void)
{
Process * p = d->owner;
OffsetGroup * OG_Descriptors = p->getDescriptor()->getGroup("Materials")->getGroup("descriptors");
DfVector <uint32_t> p_colors (OG_Descriptors->getAddress ("colors_vector"));
vector <char *> & p_colors = *(vector<char*> *) OG_Descriptors->getAddress ("colors_vector");
uint32_t size = p_colors.size();
color.clear();
@ -237,7 +588,7 @@ bool Materials::ReadCreatureTypesEx (void)
uint32_t sizeof_string = OG_string->getHexValue ("sizeof");
OffsetGroup * OG_Mats = mem->getGroup("Materials");
DfVector <uint32_t> p_races (OG_Mats->getAddress ("creature_type_vector"));
vector <char *> & p_races = *(vector<char*> *) OG_Mats->getAddress ("creature_type_vector");
OffsetGroup * OG_Creature = OG_Mats->getGroup("creature");
uint32_t castes_vector_offset = OG_Creature->getOffset ("caste_vector");
@ -287,13 +638,13 @@ bool Materials::ReadCreatureTypesEx (void)
mat.tilecolor.back = p->readWord( p_races[i] + tile_color_offset + 2 );
mat.tilecolor.bright = p->readWord( p_races[i] + tile_color_offset + 4 );
DfVector <uint32_t> p_castes(p_races[i] + castes_vector_offset);
vector <char *> & p_castes = *(vector<char*> *) (p_races[i] + castes_vector_offset);
sizecas = p_castes.size();
for (uint32_t j = 0; j < sizecas;j++)
{
/* caste name */
t_creaturecaste caste;
uint32_t caste_start = p_castes[j];
char * caste_start = p_castes[j];
caste.id = p->readSTLString (caste_start);
caste.singular = p->readSTLString (caste_start + sizeof_string);
caste.plural = p->readSTLString (caste_start + 2 * sizeof_string);
@ -303,13 +654,13 @@ bool Materials::ReadCreatureTypesEx (void)
{
/* color mod reading */
// Caste + offset > color mod vector
DfVector <uint32_t> p_colormod(caste_start + caste_colormod_offset);
vector <char *> & p_colormod = *(vector<char*> *) (caste_start + caste_colormod_offset);
sizecolormod = p_colormod.size();
caste.ColorModifier.resize(sizecolormod);
for(uint32_t k = 0; k < sizecolormod;k++)
{
// color mod [0] -> color list
DfVector <uint32_t> p_colorlist(p_colormod[k]);
vector <uint32_t> & p_colorlist = *(vector<uint32_t> *) (p_colormod[k]);
sizecolorlist = p_colorlist.size();
caste.ColorModifier[k].colorlist.resize(sizecolorlist);
for(uint32_t l = 0; l < sizecolorlist; l++)
@ -320,7 +671,7 @@ bool Materials::ReadCreatureTypesEx (void)
caste.ColorModifier[k].enddate = p->readDWord( p_colormod[k] + color_modifier_enddate_offset );
}
/* body parts */
DfVector <uint32_t> p_bodypart(caste_start + caste_bodypart_offset);
vector <char *> & p_bodypart = *(vector<char*> *) (caste_start + caste_bodypart_offset);
caste.bodypart.empty();
sizebp = p_bodypart.size();
for(uint32_t k = 0; k < sizebp; k++)
@ -338,7 +689,7 @@ bool Materials::ReadCreatureTypesEx (void)
}
mat.castes.push_back(caste);
}
DfVector <uint32_t> p_extract(p_races[i] + extract_vector_offset);
vector <void *> & p_extract = *(vector<void*> *) (p_races[i] + extract_vector_offset);
for(uint32_t j = 0; j < p_extract.size(); j++)
{
t_creatureextract extract;

@ -29,13 +29,13 @@ distribution.
#include <map>
using namespace std;
#include "dfhack/VersionInfo.h"
#include "dfhack/Types.h"
#include "dfhack/Error.h"
#include "dfhack/Process.h"
#include "VersionInfo.h"
#include "Types.h"
#include "Error.h"
#include "MemAccess.h"
#include "ModuleFactory.h"
#include "dfhack/Core.h"
#include "dfhack/modules/Notes.h"
#include "Core.h"
#include "modules/Notes.h"
using namespace DFHack;
Module* DFHack::createNotes()

@ -30,13 +30,12 @@ distribution.
#include <cassert>
using namespace std;
#include "dfhack/modules/Translation.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/Types.h"
#include "modules/Translation.h"
#include "VersionInfo.h"
#include "MemAccess.h"
#include "Types.h"
#include "ModuleFactory.h"
#include <dfhack/Core.h>
#include "Core.h"
using namespace DFHack;
Module* DFHack::createTranslation()
@ -46,8 +45,8 @@ Module* DFHack::createTranslation()
struct Translation::Private
{
uint32_t genericAddress;
uint32_t transAddress;
void * genericAddress;
void * transAddress;
uint32_t word_table_offset;
uint32_t sizeof_string;
@ -97,15 +96,15 @@ bool Translation::Start()
return false;
Process * p = c.p;
Finish();
DfVector <uint32_t> genericVec (d->genericAddress);
DfVector <uint32_t> transVec (d->transAddress);
vector <char *> & genericVec = *(vector <char *> *) d->genericAddress;
vector <char *> & transVec = *(vector <char *> *) d->transAddress;
DFDict & translations = d->dicts.translations;
DFDict & foreign_languages = d->dicts.foreign_languages;
translations.resize(10);
for (uint32_t i = 0;i < genericVec.size();i++)
{
uint32_t genericNamePtr = genericVec.at(i);
char * genericNamePtr = genericVec[i];
for(int j=0; j<10;j++)
{
string word = p->readSTLString (genericNamePtr + j * d->sizeof_string);
@ -116,11 +115,11 @@ bool Translation::Start()
foreign_languages.resize(transVec.size());
for (uint32_t i = 0; i < transVec.size();i++)
{
uint32_t transPtr = transVec.at(i);
DfVector <uint32_t> trans_names_vec (transPtr + d->word_table_offset);
char * transPtr = transVec.at(i);
vector <void *> & trans_names_vec = *(vector <void *> *) (transPtr + d->word_table_offset);
for (uint32_t j = 0;j < trans_names_vec.size();j++)
{
uint32_t transNamePtr = trans_names_vec.at(j);
void * transNamePtr = trans_names_vec[j];
string name = p->readSTLString (transNamePtr);
foreign_languages[i].push_back (name);
}

@ -34,18 +34,17 @@ distribution.
using namespace std;
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/Error.h"
#include "dfhack/Types.h"
#include "VersionInfo.h"
#include "MemAccess.h"
#include "Error.h"
#include "Types.h"
// we connect to those
#include "dfhack/modules/Materials.h"
#include "dfhack/modules/Units.h"
#include "dfhack/modules/Translation.h"
#include "modules/Materials.h"
#include "modules/Units.h"
#include "modules/Translation.h"
#include "ModuleFactory.h"
#include <dfhack/Core.h>
#include "Core.h"
using namespace DFHack;
@ -54,8 +53,8 @@ struct Units::Private
bool Inited;
bool Started;
uint32_t dwarf_race_index_addr;
uint32_t dwarf_civ_id_addr;
void * dwarf_race_index_addr;
void * dwarf_civ_id_addr;
bool IdMapReady;
std::map<int32_t, int32_t> IdMap;
@ -86,8 +85,8 @@ Units::Units()
try
{
creatures = (vector <df_unit *> *) OG_Creatures->getAddress ("vector");
d->dwarf_race_index_addr = OG_Creatures->getAddress("current_race");
d->dwarf_civ_id_addr = OG_Creatures->getAddress("current_civ");
d->dwarf_race_index_addr = (void *) OG_Creatures->getAddress("current_race");
d->dwarf_civ_id_addr = (void *) OG_Creatures->getAddress("current_civ");
}
catch(Error::All&){};
d->Inited = true;

@ -30,14 +30,13 @@ distribution.
#include <map>
using namespace std;
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/Types.h"
#include "dfhack/modules/Vegetation.h"
#include "dfhack/modules/Translation.h"
#include "VersionInfo.h"
#include "MemAccess.h"
#include "Types.h"
#include "modules/Vegetation.h"
#include "modules/Translation.h"
#include "ModuleFactory.h"
#include <dfhack/Core.h>
#include "Core.h"
using namespace DFHack;
Module* DFHack::createVegetation()

@ -29,18 +29,18 @@ distribution.
#include <map>
using namespace std;
#include "dfhack/VersionInfo.h"
#include "dfhack/Types.h"
#include "dfhack/Error.h"
#include "dfhack/Process.h"
#include "dfhack/modules/Vermin.h"
#include "VersionInfo.h"
#include "Types.h"
#include "Error.h"
#include "MemAccess.h"
#include "modules/Vermin.h"
#include "ModuleFactory.h"
#include "dfhack/Core.h"
#include "Core.h"
using namespace DFHack;
struct Vermin::Private
{
uint32_t spawn_points_vector;
void * spawn_points_vector;
uint32_t race_offset;
uint32_t type_offset;
uint32_t position_offset;
@ -106,7 +106,6 @@ SpawnPoints* Vermin::getSpawnPoints()
cerr << "Couldn't get spawn points: Vermin module not inited" << endl;
return NULL;
}
return new SpawnPoints(this);
}
@ -120,15 +119,11 @@ SpawnPoints::SpawnPoints(Vermin* v_)
cerr << "Couldn't get spawn points: Vermin module not inited" << endl;
return;
}
//p_sp = new DfVector <uint32_t> (v->d->spawn_points_vector);
//p_sp = new vector <void*> (v->d->spawn_points_vector);
p_sp = (vector <void*>*) (v->d->spawn_points_vector);
p_sp = (vector <char*>*) (v->d->spawn_points_vector);
}
SpawnPoints::~SpawnPoints()
{
// Do NOT delete p_sp; it's a pointer to memory the game owns.
}
size_t SpawnPoints::size()
@ -145,7 +140,7 @@ bool SpawnPoints::Read (const uint32_t index, t_spawnPoint & sp)
return false;
// read pointer from vector at position
uint32_t temp = (uint32_t) p_sp->at (index);
char * temp = p_sp->at (index);
sp.origin = temp;
sp.race = v->d->owner->readWord(temp + v->d->race_offset);
@ -166,7 +161,7 @@ bool SpawnPoints::Write (const uint32_t index, t_spawnPoint & sp)
return false;
// read pointer from vector at position
uint32_t temp = (uint32_t) p_sp->at (index);
char * temp = p_sp->at (index);
v->d->owner->writeWord(temp + v->d->race_offset, sp.race);
v->d->owner->writeWord(temp + v->d->type_offset, sp.type);

@ -30,13 +30,13 @@ distribution.
#include <cstring>
using namespace std;
#include "dfhack/modules/World.h"
#include "dfhack/Process.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Types.h"
#include "dfhack/Error.h"
#include "modules/World.h"
#include "MemAccess.h"
#include "VersionInfo.h"
#include "Types.h"
#include "Error.h"
#include "ModuleFactory.h"
#include <dfhack/Core.h>
#include "Core.h"
using namespace DFHack;
@ -54,22 +54,22 @@ struct World::Private
bool Inited;
bool PauseInited;
uint32_t pause_state_offset;
void * pause_state_offset;
bool StartedTime;
uint32_t year_offset;
uint32_t tick_offset;
void * year_offset;
void * tick_offset;
bool StartedWeather;
uint32_t weather_offset;
char * weather_offset;
bool StartedMode;
uint32_t gamemode_offset;
uint32_t controlmode_offset;
uint32_t controlmodecopy_offset;
void * gamemode_offset;
void * controlmode_offset;
void * controlmodecopy_offset;
bool StartedFolder;
uint32_t folder_name_offset;
void * folder_name_offset;
Process * owner;
};

@ -9,17 +9,16 @@
#include <set>
using namespace std;
#include "dfhack/Types.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/modules/Items.h"
#include "dfhack/modules/Units.h"
#include "dfhack/modules/kitchen.h"
#include "Types.h"
#include "VersionInfo.h"
#include "MemAccess.h"
#include "modules/Materials.h"
#include "modules/Items.h"
#include "modules/Units.h"
#include "modules/kitchen.h"
#include "ModuleFactory.h"
#include <dfhack/Core.h>
#include <dfhack/Virtual.h>
#include "Core.h"
#include "Virtual.h"
namespace DFHack
{
@ -44,9 +43,9 @@ namespace Kitchen
std::vector<t_materialIndex>& materialIndices; // the material index vector of the kitchen exclusion list
std::vector<t_exclusionType>& exclusionTypes; // the exclusion type vector of the kitchen excluions list
static uint32_t addr(const DFHack::Core& core, int index)
static void * addr(const DFHack::Core& core, int index)
{
static uint32_t start = core.vinfo->getAddress("kitchen_limits");
static char * start = core.vinfo->getAddress("kitchen_limits");
return start + sizeof(std::vector<int>) * index;
};
};

@ -0,0 +1 @@
Subproject commit d03375ddbd695fda2deb42dd13aa352efccebc60

@ -1,944 +0,0 @@
#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;
my $input_dir = $ARGV[0] || '.';
my $output_dir = $ARGV[1] || 'codegen';
my $main_namespace = $ARGV[2] || 'df';
my $export_prefix = 'DFHACK_EXPORT ';
my %types;
my %type_files;
# Misc XML analysis
our $typename;
our $filename;
sub parse_address($;$) {
my ($str,$in_bits) = @_;
return undef unless defined $str;
# Parse the format used by offset attributes in xml
$str =~ /^0x([0-9a-f]+)(?:\.([0-7]))?$/
or die "Invalid address syntax: $str\n";
my ($full, $bv) = ($1, $2);
die "Bits not allowed: $str\n" unless $in_bits;
return $in_bits ? (hex($full)*8 + ($bv||0)) : hex($full);
}
sub check_bad_attrs($;$$) {
my ($tag, $allow_size, $allow_align) = @_;
die "Cannot use size, alignment or offset for ".$tag->nodeName."\n"
if ((!$allow_size && defined $tag->getAttribute('size')) ||
defined $tag->getAttribute('offset') ||
(!$allow_align && defined $tag->getAttribute('alignment')));
}
sub check_name($) {
my ($name) = @_;
$name =~ /^[_a-zA-Z][_a-zA-Z0-9]*$/
or die "Invalid identifier: $name\n";
return $name;
}
sub is_attr_true($$) {
my ($tag, $name) = @_;
return ($tag->getAttribute($name)||'') eq 'true';
}
sub type_header_def($) {
my ($name) = @_;
return uc($main_namespace).'_'.uc($name).'_H';
}
sub translate_lookup($) {
my ($str) = @_;
return undef unless $str && $str =~ /^\$global((\.[_a-zA-Z0-9]+)+)$/;
my @fields = split /\./, substr($1,1);
my $expr = "df::global::".shift(@fields);
for my $fn (@fields) {
$expr = "_toref($expr).$fn";
}
return $expr;
}
# Text generation with indentation
our @lines;
our $indentation = 0;
sub with_emit(&;$) {
# Executes the code block, and returns emitted lines
my ($blk, $start_indent) = @_;
local @lines;
local $indentation = ($start_indent||0);
$blk->();
return @lines;
}
sub emit(@) {
# Emit an indented line to be returned from with_emit
my $line = join('',map { defined($_) ? $_ : '' } @_);
$line = (' 'x$indentation).$line unless length($line) == 0;
push @lines, $line;
}
sub indent(&) {
# Indent lines emitted from the block by one step
my ($blk) = @_;
local $indentation = $indentation+2;
$blk->();
}
sub outdent(&) {
# Unindent lines emitted from the block by one step
my ($blk) = @_;
local $indentation = ($indentation >= 2 ? $indentation-2 : 0);
$blk->();
}
sub emit_block(&;$$) {
# Emit a full {...} block with indentation
my ($blk, $prefix, $suffix) = @_;
$prefix ||= '';
$suffix ||= '';
emit $prefix,'{';
&indent($blk);
emit '}',$suffix;
}
# Static file output
my @static_lines;
my %static_includes;
sub with_emit_static(&) {
my ($blk) = @_;
$static_includes{$typename}++;
push @static_lines, &with_emit($blk,2);
}
# Anonymous variable names
our $anon_id = 0;
our $anon_prefix;
sub ensure_name($) {
# If the name is empty, assign an auto-generated one
my ($name) = @_;
unless ($name) {
$name = $anon_prefix.(($anon_id == 0) ? '' : '_'.$anon_id);
$anon_id++;
}
return check_name($name);
}
sub with_anon(&;$) {
# Establish a new anonymous namespace
my ($blk,$stem) = @_;
local $anon_id = $stem ? 0 : 1;
local $anon_prefix = ($stem||'anon');
$blk->();
}
# Primitive types
my @primitive_type_list =
qw(int8_t uint8_t int16_t uint16_t
int32_t uint32_t int64_t uint64_t
s-float
bool ptr-string stl-string flag-bit
pointer);
my %primitive_aliases = (
'stl-string' => 'std::string',
'ptr-string' => 'char*',
'flag-bit' => 'void',
'pointer' => 'void*',
's-float' => 'float',
);
my %primitive_types;
$primitive_types{$_}++ for @primitive_type_list;
sub primitive_type_name($) {
my ($tag_name) = @_;
$primitive_types{$tag_name}
or die "Not primitive: $tag_name\n";
return $primitive_aliases{$tag_name} || $tag_name;
}
# Type references
our %weak_refs;
our %strong_refs;
sub register_ref($;$) {
# Register a reference to another type.
# Strong ones require the type to be included.
my ($ref, $is_strong) = @_;
if ($ref) {
my $type = $types{$ref}
or die "Unknown type $ref referenced.\n";
if ($is_strong) {
$strong_refs{$ref}++;
} else {
$weak_refs{$ref}++;
}
}
}
# Determines if referenced other types should be included or forward-declared
our $is_strong_ref = 1;
sub with_struct_block(&$;$%) {
my ($blk, $tag, $name, %flags) = @_;
my $kwd = (is_attr_true($tag,'is-union') ? "union" : "struct");
my $exp = $flags{-export} ? $export_prefix : '';
my $prefix = $kwd.' '.$exp.($name ? $name.' ' : '');
emit_block {
local $_;
local $is_strong_ref = 1; # reset the state
if ($flags{-no_anon}) {
$blk->();
} else {
&with_anon($blk);
}
} $prefix, ";";
}
sub decode_type_name_ref($;%) {
# Interpret the type-name field of a tag
my ($tag,%flags) = @_;
my $force_type = $flags{-force_type};
my $force_strong = $flags{-force_strong};
my $tname = $tag->getAttribute($flags{-attr_name} || 'type-name')
or return undef;
if ($primitive_types{$tname}) {
die "Cannot use type $tname as type-name of ".$tag->nodeName."\n"
if ($force_type && $force_type ne 'primitive');
return primitive_type_name($tname);
} else {
register_ref $tname, ($force_strong||$is_strong_ref);
die "Cannot use type $tname as type-name of ".$tag->nodeName."\n"
if ($force_type && $force_type ne $types{$tname}->nodeName);
return $main_namespace.'::'.$tname;
}
}
# CONDITIONALS
sub is_conditional($) {
my ($tag) = @_;
return $tag->nodeName =~ /^(cond-if|cond-elseif)$/;
}
sub translate_if_cond($) {
my ($tag) = @_;
my @rules;
if (my $defvar = $tag->getAttribute('defined')) {
push @rules, "defined($defvar)";
}
if (my $cmpvar = $tag->getAttribute('var')) {
if (my $cmpval = $tag->getAttribute('lt')) {
push @rules, "($cmpvar < $cmpval)";
}
if (my $cmpval = $tag->getAttribute('le')) {
push @rules, "($cmpvar <= $cmpval)";
}
if (my $cmpval = $tag->getAttribute('eq')) {
push @rules, "($cmpvar == $cmpval)";
}
if (my $cmpval = $tag->getAttribute('ge')) {
push @rules, "($cmpvar >= $cmpval)";
}
if (my $cmpval = $tag->getAttribute('gt')) {
push @rules, "($cmpvar > $cmpval)";
}
if (my $cmpval = $tag->getAttribute('ne')) {
push @rules, "($cmpvar != $cmpval)";
}
}
return '('.(join(' && ',@rules) || '1').')';
}
our $in_cond = 0;
sub render_cond_if($$$;@) {
my ($tag, $in_elseif, $render_cb, @tail) = @_;
local $in_cond = 1;
{
local $indentation = 0;
my $op = ($in_elseif && $in_elseif >= 2) ? '#elif' : '#if';
emit $op, ' ', translate_if_cond($tag);
}
for my $child ($tag->findnodes('child::*')) {
&render_cond($child, $render_cb, @tail);
}
unless ($in_elseif) {
local $indentation = 0;
emit "#endif";
}
}
sub render_cond($$;@) {
my ($tag, $render_cb, @tail) = @_;
my $tag_name = $tag->nodeName;
if ($tag_name eq 'cond-if') {
render_cond_if($tag, 0, $render_cb, @tail);
} elsif ($tag_name eq 'cond-elseif') {
my $idx = 1;
for my $child ($tag->findnodes('child::*')) {
($child->nodeName eq 'cond-if')
or die "Only cond-if tags may be inside a cond-switch: ".$child->nodeName."\n";
render_cond_if($child, $idx++, $render_cb, @tail);
}
{
local $indentation = 0;
emit "#endif";
}
} else {
local $_ = $tag;
$render_cb->($tag, @tail);
}
}
# ENUM
sub render_enum_core($$) {
my ($name,$tag) = @_;
my $base = 0;
emit_block {
my @items = $tag->findnodes('child::*');
my $idx = 0;
for my $item (@items) {
render_cond $item, sub {
my $tag = $_->nodeName;
return if $tag eq 'enum-attr';
($tag eq 'enum-item')
or die "Invalid enum member: ".$item->nodeName."\n";
my $name = ensure_name $_->getAttribute('name');
my $value = $_->getAttribute('value');
$base = ($idx == 0 && !$in_cond) ? $value : undef if defined $value;
$idx++;
emit $name, (defined($value) ? ' = '.$value : ''), ',';
};
}
emit "_last_item_of_$name";
} "enum $name ", ";";
return $base;
}
sub render_enum_tables($$$) {
my ($name,$tag,$base) = @_;
# Enumerate enum attributes
my %aidx = ('key' => 0);
my @anames = ('key');
my @avals = ('NULL');
my @atypes = ('const char*');
my @atnames = (undef);
for my $attr ($tag->findnodes('child::enum-attr')) {
my $name = $attr->getAttribute('name') or die "Unnamed enum-attr.\n";
my $type = $attr->getAttribute('type-name');
my $def = $attr->getAttribute('default-value');
die "Duplicate attribute $name.\n" if exists $aidx{$name};
check_name $name;
$aidx{$name} = scalar @anames;
push @anames, $name;
push @atnames, $type;
if ($type) {
push @atypes, $type;
push @avals, (defined $def ? $def : "($type)0");
} else {
push @atypes, 'const char*';
push @avals, (defined $def ? "\"$def\"" : 'NULL');
}
}
# Emit accessor function prototypes
emit "const $name _first_item_of_$name = ($name)$base;";
emit_block {
emit "return (value >= _first_item_of_$name && value < _last_item_of_$name);";
} "inline bool is_valid($name value) ";
for (my $i = 0; $i < @anames; $i++) {
emit "${export_prefix}$atypes[$i] get_$anames[$i]($name value);";
}
# Emit implementation
with_emit_static {
emit_block {
emit_block {
# Emit the entry type
emit_block {
for (my $i = 0; $i < @anames; $i++) {
emit "$atypes[$i] $anames[$i];";
}
} "struct _info_entry ", ";";
# Emit the info table
emit_block {
for my $item ($tag->findnodes('child::*')) {
render_cond $item, sub {
my $tag = $_->nodeName;
return if $tag eq 'enum-attr';
# Assemble item-specific attr values
my @evals = @avals;
my $name = $_->getAttribute('name');
$evals[0] = "\"$name\"" if $name;
for my $attr ($_->findnodes('child::item-attr')) {
my $name = $attr->getAttribute('name') or die "Unnamed item-attr.\n";
my $value = $attr->getAttribute('value') or die "No-value item-attr.\n";
my $idx = $aidx{$name} or die "Unknown item-attr: $name\n";
if ($atnames[$idx]) {
$evals[$idx] = $value;
} else {
$evals[$idx] = "\"$value\"";
}
}
emit "{ ",join(', ',@evals)," },";
};
}
emit "{ ",join(', ',@avals)," }";
} "static const _info_entry _info[] = ", ";";
for (my $i = 0; $i < @anames; $i++) {
emit_block {
emit "return is_valid(value) ? _info[value - $base].$anames[$i] : $avals[$i];";
} "$atypes[$i] get_$anames[$i]($name value) ";
}
} "namespace $name ";
} "namespace enums ";
};
}
sub render_enum_type {
my ($tag) = @_;
emit_block {
emit_block {
my $base = render_enum_core($typename,$tag);
if (defined $base) {
render_enum_tables($typename,$tag,$base);
} else {
print STDERR "Warning: complex enum: $typename\n";
}
} "namespace $typename ";
} "namespace enums ";
emit "using enums::",$typename,"::",$typename,";";
}
# BITFIELD
sub get_primitive_base($;$) {
my ($tag, $default) = @_;
my $base = $tag->getAttribute('base-type') || $default || 'uint32_t';
$primitive_types{$base} or die "Must be primitive: $base\n";
return $base;
}
sub render_bitfield_core {
my ($name, $tag) = @_;
emit_block {
emit get_primitive_base($tag), ' whole;';
emit_block {
for my $item ($tag->findnodes('child::*')) {
render_cond $item, sub {
my ($item) = @_;
($item->nodeName eq 'flag-bit')
or die "Invalid bitfield member:".$item->nodeName."\n";
check_bad_attrs($item);
my $name = ensure_name $item->getAttribute('name');
my $size = $item->getAttribute('count') || 1;
emit "unsigned ", $name, " : ", $size, ";";
};
}
} "struct ", " bits;";
} "union $name ", ";";
}
sub render_bitfield_type {
my ($tag) = @_;
render_bitfield_core($typename,$tag);
}
# STRUCT
my %struct_field_handlers;
sub get_struct_fields($) {
# Retrieve subtags that are actual struct fields
my ($struct_tag) = @_;
local $_;
return grep {
my $tag = $_->nodeName;
die "Unknown field tag: $tag\n"
unless exists $struct_field_handlers{$tag};
$struct_field_handlers{$tag};
} $struct_tag->findnodes('child::*');
}
sub get_struct_field_type($) {
# Dispatch on the tag name, and retrieve the type prefix & suffix
my ($tag) = @_;
my $handler = $struct_field_handlers{$tag->nodeName}
or die "Unexpected tag: ".$tag->nodeName;
return $handler->($tag);
}
sub do_render_struct_field($) {
my ($tag) = @_;
my $tag_name = $tag->nodeName;
my $field_name = $tag->getAttribute('name');
# Special case: anonymous compounds.
if ($tag_name eq 'compound' && !defined $field_name &&
!defined $tag->getAttribute('type-name'))
{
check_bad_attrs($tag);
with_struct_block {
render_struct_field($_) for get_struct_fields($tag);
} $tag, undef, -no_anon => 1;
return;
}
# Otherwise, create the name if necessary, and render
my $name = ensure_name $field_name;
with_anon {
my ($prefix, $postfix) = get_struct_field_type($tag);
emit $prefix, ' ', $name, $postfix, ';';
} "T_$name";
}
sub render_struct_field($) {
my ($tag) = @_;
render_cond $tag, \&do_render_struct_field;
}
sub emit_typedef($$) {
# Convert a prefix/postfix pair into a single name
my ($pre, $post) = @_;
my $name = ensure_name undef;
emit 'typedef ', $pre, ' ', $name, $post, ';';
return $name;
}
sub get_container_item_type($$;$) {
# Interpret the type-name and nested fields for a generic container type
my ($tag,$strong_ref,$allow_void) = @_;
check_bad_attrs($tag);
my $prefix;
my $postfix = '';
local $is_strong_ref = $strong_ref;
unless ($prefix = decode_type_name_ref($tag)) {
my @fields = get_struct_fields($tag);
if (scalar(@fields) == 1 && !is_conditional($fields[0])) {
($prefix, $postfix) = get_struct_field_type($fields[0]);
} elsif (scalar(@fields) == 0) {
$allow_void or die "Empty container: ".$tag->nodeName."\n";
$prefix = $allow_void;
} else {
$prefix = ensure_name undef;
with_struct_block {
render_struct_field($_) for @fields;
} $tag, $prefix;
}
}
return ($prefix,$postfix) if wantarray;
return emit_typedef($prefix, $postfix) if $postfix;
return $prefix;
}
sub get_primitive_field_type {
# Primitive type handler
my ($tag,$fname) = @_;
check_bad_attrs($tag);
my $name = $tag->nodeName;
return (primitive_type_name($name), "");
}
sub get_static_string_type {
# Static string handler
my ($tag, $fname) = @_;
check_bad_attrs($tag, 1);
my $count = $tag->getAttribute('size') || 0;
return ('char', "[$count]");
}
sub get_padding_type {
# Padding handler. Supports limited alignment.
my ($tag, $fname) = @_;
check_bad_attrs($tag, 1, 1);
my $count = $tag->getAttribute('size') || 0;
my $align = $tag->getAttribute('alignment') || 1;
if ($align == 1) {
return ('char', "[$count]");
} elsif ($align == 2) {
($count % 2 == 0) or die "Size not aligned in padding: $count at $align\n";
return ('short', "[".($count/2)."]");
} elsif ($align == 4) {
($count % 4 == 0) or die "Size not aligned in padding: $count at $align\n";
return ('int', "[".($count/4)."]");
} else {
die "Bad padding alignment $align in $typename in $filename\n";
}
}
sub get_static_array_type {
# static-array handler
my ($tag, $fname) = @_;
my ($pre, $post) = get_container_item_type($tag, 1);
my $count = $tag->getAttribute('count')
or die "Count is mandatory for static-array in $typename in $filename\n";
return ($pre, "[$count]".$post);
}
sub get_pointer_type($) {
# pointer handler
my ($tag) = @_;
my $item = get_container_item_type($tag, 0, 'void');
return ($item.'*', '');
}
sub get_compound_type($) {
# compound (nested struct) handler
my ($tag) = @_;
check_bad_attrs($tag);
my $tname = decode_type_name_ref($tag);
unless ($tname) {
$tname = ensure_name undef;
with_struct_block {
render_struct_field($_) for get_struct_fields($tag);
} $tag, $tname;
}
return ($tname,'');
}
sub get_bitfield_type($) {
# nested bitfield handler
my ($tag) = @_;
check_bad_attrs($tag);
my $tname = decode_type_name_ref($tag, -force_type => 'bitfield-type');
unless ($tname) {
$tname = ensure_name undef;
with_anon {
render_bitfield_core($tname, $tag);
};
}
return ($tname,'');
}
sub get_enum_type($) {
# nested enum handler
my ($tag) = @_;
check_bad_attrs($tag);
my $tname = decode_type_name_ref($tag, -force_type => 'enum-type', -force_strong => 1);
my $base = get_primitive_base($tag, 'int32_t');
unless ($tname) {
$tname = ensure_name undef;
with_anon {
render_enum_core($tname,$tag);
};
}
return ("enum_field<$tname,$base>", '');
}
sub get_stl_vector_type($) {
# STL vector
my ($tag) = @_;
my $item = get_container_item_type($tag,1,'void*');
$item = 'char' if $item eq 'bool';
return ("std::vector<$item>", '');
}
sub get_stl_bit_vector_type($) {
# STL bit vector
my ($tag) = @_;
check_bad_attrs($tag);
return ("std::vector<bool>", '');
}
sub get_df_flagarray_type($) {
# DF flag array
my ($tag) = @_;
check_bad_attrs($tag);
my $type = decode_type_name_ref($tag, -attr_name => 'index-enum', -force_type => 'enum-type', -force_strong => 1) || 'int';
return ("BitArray<$type>", '');
}
# Struct dispatch table and core
%struct_field_handlers = (
'comment' => undef, # skip
'code-helper' => undef, # skip
'cond-if' => sub { die "cond handling error"; },
'cond-elseif' => sub { die "cond handling error"; },
'static-string' => \&get_static_string_type,
'padding' => \&get_padding_type,
'static-array' => \&get_static_array_type,
'pointer' => \&get_pointer_type,
'compound' => \&get_compound_type,
'bitfield' => \&get_bitfield_type,
'enum' => \&get_enum_type,
'stl-vector' => \&get_stl_vector_type,
'stl-bit-vector' => \&get_stl_bit_vector_type,
'df-flagarray' => \&get_df_flagarray_type,
);
$struct_field_handlers{$_} ||= \&get_primitive_field_type for @primitive_type_list;
sub emit_find_instance {
my ($tag) = @_;
my $instance_vector = translate_lookup $tag->getAttribute('instance-vector');
if ($instance_vector) {
emit "static std::vector<$typename*> &get_vector();";
emit "static $typename *find(int id);";
with_emit_static {
emit_block {
emit "return ", $instance_vector, ";";
} "std::vector<$typename*>& ${typename}::get_vector() ";
emit_block {
emit "std::vector<$typename*> &vec_ = get_vector();";
if (my $id = $tag->getAttribute('key-field')) {
emit "return binsearch_in_vector(vec_, &${typename}::$id, id_);";
} else {
emit "return (id_ >= 0 && id_ < vec_.size()) ? vec_[id_] : NULL;";
}
} "$typename *${typename}::find(int id_) ";
}
}
}
sub render_struct_type {
my ($tag) = @_;
my $tag_name = $tag->nodeName;
my $is_class = ($tag_name eq 'class-type');
my $has_methods = $is_class || is_attr_true($tag, 'has-methods');
my $inherits = $tag->getAttribute('inherits-from');
my $original_name = $tag->getAttribute('original-name');
my $ispec = '';
if ($inherits) {
register_ref $inherits, 1;
$ispec = ' : '.$inherits;
} elsif ($is_class) {
$ispec = ' : virtual_class';
}
with_struct_block {
render_struct_field($_) for get_struct_fields($tag);
emit_find_instance($tag);
if ($has_methods) {
if ($is_class) {
emit "static class_virtual_identity<$typename> _identity;";
with_emit_static {
emit "class_virtual_identity<$typename> ${typename}::_identity(",
"\"$typename\",",
($original_name ? "\"$original_name\"" : 'NULL'), ',',
($inherits ? "&${inherits}::_identity" : 'NULL'),
");";
}
}
outdent {
emit "protected:";
};
if ($is_class) {
emit "virtual ~",$typename,"() {}";
} else {
emit "~",$typename,"() {}";
}
}
} $tag, "$typename$ispec", -export => 1;
}
# MAIN BODY
# Collect all type definitions from XML files
sub add_type_to_hash($) {
my ($type) = @_;
my $name = $type->getAttribute('type-name')
or die "Type without a name in $filename\n";
die "Duplicate definition of $name in $filename\n" if $types{$name};
local $typename = $name;
check_bad_attrs $type;
$types{$name} = $type;
$type_files{$name} = $filename;
}
for my $fn (glob "$input_dir/*.xml") {
local $filename = $fn;
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file($filename);
add_type_to_hash $_ foreach $doc->findnodes('/data-definition/enum-type');
add_type_to_hash $_ foreach $doc->findnodes('/data-definition/bitfield-type');
add_type_to_hash $_ foreach $doc->findnodes('/data-definition/struct-type');
add_type_to_hash $_ foreach $doc->findnodes('/data-definition/class-type');
}
# Generate text representations
my %type_handlers = (
'enum-type' => \&render_enum_type,
'bitfield-type' => \&render_bitfield_type,
'class-type' => \&render_struct_type,
'struct-type' => \&render_struct_type,
);
my %type_data;
for my $name (sort { $a cmp $b } keys %types) {
local $typename = $name;
local $filename = $type_files{$typename};
local %weak_refs;
local %strong_refs;
eval {
my $type = $types{$typename};
# Emit the actual type definition
my @code = with_emit {
with_anon {
$type_handlers{$type->nodeName}->($type);
};
} 2;
delete $weak_refs{$name};
delete $strong_refs{$name};
# Add wrapping
my @all = with_emit {
my $def = type_header_def($typename);
emit "#ifndef $def";
emit "#define $def";
for my $strong (sort { $a cmp $b } keys %strong_refs) {
my $sdef = type_header_def($strong);
emit "#ifndef $sdef";
emit "#include \"$strong.h\"";
emit "#endif";
}
emit_block {
for my $weak (sort { $a cmp $b } keys %weak_refs) {
next if $strong_refs{$weak};
my $ttype = $types{$weak};
my $tstr = 'struct';
$tstr = 'enum' if $ttype->nodeName eq 'enum-type';
$tstr = 'union' if $ttype->nodeName eq 'bitfield-type';
$tstr = 'union' if ($ttype->nodeName eq 'struct-type' && is_attr_true($ttype,'is-union'));
emit $tstr, ' ', $weak, ';';
}
push @lines, @code;
} "namespace $main_namespace ";
emit "#endif";
};
$type_data{$typename} = \@all;
};
if ($@) {
print 'Error: '.$@."Type $typename in $filename ignored\n";
}
}
# Write output files
mkdir $output_dir;
{
# Delete the old files
for my $name (glob "$output_dir/*.h") {
unlink $name;
}
# Write out the headers
local $, = "\n";
local $\ = "\n";
for my $name (keys %type_data) {
open FH, ">$output_dir/$name.h";
print FH "/* THIS FILE WAS GENERATED. DO NOT EDIT. */";
print FH @{$type_data{$name}};
close FH;
}
# Write out the static file
open FH, ">$output_dir/static.inc";
print FH "/* THIS FILE WAS GENERATED. DO NOT EDIT. */";
for my $name (sort { $a cmp $b } keys %static_includes) {
print FH "#include \"$name.h\"";
}
print FH "namespace $main_namespace {";
print FH @static_lines;
print FH '}';
close FH;
}

@ -1,58 +0,0 @@
<data-definition>
<class-type type-name='building_def' original-name='building_defst' key-field='code'>
<stl-string name="code"/>
<int32_t name="index"/>
<stl-string name="name"/>
<int32_t name='unk_40'/>
<int32_t name='unk_44'/>
<static-array name='name_color' count='3' type-name='int16_t'/>
<static-array name='tile' count='4'>
<static-array count='31'>
<static-array count='31' type-name='uint8_t'/>
</static-array>
</static-array>
<static-array name='tile_color' count='3'>
<static-array count='4'>
<static-array count='31'>
<static-array count='31' type-name='uint8_t'/>
</static-array>
</static-array>
</static-array>
<static-array name='tile_block' count='31'>
<static-array count='31' type-name='uint8_t'/>
</static-array>
<int32_t name='build_key'/>
<bool name='needs_magma'/>
<stl-vector name="build_items">
<pointer/>
</stl-vector>
<int32_t name="dim_x"/>
<int32_t name="dim_y"/>
<int32_t name="workloc_x"/>
<int32_t name="workloc_y"/>
<stl-vector name="build_labors">
<enum base-type='int32_t' type-name='unit_labor'/>
</stl-vector>
<stl-string name="labor_description"/>
<int32_t name="build_stages"/>
</class-type>
<class-type type-name='building_def_workshopst' inherits-from='building_def'/>
<class-type type-name='building_def_furnacest' inherits-from='building_def'/>
</data-definition>
<!--
Local Variables:
indent-tabs-mode: nil
nxml-child-indent: 4
End:
-->

@ -1,403 +0,0 @@
<data-definition>
<bitfield-type type-name='building_flags'>
<flag-bit name='exists' comment='actually built, not just ordered'/>
<flag-bit/>
<flag-bit name='room_collision' comment='major intersection with another room?'/>
<flag-bit/>
<flag-bit name='justice'/>
</bitfield-type>
<class-type type-name='building' original-name='buildingst'
instance-vector='$global.world.buildings.all' key-field='id'>
<int32_t name='x1' comment='left'/>
<int32_t name='y1'/>
<int32_t name='x2' comment='work location'/>
<int32_t name='x3' comment='right'/>
<int32_t name='y3'/>
<int32_t name='y2'/>
<int32_t name='z'/>
<compound name='flags' type-name='building_flags'/>
<int16_t name='materialType' ref-target='material' aux-value='$$.materialIndex'/>
<int32_t name='materialIndex'/>
<compound name='room'>
<pointer name='extents' type-name='uint8_t'>
<comment>0 - not room; 1 in stockpile; 2 wall; 3 inner; 4 distance boundary.</comment>
</pointer>
<int32_t name='x'/>
<int32_t name='y'/>
<int32_t name='width'/>
<int32_t name='height'/>
</compound>
<int32_t name='age'/>
<int16_t name='race' ref-target='creature_raw'/>
<int32_t name='id'/>
<stl-vector name='jobs'>
<pointer type-name='job'/>
</stl-vector>
<stl-vector name='meetings'>
<pointer type-name='meeting_ref'/>
</stl-vector>
<stl-vector name='unk6' type-name='pointer'/>
<bool name='is_room'/>
<stl-vector name='children' comment='other buildings within this room'>
<pointer type-name='building'/>
</stl-vector>
<stl-vector name='parents' comment='rooms this building belongs to'>
<pointer type-name='building'/>
</stl-vector>
<pointer type-name='unit' name='owner'/>
<stl-vector name='unk7' type-name='pointer'/>
<stl-string name='name'/>
<stl-vector name='activities'>
<pointer>
<int32_t name='id' ref-target='activity_entry'/>
<int32_t name='is_group'/>
</pointer>
</stl-vector>
</class-type>
-- stockpile --
<class-type type-name='building_stockpilest' inherits-from='building'>
<compound type-name='stockpile_settings' name='settings'/>
<int16_t name='max_barrels'/>
<int16_t name='max_bins'/>
<stl-vector name='container_type'>
<enum base-type='int16_t' type-name='item_type'/>
</stl-vector>
<stl-vector name='container_item_id'>
<int32_t ref-target='item'/>
</stl-vector>
<stl-vector name='container_x' type-name='int16_t'/>
<stl-vector name='container_y' type-name='int16_t'/>
<pointer name='give_to' type-name='building_stockpilest'/>
<stl-vector name='take_from'>
<pointer type-name='building_stockpilest'/>
</stl-vector>
<int32_t name='stockpile_number'/>
</class-type>
-- zone --
<class-type type-name='building_civzonest' inherits-from='building'>
</class-type>
-- actual --
<class-type type-name='building_actual' inherits-from='building'
original-name='building_actualst'>
<int16_t name='construction_stage'
comment='0 not started, then 1 or 3 max depending on type'/>
<stl-vector name='contained_items'>
<pointer>
<pointer name='item' type-name='item'/>
<int16_t name='use_mode'/>
</pointer>
</stl-vector>
<pointer name='design' type-name='building_design'/>
</class-type>
<struct-type type-name='building_design'>
<int32_t name='architect' ref-target='historical_figure'/>
<int32_t name='unk2' comment='-1'/>
<int16_t name='unk3'/>
<int32_t name='builder1' ref-target='historical_figure'/>
<int32_t name='unk5' comment='-1'/>
<int16_t name='unk6'/>
<int16_t name='build_timer1' comment='+1 per 10 frames while building'/>
<int32_t name='builder2' ref-target='historical_figure'/>
<int16_t name='build_timer2'/>
<int16_t name='unk8b'/>
<int16_t name='unk9'/>
<bitfield name='flags' base-type='uint32_t'>
<flag-bit name='rough' comment='rough gabbro road'/>
<flag-bit name='built'/>
<flag-bit name='designed'/>
</bitfield>
<int32_t name='unk11'/>
<int32_t name='unk12'/>
<int32_t name='unk13'/>
</struct-type>
-- workshops --
<enum-type type-name='furnace_type'>
<enum-item name="WoodFurnace"/>
<enum-item name="Smelter"/>
<enum-item name="GlassFurnace"/>
<enum-item name="Kiln"/>
<enum-item name="MagmaSmelter"/>
<enum-item name="MagmaGlassFurnace"/>
<enum-item name="MagmaKiln"/>
<enum-item name="Custom"/>
</enum-type>
<class-type type-name='building_furnacest' inherits-from='building_actual'>
<stl-vector name='melt_remainder' type-name='int32_t'
index-refers-to='(material-by-id 0 $)'/>
<int16_t name="unk_108"/>
<enum base-type='int16_t' name="type" type-name='furnace_type'/>
<stl-vector name="permitted_workers">
<int32_t ref-target='unit'/>
</stl-vector>
<int32_t name="min_level"/>
<int32_t name="max_level"/>
<int32_t name="custom_type" refers-to='$global.world.raws.buildings.furnaces[$]'/>
</class-type>
<enum-type type-name='workshop_type'>
<enum-item name="Carpenters"/>
<enum-item name="Farmers"/>
<enum-item name="Masons"/>
<enum-item name="Craftdwarfs"/>
<enum-item name="Jewelers"/>
<enum-item name="MetalsmithsForge"/>
<enum-item name="MagmaForge"/>
<enum-item name="Bowyers"/>
<enum-item name="Mechanics"/>
<enum-item name="Siege"/>
<enum-item name="Butchers"/>
<enum-item name="Leatherworks"/>
<enum-item name="Tanners"/>
<enum-item name="Clothiers"/>
<enum-item name="Fishery"/>
<enum-item name="Still"/>
<enum-item name="Loom"/>
<enum-item name="Quern"/>
<enum-item name="Kennels"/>
<enum-item name="Kitchen"/>
<enum-item name="Ashery"/>
<enum-item name="Dyers"/>
<enum-item name="Millstone"/>
<enum-item name="Custom"/>
</enum-type>
<class-type type-name='building_workshopst' inherits-from='building_actual'>
<enum base-type='int16_t' name="type" type-name='workshop_type'/>
<stl-vector name="permitted_workers">
<int32_t ref-target='unit'/>
</stl-vector>
<int32_t name="min_level"/>
<int32_t name="max_level"/>
<int32_t name="machine_id" ref-target='machine'/>
<int32_t name="unk_118"/>
<int32_t name="custom_type" refers-to='$global.world.raws.buildings.workshops[$]'/>
</class-type>
-- misc --
<class-type type-name='building_animaltrapst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_archerytargetst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_armorstandst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_bars_verticalst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_bars_floorst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_bedst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_boxst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_bridgest' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_cabinetst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_cagest' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_chainst' inherits-from='building_actual'>
<pointer name='assigned' type-name='unit'/>
<pointer name='chained' type-name='unit'/>
<int16_t name='unk'/>
</class-type>
<class-type type-name='building_chairst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_coffinst' inherits-from='building_actual'>
<bitfield name='burial_mode' base-type='uint16_t'>
<flag-bit name='allow_burial'/>
<flag-bit name='no_citizens'/>
<flag-bit name='no_pets'/>
</bitfield>
</class-type>
<class-type type-name='building_constructionst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_doorst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_farmplotst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_floodgatest' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_grate_floorst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_grate_wallst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_hatchst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_hivest' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_nestst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_nest_boxst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_roadst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_road_dirtst' inherits-from='building_roadst'>
</class-type>
<class-type type-name='building_road_pavedst' inherits-from='building_roadst'>
</class-type>
<class-type type-name='building_shopst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_siegeenginest' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_slabst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_statuest' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_supportst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_tablest' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_traction_benchst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_tradedepotst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_trapst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_wagonst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_weaponst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_weaponrackst' inherits-from='building_actual'>
<int16_t name='unk_c0'/>
<stl-vector name='assignments'>
<pointer>
<int32_t name='squad_id' ref-target='squad'/>
<compound name='mode' type-name='squad_use_flags'/>
</pointer>
</stl-vector>
<int32_t name='unk_d0'/>
</class-type>
<class-type type-name='building_wellst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_windowst' inherits-from='building_actual'>
</class-type>
<class-type type-name='building_window_glassst' inherits-from='building_windowst'>
</class-type>
<class-type type-name='building_window_gemst' inherits-from='building_windowst'>
</class-type>
</data-definition>
<!--
Local Variables:
indent-tabs-mode: nil
nxml-child-indent: 4
End:
-->

@ -1,592 +0,0 @@
<data-definition>
<enum-type type-name='creature_raw_flags'>
<enum-item/>
<enum-item name='EQUIPMENT_WAGON'/>
<enum-item name='MUNDANE'/>
<enum-item name='VERMIN_EATER'/>
<enum-item name='VERMIN_GROUNDER'/>
<enum-item name='VERMIN_ROTTER'/>
<enum-item name='VERMIN_SOIL'/>
<enum-item name='VERMIN_SOIL_COLONY'/>
<enum-item name='LARGE_ROAMING'/>
<enum-item name='VERMIN_FISH'/>
<enum-item name='LOOSE_CLUSTERS'/>
<enum-item name='FANCIFUL'/>
<enum-item name='BIOME_MOUNTAIN'/>
<enum-item name='BIOME_GLACIER'/>
<enum-item name='BIOME_TUNDRA'/>
<enum-item name='BIOME_SWAMP_TEMPERATE_FRESHWATER'/>
<enum-item name='BIOME_SWAMP_TEMPERATE_SALTWATER'/>
<enum-item name='BIOME_MARSH_TEMPERATE_FRESHWATER'/>
<enum-item name='BIOME_MARSH_TEMPERATE_SALTWATER'/>
<enum-item name='BIOME_SWAMP_TROPICAL_FRESHWATER'/>
<enum-item name='BIOME_SWAMP_TROPICAL_SALTWATER'/>
<enum-item name='BIOME_SWAMP_MANGROVE'/>
<enum-item name='BIOME_MARSH_TROPICAL_FRESHWATER'/>
<enum-item name='BIOME_MARSH_TROPICAL_SALTWATER'/>
<enum-item name='BIOME_FOREST_TAIGA'/>
<enum-item name='BIOME_FOREST_TEMPERATE_CONIFER'/>
<enum-item name='BIOME_FOREST_TEMPERATE_BROADLEAF'/>
<enum-item name='BIOME_FOREST_TROPICAL_CONIFER'/>
<enum-item name='BIOME_FOREST_TROPICAL_DRY_BROADLEAF'/>
<enum-item name='BIOME_FOREST_TROPICAL_MOIST_BROADLEAF'/>
<enum-item name='BIOME_GRASSLAND_TEMPERATE'/>
<enum-item name='BIOME_SAVANNA_TEMPERATE'/>
<enum-item name='BIOME_SHRUBLAND_TEMPERATE'/>
<enum-item name='BIOME_GRASSLAND_TROPICAL'/>
<enum-item name='BIOME_SAVANNA_TROPICAL'/>
<enum-item name='BIOME_SHRUBLAND_TROPICAL'/>
<enum-item name='BIOME_DESERT_BADLAND'/>
<enum-item name='BIOME_DESERT_ROCK'/>
<enum-item name='BIOME_DESERT_SAND'/>
<enum-item name='BIOME_OCEAN_TROPICAL'/>
<enum-item name='BIOME_OCEAN_TEMPERATE'/>
<enum-item name='BIOME_OCEAN_ARCTIC'/>
<enum-item name='BIOME_SUBTERRANEAN_WATER'/>
<enum-item name='BIOME_SUBTERRANEAN_CHASM'/>
<enum-item name='BIOME_SUBTERRANEAN_LAVA'/>
<enum-item name='BIOME_POOL_TEMPERATE_FRESHWATER'/>
<enum-item name='BIOME_POOL_TEMPERATE_BRACKISHWATER'/>
<enum-item name='BIOME_POOL_TEMPERATE_SALTWATER'/>
<enum-item name='BIOME_POOL_TROPICAL_FRESHWATER'/>
<enum-item name='BIOME_POOL_TROPICAL_BRACKISHWATER'/>
<enum-item name='BIOME_POOL_TROPICAL_SALTWATER'/>
<enum-item name='BIOME_LAKE_TEMPERATE_FRESHWATER'/>
<enum-item name='BIOME_LAKE_TEMPERATE_BRACKISHWATER'/>
<enum-item name='BIOME_LAKE_TEMPERATE_SALTWATER'/>
<enum-item name='BIOME_LAKE_TROPICAL_FRESHWATER'/>
<enum-item name='BIOME_LAKE_TROPICAL_BRACKISHWATER'/>
<enum-item name='BIOME_LAKE_TROPICAL_SALTWATER'/>
<enum-item name='BIOME_RIVER_TEMPERATE_FRESHWATER'/>
<enum-item name='BIOME_RIVER_TEMPERATE_BRACKISHWATER'/>
<enum-item name='BIOME_RIVER_TEMPERATE_SALTWATER'/>
<enum-item name='BIOME_RIVER_TROPICAL_FRESHWATER'/>
<enum-item name='BIOME_RIVER_TROPICAL_BRACKISHWATER'/>
<enum-item name='BIOME_RIVER_TROPICAL_SALTWATER'/>
<enum-item name='GOOD'/>
<enum-item name='EVIL'/>
<enum-item name='SAVAGE'/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item name='GENERATED'/>
<enum-item/>
<enum-item/>
<enum-item name='DOES_NOT_EXIST'/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item name='ARTIFICIAL_HIVEABLE'/>
<enum-item name='UBIQUITOUS'/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
<enum-item/>
</enum-type>
<struct-type type-name='body_part_layer_raw' key-field='layer_name'>
<stl-string name='layer_name'/>
<int32_t name='tissue_id'/>
<df-flagarray name='flags'/>
<int32_t name='unk2'/>
<int32_t name='healing_rate'/>
<int32_t name='vascular'/>
<int32_t name='pain_receptors'/>
<int32_t name='unk6'/>
<int16_t name='unk7'/>
<stl-vector name='unk8'/>
<int32_t name='layer_id' comment='across all body parts'/>
<int32_t name='unk10'/>
<int32_t name='unk11'/>
<int32_t name='layer_depth' comment='-1 for skin and internal organs'/>
<int32_t name='unk13'/>
<int32_t name='unk14'/>
<int32_t name='unk15'/>
<int32_t name='unk16'/>
</struct-type>
<struct-type type-name='body_part_raw' key-field='part_name'>
<stl-string name='part_code'/>
<stl-string name='part_name'/>
<int16_t name='con_part_id'/>
<df-flagarray name='flags'/>
<stl-vector name='layers'>
<pointer type-name='body_part_layer_raw'/>
</stl-vector>
<int32_t name='unk2'/>
<int32_t name='unk3'/>
<int32_t name='unk4'/>
<int32_t name='unk5'/>
<int32_t name='relsize'/>
<int32_t name='unk7'/>
<int16_t name='unk7b'/>
<stl-vector name='name_singular'>
<pointer type-name='stl-string'/>
</stl-vector>
<stl-vector name='name_plural'>
<pointer type-name='stl-string'/>
</stl-vector>
<pointer name='bp_relation_part_id'>
<stl-vector type-name='int16_t'/>
</pointer>
<pointer name='bp_relation_code'>
<stl-vector type-name='int16_t'/> // 0 around of, 1 around by
</pointer>
<pointer name='bp_relation_coverage'>
<stl-vector type-name='int16_t'/>
</pointer>
<uint16_t name='min_temp'/>
<uint16_t name='max_temp'/>
<uint16_t name='temp_factor'/>
<int32_t name='unused'/>
<int32_t name='unk11'/>
<int16_t name='unk12'/>
</struct-type>
<struct-type type-name='caste_raw' key-field='caste_id'>
<stl-string name='caste_id'/>
<code-helper name='find-instance'>$global.world.raws.creatures.all[$$].caste[$]</code-helper>
<static-array type-name='stl-string' name='caste_name' count='3'/>
<stl-string name='vermin_bite_txt'/>
<stl-string name='gnawer_txt'/>
<static-array type-name='stl-string' name='baby_name' count='2'/>
<static-array type-name='stl-string' name='child_name' count='2'/>
<static-array type-name='stl-string' name='itemcorpse_str' count='5'/> // temporary
<static-array type-name='stl-string' name='remains' count='2'/>
<stl-string name='description'/>
<static-array type-name='stl-string' name='mannerisms' count='17'>
<comment>fingers[2], nose, ear, head, eyes, mouth, hair, knuckles, lips, cheek, nails, f eet, arms, hands, tongue, leg</comment>
</static-array>
<uint8_t name='caste_tile'/>
<uint8_t name='caste_soldier_tile'/>
<uint8_t name='caste_alttile'/>
<uint8_t name='caste_soldier_alttile'/>
<uint8_t name='caste_glowtile'/>
<uint16_t name='homeotherm'/>
<int16_t name='unk1_1'/>
<int16_t name='unk1_2'/>
<uint16_t name='fixed_temp'/>
<static-array type-name='int16_t' name='caste_color' count='3'/>
<compound name='misc'>
<int16_t name='litter_size_min'/>
<int16_t name='litter_size_max'/>
<int16_t name='penetratepower'/>
<int16_t name='vermin_bite_chance'/>
<int16_t name='grasstrample'/>
<int16_t name='buildingdestroyer'/>
<enum base-type='int16_t' name='itemcorpse_itemtype' type-name='item_type'/>
<int16_t name='itemcorpse_itemsubtype'/>
<int16_t name='itemcorpse_materialtype'
ref-target='material' aux-value='$$.itemcorpse_materialindex'/>
<int16_t name='itemcorpse_materialindex'/> // NOT 32-bit!
<int16_t name='itemcorpse_quality'/>
<static-array type-name='int16_t' name='remains_color' count='3'/>
<int16_t name='difficulty'/>
<static-array type-name='int16_t' name='caste_glowcolor' count='3'/>
<int16_t name='beach_frequency'/>
<int16_t name='clutch_size_min'/>
<int16_t name='clutch_size_max'/>
<int32_t name='speed'/>
<int32_t name='modvalue'/>
<int32_t name='petvalue'/>
<int32_t name='milkable'/>
<int32_t name='viewrange'/>
<int32_t name='maxage_min'/>
<int32_t name='maxage_max'/>
<static-array type-name='int32_t' name='unk3' count='2'/>
<int32_t name='swim_speed'/>
<int32_t name='trade_capacity'/>
<int32_t name='unk4'/>
<int32_t name='pop_ratio'/>
<int32_t name='adult_size'/>
<static-array type-name='int32_t' name='unk5' count='4'/>
<static-array type-name='int32_t' name='attack_trigger' count='3'/>
<int32_t name='egg_size'/>
<int32_t name='grazer'/>
<int32_t name='petvalue_divisor'/>
<int32_t name='prone_to_rage'/>
<static-array type-name='int32_t' name='unk6' count='29'/>
</compound>
<static-array name='personality' count='30'>
<int16_t name='a'/>
<int16_t name='b'/>
<int16_t name='c'/>
</static-array>
<df-flagarray name='flags'/>
<int32_t name='unk7'/>
<stl-vector name='body_parts'>
<pointer type-name='body_part_raw'/>
</stl-vector>
<stl-vector name='attacks'>
<pointer/>
</stl-vector>
<compound name='unknown1'>
<int32_t name='unk8'/>
<stl-vector type-name='int16_t' name='unk9a'/>
<stl-vector type-name='int16_t' name='unk9b'/>
<stl-vector name='unk10'/>
<stl-vector name='unk11'/>
<stl-vector name='unk12'/>
<stl-vector type-name='int16_t' name='unk13'/>
<stl-vector type-name='int32_t' name='unk14'/>
</compound>
<static-array type-name='int32_t' name='unk15' count='4'/>
<stl-vector name='caste_speech_1'/>
<stl-vector name='caste_speech_2'/>
<static-array name='skill_rates' count='116'>
<static-array type-name='int32_t' count='4'/>
</static-array>
<compound name='attributes'>
<static-array name='phys_att_range' count='7'>
<static-array type-name='int32_t' count='6'/>
</static-array>
<static-array name='ment_att_range' count='7'>
<static-array type-name='int32_t' count='13'/>
</static-array>
<static-array name='phys_att_rates' count='4'>
<static-array type-name='int32_t' count='6'/>
</static-array>
<static-array name='ment_att_rates' count='4'>
<static-array type-name='int32_t' count='13'/>
</static-array>
<static-array type-name='int32_t' name='phys_att_cap_perc' count='6'/>
<static-array type-name='int32_t' name='ment_att_cap_perc' count='13'/>
</compound>
<int8_t name='gender'/>
<stl-vector type-name='int32_t' name='body_size_1'/>
<stl-vector type-name='int32_t' name='body_size_2'/>
<static-array name='unk16' count='19'>
<stl-vector/>
</static-array>
<static-array type-name='int32_t' name='unk17' count='2'/>
<stl-vector type-name='int16_t' name='natural_skill_id'/>
<stl-vector type-name='int32_t' name='natural_skill_exp'/>
<stl-vector type-name='int32_t' name='natural_skill_lvl'/>
<static-array name='caste_profession_name' count='106'>
<stl-string name='singular'/>
<stl-string name='plural'/>
</static-array>
<compound name='extracts'>
<stl-vector type-name='int16_t' name='extract_mat'/>
<stl-vector type-name='int32_t' name='extract_matidx'/>
<static-array name='extract_str' count='3'>
<stl-vector>
<pointer type-name='stl-string'/>
</stl-vector>
</static-array>
<int16_t name='milkable_mat'/>
<int32_t name='milkable_matidx'/>
<static-array name='milkable_str' count='3'>
<stl-string/>
</static-array>
<int16_t name='webber_mat'/>
<int32_t name='webber_matidx'/>
<static-array name='webber_str' count='3'>
<stl-string/>
</static-array>
<int16_t name='vermin_bite_mat'/>
<int32_t name='vermin_bite_matidx'/>
<int16_t name='vermin_bite_chance'/>
<static-array name='vermin_bite_str' count='3'>
<stl-string/>
</static-array>
<int16_t name='tendons_mat'/>
<int32_t name='tendons_matidx'/>
<static-array name='tendons_str' count='3'>
<stl-string/>
</static-array>
<int32_t name='tendons_heal'/>
<int16_t name='ligaments_mat'/>
<int32_t name='ligaments_matidx'/>
<static-array name='ligaments_str' count='3'>
<stl-string/>
</static-array>
<int32_t name='ligaments_heal'/>
<int16_t name='blood_state'/>
<int16_t name='blood_mat'/>
<int32_t name='blood_matidx'/>
<static-array name='blood_str' count='3'>
<stl-string/>
</static-array>
<int16_t name='pus_state'/>
<int16_t name='pus_mat'/>
<int32_t name='pus_matidx'/>
<static-array name='pus_str' count='3'>
<stl-string/>
</static-array>
<stl-vector type-name='int16_t' name='material_breath_attack_mattype'/>
<stl-vector type-name='int32_t' name='material_breath_attack_matindex'/>
<static-array name='material_breath_attack_str' count='3'>
<stl-vector>
<pointer type-name='stl-string'/>
</stl-vector>
</static-array>
<stl-vector type-name='int16_t' name='material_breath_attack_type'/>
<stl-vector type-name='int16_t' name='egg_material_mattype'/>
<stl-vector type-name='int32_t' name='egg_material_matindex'/>
<static-array name='egg_material_str' count='3'>
<stl-vector>
<pointer type-name='stl-string'/>
</stl-vector>
</static-array>
<stl-vector name='lays_unusual_eggs_itemtype'>
<enum base-type='int16_t' type-name='item_type'/>
</stl-vector>
<stl-vector name='lays_unusual_eggs_itemsubtype'/>
<stl-vector type-name='int16_t' name='lays_unusual_eggs_mattype'/>
<stl-vector type-name='int32_t' name='lays_unusual_eggs_matindex'/>
<static-array name='lays_unusual_eggs_str' count='5'>
<stl-vector>
<pointer type-name='stl-string'/>
</stl-vector>
</static-array>
</compound>
<stl-vector name='unk22'/>
<stl-vector name='creature_class'>
<pointer type-name='stl-string'/>
</stl-vector>
<compound name='unknown2'>
<stl-vector name='unk23a'/>
<stl-vector name='unk23b'/>
<stl-vector name='unk23c'/>
<df-flagarray name='unk24_flags'/>
<df-flagarray name='unk25_flags'/>
<static-array type-name='int32_t' name='unk26' count='33'/>
<static-array name='unk27' count='5'><stl-vector/></static-array>
<static-array type-name='int32_t' name='unk28' count='2'/>
</compound>
<static-array type-name='int32_t' name='habit_num' count='2'/>
<static-array name='habit' count='2'><stl-vector/></static-array>
<static-array name='lair' count='2'><stl-vector/></static-array>
<static-array name='lair_characteristic' count='2'><stl-vector/></static-array>
<static-array name='lair_hunter_speech' count='2'><stl-vector/></static-array>
<static-array name='unk29' count='2'><stl-vector/></static-array>
<static-array name='specific_food' count='2'><stl-vector/></static-array>
<static-array name='unk30' count='3'><stl-vector/></static-array>
</struct-type>
<struct-type type-name='creature_raw' key-field='creature_id'>
<stl-string name='creature_id'/>
<code-helper name='find-instance'>$global.world.raws.creatures.all[$]</code-helper>
<static-array type-name='stl-string' name='name' count='3'/>
<static-array type-name='stl-string' name='general_baby_name' count='2'/>
<static-array type-name='stl-string' name='general_child_name' count='2'/>
<uint8_t name='creature_tile'/>
<uint8_t name='creature_soldier_tile'/>
<uint8_t name='alttile'/>
<uint8_t name='soldier_alttile'/>
<uint8_t name='glowtile'/>
<int16_t name='unk1'/>
<int16_t name='unk2'/>
<int16_t name='frequency'/>
<static-array type-name='int16_t' name='population_number' count='2'/>
<static-array type-name='int16_t' name='cluster_number' count='2'/>
<static-array type-name='int16_t' name='triggerable_group' count='2'/>
<static-array type-name='int16_t' name='color' count='3'/>
<static-array type-name='int16_t' name='glowcolor' count='3'/>
<int32_t name='adultsize'/>
<stl-vector name='prefstring'>
<pointer type-name='stl-string'/>
</stl-vector>
<stl-vector type-name='int16_t' name='sphere'/>
<stl-vector name='caste'>
<pointer type-name='caste_raw'/>
</stl-vector>
<stl-vector type-name='int32_t' name='pop_ratio'/>
<df-flagarray name='flags' index-enum='creature_raw_flags'/>
<compound name='stuff'>
<static-array name='stuff1' count='2'>
<static-array type-name='int32_t' count='7'/>
</static-array>
<static-array name='stuff2a' count='7'>
<static-array type-name='int32_t' count='12'/>
</static-array>
<static-array name='stuff2b' count='7'>
<static-array type-name='int32_t' count='12'/>
</static-array>
<static-array type-name='int32_t' name='unk3' count='84'/>
<static-array name='stuff3a' count='7'>
<static-array type-name='int32_t' count='106'/>
</static-array>
<static-array name='stuff3b' count='7'>
<static-array type-name='int32_t' count='106'/>
</static-array>
<static-array type-name='int8_t' name='stuff4' count='7'/>
<static-array name='stuff2c' count='7'>
<static-array type-name='int8_t' count='12'/>
</static-array>
<static-array type-name='int8_t' name='unk4' count='42'/>
<static-array name='stuff3c' count='7'>
<static-array type-name='int8_t' count='106'/>
</static-array>
</compound>
<stl-vector name='unk5'/>
<stl-vector name='speech1'/>
<stl-vector name='speech2'/>
<stl-vector name='speech3'/>
<stl-vector name='material'>
<pointer type-name='material'/>
</stl-vector>
<stl-vector type-name='pointer' name='tissue'/>
<static-array name='profession_name' count='106'>
<stl-string name='singular'/>
<stl-string name='plural'/>
</static-array>
<pointer name='unk6pa'/>
<pointer name='unk6pb'/>
<stl-vector type-name='int32_t' name='unk6'/>
<stl-vector type-name='int32_t' name='unk7'/>
<stl-vector type-name='int32_t' name='hive_product_0'/>
<stl-vector type-name='int32_t' name='hive_product_1'/>
<stl-vector type-name='int16_t' name='hive_product_2'/>
<stl-vector type-name='int16_t' name='hive_product_3'/>
<stl-vector type-name='int16_t' name='hive_product_4'/>
<stl-vector type-name='int32_t' name='hive_product_5'/>
<static-array name='hive_product_tmpstr' count='5'>
<stl-vector>
<pointer type-name='stl-string'/>
</stl-vector>
</static-array>
<int32_t name='unk8'/>
<stl-vector name='raws'>
<pointer type-name='stl-string'/>
</stl-vector>
</struct-type>
</data-definition>
<!--
Local Variables:
indent-tabs-mode: nil
nxml-child-indent: 4
End:
-->

@ -1,129 +0,0 @@
<data-definition>
<enum-type type-name='d_init_nickname'>
<enum-item name='REPLACE_FIRST'/>
<enum-item name='CENTRALIZE'/>
<enum-item name='REPLACE_ALL'/>
</enum-type>
<enum-type type-name='d_init_z_view'>
<enum-item name='OFF'/>
<enum-item name='UNHIDDEN'/>
<enum-item name='CREATURE'/>
<enum-item name='ON'/>
</enum-type>
<enum-type type-name='d_init_idlers'>
<enum-item name='OFF' value='-1'/>
<enum-item name='TOP'/>
<enum-item name='BOTTOM'/>
</enum-type>
<enum-type type-name='d_init_tunnel'>
<enum-item name='NO'/>
<enum-item name='FINDER'/>
<enum-item name='ALWAYS'/>
</enum-type>
<enum-type type-name='d_init_flags1'>
<enum-item name='VARIED_GROUND_TILES'/>
<enum-item name='ENGRAVINGS_START_OBSCURED'/>
<enum-item name='SHOW_IMP_QUALITY'/>
<enum-item name='SHOW_FLOW_AMOUNTS'/>
</enum-type>
<enum-type type-name='d_init_flags2'>
<enum-item name='MORE'/>
<enum-item name='ADVENTURER_TRAPS'/>
<enum-item name='ADVENTURER_ALWAYS_CENTER'/>
</enum-type>
<enum-type type-name='d_init_flags3'>
<enum-item name='COFFIN_NO_PETS_DEFAULT'/>
</enum-type>
<enum-type type-name='d_init_flags4'>
<enum-item name='TEMPERATURE'/>
<enum-item name='WEATHER'/>
<enum-item name='ECONOMY'/>
<enum-item name='ZERO_RENT'/>
<enum-item name='AUTOSAVE_SEASONAL'/>
<enum-item name='AUTOSAVE_YEARLY'/>
<enum-item name='AUTOSAVE_PAUSE'/>
<enum-item name='AUTOBACKUP'/>
<enum-item name='INITIAL_SAVE'/>
<enum-item name='INVADERS'/>
<enum-item name='CAVEINS'/>
<enum-item name='ARTIFACTS'/>
<enum-item name='LOG_MAP_REJECTS'/>
<enum-item name='PAUSE_ON_LOAD'/>
<enum-item name='EMBARK_WARNING_ALWAYS'/>
<enum-item name='SHOW_ALL_HISTORY_IN_DWARF_MODE'/>
<enum-item name='TESTING_ARENA'/>
<enum-item name='WALKING_SPREADS_SPATTER_DWF'/>
<enum-item name='WALKING_SPREADS_SPATTER_ADV'/>
</enum-type>
<struct-type type-name='d_init'>
<df-flagarray name='flags1' index-enum='d_init_flags1'/>
<enum name="nickname_dwarf" type-name='d_init_nickname'/>
<enum name="nickname_adventure" type-name='d_init_nickname'/>
<enum name="nickname_legends" type-name='d_init_nickname'/>
<enum name="nickname_dwarf2" type-name='d_init_nickname'/>
<int32_t name="unk_18"/>
<int32_t name="unk_1c"/>
<uint8_t name='sky_tile'/>
<static-array name='sky_color' type-name='int16_t' count='3'/>
<uint8_t name='chasm_tile'/>
<uint8_t name='pillar_tile'/>
<static-array name='chasm_color' type-name='int16_t' count='3'/>
<compound name='wound_color'>
<static-array name='none' type-name='int16_t' count='3'/>
<static-array name='minor' type-name='int16_t' count='3'/>
<static-array name='inhibited' type-name='int16_t' count='3'/>
<static-array name='function_loss' type-name='int16_t' count='3'/>
<static-array name='broken' type-name='int16_t' count='3'/>
<static-array name='missing' type-name='int16_t' count='3'/>
</compound>
<enum name="idlers" base-type='int16_t' type-name='d_init_idlers'/>
<enum name="show_embark_tunnel" base-type='int16_t' type-name='d_init_tunnel'/>
<df-flagarray name='flags2' index-enum='d_init_flags2'/>
<int32_t name="display_length"/>
<enum name="adventurer_z_view" type-name='d_init_z_view'/>
<int32_t name="adventurer_z_view_size"/>
<df-flagarray name='flags3' index-enum='d_init_flags3'/>
<int32_t name="population_cap"/>
<int32_t name="baby_cap_absolute"/>
<int32_t name="baby_cap_percent"/>
<static-array name='path_cost' type-name='int32_t' count='4'/>
<static-array name='embark_rect' type-name='int16_t' count='2'/>
<compound name='store_dist'>
<int16_t name='item_decrease'/>
<int16_t name='seed_combine'/>
<int16_t name='bucket_combine'/>
<int16_t name='barrel_combine'/>
<int16_t name='bin_combine'/>
</compound>
<df-flagarray name='flags4' index-enum='d_init_flags4'/>
85266c0
</struct-type>
</data-definition>
<!--
Local Variables:
indent-tabs-mode: nil
nxml-child-indent: 4
End:
-->

@ -1,126 +0,0 @@
<data-definition>
<struct-type type-name='historical_figure' instance-vector='$global.world.history.figures' key-field='id'>
<enum base-type='int16_t' name='profession' type-name='profession'/>
<int16_t name='race' ref-target='creature_raw'/>
<int16_t name='caste' ref-target='caste_raw' aux-value='$$.race'/>
<int8_t name='sex'/>
<int32_t name='appeared_year'/>
<int32_t name='born_year'/>
<int32_t name='born_seconds'/>
<int32_t name='old_year'/>
<int32_t name='old_seconds'/>
<int32_t name='died_year'/>
<int32_t name='died_seconds'/>
<compound type-name='language_name' name='name'/>
<code-helper name='describe'>
(describe-obj $.name)
(awhen (find-creature $.race)
(fmt "~:(~A ~A~)" $it.caste[$.caste].caste_id $it.creature_id))
</code-helper>
<int32_t name='civ_id' ref-target='historical_entity'/>
<int32_t name='population_id' ref-target='entity_population'/>
<df-flagarray name='flags'/>
<int32_t name='unit_id' ref-target='unit'/>
<int32_t name='id'/>
<int32_t name='unk4'/>
<stl-vector name='entity_links'/>
<stl-vector name='site_links'/>
<stl-vector name='histfig_links'/>
<pointer name='unk6'/>
<static-array name='unk7' count='5' type-name='int32_t' comment='empty'/>
</struct-type>
<class-type type-name='history_event' original-name='history_eventst'
instance-vector='$global.world.history.events' key-field='id'>
<int32_t name='year'/>
<int32_t name='seconds'/>
<df-flagarray name='flags'/>
<int32_t name='id'/>
</class-type>
<class-type type-name='history_event_masterpiece_createdst' inherits-from='history_event'>
<int32_t name='maker' ref-target='historical_figure'/>
<int32_t name='maker_entity' ref-target='historical_entity'/>
<int32_t name='site' ref-target='world_site'/>
</class-type>
<class-type type-name='history_event_masterpiece_created_itemst'
inherits-from='history_event_masterpiece_createdst'>
<enum base-type='int32_t' name='skill_used' type-name='job_skill'/>
<enum base-type='int16_t' name='item_type' type-name='item_type'/>
<int16_t name='item_subtype' refers-to='(item-subtype-target $$._parent.item_type $)'/>
<int16_t name='mat_type' ref-target='material' aux-value='$$.mat_index'/>
<int16_t name='mat_index'/>
<int32_t name='item_id' ref-target='item'/>
</class-type>
<class-type type-name='history_event_masterpiece_created_foodst'
inherits-from='history_event_masterpiece_createdst'>
<int32_t name='unk1'/>
<int16_t name='item_subtype' refers-to='$global.world.raws.itemdefs.food[$]'/>
<int32_t name='item_id' ref-target='item'/>
</class-type>
<struct-type type-name='world_history'>
dtor 8532fa0
<stl-vector name='events'>
<pointer type-name='history_event'/>
</stl-vector>
<stl-vector name='events2'>
<pointer type-name='history_event'/>
</stl-vector>
<stl-vector name='figures'>
<pointer type-name='historical_figure'/>
</stl-vector>
<static-array name='other_events' count='9'>
<stl-vector>
<pointer type-name='history_event'/>
</stl-vector>
</static-array>
<stl-vector name='ages'>
<pointer/>
</stl-vector>
<stl-vector name='unk1' type-name='int32_t'/>
<stl-vector name='unk2' type-name='int16_t'/>
<int32_t/>
<int32_t/>
<int32_t/>
<int32_t/>
<stl-vector/>
<stl-vector/>
<stl-vector/>
<stl-vector/>
<stl-vector/>
<stl-vector/>
<bool/>
<stl-vector/>
<int32_t/>
<int32_t/>
<int32_t/>
</struct-type>
</data-definition>
<!--
Local Variables:
indent-tabs-mode: nil
nxml-child-indent: 4
End:
-->

Some files were not shown because too many files have changed in this diff Show More