From a962299c20160eed352a51dc036ec65169651146 Mon Sep 17 00:00:00 2001 From: doomchild Date: Wed, 26 May 2010 14:46:06 -0500 Subject: [PATCH 001/122] cleaned up header includes --- library/include/DFHack_C.h | 14 ++- library/include/dfhack-c/DFContext_C.h | 5 +- library/include/dfhack-c/DFTypes_C.h | 5 +- .../include/dfhack-c/modules/Buildings_C.h | 6 +- .../dfhack-c/modules/Constructions_C.h | 6 +- .../include/dfhack-c/modules/Creatures_C.h | 4 - library/include/dfhack-c/modules/Gui_C.h | 6 +- library/include/dfhack-c/modules/Items_C.h | 11 +- library/include/dfhack-c/modules/Maps_C.h | 12 +- .../include/dfhack-c/modules/Materials_C.h | 7 +- library/include/dfhack-c/modules/Position_C.h | 2 +- .../include/dfhack-c/modules/Translation_C.h | 6 +- .../include/dfhack-c/modules/Vegetation_C.h | 6 +- library/include/dfhack-c/modules/WindowIO_C.h | 43 +++++++ library/include/dfhack-c/modules/World_C.h | 47 ++++++++ library/modules/Buildings_C.cpp | 12 -- library/modules/Constructions_C.cpp | 7 -- library/modules/Creatures_C.cpp | 14 --- library/modules/Gui_C.cpp | 10 +- library/modules/Items_C.cpp | 17 --- library/modules/Maps_C.cpp | 12 -- library/modules/Materials_C.cpp | 13 --- library/modules/Position_C.cpp | 8 -- library/modules/WindowIO_C.cpp | 64 +++++++++++ library/modules/World_C.cpp | 105 ++++++++++++++++++ 25 files changed, 285 insertions(+), 157 deletions(-) create mode 100644 library/include/dfhack-c/modules/WindowIO_C.h create mode 100644 library/include/dfhack-c/modules/World_C.h create mode 100644 library/modules/WindowIO_C.cpp create mode 100644 library/modules/World_C.cpp diff --git a/library/include/DFHack_C.h b/library/include/DFHack_C.h index 8eb381595..f08c31131 100644 --- a/library/include/DFHack_C.h +++ b/library/include/DFHack_C.h @@ -25,12 +25,20 @@ distribution. #ifndef DFHACK_C_API #define DFHACK_C_API -typedef void DFHackObject; +#include +#include +#include +#include +#include +#include "dfhack/DFGlobal.h" #include "dfhack/DFExport.h" #include "dfhack/DFIntegers.h" -#include "dfhack-c/DFContext_C.h" -#include "dfhack-c/DFTypes_C.h" + +using namespace std; +using namespace DFHack; + +typedef void DFHackObject; #ifdef __cplusplus extern "C" { diff --git a/library/include/dfhack-c/DFContext_C.h b/library/include/dfhack-c/DFContext_C.h index 32ecca9e9..365c235b9 100644 --- a/library/include/dfhack-c/DFContext_C.h +++ b/library/include/dfhack-c/DFContext_C.h @@ -25,10 +25,7 @@ distribution. #ifndef DFHACK_C_CONTEXT #define DFHACK_C_CONTEXT -#include "dfhack/DFExport.h" -#include "dfhack/DFIntegers.h" - -typedef void DFHackObject; +#include "DFHack_C.h" #ifdef __cplusplus extern "C" { diff --git a/library/include/dfhack-c/DFTypes_C.h b/library/include/dfhack-c/DFTypes_C.h index 18c8de3b3..a05adc2fc 100644 --- a/library/include/dfhack-c/DFTypes_C.h +++ b/library/include/dfhack-c/DFTypes_C.h @@ -25,13 +25,10 @@ distribution. #ifndef TYPES_C_API #define TYPES_C_API -#include "dfhack/DFExport.h" -#include "dfhack/DFIntegers.h" +#include "DFHack_C.h" #include "dfhack/DFTypes.h" #include "dfhack/modules/Materials.h" -using namespace DFHack; - #ifdef __cplusplus extern "C" { #endif diff --git a/library/include/dfhack-c/modules/Buildings_C.h b/library/include/dfhack-c/modules/Buildings_C.h index c69da83e0..6b1632dd2 100644 --- a/library/include/dfhack-c/modules/Buildings_C.h +++ b/library/include/dfhack-c/modules/Buildings_C.h @@ -25,13 +25,9 @@ distribution. #ifndef BUILDINGS_C_API #define BUILDINGS_C_API -#include "dfhack/DFExport.h" -#include "dfhack/DFIntegers.h" +#include "DFHack_C.h" #include "dfhack/DFTypes.h" #include "dfhack/modules/Buildings.h" -#include "DFHack_C.h" - -using namespace DFHack; #ifdef __cplusplus extern "C" { diff --git a/library/include/dfhack-c/modules/Constructions_C.h b/library/include/dfhack-c/modules/Constructions_C.h index c34527b1d..f339b6bcc 100644 --- a/library/include/dfhack-c/modules/Constructions_C.h +++ b/library/include/dfhack-c/modules/Constructions_C.h @@ -25,13 +25,9 @@ distribution. #ifndef CONSTRUCTIONS_C_API #define CONSTRUCTIONS_C_API -#include "dfhack/DFExport.h" -#include "dfhack/DFIntegers.h" +#include "DFHack_C.h" #include "dfhack/DFTypes.h" #include "dfhack/modules/Constructions.h" -#include "DFHack_C.h" - -using namespace DFHack; #ifdef __cplusplus extern "C" { diff --git a/library/include/dfhack-c/modules/Creatures_C.h b/library/include/dfhack-c/modules/Creatures_C.h index 93502ffe6..bbc9e6f54 100644 --- a/library/include/dfhack-c/modules/Creatures_C.h +++ b/library/include/dfhack-c/modules/Creatures_C.h @@ -25,15 +25,11 @@ distribution. #ifndef CREATURES_C_API #define CREATURES_C_API -#include "dfhack/DFExport.h" -#include "dfhack/DFIntegers.h" #include "DFHack_C.h" #include "dfhack/DFTypes.h" #include "dfhack/modules/Materials.h" #include "dfhack/modules/Creatures.h" -using namespace DFHack; - #ifdef __cplusplus extern "C" { #endif diff --git a/library/include/dfhack-c/modules/Gui_C.h b/library/include/dfhack-c/modules/Gui_C.h index 0bd68f3fc..2373d458d 100644 --- a/library/include/dfhack-c/modules/Gui_C.h +++ b/library/include/dfhack-c/modules/Gui_C.h @@ -25,11 +25,9 @@ distribution. #ifndef GUI_C_API #define GUI_C_API -#include "dfhack/DFExport.h" -#include "dfhack/DFIntegers.h" +#include "DFHack_C.h" #include "dfhack/DFTypes.h" - -using namespace DFHack; +#include "dfhack/modules/Gui.h" #ifdef __cplusplus extern "C" { diff --git a/library/include/dfhack-c/modules/Items_C.h b/library/include/dfhack-c/modules/Items_C.h index 0568e9088..5c1e08e48 100644 --- a/library/include/dfhack-c/modules/Items_C.h +++ b/library/include/dfhack-c/modules/Items_C.h @@ -25,15 +25,10 @@ distribution. #ifndef ITEMS_C_API #define ITEMS_C_API -#include "dfhack/DFExport.h" -#include "dfhack/DFIntegers.h" -#include "Internal.h" - -using namespace DFHack; - -#include "dfhack/DFTypes.h" -#include "dfhack/modules/Items.h" #include "DFHack_C.h" +#include "dfhack/DFProcess.h" +#include "dfhack-c/DFTypes_C.h" +#include "dfhack/modules/Items.h" #ifdef __cplusplus extern "C" { diff --git a/library/include/dfhack-c/modules/Maps_C.h b/library/include/dfhack-c/modules/Maps_C.h index e37d3640a..299f0d5f5 100644 --- a/library/include/dfhack-c/modules/Maps_C.h +++ b/library/include/dfhack-c/modules/Maps_C.h @@ -25,19 +25,9 @@ distribution. #ifndef MAPS_C_API #define MAPS_C_API -#include "dfhack/DFExport.h" -#include "dfhack/DFIntegers.h" -#include -#include -#include - -using namespace std; - +#include "DFHack_C.h" #include "dfhack/DFTypes.h" #include "dfhack/modules/Maps.h" -#include "DFHack_C.h" - -using namespace DFHack; #ifdef __cplusplus extern "C" { diff --git a/library/include/dfhack-c/modules/Materials_C.h b/library/include/dfhack-c/modules/Materials_C.h index ef56ac627..25a9a7df3 100644 --- a/library/include/dfhack-c/modules/Materials_C.h +++ b/library/include/dfhack-c/modules/Materials_C.h @@ -25,14 +25,9 @@ distribution. #ifndef MATERIALS_C_API #define MATERIALS_C_API -#include "dfhack/DFExport.h" -#include "dfhack/DFIntegers.h" -#include "dfhack/DFTypes.h" -#include "dfhack/modules/Materials.h" #include "DFHack_C.h" #include "dfhack-c/DFTypes_C.h" - -using namespace DFHack; +#include "dfhack/modules/Materials.h" #ifdef __cplusplus extern "C" { diff --git a/library/include/dfhack-c/modules/Position_C.h b/library/include/dfhack-c/modules/Position_C.h index 3b2f1dc0b..665e400bf 100644 --- a/library/include/dfhack-c/modules/Position_C.h +++ b/library/include/dfhack-c/modules/Position_C.h @@ -25,8 +25,8 @@ distribution. #ifndef POSITION_C_API #define POSITION_C_API -#include "dfhack/DFExport.h" #include "DFHack_C.h" +#include "dfhack/modules/Position.h" #ifdef __cplusplus extern "C" { diff --git a/library/include/dfhack-c/modules/Translation_C.h b/library/include/dfhack-c/modules/Translation_C.h index 2e1aaf457..8cbcf4e91 100644 --- a/library/include/dfhack-c/modules/Translation_C.h +++ b/library/include/dfhack-c/modules/Translation_C.h @@ -25,13 +25,9 @@ distribution. #ifndef TRANSLATION_C_API #define TRANSLATION_C_API -#include "dfhack/DFExport.h" -#include "dfhack/DFIntegers.h" +#include "DFHack_C.h" #include "dfhack/DFTypes.h" #include "dfhack/modules/Translation.h" -#include "DFHack_C.h" - -using namespace DFHack; #ifdef __cplusplus extern "C" { diff --git a/library/include/dfhack-c/modules/Vegetation_C.h b/library/include/dfhack-c/modules/Vegetation_C.h index c57c3948a..017d30a7b 100644 --- a/library/include/dfhack-c/modules/Vegetation_C.h +++ b/library/include/dfhack-c/modules/Vegetation_C.h @@ -25,13 +25,9 @@ distribution. #ifndef VEGETATION_C_API #define VEGETATION_C_API -#include "dfhack/DFExport.h" -#include "dfhack/DFIntegers.h" +#include "DFHack_C.h" #include "dfhack/DFTypes.h" #include "dfhack/modules/Vegetation.h" -#include "DFHack_C.h" - -using namespace DFHack; #ifdef __cplusplus extern "C" { diff --git a/library/include/dfhack-c/modules/WindowIO_C.h b/library/include/dfhack-c/modules/WindowIO_C.h new file mode 100644 index 000000000..072a4f352 --- /dev/null +++ b/library/include/dfhack-c/modules/WindowIO_C.h @@ -0,0 +1,43 @@ +/* +www.sourceforge.net/projects/dfhack +Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild + +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. +*/ + +#ifndef WINDOWIO_C_API +#define WINDOWIO_C_API + +#include "DFHack_C.h" +#include "dfhack/modules/WindowIO.h" + +#ifdef __cplusplus +extern "C" { +#endif + +DFHACK_EXPORT int WindowIO_TypeStr(DFHackObject* window, const char* input, int delay, bool useShift); + +DFHACK_EXPORT int WindowIO_TypeSpecial(DFHackObject* window, t_special command, int count, int delay); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/library/include/dfhack-c/modules/World_C.h b/library/include/dfhack-c/modules/World_C.h new file mode 100644 index 000000000..f6261a738 --- /dev/null +++ b/library/include/dfhack-c/modules/World_C.h @@ -0,0 +1,47 @@ +/* +www.sourceforge.net/projects/dfhack +Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild + +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. +*/ + +#ifndef WORLD_C_API +#define WORLD_C_API + +#include "DFHack_C.h" +#include "dfhack/modules/World.h" + +#ifdef __cplusplus +extern "C" { +#endif + +DFHACK_EXPORT int World_Start(DFHackObject* world); +DFHACK_EXPORT int World_Finish(DFHackObject* world); + +DFHACK_EXPORT int World_ReadCurrentTick(DFHackObject* world, uint32_t* tick); +DFHACK_EXPORT int World_ReadCurrentYear(DFHackObject* world, uint32_t* year); +DFHACK_EXPORT int World_ReadCurrentMonth(DFHackObject* world, uint32_t* month); +DFHACK_EXPORT int World_ReadCurrentDay(DFHackObject* world, uint32_t* day); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/library/modules/Buildings_C.cpp b/library/modules/Buildings_C.cpp index 18bd77922..7eaaa48a6 100644 --- a/library/modules/Buildings_C.cpp +++ b/library/modules/Buildings_C.cpp @@ -22,20 +22,8 @@ must not be misrepresented as being the original software. distribution. */ -#include "dfhack/DFIntegers.h" -#include -#include -#include "stdio.h" - -using namespace std; - -#include "Internal.h" -#include "dfhack/DFTypes.h" -#include "dfhack/modules/Buildings.h" #include "dfhack-c/modules/Buildings_C.h" -using namespace DFHack; - #ifdef __cplusplus extern "C" { #endif diff --git a/library/modules/Constructions_C.cpp b/library/modules/Constructions_C.cpp index 93afdae01..03e89ca23 100644 --- a/library/modules/Constructions_C.cpp +++ b/library/modules/Constructions_C.cpp @@ -22,15 +22,8 @@ must not be misrepresented as being the original software. distribution. */ -#include "dfhack/DFIntegers.h" - -#include "Internal.h" -#include "dfhack/DFTypes.h" -#include "dfhack/modules/Constructions.h" #include "dfhack-c/modules/Constructions_C.h" -using namespace DFHack; - #ifdef __cplusplus extern "C" { #endif diff --git a/library/modules/Creatures_C.cpp b/library/modules/Creatures_C.cpp index 1aac93110..731ac8611 100644 --- a/library/modules/Creatures_C.cpp +++ b/library/modules/Creatures_C.cpp @@ -22,21 +22,7 @@ must not be misrepresented as being the original software. distribution. */ -#include "dfhack/DFExport.h" -#include "dfhack/DFIntegers.h" -#include -#include -#include - -using namespace std; - -#include "dfhack/DFTypes.h" -#include "dfhack/modules/Materials.h" -#include "dfhack/modules/Creatures.h" #include "dfhack-c/modules/Creatures_C.h" -#include "DFHack_C.h" - -using namespace DFHack; #ifdef __cplusplus extern "C" { diff --git a/library/modules/Gui_C.cpp b/library/modules/Gui_C.cpp index 586eb1dd0..da17d2a18 100644 --- a/library/modules/Gui_C.cpp +++ b/library/modules/Gui_C.cpp @@ -21,16 +21,8 @@ must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ -#include -#include -#include "DFHack_C.h" -#include "dfhack-c/modules/Gui_C.h" -#include "dfhack/DFIntegers.h" - -#include "Internal.h" -#include "dfhack/modules/Gui.h" -using namespace DFHack; +#include "dfhack-c/modules/Gui_C.h" #ifdef __cplusplus extern "C" { diff --git a/library/modules/Items_C.cpp b/library/modules/Items_C.cpp index 3ac54c46a..75e555c79 100644 --- a/library/modules/Items_C.cpp +++ b/library/modules/Items_C.cpp @@ -22,25 +22,8 @@ must not be misrepresented as being the original software. distribution. */ -#include -#include -#include -#include "dfhack/DFExport.h" -#include "dfhack/DFIntegers.h" -#include "DFHack_C.h" - -#include "dfhack/DFTypes.h" - -using namespace std; -using namespace DFHack; - -#include "dfhack/DFProcess.h" -#include "dfhack/modules/Materials.h" -#include "dfhack/modules/Items.h" -#include "dfhack-c/DFTypes_C.h" #include "dfhack-c/modules/Items_C.h" - #ifdef __cplusplus extern "C" { #endif diff --git a/library/modules/Maps_C.cpp b/library/modules/Maps_C.cpp index ccac26447..5b41fff07 100644 --- a/library/modules/Maps_C.cpp +++ b/library/modules/Maps_C.cpp @@ -22,20 +22,8 @@ must not be misrepresented as being the original software. distribution. */ -#include "dfhack/DFIntegers.h" -#include -#include -#include - -using namespace std; - -#include "Internal.h" -#include "dfhack/DFTypes.h" -#include "dfhack/modules/Maps.h" #include "dfhack-c/modules/Maps_C.h" -using namespace DFHack; - #ifdef __cplusplus extern "C" { #endif diff --git a/library/modules/Materials_C.cpp b/library/modules/Materials_C.cpp index dee99fbaa..a1f379032 100644 --- a/library/modules/Materials_C.cpp +++ b/library/modules/Materials_C.cpp @@ -22,21 +22,8 @@ must not be misrepresented as being the original software. distribution. */ -#include "dfhack/DFIntegers.h" -#include -#include -#include - -using namespace std; - -#include "Internal.h" -#include "dfhack/DFTypes.h" -#include "dfhack/modules/Materials.h" -#include "dfhack-c/DFTypes_C.h" #include "dfhack-c/modules/Materials_C.h" -using namespace DFHack; - #ifdef __cplusplus extern "C" { #endif diff --git a/library/modules/Position_C.cpp b/library/modules/Position_C.cpp index 72405d9b7..0144abdb3 100644 --- a/library/modules/Position_C.cpp +++ b/library/modules/Position_C.cpp @@ -22,15 +22,7 @@ must not be misrepresented as being the original software. distribution. */ -#include -#include #include "dfhack-c/modules/Position_C.h" -#include "dfhack/DFIntegers.h" - -#include "Internal.h" -#include "dfhack/modules/Position.h" - -using namespace DFHack; #ifdef __cplusplus extern "C" { diff --git a/library/modules/WindowIO_C.cpp b/library/modules/WindowIO_C.cpp new file mode 100644 index 000000000..b404736ec --- /dev/null +++ b/library/modules/WindowIO_C.cpp @@ -0,0 +1,64 @@ +/* +www.sourceforge.net/projects/dfhack +Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild + +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. +*/ + +using namespace std; + +#include "dfhack/DFIntegers.h" +#include "DFHack.h" +#include "DFHack_C.h" +#include "dfhack/modules/WindowIO.h" +#include "dfhack-c/modules/WindowIO_C.h" + +using namespace DFHack; + + +#ifdef __cplusplus +extern "C" { +#endif + +int WindowIO_TypeStr(DFHackObject* window, const char* input, int delay, bool useShift) +{ + if(window != NULL) + { + ((DFHack::WindowIO*)window)->TypeStr(input, delay, useShift); + return 1; + } + + return -1; +} + +int WindowIO_TypeSpecial(DFHackObject* window, t_special command, int count, int delay) +{ + if(window != NULL) + { + ((DFHack::WindowIO*)window)->TypeSpecial(command, count, delay); + return 1; + } + + return -1; +} + +#ifdef __cplusplus +} +#endif diff --git a/library/modules/World_C.cpp b/library/modules/World_C.cpp new file mode 100644 index 000000000..a5be3bcd0 --- /dev/null +++ b/library/modules/World_C.cpp @@ -0,0 +1,105 @@ +/* +www.sourceforge.net/projects/dfhack +Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild + +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 "DFHack_C.h" +#include "dfhack/modules/World.h" +#include "dfhack-c/modules/World_C.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int World_Start(DFHackObject* world) +{ + if(world != NULL) + { + if(((DFHack::World*)world)->Start()) + return 1; + else + return 0; + } + + return -1; +} + +int World_Finish(DFHackObject* world) +{ + if(world != NULL) + { + if(((DFHack::World*)world)->Finish()) + return 1; + else + return 0; + } + + return -1; +} + +int World_ReadCurrentTick(DFHackObject* world, uint32_t* tick) +{ + if(world != NULL) + { + *tick = ((DFHack::World*)world)->ReadCurrentTick(); + return 1; + } + + return -1; +} + +int World_ReadCurrentYear(DFHackObject* world, uint32_t* year) +{ + if(world != NULL) + { + *year = ((DFHack::World*)world)->ReadCurrentYear(); + return 1; + } + + return -1; +} + +int World_ReadCurrentMonth(DFHackObject* world, uint32_t* month) +{ + if(world != NULL) + { + *month = ((DFHack::World*)world)->ReadCurrentMonth(); + return 1; + } + + return -1; +} + +int World_ReadCurrentDay(DFHackObject* world, uint32_t* day) +{ + if(world != NULL) + { + *day = ((DFHack::World*)world)->ReadCurrentDay(); + return 1; + } + + return -1; +} + +#ifdef __cplusplus +} +#endif From 6e91b7c9debdae92394a4fb95caee560b4cbc5bf Mon Sep 17 00:00:00 2001 From: doomchild Date: Wed, 26 May 2010 14:51:39 -0500 Subject: [PATCH 002/122] updated to include WindowIO_C and World_C --- library/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index ce44079cf..9c8d4d51b 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -91,6 +91,8 @@ modules/Position_C.cpp modules/Materials_C.cpp modules/Translation_C.cpp modules/Vegetation_C.cpp +modules/WindowIO_C.cpp +modules/World_C.cpp ) SET(PROJECT_HDRS_LINUX From 3caac25145b300226c213f01e037eea69dd8b89a Mon Sep 17 00:00:00 2001 From: doomchild Date: Thu, 27 May 2010 12:34:43 -0500 Subject: [PATCH 003/122] changed callback signatures to allow for return codes --- library/DFTypes_C.cpp | 44 ++++++++++++++-------------- library/include/dfhack-c/DFTypes_C.h | 38 ++++++++++++------------ library/modules/Materials_C.cpp | 32 +++++++++++++++----- 3 files changed, 65 insertions(+), 49 deletions(-) diff --git a/library/DFTypes_C.cpp b/library/DFTypes_C.cpp index 2a27ad292..6d3f8d789 100644 --- a/library/DFTypes_C.cpp +++ b/library/DFTypes_C.cpp @@ -41,31 +41,31 @@ using namespace DFHack; extern "C" { #endif -int8_t* (*alloc_byte_buffer_callback)(uint32_t) = NULL; -int16_t* (*alloc_short_buffer_callback)(uint32_t) = NULL; -int32_t* (*alloc_int_buffer_callback)(uint32_t) = NULL; +int (*alloc_byte_buffer_callback)(int8_t*, uint32_t) = NULL; +int (*alloc_short_buffer_callback)(int16_t*, uint32_t) = NULL; +int (*alloc_int_buffer_callback)(int32_t*, uint32_t) = NULL; -uint8_t* (*alloc_ubyte_buffer_callback)(uint32_t) = NULL; -uint16_t* (*alloc_ushort_buffer_callback)(uint32_t) = NULL; -uint32_t* (*alloc_uint_buffer_callback)(uint32_t) = NULL; +int (*alloc_ubyte_buffer_callback)(uint8_t*, uint32_t) = NULL; +int (*alloc_ushort_buffer_callback)(uint16_t*, uint32_t) = NULL; +int (*alloc_uint_buffer_callback)(uint32_t*, uint32_t) = NULL; -char* (*alloc_char_buffer_callback)(uint32_t) = NULL; +int (*alloc_char_buffer_callback)(char*, uint32_t) = NULL; -t_matgloss* (*alloc_matgloss_buffer_callback)(int) = NULL; -t_descriptor_color* (*alloc_descriptor_buffer_callback)(int) = NULL; -t_matglossOther* (*alloc_matgloss_other_buffer_callback)(int) = NULL; +int (*alloc_matgloss_buffer_callback)(t_matgloss*, uint32_t) = NULL; +int (*alloc_descriptor_buffer_callback)(t_descriptor_color*, uint32_t) = NULL; +int (*alloc_matgloss_other_buffer_callback)(t_matglossOther*, uint32_t) = NULL; -c_colormodifier* (*alloc_empty_colormodifier_callback)(void) = NULL; -c_colormodifier* (*alloc_colormodifier_callback)(const char*, uint32_t) = NULL; -c_colormodifier* (*alloc_colormodifier_buffer_callback)(uint32_t) = NULL; +int (*alloc_empty_colormodifier_callback)(c_colormodifier*) = NULL; +int (*alloc_colormodifier_callback)(c_colormodifier*, const char*, uint32_t) = NULL; +int (*alloc_colormodifier_buffer_callback)(c_colormodifier*, uint32_t) = NULL; -c_creaturecaste* (*alloc_empty_creaturecaste_callback)(void) = NULL; -c_creaturecaste* (*alloc_creaturecaste_callback)(const char*, const char*, const char*, const char*, uint32_t, uint32_t) = NULL; -c_creaturecaste* (*alloc_creaturecaste_buffer_callback)(uint32_t) = NULL; +int (*alloc_empty_creaturecaste_callback)(c_creaturecaste*)= NULL; +int (*alloc_creaturecaste_callback)(c_creaturecaste*, const char*, const char*, const char*, const char*, uint32_t, uint32_t) = NULL; +int (*alloc_creaturecaste_buffer_callback)(c_creaturecaste*, uint32_t) = NULL; -c_creaturetype* (*alloc_empty_creaturetype_callback)(void) = NULL; -c_creaturetype* (*alloc_creaturetype_callback)(const char*, uint32_t, uint32_t, uint8_t, uint16_t, uint16_t, uint16_t) = NULL; -c_creaturetype* (*alloc_creaturetype_buffer_callback)(uint32_t) = NULL; +int (*alloc_empty_creaturetype_callback)(c_creaturetype*) = NULL; +int (*alloc_creaturetype_callback)(c_creaturetype*, const char*, uint32_t, uint32_t, uint8_t, uint16_t, uint16_t, uint16_t) = NULL; +int (*alloc_creaturetype_buffer_callback)(c_creaturetype*, uint32_t) = NULL; #ifdef __cplusplus } @@ -76,7 +76,7 @@ int ColorListConvert(t_colormodifier* src, c_colormodifier* dest) if(src == NULL) return -1; - dest = ((*alloc_colormodifier_callback)(src->part, src->colorlist.size())); + ((*alloc_colormodifier_callback)(dest, src->part, src->colorlist.size())); copy(src->colorlist.begin(), src->colorlist.end(), dest->colorlist); @@ -88,7 +88,7 @@ int CreatureCasteConvert(t_creaturecaste* src, c_creaturecaste* dest) if(src == NULL) return -1; - dest = ((*alloc_creaturecaste_callback)(src->rawname, src->singular, src->plural, src->adjective, src->ColorModifier.size(), src->bodypart.size())); + ((*alloc_creaturecaste_callback)(dest, src->rawname, src->singular, src->plural, src->adjective, src->ColorModifier.size(), src->bodypart.size())); for(int i = 0; i < dest->colorModifierLength; i++) ColorListConvert(&src->ColorModifier[i], &dest->ColorModifier[i]); @@ -103,7 +103,7 @@ int CreatureTypeConvert(t_creaturetype* src, c_creaturetype* dest) if(src == NULL) return -1; - dest = ((*alloc_creaturetype_callback)(src->rawname, src->castes.size(), src->extract.size(), src->tile_character, src->tilecolor.fore, src->tilecolor.back, src->tilecolor.bright)); + ((*alloc_creaturetype_callback)(dest, src->rawname, src->castes.size(), src->extract.size(), src->tile_character, src->tilecolor.fore, src->tilecolor.back, src->tilecolor.bright)); for(int i = 0; i < dest->castesCount; i++) CreatureCasteConvert(&src->castes[i], &dest->castes[i]); diff --git a/library/include/dfhack-c/DFTypes_C.h b/library/include/dfhack-c/DFTypes_C.h index a05adc2fc..bf604e13e 100644 --- a/library/include/dfhack-c/DFTypes_C.h +++ b/library/include/dfhack-c/DFTypes_C.h @@ -33,19 +33,19 @@ distribution. extern "C" { #endif -DFHACK_EXPORT extern int8_t* (*alloc_byte_buffer_callback)(uint32_t); -DFHACK_EXPORT extern int16_t* (*alloc_short_buffer_callback)(uint32_t); -DFHACK_EXPORT extern int32_t* (*alloc_int_buffer_callback)(uint32_t); +DFHACK_EXPORT extern int (*alloc_byte_buffer_callback)(int8_t*, uint32_t); +DFHACK_EXPORT extern int (*alloc_short_buffer_callback)(int16_t*, uint32_t); +DFHACK_EXPORT extern int (*alloc_int_buffer_callback)(int32_t*, uint32_t); -DFHACK_EXPORT extern uint8_t* (*alloc_ubyte_buffer_callback)(uint32_t); -DFHACK_EXPORT extern uint16_t* (*alloc_ushort_buffer_callback)(uint32_t); -DFHACK_EXPORT extern uint32_t* (*alloc_uint_buffer_callback)(uint32_t); +DFHACK_EXPORT extern int (*alloc_ubyte_buffer_callback)(uint8_t*, uint32_t); +DFHACK_EXPORT extern int (*alloc_ushort_buffer_callback)(uint16_t*, uint32_t); +DFHACK_EXPORT extern int (*alloc_uint_buffer_callback)(uint32_t*, uint32_t); -DFHACK_EXPORT extern char* (*alloc_char_buffer_callback)(uint32_t); +DFHACK_EXPORT extern int (*alloc_char_buffer_callback)(char*, uint32_t); -DFHACK_EXPORT extern t_matgloss* (*alloc_matgloss_buffer_callback)(int); -DFHACK_EXPORT extern t_descriptor_color* (*alloc_descriptor_buffer_callback)(int); -DFHACK_EXPORT extern t_matglossOther* (*alloc_matgloss_other_buffer_callback)(int); +DFHACK_EXPORT extern int (*alloc_matgloss_buffer_callback)(t_matgloss*, uint32_t); +DFHACK_EXPORT extern int (*alloc_descriptor_buffer_callback)(t_descriptor_color*, uint32_t); +DFHACK_EXPORT extern int (*alloc_matgloss_other_buffer_callback)(t_matglossOther*, uint32_t); struct c_colormodifier { @@ -54,9 +54,9 @@ struct c_colormodifier uint32_t colorlistLength; }; -DFHACK_EXPORT extern c_colormodifier* (*alloc_empty_colormodifier_callback)(void); -DFHACK_EXPORT extern c_colormodifier* (*alloc_colormodifier_callback)(const char*, uint32_t); -DFHACK_EXPORT extern c_colormodifier* (*alloc_colormodifier_buffer_callback)(uint32_t); +DFHACK_EXPORT extern int (*alloc_empty_colormodifier_callback)(c_colormodifier*); +DFHACK_EXPORT extern int (*alloc_colormodifier_callback)(c_colormodifier*, const char*, uint32_t); +DFHACK_EXPORT extern int (*alloc_colormodifier_buffer_callback)(c_colormodifier*, uint32_t); struct c_creaturecaste { @@ -72,9 +72,9 @@ struct c_creaturecaste uint32_t bodypartLength; }; -DFHACK_EXPORT extern c_creaturecaste* (*alloc_empty_creaturecaste_callback)(void); -DFHACK_EXPORT extern c_creaturecaste* (*alloc_creaturecaste_callback)(const char*, const char*, const char*, const char*, uint32_t, uint32_t); -DFHACK_EXPORT extern c_creaturecaste* (*alloc_creaturecaste_buffer_callback)(uint32_t); +DFHACK_EXPORT extern int (*alloc_empty_creaturecaste_callback)(c_creaturecaste*); +DFHACK_EXPORT extern int (*alloc_creaturecaste_callback)(c_creaturecaste*, const char*, const char*, const char*, const char*, uint32_t, uint32_t); +DFHACK_EXPORT extern int (*alloc_creaturecaste_buffer_callback)(c_creaturecaste*, uint32_t); struct c_creaturetype { @@ -96,9 +96,9 @@ struct c_creaturetype } tilecolor; }; -DFHACK_EXPORT extern c_creaturetype* (*alloc_empty_creaturetype_callback)(void); -DFHACK_EXPORT extern c_creaturetype* (*alloc_creaturetype_callback)(const char*, uint32_t, uint32_t, uint8_t, uint16_t, uint16_t, uint16_t); -DFHACK_EXPORT extern c_creaturetype* (*alloc_creaturetype_buffer_callback)(uint32_t); +DFHACK_EXPORT extern int (*alloc_empty_creaturetype_callback)(c_creaturetype*); +DFHACK_EXPORT extern int (*alloc_creaturetype_callback)(c_creaturetype*, const char*, uint32_t, uint32_t, uint8_t, uint16_t, uint16_t, uint16_t); +DFHACK_EXPORT extern int (*alloc_creaturetype_buffer_callback)(c_creaturetype*, uint32_t); #ifdef __cplusplus } diff --git a/library/modules/Materials_C.cpp b/library/modules/Materials_C.cpp index a1f379032..1d70f8716 100644 --- a/library/modules/Materials_C.cpp +++ b/library/modules/Materials_C.cpp @@ -220,7 +220,9 @@ t_matgloss* Materials_getInorganic(DFHackObject* mat) if(materials->inorganic.size() > 0) { - t_matgloss* buf = ((*alloc_matgloss_buffer_callback)(materials->inorganic.size())); + t_matgloss* buf; + + ((*alloc_matgloss_buffer_callback)(buf, materials->inorganic.size())); if(buf != NULL) { @@ -242,7 +244,9 @@ t_matgloss* Materials_getOrganic(DFHackObject* mat) if(materials->organic.size() > 0) { - t_matgloss* buf = ((*alloc_matgloss_buffer_callback)(materials->organic.size())); + t_matgloss* buf; + + ((*alloc_matgloss_buffer_callback)(buf, materials->organic.size())); if(buf != NULL) { @@ -264,7 +268,9 @@ t_matgloss* Materials_getTree(DFHackObject* mat) if(materials->tree.size() > 0) { - t_matgloss* buf = ((*alloc_matgloss_buffer_callback)(materials->tree.size())); + t_matgloss* buf; + + ((*alloc_matgloss_buffer_callback)(buf, materials->tree.size())); if(buf != NULL) { @@ -286,7 +292,9 @@ t_matgloss* Materials_getPlant(DFHackObject* mat) if(materials->plant.size() > 0) { - t_matgloss* buf = ((*alloc_matgloss_buffer_callback)(materials->plant.size())); + t_matgloss* buf; + + ((*alloc_matgloss_buffer_callback)(buf, materials->plant.size())); if(buf != NULL) { @@ -308,7 +316,9 @@ t_matgloss* Materials_getRace(DFHackObject* mat) if(materials->race.size() > 0) { - t_matgloss* buf = ((*alloc_matgloss_buffer_callback)(materials->race.size())); + t_matgloss* buf; + + ((*alloc_matgloss_buffer_callback)(buf, materials->race.size())); if(buf != NULL) { @@ -332,7 +342,9 @@ c_creaturetype* Materials_getRaceEx(DFHackObject* mat) if(matSize > 0) { - c_creaturetype* buf = ((*alloc_creaturetype_buffer_callback)(matSize)); + c_creaturetype* buf; + + ((*alloc_creaturetype_buffer_callback)(buf, matSize)); if(buf != NULL) { @@ -355,7 +367,9 @@ t_descriptor_color* Materials_getColor(DFHackObject* mat) if(materials->color.size() > 0) { - t_descriptor_color* buf = ((*alloc_descriptor_buffer_callback)(materials->color.size())); + t_descriptor_color* buf; + + ((*alloc_descriptor_buffer_callback)(buf, materials->color.size())); if(buf != NULL) { @@ -377,7 +391,9 @@ t_matglossOther* Materials_getOther(DFHackObject* mat) if(materials->other.size() > 0) { - t_matglossOther* buf = ((*alloc_matgloss_other_buffer_callback)(materials->other.size())); + t_matglossOther* buf; + + ((*alloc_matgloss_other_buffer_callback)(buf, materials->other.size())); if(buf != NULL) { From 66159d4221cd2c4c9c68cae63113d05a2ac05fb6 Mon Sep 17 00:00:00 2001 From: doomchild Date: Thu, 27 May 2010 12:35:40 -0500 Subject: [PATCH 004/122] updated to use new callback signatures --- library/python/c api/context.py | 12 +++++- library/python/c api/maps.py | 4 +- library/python/c api/pydftypes.py | 34 +++++++++++----- library/python/c api/util.py | 68 +++++++++++++++++++++---------- 4 files changed, 82 insertions(+), 36 deletions(-) diff --git a/library/python/c api/context.py b/library/python/c api/context.py index 592359f57..eed236b09 100644 --- a/library/python/c api/context.py +++ b/library/python/c api/context.py @@ -170,7 +170,9 @@ class Context(object): return self._tran_obj def reveal(): - df = API("Memory.xml") + df_cm = ContextManager("Memory.xml") + df = df_cm.get_single_context() + df.attach() m = df.maps @@ -193,3 +195,11 @@ def reveal(): m.finish() df.detach() + +def resume(): + df_cm = ContextManager("Memory.xml") + df = df_cm.get_single_context() + + df.attach() + df.force_resume() + df.detach() diff --git a/library/python/c api/maps.py b/library/python/c api/maps.py index 1db1985d8..f5f69cfb5 100644 --- a/library/python/c api/maps.py +++ b/library/python/c api/maps.py @@ -1,6 +1,6 @@ from ctypes import * -from pydftypes import libdfhack -from util import _uintify +from pydftypes import * +from util import _uintify, uint_ptr libdfhack.Maps_getSize.argtypes = [ c_void_p, uint_ptr, uint_ptr, uint_ptr ] libdfhack.Maps_ReadTileTypes.argtypes = [ c_void_p, c_uint, c_uint, c_uint, POINTER(TileTypes40d) ] diff --git a/library/python/c api/pydftypes.py b/library/python/c api/pydftypes.py index 78a90e57f..376d99238 100644 --- a/library/python/c api/pydftypes.py +++ b/library/python/c api/pydftypes.py @@ -87,12 +87,15 @@ class Matgloss(Structure): ("bright", c_byte), ("name", c_char * 128)] -def _alloc_matgloss_buffer_callback(count): +def _alloc_matgloss_buffer_callback(ptr, count): allocated = _allocate_array(Matgloss, count) - return allocated[1] + ptr = addressof(allocated[0]) -libdfhack.alloc_matgloss_buffer_callback = CFUNCTYPE(POINTER(Matgloss), c_int)(_alloc_matgloss_buffer_callback) + return 1 + +_matgloss_functype = CFUNCTYPE(c_int, POINTER(Matgloss), c_uint) +libdfhack.alloc_matgloss_buffer_callback = _matgloss_functype(_alloc_matgloss_buffer_callback) class MatglossPair(Structure): _fields_ = [("type", c_short), @@ -105,12 +108,15 @@ class DescriptorColor(Structure): ("b", c_float), ("name", c_char * 128)] -def _alloc_descriptor_buffer_callback(count): +def _alloc_descriptor_buffer_callback(ptr, count): allocated = _allocate_array(DescriptorColor, count) - return allocated[1] + ptr = addressof(allocated[0]) + + return 1 -libdfhack.alloc_descriptor_buffer_callback = CFUNCTYPE(POINTER(DescriptorColor), c_int)(_alloc_descriptor_buffer_callback) +_descriptor_functype = CFUNCTYPE(c_int, POINTER(DescriptorColor), c_uint) +libdfhack.alloc_descriptor_buffer_callback = _descriptor_functype(_alloc_descriptor_buffer_callback) class MatglossOther(Structure): _fields_ = [("rawname", c_char * 128)] @@ -118,9 +124,12 @@ class MatglossOther(Structure): def _alloc_matgloss_other_buffer_callback(count): allocated = _allocate_array(MatglossOther, count) - return allocated[1] + ptr = addressof(allocated[0]) -libdfhack.alloc_matgloss_other_buffer_callback = CFUNCTYPE(POINTER(MatglossOther), c_int)(_alloc_matgloss_other_buffer_callback) + return 1 + +_matgloss_other_functype = CFUNCTYPE(c_int, POINTER(MatglossOther), c_uint) +libdfhack.alloc_matgloss_other_buffer_callback = _matgloss_other_functype(_alloc_matgloss_other_buffer_callback) class Building(Structure): _fields_ = [("origin", c_uint), @@ -297,7 +306,10 @@ class ColorModifier(Structure): ColorModifierPtr = POINTER(ColorModifier) -def _alloc_empty_colormodifier_callback(): - return ColorModifierPtr(ColorModifier()) +def _alloc_empty_colormodifier_callback(ptr): + ptr = ColorModifierPtr(ColorModifier()) + + return 1 -libdfhack.alloc_empty_colormodifier_callback = CFUNCTYPE(ColorModifierPtr)(_alloc_empty_colormodifier_callback) +_empty_colormodifier_functype = CFUNCTYPE(c_int, ColorModifierPtr) +libdfhack.alloc_empty_colormodifier_callback = _empty_colormodifier_functype(_alloc_empty_colormodifier_callback) diff --git a/library/python/c api/util.py b/library/python/c api/util.py index 4f3f06958..d0849b1d8 100644 --- a/library/python/c api/util.py +++ b/library/python/c api/util.py @@ -1,5 +1,8 @@ from ctypes import * +uint_ptr = POINTER(c_uint) +int_ptr = POINTER(c_int) + def _uintify(x, y, z): return (c_uint(x), c_uint(y), c_uint(z)) @@ -13,54 +16,75 @@ def _allocate_array(t_type, count): return (arr, ptr) -def _alloc_int_buffer(count): +def _alloc_int_buffer(ptr, count): a = _allocate_array(c_int, count) - return a[1] + ptr = addressof(a[0]) + + return 1 -alloc_int_buffer = CFUNCTYPE(POINTER(c_int), c_uint)(_alloc_int_buffer) +_int_functype = CFUNCTYPE(c_int, POINTER(c_int), c_uint) +alloc_int_buffer = _int_functype(_alloc_int_buffer) -def _alloc_uint_buffer(count): +def _alloc_uint_buffer(ptr, count): a = _allocate_array(c_uint, count) - return a[1] + ptr = addressof(a[0]) + + return 1 -alloc_uint_buffer = CFUNCTYPE(POINTER(c_uint), c_uint)(_alloc_uint_buffer) +_uint_functype = CFUNCTYPE(c_int, POINTER(c_uint), c_uint) +alloc_uint_buffer = _uint_functype(_alloc_uint_buffer) -def _alloc_short_buffer(count): +def _alloc_short_buffer(ptr, count): a = _allocate_array(c_short, count) - return a[1] + ptr = addressof(a[0]) -alloc_short_buffer = CFUNCTYPE(POINTER(c_short), c_uint)(_alloc_short_buffer) + return 1 -def _alloc_ushort_buffer(count): +_short_functype = CFUNCTYPE(c_int, POINTER(c_short), c_uint) +alloc_short_buffer = _short_functype(_alloc_short_buffer) + +def _alloc_ushort_buffer(ptr, count): a = _allocate_array(c_ushort, count) - return a[1] + ptr = addressof(a[0]) + + return 1 -alloc_ushort_buffer = CFUNCTYPE(POINTER(c_ushort), c_uint)(_alloc_ushort_buffer) +_ushort_functype = CFUNCTYPE(c_int, POINTER(c_ushort), c_uint) +alloc_ushort_buffer = _ushort_functype(_alloc_ushort_buffer) -def _alloc_byte_buffer(count): +def _alloc_byte_buffer(ptr, count): a = _allocate_array(c_byte, count) - return a[1] + ptr = addressof(a[0]) -alloc_byte_buffer = CFUNCTYPE(POINTER(c_byte), c_uint)(_alloc_byte_buffer) + return 1 -def _alloc_ubyte_buffer(count): +_byte_functype = CFUNCTYPE(c_int, POINTER(c_byte), c_uint) +alloc_byte_buffer = _byte_functype(_alloc_byte_buffer) + +def _alloc_ubyte_buffer(ptr, count): a = _allocate_array(c_ubyte, count) - return a[1] + ptr = addressof(a[0]) + + return 1 -alloc_ubyte_buffer = CFUNCTYPE(POINTER(c_ubyte), c_uint)(_alloc_ubyte_buffer) +_ubyte_functype = CFUNCTYPE(c_int, POINTER(c_ubyte), c_uint) +alloc_ubyte_buffer = _ubyte_functype(_alloc_ubyte_buffer) -def _alloc_char_buffer(count): +def _alloc_char_buffer(ptr, count): c = create_string_buffer(count) - ptr = c_void_p() + if ptr is None: + ptr = c_void_p + ptr = addressof(c) - return ptr + return 1 -alloc_char_buffer = CFUNCTYPE(POINTER(c_char), c_uint)(_alloc_char_buffer) +_char_functype = CFUNCTYPE(c_int, POINTER(c_char), c_uint) +alloc_char_buffer = _char_functype(_alloc_char_buffer) From ab40868b2905ae4905595cd346d68f6365273194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 28 May 2010 05:18:32 +0200 Subject: [PATCH 005/122] ProcessEnumerator tracks processes properly now. --- library/CMakeLists.txt | 3 +- library/DFProcessEnumerator-linux.cpp | 135 -------- library/DFProcessEnumerator-windows.cpp | 147 --------- library/DFProcessEnumerator.cpp | 318 +++++++++++++++++++ library/include/dfhack/DFProcess.h | 43 ++- library/include/dfhack/DFProcessEnumerator.h | 6 +- tools/examples/CMakeLists.txt | 4 + tools/examples/processenum.cpp | 57 ++++ 8 files changed, 401 insertions(+), 312 deletions(-) delete mode 100644 library/DFProcessEnumerator-linux.cpp delete mode 100644 library/DFProcessEnumerator-windows.cpp create mode 100644 library/DFProcessEnumerator.cpp create mode 100644 tools/examples/processenum.cpp diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index ce44079cf..fc267e789 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -57,6 +57,7 @@ DFMemInfo.cpp DFMemInfoManager.cpp DFContextManager.cpp DFContext.cpp +DFProcessEnumerator.cpp ContextShared.cpp DFContext_C.cpp DFTypes_C.cpp @@ -105,14 +106,12 @@ DFProcess-linux.cpp DFProcess-linux-SHM.cpp DFProcess-linux-wine.cpp modules/WindowIO-linux.cpp -DFProcessEnumerator-linux.cpp ) SET(PROJECT_SRCS_WINDOWS DFProcess-windows.cpp DFProcess-windows-SHM.cpp modules/WindowIO-windows.cpp -DFProcessEnumerator-windows.cpp ) IF(UNIX) diff --git a/library/DFProcessEnumerator-linux.cpp b/library/DFProcessEnumerator-linux.cpp deleted file mode 100644 index 3ee14ef80..000000000 --- a/library/DFProcessEnumerator-linux.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* -www.sourceforge.net/projects/dfhack -Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf - -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 "dfhack/DFProcessEnumerator.h" -#include "dfhack/DFProcess.h" -#include "dfhack/DFMemInfo.h" -#include "dfhack/DFMemInfoManager.h" -#include -#include -#include -#include -#include "shms.h" - -using namespace DFHack; - -class DFHack::ProcessEnumerator::Private -{ - public: - Private(){}; - MemInfoManager *meminfo; - std::vector processes; -}; - -bool ProcessEnumerator::findProcessess() -{ - DIR *dir_p; - struct dirent *dir_entry_p; - // Open /proc/ directory - dir_p = opendir("/proc/"); - // Reading /proc/ entries - while(NULL != (dir_entry_p = readdir(dir_p))) - { - // Only PID folders (numbers) - if (strspn(dir_entry_p->d_name, "0123456789") != strlen(dir_entry_p->d_name)) - { - continue; - } - Process *p1 = new SHMProcess(atoi(dir_entry_p->d_name),d->meminfo->meminfo); - if(p1->isIdentified()) - { - d->processes.push_back(p1); - continue; - } - else - { - delete p1; - } - Process *p2 = new NormalProcess(atoi(dir_entry_p->d_name),d->meminfo->meminfo); - if(p2->isIdentified()) - { - d->processes.push_back(p2); - continue; - } - else - { - delete p2; - } - Process *p3 = new WineProcess(atoi(dir_entry_p->d_name),d->meminfo->meminfo); - if(p3->isIdentified()) - { - d->processes.push_back(p3); - continue; - } - else - { - delete p3; - } - - } - closedir(dir_p); - // return value depends on if we found some DF processes - if(d->processes.size()) - { - return true; - } - return false; -} - -uint32_t ProcessEnumerator::size() -{ - return d->processes.size(); -} - - -Process * ProcessEnumerator::operator[](uint32_t index) -{ - assert(index < d->processes.size()); - return d->processes[index]; -} - - -ProcessEnumerator::ProcessEnumerator( string path_to_xml ) -: d(new Private()) -{ - d->meminfo = new MemInfoManager(path_to_xml); -} - -void ProcessEnumerator::purge() -{ - for(uint32_t i = 0;i < d->processes.size();i++) - { - delete d->processes[i]; - } - d->processes.clear(); -} - -ProcessEnumerator::~ProcessEnumerator() -{ - // delete all processes - purge(); - delete d->meminfo; - delete d; -} diff --git a/library/DFProcessEnumerator-windows.cpp b/library/DFProcessEnumerator-windows.cpp deleted file mode 100644 index bec67361d..000000000 --- a/library/DFProcessEnumerator-windows.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* -www.sourceforge.net/projects/dfhack -Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf - -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 "dfhack/DFProcessEnumerator.h" -#include "dfhack/DFProcess.h" -#include "dfhack/DFMemInfo.h" -#include "dfhack/DFMemInfoManager.h" -using namespace DFHack; - -class DFHack::ProcessEnumerator::Private -{ - public: - Private(){}; - MemInfoManager *meminfo; - std::vector processes; -}; - -// some magic - will come in handy when we start doing debugger stuff on Windows -bool EnableDebugPriv() -{ - bool bRET = FALSE; - TOKEN_PRIVILEGES tp; - HANDLE hToken; - - if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid)) - { - if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) - { - if (hToken != INVALID_HANDLE_VALUE) - { - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - tp.PrivilegeCount = 1; - if (AdjustTokenPrivileges(hToken, FALSE, &tp, 0, 0, 0)) - { - bRET = TRUE; - } - CloseHandle(hToken); - } - } - } - return bRET; -} - -// WINDOWS version of the process finder -bool ProcessEnumerator::findProcessess() -{ - // Get the list of process identifiers. - DWORD ProcArray[2048], memoryNeeded, numProccesses; - //EnableDebugPriv(); - if ( !EnumProcesses( ProcArray, sizeof(ProcArray), &memoryNeeded ) ) - { - cout << "EnumProcesses fail'd" << endl; - return false; - } - - // Calculate how many process identifiers were returned. - numProccesses = memoryNeeded / sizeof(DWORD); - EnableDebugPriv(); - - // iterate through processes - for ( int i = 0; i < (int)numProccesses; i++ ) - { - Process *p = new SHMProcess(ProcArray[i],d->meminfo->meminfo); - if(p->isIdentified()) - { - d->processes.push_back(p); - continue; - } - else - { - delete p; - p = 0; - } - p = new NormalProcess(ProcArray[i],d->meminfo->meminfo); - if(p->isIdentified()) - { - d->processes.push_back(p); - continue; - } - else - { - delete p; - p = 0; - } - } - if(d->processes.size()) - return true; - return false; -} - -uint32_t ProcessEnumerator::size() -{ - return d->processes.size(); -}; - - -Process * ProcessEnumerator::operator[](uint32_t index) -{ - assert(index < d->processes.size()); - return d->processes[index]; -}; - - -ProcessEnumerator::ProcessEnumerator( string path_to_xml ) -: d(new Private()) -{ - d->meminfo = new MemInfoManager(path_to_xml); -} - -void ProcessEnumerator::purge() -{ - for(uint32_t i = 0;i < d->processes.size();i++) - { - delete d->processes[i]; - } - d->processes.clear(); -} - -ProcessEnumerator::~ProcessEnumerator() -{ - // delete all processes - purge(); - delete d->meminfo; - delete d; -} diff --git a/library/DFProcessEnumerator.cpp b/library/DFProcessEnumerator.cpp new file mode 100644 index 000000000..67132917d --- /dev/null +++ b/library/DFProcessEnumerator.cpp @@ -0,0 +1,318 @@ +/* +www.sourceforge.net/projects/dfhack +Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf + +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 "dfhack/DFProcessEnumerator.h" +#include "dfhack/DFProcess.h" +#include "dfhack/DFMemInfo.h" +#include "dfhack/DFMemInfoManager.h" + +using namespace DFHack; + +typedef std::vector PROC_V; +typedef std::map PID2PROC; + +class DFHack::ProcessEnumerator::Private +{ + public: + Private(){}; + MemInfoManager *meminfo; + PROC_V Processes; + PID2PROC ProcMap; + Process *GetProcessObject(ProcessID ID); + void EnumPIDs (vector &PIDs); +}; + +#ifdef LINUX_BUILD +//FIXME: wasteful +Process *ProcessEnumerator::Private::GetProcessObject(ProcessID ID) +{ + + Process *p1 = new SHMProcess(ID.pid,meminfo->meminfo); + if(p1->isIdentified()) + return p1; + else + delete p1; + + Process *p2 = new NormalProcess(ID.pid,meminfo->meminfo); + if(p2->isIdentified()) + return p2; + else + delete p2; + + Process *p3 = new WineProcess(ID.pid,meminfo->meminfo); + if(p3->isIdentified()) + return p3; + else + delete p3; + return 0; +} + +void ProcessEnumerator::Private::EnumPIDs (vector &PIDs) +{ + DIR *dir_p; + struct dirent *dir_entry_p; + struct stat st; + char fullname[512]; + fullname[0] = 0; + PIDs.clear(); // make sure the vector is clear + + // Open /proc/ directory + dir_p = opendir("/proc/"); + // Reading /proc/ entries + while(NULL != (dir_entry_p = readdir(dir_p))) + { + // Only PID folders (numbers) + if (strspn(dir_entry_p->d_name, "0123456789") != strlen(dir_entry_p->d_name)) + { + continue; + } + sprintf(fullname, "/proc/%s", dir_entry_p->d_name); + int ierr = stat (fullname, &st); + if (ierr != 0) + { + printf("Cannot stat %s: ierr= %d\n", fullname, ierr); + continue; + } + uint64_t Pnum = atoi(dir_entry_p->d_name); + uint64_t ctime = st.st_ctime; + PIDs.push_back(ProcessID(ctime,Pnum)); + } + closedir(dir_p); +} +#endif + +#ifndef LINUX_BUILD +Process *ProcessEnumerator::Private::GetProcessObject(ProcessID ID) +{ + + Process *p1 = new SHMProcess(ID.pid,meminfo->meminfo); + if(p1->isIdentified()) + return p1; + else + delete p1; + + Process *p2 = new NormalProcess(ID.pid,meminfo->meminfo); + if(p2->isIdentified()) + return p2; + else + delete p2; + return 0; +} +// some magic - will come in handy when we start doing debugger stuff on Windows +bool EnableDebugPriv() +{ + bool bRET = FALSE; + TOKEN_PRIVILEGES tp; + HANDLE hToken; + + if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid)) + { + if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) + { + if (hToken != INVALID_HANDLE_VALUE) + { + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + tp.PrivilegeCount = 1; + if (AdjustTokenPrivileges(hToken, FALSE, &tp, 0, 0, 0)) + { + bRET = TRUE; + } + CloseHandle(hToken); + } + } + } + return bRET; +} + +// Convert Windows FileTime structs to POSIX timestamp +// from http://frenk.wordpress.com/2009/12/14/convert-filetime-to-unix-timestamp/ +uint64_t FileTime_to_POSIX(FILETIME ft) +{ + // takes the last modified date + LARGE_INTEGER date, adjust; + date.HighPart = ft.dwHighDateTime; + date.LowPart = ft.dwLowDateTime; + + // 100-nanoseconds = milliseconds * 10000 + adjust.QuadPart = 11644473600000 * 10000; + + // removes the diff between 1970 and 1601 + date.QuadPart -= adjust.QuadPart; + + // converts back from 100-nanoseconds to seconds + return date.QuadPart / 10000000; +} + +void ProcessEnumerator::Private::EnumPIDs (vector &PIDs) +{ + FILETIME ftCreate, ftExit, ftKernel, ftUser; + + PIDs.clear(); // make sure the vector is clear + + // Get the list of process identifiers. + DWORD ProcArray[2048], memoryNeeded, numProccesses; + //EnableDebugPriv(); + if ( !EnumProcesses( ProcArray, sizeof(ProcArray), &memoryNeeded ) ) + { + cout << "EnumProcesses fail'd" << endl; + return; + } + // Calculate how many process identifiers were returned. + numProccesses = memoryNeeded / sizeof(DWORD); + EnableDebugPriv(); + // iterate through processes + for ( int i = 0; i < (int)numProccesses; i++ ) + { + HANDLE proc = OpenProcess (PROCESS_QUERY_INFORMATION, false, ProcArray[i]); + if(!proc) + continue; + if(GetProcessTimes(proc, &ftCreate, &ftExit, &ftKernel, &ftUser)) + { + uint64_t ctime = FileTime_to_POSIX(ftCreate); + uint64_t Pnum = ProcArray[i]; + PIDs.push_back(ProcessID(ctime,Pnum)); + } + CloseHandle(proc); + } +} +#endif + +bool ProcessEnumerator::Refresh( PROC_V * invalidated_processes) +{ + // PIDs to process + vector PIDs; + // this will be the new process map + PID2PROC temporary; + // clear the vector other access + d->Processes.clear(); + if(invalidated_processes) + invalidated_processes->clear(); + + d->EnumPIDs(PIDs); + + for(uint64_t i = 0; i < PIDs.size();i++) + { + ProcessID & PID = PIDs[i]; + // check if we know about the OS process already + PID2PROC::iterator found= d->ProcMap.find(PID); + if( found != d->ProcMap.end()) + { + // we do + // check if it does have a DFHack Process object associated with it + Process * p = (*found).second; + if(p) + { + // add it back to the vector we export + d->Processes.push_back(p); + } + // remove the OS Process from ProcMap + d->ProcMap.erase(found); + // add the OS Process to what will be the new ProcMap + temporary[PID] = p; + } + else + { + // an OS process we don't know yet! + // try to make a DFHack Process object for it + if(Process*p = d->GetProcessObject(PID)) + { + // allright. this is something that can be used + d->Processes.push_back(p); + temporary[PID] = p; + } + else + { + // just a process. we track it anyway. Why not. + temporary[PID] = 0; + } + } + } + // now the vector we export is filled again and a temporary map with valid processes is created. + // we iterate over the old Process map and destroy all the processes that are dead. + for(PID2PROC::const_iterator idx = d->ProcMap.begin(); idx != d->ProcMap.end();++idx) + { + Process * p = (*idx).second; + if(p) + { + if(invalidated_processes) + { + invalidated_processes->push_back(p); + } + else + { + delete p; + } + } + } + d->ProcMap.swap(temporary); + // return value depends on if we found some DF processes + if(d->Processes.size()) + { + return true; + } + return false; +} + +bool ProcessEnumerator::findProcessess() +{ + return Refresh(); +} + +uint32_t ProcessEnumerator::size() +{ + return d->Processes.size(); +} + + +Process * ProcessEnumerator::operator[](uint32_t index) +{ + assert(index < d->Processes.size()); + return d->Processes[index]; +} + + +ProcessEnumerator::ProcessEnumerator( string path_to_xml ) +: d(new Private()) +{ + d->meminfo = new MemInfoManager(path_to_xml); +} + +void ProcessEnumerator::purge() +{ + for(uint32_t i = 0;i < d->Processes.size();i++) + { + delete d->Processes[i]; + } + d->ProcMap.clear(); + d->Processes.clear(); +} + +ProcessEnumerator::~ProcessEnumerator() +{ + // delete all processes + purge(); + delete d->meminfo; + delete d; +} diff --git a/library/include/dfhack/DFProcess.h b/library/include/dfhack/DFProcess.h index 686d7cc40..2fc2620d0 100644 --- a/library/include/dfhack/DFProcess.h +++ b/library/include/dfhack/DFProcess.h @@ -35,6 +35,25 @@ namespace DFHack class Process; class Window; + struct ProcessID + { + ProcessID(const uint64_t _time, const uint64_t _pid): time(_time), pid(_pid){}; + bool operator==(const ProcessID &other) const + { + return (other.time == time && other.pid == pid); + } + bool operator< (const ProcessID& ms) const + { + if (time < ms.time) + return true; + else if(time == ms.time) + return pid < ms.pid ; + return false; + } + uint64_t time; + uint64_t pid; + }; + // structure describing a memory range struct DFHACK_EXPORT t_memrange { @@ -130,12 +149,6 @@ namespace DFHack virtual char * getSHMStart (void) = 0; // set a SHM command and wait for a response, return 0 on error or throw exception virtual bool SetAndWait (uint32_t state) = 0; - /* - // wait while SHM command == state. returns 0 without the SHM - virtual bool waitWhile (uint32_t state) = 0; - // set SHM command. - virtual void setCmd (uint32_t newstate) = 0; - */ }; class DFHACK_EXPORT NormalProcess : virtual public Process @@ -200,12 +213,6 @@ namespace DFHack char * getSHMStart (void){return 0;}; // set a SHM command and wait for a response bool SetAndWait (uint32_t state){return false;}; - /* - // wait for a SHM state. returns 0 without the SHM - bool waitWhile (uint32_t state){return false;}; - // set SHM command. - void setCmd (uint32_t newstate){}; - */ }; class DFHACK_EXPORT SHMProcess : virtual public Process @@ -270,12 +277,6 @@ namespace DFHack // get the SHM start if available char * getSHMStart (void); bool SetAndWait (uint32_t state); - /* - // wait for a SHM state. returns 0 without the SHM - bool waitWhile (uint32_t state); - // set SHM command. - void setCmd (uint32_t newstate); - */ }; #ifdef LINUX_BUILD @@ -340,12 +341,6 @@ namespace DFHack // get the SHM start if available char * getSHMStart (void){return 0;}; bool SetAndWait (uint32_t state){return false;}; - /* - // wait for a SHM state. returns 0 without the SHM - bool waitWhile (uint32_t state){return false;}; - // set SHM command. - void setCmd (uint32_t newstate){}; - */ }; #endif } diff --git a/library/include/dfhack/DFProcessEnumerator.h b/library/include/dfhack/DFProcessEnumerator.h index c40253c15..0ef9b98ba 100644 --- a/library/include/dfhack/DFProcessEnumerator.h +++ b/library/include/dfhack/DFProcessEnumerator.h @@ -28,13 +28,10 @@ distribution. #include "DFPragma.h" #include "DFExport.h" -class TiXmlElement; - namespace DFHack { class memory_info; class Process; - /* * Process manager */ @@ -43,8 +40,9 @@ namespace DFHack class Private; Private * const d; public: - ProcessEnumerator( string path_to_xml); + ProcessEnumerator( string path_to_xml ); ~ProcessEnumerator(); + bool Refresh(vector * invalidated_processes = 0); bool findProcessess(); uint32_t size(); Process * operator[](uint32_t index); diff --git a/tools/examples/CMakeLists.txt b/tools/examples/CMakeLists.txt index 3662181b4..190dff3cc 100644 --- a/tools/examples/CMakeLists.txt +++ b/tools/examples/CMakeLists.txt @@ -47,6 +47,10 @@ TARGET_LINK_LIBRARIES(dftreedump dfhack) ADD_EXECUTABLE(dfspatterdump spatterdump.cpp) TARGET_LINK_LIBRARIES(dfspatterdump dfhack) +# processenum - demonstrates the use of ProcessEnumerator +ADD_EXECUTABLE(dfprocessenum processenum.cpp) +TARGET_LINK_LIBRARIES(dfprocessenum dfhack) + IF(UNIX) SET(CURSES_NEED_WIDE "YES") SET(CURSES_NEED_NCURSES "NO") diff --git a/tools/examples/processenum.cpp b/tools/examples/processenum.cpp new file mode 100644 index 000000000..1be065da7 --- /dev/null +++ b/tools/examples/processenum.cpp @@ -0,0 +1,57 @@ +// Demonstrates the use of ProcessEnumerator +// queries the Enumerator for all DF Processes on user input. Prints them to the terminal. +// also tracks processes that were invalidated + +#include +#include +#include +#include +using namespace std; + +#include +#include +using namespace DFHack; +#ifndef LINUX_BUILD +#endif +int main (void) +{ + vector inval; + ProcessEnumerator Penum("Memory.xml"); + memory_info * mem; + for(int cnt = 0; cnt < 100; cnt++) + { + // make the ProcessEnumerator update its list of Processes + // by passing the pointer to 'inval', we make it export expired + // processes instead of destroying them outright + // (processes expire when the OS kills them for whatever reason) + Penum.Refresh(&inval); + int nProc = Penum.size(); + int nInval = inval.size(); + + cout << "Processes:" << endl; + for(int i = 0; i < nProc; i++) + { + mem = Penum[i]->getDescriptor(); + cout << "DF instance: " << Penum[i]->getPID() + << ", " << mem->getVersion() << endl; + } + + cout << "Invalidated:" << endl; + for(int i = 0; i < nInval; i++) + { + mem = inval[i]->getDescriptor(); + cout << "DF instance: " << inval[i]->getPID() + << ", " << mem->getVersion() << endl; + // we own the expired process, we must take care of freeing its resources + delete inval[i]; + } + cout << "<-* Press Enter to refresh *->" << endl << endl; + cin.ignore(); + } + + #ifndef LINUX_BUILD + cout << "Done. Press any key to continue" << endl; + cin.ignore(); + #endif + return 0; +} From 7300e61f8ad71442008b190c8fc8bb68588d286e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sat, 29 May 2010 21:34:36 +0200 Subject: [PATCH 006/122] ContextManager and ProcessEnumerator have the basic functionality done. Created a test program to validate them and show how to use them. --- library/DFContextManager.cpp | 149 +++++++++++++++++-- library/DFProcessEnumerator.cpp | 101 ++++++++++--- library/include/dfhack/DFContextManager.h | 24 ++- library/include/dfhack/DFProcessEnumerator.h | 18 ++- tools/examples/processenum.cpp | 127 ++++++++++++---- 5 files changed, 348 insertions(+), 71 deletions(-) diff --git a/library/DFContextManager.cpp b/library/DFContextManager.cpp index 636325bdc..605a240ba 100644 --- a/library/DFContextManager.cpp +++ b/library/DFContextManager.cpp @@ -41,23 +41,90 @@ distribution. using namespace DFHack; namespace DFHack { - class DFContextMgrPrivate + class ContextManager::Private { public: - DFContextMgrPrivate(){}; - ~DFContextMgrPrivate(){}; + Private(){}; + ~Private(){}; string xml; // path to xml vector contexts; ProcessEnumerator * pEnum; }; } +class DFHack::BadContexts::Private +{ + public: + Private(){}; + vector bad; +}; + + +BadContexts::BadContexts():d(new Private()){} + +BadContexts::~BadContexts() +{ + clear(); + delete d; +} + +bool BadContexts::Contains(Process* p) +{ + for(int i = 0; i < d->bad.size(); i++) + { + if((d->bad[i])->getProcess() == p) + return true; + } + return false; +} + +bool BadContexts::Contains(Context* c) +{ + for(int i = 0; i < d->bad.size(); i++) + { + if(d->bad[i] == c) + return true; + } + return false; +} + +uint32_t BadContexts::size() +{ + return d->bad.size(); +} + +void BadContexts::clear() +{ + for(int i = 0; i < d->bad.size(); i++) + { + // delete both Process and Context! + // process has to be deleted after context, because Context does some + // cleanup on delete (detach, etc.) + Process * to_kill = d->bad[i]->getProcess(); + delete d->bad[i]; + delete to_kill; + } + d->bad.clear(); +} + +void BadContexts::push_back(Context* c) +{ + if(c) + d->bad.push_back(c); +} + +Context * BadContexts::operator[](uint32_t index) +{ + if(index < d->bad.size()) + return d->bad[index]; + return 0; +} -ContextManager::ContextManager (const string path_to_xml) : d (new DFContextMgrPrivate()) +ContextManager::ContextManager (const string path_to_xml) : d (new Private()) { - d->pEnum = 0; d->xml = QUOT (MEMXML_DATA_PATH); d->xml += "/"; d->xml += path_to_xml; + d->pEnum = new ProcessEnumerator(d->xml); } ContextManager::~ContextManager() @@ -66,26 +133,76 @@ ContextManager::~ContextManager() delete d; } -uint32_t ContextManager::Refresh() +uint32_t ContextManager::Refresh( BadContexts* bad_contexts ) { - purge(); - if(d->pEnum != 0) - d->pEnum = new ProcessEnumerator(d->xml); - else + // handle expired processes, remove stale Contexts { - delete d->pEnum; - d->pEnum = new ProcessEnumerator(d->xml); + BadProcesses expired; + // get new list od living and expired Process objects + d->pEnum->Refresh(&expired); + + // scan expired, kill contexts if necessary + vector ::iterator it = d->contexts.begin();; + while(it != d->contexts.end()) + { + Process * test = (*it)->getProcess(); + if(expired.Contains(test)) + { + // ok. we have an expired context here. + if(!bad_contexts) + { + // with nowhere to put the context, we have to destroy it + delete *it; + // stop tracking it and advance the iterator + it = d->contexts.erase(it); + continue; + } + else + { + // we stuff the context into bad_contexts + bad_contexts->push_back(*it); + // stop tracking it and advance the iterator + it = d->contexts.erase(it); + // remove process from the 'expired' container, it is tracked by bad_contexts now + // (which is responsible for freeing it). + expired.excise(test); + continue; + } + } + else it++; // not expired, just advance to next one + } + // no expired contexts are in the d->contexts vector now + // all processes remaining in 'expired' are now destroyed along with it } - d->pEnum->purge(); - d->pEnum->findProcessess(); + int numProcesses = d->pEnum->size(); + int numContexts = d->contexts.size(); + vector newContexts; + // enumerate valid processes for(int i = 0; i < numProcesses; i++) { - Context * c = new Context(d->pEnum->operator[](i)); - d->contexts.push_back(c); + Process * test = d->pEnum->operator[](i); + bool exists = false; + // scan context vector for this process + for(int j = 0; j < numContexts; j++) + { + if((d->contexts[j])->getProcess() == test) + { + // already have that one, skip + exists = true; + } + } + if(!exists) + { + // new process needs a new context + Context * c = new Context(d->pEnum->operator[](i)); + newContexts.push_back(c); + } } + d->contexts.insert(d->contexts.end(), newContexts.begin(), newContexts.end()); return d->contexts.size(); } + uint32_t ContextManager::size() { return d->contexts.size(); diff --git a/library/DFProcessEnumerator.cpp b/library/DFProcessEnumerator.cpp index 67132917d..8c537c13b 100644 --- a/library/DFProcessEnumerator.cpp +++ b/library/DFProcessEnumerator.cpp @@ -44,7 +44,76 @@ class DFHack::ProcessEnumerator::Private void EnumPIDs (vector &PIDs); }; -#ifdef LINUX_BUILD +class DFHack::BadProcesses::Private +{ + public: + Private(){}; + PROC_V bad; +}; + +BadProcesses::BadProcesses():d(new Private()){} + +BadProcesses::~BadProcesses() +{ + clear(); + delete d; +} + +bool BadProcesses::Contains(Process* p) +{ + for(int i = 0; i < d->bad.size(); i++) + { + if(d->bad[i] == p) + return true; + } + return false; +} + +bool BadProcesses::excise(Process* p) +{ + vector::iterator it = d->bad.begin(); + while(it != d->bad.end()) + { + if((*it) == p) + { + d->bad.erase(it); + return true; + } + else + { + it++; + } + } + return false; +} + +uint32_t BadProcesses::size() +{ + return d->bad.size(); +} + +void BadProcesses::clear() +{ + for(int i = 0; i < d->bad.size(); i++) + { + delete d->bad[i]; + } + d->bad.clear(); +} + +void BadProcesses::push_back(Process* p) +{ + if(p) + d->bad.push_back(p); +} + +Process * BadProcesses::operator[](uint32_t index) +{ + if(index < d->bad.size()) + return d->bad[index]; + return 0; +} + //FIXME: wasteful Process *ProcessEnumerator::Private::GetProcessObject(ProcessID ID) { @@ -54,21 +123,23 @@ Process *ProcessEnumerator::Private::GetProcessObject(ProcessID ID) return p1; else delete p1; - + Process *p2 = new NormalProcess(ID.pid,meminfo->meminfo); if(p2->isIdentified()) return p2; else delete p2; - +#ifdef LINUX_BUILD Process *p3 = new WineProcess(ID.pid,meminfo->meminfo); if(p3->isIdentified()) return p3; else delete p3; return 0; +#endif } +#ifdef LINUX_BUILD void ProcessEnumerator::Private::EnumPIDs (vector &PIDs) { DIR *dir_p; @@ -104,22 +175,6 @@ void ProcessEnumerator::Private::EnumPIDs (vector &PIDs) #endif #ifndef LINUX_BUILD -Process *ProcessEnumerator::Private::GetProcessObject(ProcessID ID) -{ - - Process *p1 = new SHMProcess(ID.pid,meminfo->meminfo); - if(p1->isIdentified()) - return p1; - else - delete p1; - - Process *p2 = new NormalProcess(ID.pid,meminfo->meminfo); - if(p2->isIdentified()) - return p2; - else - delete p2; - return 0; -} // some magic - will come in handy when we start doing debugger stuff on Windows bool EnableDebugPriv() { @@ -199,19 +254,19 @@ void ProcessEnumerator::Private::EnumPIDs (vector &PIDs) } #endif -bool ProcessEnumerator::Refresh( PROC_V * invalidated_processes) +bool ProcessEnumerator::Refresh( BadProcesses* invalidated_processes) { // PIDs to process vector PIDs; // this will be the new process map PID2PROC temporary; - // clear the vector other access + // clear the vector d->Processes.clear(); if(invalidated_processes) invalidated_processes->clear(); - + d->EnumPIDs(PIDs); - + for(uint64_t i = 0; i < PIDs.size();i++) { ProcessID & PID = PIDs[i]; diff --git a/library/include/dfhack/DFContextManager.h b/library/include/dfhack/DFContextManager.h index 3337755d7..acf738bca 100644 --- a/library/include/dfhack/DFContextManager.h +++ b/library/include/dfhack/DFContextManager.h @@ -35,18 +35,36 @@ distribution. namespace DFHack { class Context; - class DFContextMgrPrivate; + class BadContexts; + class Process; + class DFHACK_EXPORT ContextManager { - DFContextMgrPrivate * const d; + class Private; + Private * const d; public: ContextManager(const std::string path_to_xml); ~ContextManager(); - uint32_t Refresh(); + uint32_t Refresh(BadContexts* bad_contexts = 0); uint32_t size(); Context * operator[](uint32_t index); Context * getSingleContext(); void purge(void); }; + class DFHACK_EXPORT BadContexts + { + class Private; + Private * const d; + void push_back(Context * c); + friend class ContextManager; + public: + BadContexts(); + ~BadContexts(); + bool Contains(Context* c); + bool Contains(Process* p); + uint32_t size(); + void clear(); + Context * operator[](uint32_t index); + }; } // namespace DFHack #endif // CONTEXTMANAGER_H_INCLUDED diff --git a/library/include/dfhack/DFProcessEnumerator.h b/library/include/dfhack/DFProcessEnumerator.h index 0ef9b98ba..4e618ae27 100644 --- a/library/include/dfhack/DFProcessEnumerator.h +++ b/library/include/dfhack/DFProcessEnumerator.h @@ -32,6 +32,7 @@ namespace DFHack { class memory_info; class Process; + class BadProcesses; /* * Process manager */ @@ -42,11 +43,26 @@ namespace DFHack public: ProcessEnumerator( string path_to_xml ); ~ProcessEnumerator(); - bool Refresh(vector * invalidated_processes = 0); + bool Refresh(BadProcesses * invalidated_processes = 0); bool findProcessess(); uint32_t size(); Process * operator[](uint32_t index); void purge(void); }; + class DFHACK_EXPORT BadProcesses + { + class Private; + Private * const d; + void push_back(Process * p); + friend class ProcessEnumerator; + public: + BadProcesses(); + ~BadProcesses(); + bool Contains(Process* p); + bool excise (Process* p); + uint32_t size(); + void clear(); + Process * operator[](uint32_t index); + }; } #endif // PROCESSMANAGER_H_INCLUDED diff --git a/tools/examples/processenum.cpp b/tools/examples/processenum.cpp index 1be065da7..1910ca733 100644 --- a/tools/examples/processenum.cpp +++ b/tools/examples/processenum.cpp @@ -13,42 +13,113 @@ using namespace std; using namespace DFHack; #ifndef LINUX_BUILD #endif + +void printhelp () +{ + cout << "enter empty line for next try." << endl; + cout << "enter 'next' or 'n' for next test." << endl; + cout << "enter 'help' to show this text again." << endl; +} + +int inputwait (const char * prompt) +{ +inputwait_reset: + string command = ""; + cout <<"[" << prompt << "]# "; + getline(cin, command); + if(command == "help") + { + printhelp(); + goto inputwait_reset; + } + else if(command == "") + { + return 1; + } + else if(command == "next") + { + return 0; + } + else + { + cout << "Command not recognized. Try 'help' for a list of valid commands." << endl; + goto inputwait_reset; + } + return 0; +} + int main (void) { - vector inval; - ProcessEnumerator Penum("Memory.xml"); - memory_info * mem; - for(int cnt = 0; cnt < 100; cnt++) + printhelp(); + cout << endl; + // first test ProcessEnumerator and BadProcesses { - // make the ProcessEnumerator update its list of Processes - // by passing the pointer to 'inval', we make it export expired - // processes instead of destroying them outright - // (processes expire when the OS kills them for whatever reason) - Penum.Refresh(&inval); - int nProc = Penum.size(); - int nInval = inval.size(); - - cout << "Processes:" << endl; - for(int i = 0; i < nProc; i++) + cout << "Testing ProcessEnumerator" << endl; + ProcessEnumerator Penum("Memory.xml"); + memory_info * mem; + do { - mem = Penum[i]->getDescriptor(); - cout << "DF instance: " << Penum[i]->getPID() - << ", " << mem->getVersion() << endl; - } + // make the ProcessEnumerator update its list of Processes + // by passing the pointer to 'inval', we make it export expired + // processes instead of destroying them outright + // (processes expire when the OS kills them for whatever reason) + BadProcesses inval; + Penum.Refresh(&inval); + int nProc = Penum.size(); + int nInval = inval.size(); + + cout << "Processes:" << endl; + for(int i = 0; i < nProc; i++) + { + mem = Penum[i]->getDescriptor(); + cout << "DF instance: " << Penum[i]->getPID() + << ", " << mem->getVersion() << endl; + } - cout << "Invalidated:" << endl; - for(int i = 0; i < nInval; i++) + cout << "Invalidated:" << endl; + for(int i = 0; i < nInval; i++) + { + mem = inval[i]->getDescriptor(); + cout << "DF instance: " << inval[i]->getPID() + << ", " << mem->getVersion() << endl; + } + } + while(inputwait("ProcessEnumerator")); + } + // next test ContextManager and BadContexts + { + cout << "Testing ProcessEnumerator" << endl; + ContextManager Cman("Memory.xml"); + memory_info * mem; + do { - mem = inval[i]->getDescriptor(); - cout << "DF instance: " << inval[i]->getPID() - << ", " << mem->getVersion() << endl; - // we own the expired process, we must take care of freeing its resources - delete inval[i]; + // make the ProcessEnumerator update its list of Processes + // by passing the pointer to 'inval', we make it export expired + // processes instead of destroying them outright + // (processes expire when the OS kills them for whatever reason) + BadContexts inval; + Cman.Refresh(&inval); + int nCont = Cman.size(); + int nInval = inval.size(); + + cout << "Contexts:" << endl; + for(int i = 0; i < nCont; i++) + { + mem = Cman[i]->getMemoryInfo(); + cout << "DF instance: " << Cman[i]->getProcess()->getPID() + << ", " << mem->getVersion() << endl; + } + + cout << "Invalidated:" << endl; + for(int i = 0; i < nInval; i++) + { + mem = inval[i]->getMemoryInfo(); + cout << "DF instance: " << inval[i]->getProcess()->getPID() + << ", " << mem->getVersion() << endl; + } } - cout << "<-* Press Enter to refresh *->" << endl << endl; - cin.ignore(); + while(inputwait("ContextManager")); } - #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); From 95b44a8ef3bbe11be0822eac1d0745525df97163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sat, 29 May 2010 22:46:23 +0200 Subject: [PATCH 007/122] Documented ContextManager --- library/DFContextManager.cpp | 19 +++--- library/include/dfhack/DFContextManager.h | 77 ++++++++++++++++++++++- 2 files changed, 86 insertions(+), 10 deletions(-) diff --git a/library/DFContextManager.cpp b/library/DFContextManager.cpp index 605a240ba..5b947894d 100644 --- a/library/DFContextManager.cpp +++ b/library/DFContextManager.cpp @@ -130,6 +130,13 @@ ContextManager::ContextManager (const string path_to_xml) : d (new Private()) ContextManager::~ContextManager() { purge(); + // process enumerator has to be destroyed after we detach from processes + // because it tracks and destroys them + if(d->pEnum) + { + delete d->pEnum; + d->pEnum = 0; + } delete d; } @@ -174,7 +181,6 @@ uint32_t ContextManager::Refresh( BadContexts* bad_contexts ) // no expired contexts are in the d->contexts vector now // all processes remaining in 'expired' are now destroyed along with it } - int numProcesses = d->pEnum->size(); int numContexts = d->contexts.size(); vector newContexts; @@ -207,12 +213,14 @@ uint32_t ContextManager::size() { return d->contexts.size(); } + Context * ContextManager::operator[](uint32_t index) { if (index < d->contexts.size()) return d->contexts[index]; return 0; } + Context * ContextManager::getSingleContext() { if(!d->contexts.size()) @@ -228,16 +236,11 @@ Context * ContextManager::getSingleContext() } throw DFHack::Error::NoProcess(); } + void ContextManager::purge(void) { for(int i = 0; i < d->contexts.size();i++) delete d->contexts[i]; d->contexts.clear(); - // process enumerator has to be destroyed after we detach from processes - // because it tracks and destroys them - if(d->pEnum) - { - delete d->pEnum; - d->pEnum = 0; - } + d->pEnum->purge(); } \ No newline at end of file diff --git a/library/include/dfhack/DFContextManager.h b/library/include/dfhack/DFContextManager.h index acf738bca..c3d6b3edf 100644 --- a/library/include/dfhack/DFContextManager.h +++ b/library/include/dfhack/DFContextManager.h @@ -37,33 +37,106 @@ namespace DFHack class Context; class BadContexts; class Process; - + /** + * Used to enumerate, create and destroy Contexts. The very base of DFHack. + * @see DFHack::Context + */ class DFHACK_EXPORT ContextManager { class Private; Private * const d; public: + /** + * Constructs the ContextManager. + * @param path_to_xml the path to the file that defines memory offsets. (Memory.xml) + */ ContextManager(const std::string path_to_xml); + + /** + * Destroys the ContextManager. + */ ~ContextManager(); + + /** + * Refresh the internal list of valid Context objects. + * @param bad_contexts pointer to a BadContexts object. Not required. All contexts are automatically destroyed if the object is not provided. + * @see DFHack::BadContexts + * @return Number of tracked contexts + */ uint32_t Refresh(BadContexts* bad_contexts = 0); + + /** + * Get the number of tracked contexts. + * @return Number of tracked contexts + */ uint32_t size(); + + /** + * Get a context by index + * @param index index of the context to be returned + * @return pointer to a Context + */ Context * operator[](uint32_t index); + + /** + * Convenience method to return a single valid Context + * @return pointer to a Context + */ Context * getSingleContext(); + + /** + * Destroy all tracked Context objects + * Normally called during object destruction. Calling this from outside ContextManager is nasty. + */ void purge(void); }; + + /** + * Class used for holding a set of invalidated Context AND Process objects temporarily and destroy them safely. + * @see DFHack::Context + * @see DFHack::Process + */ class DFHACK_EXPORT BadContexts { class Private; Private * const d; void push_back(Context * c); friend class ContextManager; + void clear(); public: BadContexts(); + /** + * Destructor. + * All Processes and Contexts tracked by the BadContexts object will be destroyed also. + */ ~BadContexts(); + + /** + * Test if a Context is among the invalidated Contexts + * @param c pointer to a Context to be checked + * @return true if the Context is among the invalidated. false otherwise. + */ bool Contains(Context* c); + + /** + * Test if a Process is among the invalidated Processes/Contexts + * @param p pointer to a Process to be checked + * @see DFHack::Process + * @return true if the Process is among the invalidated. false otherwise. + */ bool Contains(Process* p); + + /** + * Get the number of tracked invalid contexts. + * @return Number of tracked invalid contexts + */ uint32_t size(); - void clear(); + + /** + * Get an invalid Context by index + * @param index index of the invalid Context to be returned + * @return pointer to an invalid Context + */ Context * operator[](uint32_t index); }; } // namespace DFHack From 5ee4acfd2ea72a4a455c3f03460f0a41e95da207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sat, 29 May 2010 23:50:14 +0200 Subject: [PATCH 008/122] Fixed build problem in C API. Beware of bad memory management! --- library/modules/Items_C.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/modules/Items_C.cpp b/library/modules/Items_C.cpp index 75e555c79..b9978f962 100644 --- a/library/modules/Items_C.cpp +++ b/library/modules/Items_C.cpp @@ -28,6 +28,8 @@ distribution. extern "C" { #endif +//FIXME: beware of bad null-termination! I haven't tested anything here, but it seems that it could be corrupting or truncating strings. + char* Items_getItemDescription(DFHackObject* items, uint32_t itemptr, DFHackObject* mats) { if(items != NULL && mats != NULL) @@ -36,7 +38,8 @@ char* Items_getItemDescription(DFHackObject* items, uint32_t itemptr, DFHackObje if(desc.size() > 0) { - char* buf = (*alloc_char_buffer_callback)(desc.size()); + char* buf; + (*alloc_char_buffer_callback)(buf,desc.size()); if(buf != NULL) { @@ -63,8 +66,8 @@ char* Items_getItemClass(DFHackObject* items, int32_t index) if(iclass.size() > 0) { - char* buf = (*alloc_char_buffer_callback)(iclass.size()); - + char* buf; + (*alloc_char_buffer_callback)(buf, iclass.size()); if(buf != NULL) { size_t len = iclass.copy(buf, iclass.size()); From 123fb5a9d045ac247c1dd36f4541f90929bb24ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 30 May 2010 05:13:59 +0200 Subject: [PATCH 009/122] Lots of comments. Using templates in the search tool. --- library/DFContextManager.cpp | 2 +- library/DFMemInfoManager.cpp | 3 +- library/DFProcessEnumerator.cpp | 13 +- library/include/dfhack/DFContext.h | 64 +++--- library/include/dfhack/DFContextManager.h | 40 ++-- library/include/dfhack/DFMemInfo.h | 24 +-- library/include/dfhack/DFProcess.h | 93 +++++---- library/include/dfhack/DFProcessEnumerator.h | 72 ++++++- library/include/dfhack/modules/Maps.h | 139 +++++++++---- .../dfhack => private}/DFMemInfoManager.h | 4 +- tools/playground/incrementalsearch.cpp | 194 ++++++++++++++---- 11 files changed, 446 insertions(+), 202 deletions(-) rename library/{include/dfhack => private}/DFMemInfoManager.h (95%) diff --git a/library/DFContextManager.cpp b/library/DFContextManager.cpp index 5b947894d..46814d90e 100644 --- a/library/DFContextManager.cpp +++ b/library/DFContextManager.cpp @@ -23,10 +23,10 @@ distribution. */ #include "Internal.h" +#include "DFMemInfoManager.h" #include "dfhack/DFProcess.h" #include "dfhack/DFProcessEnumerator.h" -#include "dfhack/DFMemInfoManager.h" #include "dfhack/DFError.h" #include "dfhack/DFContext.h" diff --git a/library/DFMemInfoManager.cpp b/library/DFMemInfoManager.cpp index 4b7f537e0..a2c0140ce 100644 --- a/library/DFMemInfoManager.cpp +++ b/library/DFMemInfoManager.cpp @@ -23,8 +23,9 @@ distribution. */ #include "Internal.h" +#include "DFMemInfoManager.h" + #include "dfhack/DFMemInfo.h" -#include "dfhack/DFMemInfoManager.h" #include "dfhack/DFError.h" using namespace DFHack; diff --git a/library/DFProcessEnumerator.cpp b/library/DFProcessEnumerator.cpp index 8c537c13b..839b59e44 100644 --- a/library/DFProcessEnumerator.cpp +++ b/library/DFProcessEnumerator.cpp @@ -23,10 +23,12 @@ distribution. */ #include "Internal.h" +#include "DFMemInfoManager.h" + #include "dfhack/DFProcessEnumerator.h" #include "dfhack/DFProcess.h" #include "dfhack/DFMemInfo.h" -#include "dfhack/DFMemInfoManager.h" + using namespace DFHack; @@ -223,7 +225,7 @@ uint64_t FileTime_to_POSIX(FILETIME ft) void ProcessEnumerator::Private::EnumPIDs (vector &PIDs) { FILETIME ftCreate, ftExit, ftKernel, ftUser; - + PIDs.clear(); // make sure the vector is clear // Get the list of process identifiers. @@ -254,7 +256,7 @@ void ProcessEnumerator::Private::EnumPIDs (vector &PIDs) } #endif -bool ProcessEnumerator::Refresh( BadProcesses* invalidated_processes) +bool ProcessEnumerator::Refresh( BadProcesses* invalidated_processes ) { // PIDs to process vector PIDs; @@ -330,11 +332,6 @@ bool ProcessEnumerator::Refresh( BadProcesses* invalidated_processes) return false; } -bool ProcessEnumerator::findProcessess() -{ - return Refresh(); -} - uint32_t ProcessEnumerator::size() { return d->Processes.size(); diff --git a/library/include/dfhack/DFContext.h b/library/include/dfhack/DFContext.h index 658d90ee1..04acc52d8 100644 --- a/library/include/dfhack/DFContext.h +++ b/library/include/dfhack/DFContext.h @@ -44,74 +44,78 @@ namespace DFHack class DFContextShared; class WindowIO; class Process; - + class DFHACK_EXPORT Context { public: Context(Process * p); ~Context(); - + bool isValid(); - + bool Attach(); bool Detach(); bool isAttached(); - + /// stop the tracked process bool Suspend(); + /// @return true if the process is stopped bool isSuspended(); - + /// stop the tracked process, asynchronous bool AsyncSuspend(); - + /// resume the tracked process bool Resume(); - + /// forces resume on Windows. This can be a bad thing with multiple tools running! bool ForceResume(); - + memory_info *getMemoryInfo(); Process* getProcess(); - + void ReadRaw (const uint32_t offset, const uint32_t size, uint8_t *target); void WriteRaw (const uint32_t offset, const uint32_t size, uint8_t *source); // FIXME: this is crap. - // get the creatures module + + /// get the creatures module Creatures * getCreatures(); - - // get the maps module + + /// get the maps module Maps * getMaps(); - - // get the gui module + + /// get the gui module Gui * getGui(); - // get the world module + /// get the world module World * getWorld(); - - // get the position module + + /// get the position module Position * getPosition(); - - // get the materials module + + /// get the materials module Materials * getMaterials(); - // get the items module + /// get the items module Items * getItems(); - - // get the translation module + + /// get the translation module Translation * getTranslation(); - - // get the vegetation module + + /// get the vegetation module Vegetation * getVegetation(); - - // get the buildings module + + /// get the buildings module Buildings * getBuildings(); - - // get the constructions module + + /// get the constructions module Constructions * getConstructions(); - - // get the Window management and I/O module + + /// get the Window management and I/O module WindowIO * getWindow(); + + // DEAD CODE, WAITING TO BE UPDATED TO DF2010 /* * Effects like mist, dragonfire or dust */ diff --git a/library/include/dfhack/DFContextManager.h b/library/include/dfhack/DFContextManager.h index c3d6b3edf..210fdb835 100644 --- a/library/include/dfhack/DFContextManager.h +++ b/library/include/dfhack/DFContextManager.h @@ -74,7 +74,7 @@ namespace DFHack /** * Get a context by index * @param index index of the context to be returned - * @return pointer to a Context + * @return pointer to a Context. 0 if the index is out of range. */ Context * operator[](uint32_t index); @@ -106,37 +106,37 @@ namespace DFHack public: BadContexts(); /** - * Destructor. - * All Processes and Contexts tracked by the BadContexts object will be destroyed also. - */ + * Destructor. + * All Processes and Contexts tracked by the BadContexts object will be destroyed also. + */ ~BadContexts(); /** - * Test if a Context is among the invalidated Contexts - * @param c pointer to a Context to be checked - * @return true if the Context is among the invalidated. false otherwise. - */ + * Test if a Context is among the invalidated Contexts + * @param c pointer to a Context to be checked + * @return true if the Context is among the invalidated. false otherwise. + */ bool Contains(Context* c); /** - * Test if a Process is among the invalidated Processes/Contexts - * @param p pointer to a Process to be checked - * @see DFHack::Process - * @return true if the Process is among the invalidated. false otherwise. - */ + * Test if a Process is among the invalidated Processes/Contexts + * @param p pointer to a Process to be checked + * @see DFHack::Process + * @return true if the Process is among the invalidated. false otherwise. + */ bool Contains(Process* p); /** - * Get the number of tracked invalid contexts. - * @return Number of tracked invalid contexts - */ + * Get the number of tracked invalid contexts. + * @return Number of tracked invalid contexts + */ uint32_t size(); /** - * Get an invalid Context by index - * @param index index of the invalid Context to be returned - * @return pointer to an invalid Context - */ + * Get an invalid Context by index + * @param index index of the invalid Context to be returned + * @return pointer to an invalid Context + */ Context * operator[](uint32_t index); }; } // namespace DFHack diff --git a/library/include/dfhack/DFMemInfo.h b/library/include/dfhack/DFMemInfo.h index 765483ecc..50a4aa55c 100644 --- a/library/include/dfhack/DFMemInfo.h +++ b/library/include/dfhack/DFMemInfo.h @@ -85,7 +85,7 @@ namespace DFHack uint32_t type_offset; // offset of type data for multiclass vector subs; }; - + class DFHACK_EXPORT memory_info { private: @@ -114,7 +114,7 @@ namespace DFHack int32_t getOffset (const char *); uint32_t getAddress (const char *); uint32_t getHexValue (const char *); - + std::string getString (const std::string&); std::string getProfession(const uint32_t) const; std::string getJob(const uint32_t) const; @@ -154,34 +154,34 @@ namespace DFHack void RebaseVTable(const int32_t offset); void setParentProcess(Process * _p); - + t_class * setClass (const char * classname, uint32_t vptr = 0, uint32_t typeoffset = 0); void setClassChild (t_class * parent, const char * classname, const char * type); - /* + /** * Get a classID from an address. The address has to point to the start of a virtual object (one with a virtual base class) * 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); - - /* + + /** * Get a ClassID when you know the classname. can fail if the class is not in the cache */ bool resolveClassnameToClassID (const std::string classname, int32_t & classID); - - /* + + /** * Get a vptr from a classname. Can fail if the type is not in the cache * limited to normal classes, variable-dependent types will resolve to the base class */ bool resolveClassnameToVPtr ( const std::string classname, uint32_t & vptr ); - - /* + + /** * Get a classname from a previous classID. Can fail if the type is not in the cache (you use bogus classID) */ bool resolveClassIDToClassname (const int32_t classID, std::string & classname); - - /* + + /** * Get the internal classID->classname mapping (for speed). DO NOT MANIPULATE THE VECTOR! */ const vector * getClassIDMapping(); diff --git a/library/include/dfhack/DFProcess.h b/library/include/dfhack/DFProcess.h index 2fc2620d0..d2f888492 100644 --- a/library/include/dfhack/DFProcess.h +++ b/library/include/dfhack/DFProcess.h @@ -72,92 +72,115 @@ namespace DFHack if (address >= start && address <= end) return true; return false; } - inline void print() - { - std::cout << std::hex << start << " - " << end << "|" << (read ? "r" : "-") << (write ? "w" : "-") << (execute ? "x" : "-") << "|" << name << std::endl; - } + uint8_t * buffer; }; class DFHACK_EXPORT Process { public: - // this is the single most important destructor ever. ~px + /// this is the single most important destructor ever. ~px virtual ~Process(){}; - // Set up stuff so we can read memory, suspends synchronously + /// Set up stuff so we can read memory, suspends synchronously virtual bool attach() = 0; - // detach from DF, resume its execution if it's suspended + /// detach from DF, resume its execution if it's suspended virtual bool detach() = 0; - - // synchronous suspend - // waits for DF to be actually suspended, - // this might take a while depending on implementation + /** + * synchronous suspend + * waits for DF to be actually suspended, + * this might take a while depending on implementation + */ virtual bool suspend() = 0; - // asynchronous suspend to use together with polling and timers + /// asynchronous suspend to use together with polling and timers virtual bool asyncSuspend() = 0; - // resume DF execution + /// resume DF execution virtual bool resume() = 0; - // force-resume DF execution + /// force-resume DF execution virtual bool forceresume() = 0; - + + /// read a 8-byte integer virtual uint64_t readQuad(const uint32_t address) = 0; + /// read a 8-byte integer virtual void readQuad(const uint32_t address, uint64_t & value) = 0; + /// write a 8-byte integer virtual void writeQuad(const uint32_t address, const uint64_t value) = 0; - + + /// read a 4-byte integer virtual uint32_t readDWord(const uint32_t address) = 0; + /// read a 4-byte integer virtual void readDWord(const uint32_t address, uint32_t & value) = 0; + /// write a 4-byte integer virtual void writeDWord(const uint32_t address, const uint32_t value) = 0; - + + /// read a float virtual float readFloat(const uint32_t address) = 0; + /// write a float virtual void readFloat(const uint32_t address, float & value) = 0; - + + /// read a 2-byte integer virtual uint16_t readWord(const uint32_t address) = 0; + /// read a 2-byte integer virtual void readWord(const uint32_t address, uint16_t & value) = 0; + /// write a 2-byte integer virtual void writeWord(const uint32_t address, const uint16_t value) = 0; - + + /// read a byte virtual uint8_t readByte(const uint32_t address) = 0; + /// read a byte virtual void readByte(const uint32_t address, uint8_t & value) = 0; + /// write a byte virtual void writeByte(const uint32_t address, const uint8_t value) = 0; - + + /// read an arbitrary amount of bytes virtual void read( uint32_t address, uint32_t length, uint8_t* buffer) = 0; + /// write an arbitrary amount of bytes virtual void write(uint32_t address, uint32_t length, uint8_t* buffer) = 0; - - // read a string + + /// read an STL string virtual const string readSTLString (uint32_t offset) = 0; + /// read an STL string virtual size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity) = 0; + /// write an STL string virtual void writeSTLString(const uint32_t address, const std::string writeString) = 0; - // get class name of an object with rtti/type info + /// get class name of an object with rtti/type info virtual string readClassName(uint32_t vptr) = 0; - + + /// read a null-terminated C string virtual const std::string readCString (uint32_t offset) = 0; - + + /// @return true if the process is suspended virtual bool isSuspended() = 0; + /// @return true if the process is attached virtual bool isAttached() = 0; + /// @return true if the process is identified -- has a Memory.xml entry virtual bool isIdentified() = 0; - - // find the thread IDs of the process + + /// find the thread IDs of the process virtual bool getThreadIDs(vector & threads ) = 0; - // get virtual memory ranges of the process (what is mapped where) + /// get virtual memory ranges of the process (what is mapped where) virtual void getMemRanges( vector & ranges ) = 0; - - // get the flattened Memory.xml entry of this process + + /// get the flattened Memory.xml entry of this process virtual memory_info *getDescriptor() = 0; - // get the DF Process ID + /// get the DF Process ID virtual int getPID() = 0; - // get module index by name and version. bool 1 = error + /// get module index by name and version. bool 1 = error virtual bool getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT) = 0; - // get the SHM start if available + /// get the SHM start if available virtual char * getSHMStart (void) = 0; - // set a SHM command and wait for a response, return 0 on error or throw exception + /// set a SHM command and wait for a response, return 0 on error or throw exception virtual bool SetAndWait (uint32_t state) = 0; }; + //////////////////////////////////////////////////////////////////////////// + // Compiler appeasement area. Not worth a look really... // + //////////////////////////////////////////////////////////////////////////// + class DFHACK_EXPORT NormalProcess : virtual public Process { friend class ProcessEnumerator; class Private; private: Private * const d; - public: NormalProcess(uint32_t pid, vector & known_versions); ~NormalProcess(); diff --git a/library/include/dfhack/DFProcessEnumerator.h b/library/include/dfhack/DFProcessEnumerator.h index 4e618ae27..0422367d5 100644 --- a/library/include/dfhack/DFProcessEnumerator.h +++ b/library/include/dfhack/DFProcessEnumerator.h @@ -33,35 +33,99 @@ namespace DFHack class memory_info; class Process; class BadProcesses; - /* - * Process manager + /** + * Process enumerator + * Used to enumerate, create and destroy Processes. + * @see DFHack::Process */ class DFHACK_EXPORT ProcessEnumerator { class Private; Private * const d; public: + /** + * Constructs the ProcessEnumerator. + * @param path_to_xml the path to the file that defines memory offsets. (Memory.xml) + */ ProcessEnumerator( string path_to_xml ); + + /** + * Destroys the ProcessEnumerator. + */ ~ProcessEnumerator(); + + /** + * Refresh the internal list of valid Process objects. + * @param invalidated_processes pointer to a BadProcesses object. Not required. All processes are automatically destroyed if the object is not provided. + * @see DFHack::BadProcesses + * @return true if there's at least one valit Process + */ bool Refresh(BadProcesses * invalidated_processes = 0); - bool findProcessess(); + + /** + * @return Number of tracked processes + */ uint32_t size(); + + /** + * Get a Process by index + * @param index index of the Process to be returned + * @return pointer to a Process. 0 if the index is out of range. + */ Process * operator[](uint32_t index); + + /** + * Destroy all tracked Process objects + * Normally called during object destruction. Calling this from outside ProcessManager is nasty. + */ void purge(void); }; + + /** + * Class used for holding a set of invalidated Process objects temporarily and destroy them safely. + * @see DFHack::Process + */ class DFHACK_EXPORT BadProcesses { class Private; Private * const d; void push_back(Process * p); friend class ProcessEnumerator; + void clear(); public: BadProcesses(); + /** + * Destructor. + * All Processes tracked by the BadProcesses object will be destroyed also. + */ ~BadProcesses(); + + /** + * Test if a Process is among the invalidated Processes + * @param p pointer to a Process to be checked + * @return true if the Process is among the invalidated. false otherwise. + */ bool Contains(Process* p); + + /** + * Remove a Process from the tracked invalidated Processes. Used by BadContexts. + * @param p pointer to a Process to be excised + * @see DFHack::BadContexts + * @return true if the Process was among the invalidated. false otherwise. + */ bool excise (Process* p); + + /** + * Get the number of tracked invalid contexts. + * @return Number of tracked invalid contexts + */ uint32_t size(); - void clear(); + + /** + * Get an invalid Process by index + * @param index index of the invalid Process to be returned + * @return pointer to an invalid Process + */ Process * operator[](uint32_t index); }; } diff --git a/library/include/dfhack/modules/Maps.h b/library/include/dfhack/modules/Maps.h index cfdb31d43..6c4dd63a3 100644 --- a/library/include/dfhack/modules/Maps.h +++ b/library/include/dfhack/modules/Maps.h @@ -11,7 +11,7 @@ namespace DFHack /*************************************************************************** T Y P E S ***************************************************************************/ - + enum e_feature { feature_Other, @@ -19,6 +19,7 @@ namespace DFHack feature_Underworld, feature_Hell_Temple }; + static const char * sa_feature[]= { (char*)"Other", @@ -26,6 +27,8 @@ namespace DFHack (char*)"Underworld", (char*)"Hell Temple" }; + + /// used as a key for the local feature map. combines X an Y coords. union planecoord { uint32_t xy; @@ -40,40 +43,60 @@ namespace DFHack return false; } }; + struct t_feature { e_feature type; + /// main material type - decides between stuff like bodily fluids, inorganics, vomit, amber, etc. int16_t main_material; + /// generally some index to a vector of material types. int32_t sub_material; - bool discovered; // placeholder. + /// placeholder + bool discovered; + /// this is NOT part of the DF feature, but an address of the feature as seen by DFhack. uint32_t origin; }; - + + /// mineral vein object struct t_vein { uint32_t vtable; + /// index into the inorganic material vector int32_t type; - int16_t assignment[16]; + /// bit mask describing how the vein maps to the map block + /// assignment[y] & (1 << x) describes the tile (x, y) of the block + int16_t assignment[16]; uint32_t flags; - uint32_t address_of; // this is NOT part of the DF vein, but an address of the vein as seen by DFhack. + /// this is NOT part of the DF vein, but an address of the vein as seen by DFhack. + uint32_t address_of; }; - // stores what tiles should appear when the ice melts + + /// stores what tiles should appear when the ice melts struct t_frozenliquidvein { uint32_t vtable; + /// a 16x16 array of the original tile types int16_t tiles[16][16]; - uint32_t address_of; // this is NOT part of the DF vein, but an address of the vein as seen by DFhack. + /// this is NOT part of the DF vein, but an address of the vein as seen by DFhack. + uint32_t address_of; }; - + + /// a 'spattervein' defines what coverings the individual map tiles have (snow, blood, etc) + /// @see PrintSplatterType in DFMiscUtils.h -- incomplete, but illustrative struct t_spattervein { uint32_t vtable; + /// generic material. uint16_t mat1; uint16_t unk1; + /// material vector index uint32_t mat2; + /// something even more specific? uint16_t mat3; + /// 16x16 array of covering 'intensity' uint8_t intensity[16][16]; - uint32_t address_of; // this is NOT part of the DF vein, but an address of the vein as seen by DFhack. + /// this is NOT part of the DF vein, but an address of the vein as seen by DFhack. + uint32_t address_of; }; enum BiomeOffset @@ -98,16 +121,25 @@ namespace DFHack traffic_restricted }; + /// type of a designation for a tile enum e_designation { + /// no designation designation_no, - designation_default, // dig walls, remove stairs and ramps, gather plants, fell trees - designation_ud_stair, // dig up/down stairs - designation_channel, // dig a channel - designation_ramp, // dig ramp out of a wall - designation_d_stair, // dig a stair down - designation_u_stair, // dig a stair up - designation_7 // whatever + /// dig walls, remove stairs and ramps, gather plants, fell trees. depends on tile type + designation_default, + /// dig up/down stairs + designation_ud_stair, + /// dig a channel + designation_channel, + /// dig ramp out of a wall + designation_ramp, + /// dig a stair down + designation_d_stair, + /// dig a stair up + designation_u_stair, + /// whatever. for completenes I guess + designation_7 }; enum e_liquidtype @@ -120,41 +152,43 @@ namespace DFHack { unsigned int flow_size : 3; // how much liquid is here? unsigned int pile : 1; // stockpile? - /* - * All the different dig designations... needs more info, probably an enum - */ + /// All the different dig designations e_designation dig : 3; unsigned int smooth : 2; unsigned int hidden : 1; - /* + /** * This one is rather involved, but necessary to retrieve the base layer matgloss index - * see http://www.bay12games.com/forum/index.php?topic=608.msg253284#msg253284 for details + * @see http://www.bay12games.com/forum/index.php?topic=608.msg253284#msg253284 */ unsigned int geolayer_index :4; unsigned int light : 1; unsigned int subterranean : 1; // never seen the light of day? unsigned int skyview : 1; // sky is visible now, it rains in here when it rains - /* + /** * Probably similar to the geolayer_index. Only with a different set of offsets and different data. * we don't use this yet */ unsigned int biome : 4; - /* + /** * 0 = water * 1 = magma */ e_liquidtype liquid_type : 1; unsigned int water_table : 1; // srsly. wtf? unsigned int rained : 1; // does this mean actual rain (as in the blue blocks) or a wet tile? - e_traffic traffic : 2; // needs enum - unsigned int flow_forbid : 1; // what? + e_traffic traffic : 2; + /// the tile is not evaluated when calculating flows? + unsigned int flow_forbid : 1; + /// no liquid spreading unsigned int liquid_static : 1; - unsigned int feature_local : 1; // this tile is a part of a feature - unsigned int feature_global : 1; // this tile is a part of a feature - unsigned int liquid_character : 2; // those ripples on streams? - + /// this tile is a part of a local feature. can be combined with 'featstone' tiles + unsigned int feature_local : 1; + /// this tile is a part of a global feature. can be combined with 'featstone' tiles + unsigned int feature_global : 1; + /// those ripples on streams? + unsigned int liquid_character : 2; }; union t_designation @@ -166,12 +200,16 @@ namespace DFHack // occupancy flags (rat,dwarf,horse,built wall,not build wall,etc) struct naked_occupancy { - unsigned int building : 3;// building type... should be an enum? + // building type... should be an enum? // 7 = door + unsigned int building : 3; + /// the tile contains a standing? creature unsigned int unit : 1; + /// the tile contains a prone creature unsigned int unit_grounded : 1; + /// the tile contains an item unsigned int item : 1; - // splatter. everyone loves splatter. + /// splatter. everyone loves splatter. this doesn't seem to be used anymore unsigned int mud : 1; unsigned int vomit :1; unsigned int broken_arrows_color :4; @@ -199,12 +237,14 @@ namespace DFHack struct naked_occupancy_grouped { - unsigned int building : 3;// building type... should be an enum? - // 7 = door + unsigned int building : 3; + /// the tile contains a standing? creature unsigned int unit : 1; + /// the tile contains a prone creature unsigned int unit_grounded : 1; + /// the tile contains an item unsigned int item : 1; - // splatter. everyone loves splatter. + /// splatter. everyone loves splatter. this doesn't seem to be used anymore unsigned int splatter : 26; }; @@ -218,12 +258,15 @@ namespace DFHack // map block flags struct naked_blockflags { - unsigned int designated : 1;// designated for jobs (digging and stuff like that) - unsigned int unk_1 : 1; // possibly related to the designated flag - // two flags required for liquid flow. no idea why + /// designated for jobs (digging and stuff like that) + unsigned int designated : 1; + /// possibly related to the designated flag + unsigned int unk_1 : 1; + /// two flags required for liquid flow. unsigned int liquid_1 : 1; unsigned int liquid_2 : 1; - unsigned int unk_2: 28; // rest of the flags is completely unknown + /// rest of the flags is completely unknown + unsigned int unk_2: 28; // there's a possibility that this flags field is shorter than 32 bits }; @@ -241,13 +284,20 @@ namespace DFHack typedef struct { + /// type of the tiles tiletypes40d tiletypes; + /// flags determining the state of the tiles designations40d designation; + /// flags determining what's on the tiles occupancies40d occupancy; + /// values used for geology/biome assignment biome_indices40d biome_indices; - uint32_t origin; // the address where it came from + /// the address where the block came from + uint32_t origin; t_blockflags blockflags; + /// index into the global feature vector int16_t global_feature; + /// index into the local feature vector... complicated int16_t local_feature; } mapblock40d; @@ -321,6 +371,7 @@ namespace DFHack * Return false/0 on failure, buffer allocated by client app, 256 items long */ bool isValidBlock(uint32_t blockx, uint32_t blocky, uint32_t blockz); + /** * Get the address of a block or 0 if block is not valid */ @@ -340,7 +391,7 @@ namespace DFHack /// read/write temperatures bool ReadTemperatures(uint32_t blockx, uint32_t blocky, uint32_t blockz, t_temperatures *temp1, t_temperatures *temp2); bool WriteTemperatures (uint32_t blockx, uint32_t blocky, uint32_t blockz, t_temperatures *temp1, t_temperatures *temp2); - + /// read/write block occupancies bool ReadOccupancy(uint32_t blockx, uint32_t blocky, uint32_t blockz, occupancies40d *buffer); bool WriteOccupancy(uint32_t blockx, uint32_t blocky, uint32_t blockz, occupancies40d *buffer); @@ -350,10 +401,8 @@ namespace DFHack bool WriteDirtyBit(uint32_t blockx, uint32_t blocky, uint32_t blockz, bool dirtybit); /// read/write the block flags - bool ReadBlockFlags(uint32_t blockx, uint32_t blocky, uint32_t blockz, - t_blockflags &blockflags); - bool WriteBlockFlags(uint32_t blockx, uint32_t blocky, uint32_t blockz, - t_blockflags blockflags); + bool ReadBlockFlags(uint32_t blockx, uint32_t blocky, uint32_t blockz, t_blockflags &blockflags); + bool WriteBlockFlags(uint32_t blockx, uint32_t blocky, uint32_t blockz, t_blockflags blockflags); /// read/write features bool ReadFeatures(uint32_t blockx, uint32_t blocky, uint32_t blockz, int16_t & local, int16_t & global); bool WriteLocalFeature(uint32_t blockx, uint32_t blocky, uint32_t blockz, int16_t local = -1); @@ -368,7 +417,7 @@ namespace DFHack std::vector* veins, std::vector* ices = 0, std::vector* splatter = 0); - + private: struct Private; Private *d; diff --git a/library/include/dfhack/DFMemInfoManager.h b/library/private/DFMemInfoManager.h similarity index 95% rename from library/include/dfhack/DFMemInfoManager.h rename to library/private/DFMemInfoManager.h index 99c34afe1..2e11ca608 100644 --- a/library/include/dfhack/DFMemInfoManager.h +++ b/library/private/DFMemInfoManager.h @@ -25,10 +25,12 @@ distribution. #ifndef MEMINFO_MANAGER_H_INCLUDED #define MEMINFO_MANAGER_H_INCLUDED -#include "DFPragma.h" +#include "dfhack/DFPragma.h" +class TiXmlElement; namespace DFHack { + class memory_info; class MemInfoManager { friend class ProcessEnumerator; diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index cc047466c..c90948c72 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -19,16 +19,125 @@ using namespace std; #endif #include +class SegmentedFinder; +class SegmentFinder +{ + public: + SegmentFinder(DFHack::t_memrange & mr, DFHack::Context * DF) + { + _DF = DF; + mr_ = mr; + mr_.buffer = (uint8_t *)malloc (mr_.end - mr_.start); + DF->ReadRaw(mr_.start,(mr_.end - mr_.start),mr_.buffer); + } + ~SegmentFinder() + { + delete mr_.buffer; + } + template + bool Find (T needle, const uint8_t increment ,vector &found, vector &newfound, P oper) + { + if(found.empty()) + { + //loop + for(uint64_t offset = 0; offset < (mr_.end - mr_.start) - sizeof(T); offset += increment) + { + if( (*(T *)(mr_.buffer + offset)) == needle) + newfound.push_back(mr_.start + offset); + } + } + else + { + for( uint64_t i = 0; i < found.size(); i++) + { + if(mr_.isInRange(found[i])) + { + uint64_t corrected = found[i] - mr_.start; + if( oper((T *)(mr_.buffer + corrected), needle) ) + newfound.push_back(found[i]); + } + } + } + return true; + } + private: + friend class SegmentedFinder; + DFHack::Context * _DF; + DFHack::t_memrange mr_; +}; + +class SegmentedFinder +{ + public: + SegmentedFinder(vector & ranges, DFHack::Context * DF) + { + _DF = DF; + for(int i = 0; i < ranges.size(); i++) + { + segments.push_back(new SegmentFinder(ranges[i], DF)); + } + } + ~SegmentedFinder() + { + for(int i = 0; i < segments.size(); i++) + { + delete segments[i]; + } + } + SegmentFinder * getSegmentForAddress (uint64_t addr) + { + for(int i = 0; i < segments.size(); i++) + { + if(segments[i]->mr_.isInRange(addr)) + { + return segments[i]; + } + } + } + template + bool Find (const T dword, const uint8_t increment, vector &found, vector &newfound, P oper) + { + newfound.clear(); + for(int i = 0; i < segments.size(); i++) + { + segments[i]->Find(dword, increment, found, newfound, oper); + } + found.clear(); + found = newfound; + return !(found.empty()); + } + private: + DFHack::Context * _DF; + vector segments; +}; + +template +bool equalityP (T *x, T y) +{ + return (*x) == y; +} + +typedef struct +{ + uint32_t start; + uint32_t finish; + uint32_t alloc_finish; +} vecTriplet; + +template +bool vectorLength (T *x, T y) +{ + return (*x) == y; +} //TODO: lots of optimization void searchLoop(DFHack::ContextManager & DFMgr, vector & ranges, int size, int alignment) { - int32_t test1; - int32_t test2; - vector found; - vector newfound; - found.reserve(100000); - newfound.reserve(100000); + uint32_t test1; + vector found; + vector newfound; + found.reserve(100); + newfound.reserve(100); //bool initial = 1; cout << "search ready - insert integers, 'p' for results" << endl; string select; @@ -50,53 +159,45 @@ void searchLoop(DFHack::ContextManager & DFMgr, vector & ran DFMgr.Refresh(); DFHack::Context * DF = DFMgr.getSingleContext(); DF->Attach(); - - newfound.clear(); - bool initial = found.empty(); - if(initial) + SegmentedFinder sf(ranges,DF); + switch(size) { - // for each range - for (int i = 0; i < ranges.size();i++) - { - // can't read? range is invalid to us - if(!ranges[i].read) - continue; - //loop - for(uint64_t offset = ranges[i].start;offset <= ranges[i].end - size; offset+=alignment) - { - DF->ReadRaw(offset, size, (uint8_t *) &test2); - if(test1 == test2 ) - found.push_back(offset); - } - } - cout << "found " << found.size() << " addresses" << endl; + case 1: + sf.Find(test1,alignment,found,newfound, equalityP); + break; + case 2: + sf.Find(test1,alignment,found,newfound, equalityP); + break; + case 4: + sf.Find(test1,alignment,found,newfound, equalityP); + break; } - else + if( found.size() == 1) { - for(int j = 0; j < found.size();j++) - { - DF->ReadRaw(found[j], size, (uint8_t *) &test2); - if(test1 == test2) - { - newfound.push_back(found[j]); - } - } - cout << "matched " << newfound.size() << " addresses out of " << found.size() << endl; - found = newfound; + cout << "Found an address!" << endl; + cout << hex << "0x" << found[0] << endl; } + else + cout << "Found " << dec << found.size() << " addresses." << endl; DF->Detach(); } else break; } } -typedef struct +/* +class VecVerifyPredicate { - uint32_t start; - uint32_t finish; - uint32_t alloc_finish; -} vecTriplet; - + public: + VecVerifyPredicate(){} + bool operator()(vecTriplet * vt, uint64_t length) + { + if(vt.start <= vt.finish && vt.finish <= vt.alloc_finish) + return true; + return false; + } +}; +*/ void searchLoopVector(DFHack::ContextManager & DFMgr, vector & ranges, uint32_t element_size) { vecTriplet load; @@ -190,7 +291,10 @@ void mkcopy(DFHack::ContextManager & DFMgr, vector & ranges, DF->Detach(); DFMgr.purge(); } - +inline void printRange(DFHack::t_memrange * tpr) +{ + std::cout << std::hex << tpr->start << " - " << tpr->end << "|" << (tpr->read ? "r" : "-") << (tpr->write ? "w" : "-") << (tpr->execute ? "x" : "-") << "|" << tpr->name << std::endl; +} int main (void) { string select; @@ -216,7 +320,7 @@ int main (void) for(int i = 0; i< ranges.size();i++) { cout << dec << "(" << i << ") "; - ranges[i].print(); + printRange(&(ranges[i])); } try_again_ranges: @@ -258,7 +362,7 @@ int main (void) selected_ranges.insert(selected_ranges.begin(),ranges.begin() + start, ranges.begin() + end); for(int i = 0; i< selected_ranges.size();i++) { - selected_ranges[i].print(); + printRange(&(selected_ranges[i])); } try_again_type: cout << "Select search type: 1=number(default), 2=vector, 3=string" << endl; From a9421db8e082bb43511f5d00b6678a9423d69049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 30 May 2010 19:02:40 +0200 Subject: [PATCH 010/122] Search tool can find strings inside DF object vectors on Linux --- tools/playground/incrementalsearch.cpp | 208 ++++++++++++++++--------- 1 file changed, 131 insertions(+), 77 deletions(-) diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index c90948c72..a7e3e4c8d 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -23,26 +23,27 @@ class SegmentedFinder; class SegmentFinder { public: - SegmentFinder(DFHack::t_memrange & mr, DFHack::Context * DF) + SegmentFinder(DFHack::t_memrange & mr, DFHack::Context * DF, SegmentedFinder * SF) { _DF = DF; mr_ = mr; mr_.buffer = (uint8_t *)malloc (mr_.end - mr_.start); DF->ReadRaw(mr_.start,(mr_.end - mr_.start),mr_.buffer); + _SF = SF; } ~SegmentFinder() { delete mr_.buffer; } - template - bool Find (T needle, const uint8_t increment ,vector &found, vector &newfound, P oper) + template + bool Find (needleType needle, const uint8_t increment ,vector &found, vector &newfound, comparator oper) { if(found.empty()) { //loop - for(uint64_t offset = 0; offset < (mr_.end - mr_.start) - sizeof(T); offset += increment) + for(uint64_t offset = 0; offset < (mr_.end - mr_.start) - sizeof(hayType); offset += increment) { - if( (*(T *)(mr_.buffer + offset)) == needle) + if( oper(_SF,(hayType *)(mr_.buffer + offset), needle) ) newfound.push_back(mr_.start + offset); } } @@ -53,7 +54,7 @@ class SegmentFinder if(mr_.isInRange(found[i])) { uint64_t corrected = found[i] - mr_.start; - if( oper((T *)(mr_.buffer + corrected), needle) ) + if( oper(_SF,(hayType *)(mr_.buffer + corrected), needle) ) newfound.push_back(found[i]); } } @@ -62,6 +63,7 @@ class SegmentFinder } private: friend class SegmentedFinder; + SegmentedFinder * _SF; DFHack::Context * _DF; DFHack::t_memrange mr_; }; @@ -74,7 +76,7 @@ class SegmentedFinder _DF = DF; for(int i = 0; i < ranges.size(); i++) { - segments.push_back(new SegmentFinder(ranges[i], DF)); + segments.push_back(new SegmentFinder(ranges[i], DF, this)); } } ~SegmentedFinder() @@ -93,41 +95,98 @@ class SegmentedFinder return segments[i]; } } + return 0; } - template - bool Find (const T dword, const uint8_t increment, vector &found, vector &newfound, P oper) + template + bool Find (const needleType needle, const uint8_t increment, vector &found, vector &newfound, comparator oper) { newfound.clear(); for(int i = 0; i < segments.size(); i++) { - segments[i]->Find(dword, increment, found, newfound, oper); + segments[i]->Find(needle, increment, found, newfound, oper); } found.clear(); found = newfound; return !(found.empty()); } + uint8_t * translate(uint64_t address) + { + for(int i = 0; i < segments.size(); i++) + { + if(segments[i]->mr_.isInRange(address)) + { + return segments[i]->mr_.buffer + address - segments[i]->mr_.start; + } + } + return 0; + } private: DFHack::Context * _DF; vector segments; }; template -bool equalityP (T *x, T y) +bool equalityP (SegmentedFinder* s, T *x, T y) { return (*x) == y; } -typedef struct +struct vecTriplet { uint32_t start; uint32_t finish; uint32_t alloc_finish; -} vecTriplet; +}; -template -bool vectorLength (T *x, T y) +template +bool vectorLength (SegmentedFinder* s, vecTriplet *x, Needle &y) { - return (*x) == y; + if(x->start <= x->finish && x->finish <= x->alloc_finish) + if((x->finish - x->start) == y) + return true; + return false; +} + +bool vectorString (SegmentedFinder* s, vecTriplet *x, const char *y) +{ + if(x->start <= x->finish && x->finish <= x->alloc_finish) + { + // deref ptr start, get ptr to firt object + uint8_t *deref1 = s->translate(x->start); + if(!deref1) + return false; + uint32_t object_ptr = *(uint32_t *)deref1; + if(!object_ptr) + return false; + // deref ptr to first object, get ptr to string + deref1 = s->translate(object_ptr); + if(!deref1) + return false; + uint32_t string_ptr = *(uint32_t *)deref1; + if(!string_ptr) + return false; + // get string location in our local cache + deref1 = s->translate(string_ptr); + if(!deref1) + return false; + char * str = (char *) deref1; + if(!str) + return false; + if(strcmp(y, str) == 0) + return true; + } + return false; +} + +bool vectorAll (SegmentedFinder* s, vecTriplet *x, int ) +{ + if(x->start <= x->finish && x->finish <= x->alloc_finish) + { + if(s->getSegmentForAddress(x->start) == s->getSegmentForAddress(x->finish) + && s->getSegmentForAddress(x->finish) == s->getSegmentForAddress(x->alloc_finish)) + return true; + } + return false; } //TODO: lots of optimization @@ -163,13 +222,13 @@ void searchLoop(DFHack::ContextManager & DFMgr, vector & ran switch(size) { case 1: - sf.Find(test1,alignment,found,newfound, equalityP); + sf.Find(test1,alignment,found,newfound, equalityP); break; case 2: - sf.Find(test1,alignment,found,newfound, equalityP); + sf.Find(test1,alignment,found,newfound, equalityP); break; case 4: - sf.Find(test1,alignment,found,newfound, equalityP); + sf.Find(test1,alignment,found,newfound, equalityP); break; } if( found.size() == 1) @@ -185,25 +244,12 @@ void searchLoop(DFHack::ContextManager & DFMgr, vector & ran } } -/* -class VecVerifyPredicate -{ - public: - VecVerifyPredicate(){} - bool operator()(vecTriplet * vt, uint64_t length) - { - if(vt.start <= vt.finish && vt.finish <= vt.alloc_finish) - return true; - return false; - } -}; -*/ void searchLoopVector(DFHack::ContextManager & DFMgr, vector & ranges, uint32_t element_size) { vecTriplet load; uint32_t length; - vector found; - vector newfound; + vector found; + vector newfound; found.reserve(100000); newfound.reserve(100000); //bool initial = 1; @@ -230,24 +276,16 @@ void searchLoopVector(DFHack::ContextManager & DFMgr, vector (0,4,found,newfound, vectorAll); + sf.Find(length*element_size,4,found,newfound, vectorLength); + if( found.size() == 1) { - // can't read? range is invalid to us - if(!ranges[i].read) - continue; - //loop - for(uint64_t offset = ranges[i].start;offset <= ranges[i].end - sizeof(vecTriplet); offset+=4) - { - DF->ReadRaw(offset, sizeof(vecTriplet), (uint8_t *) &load); - if(load.start <= load.finish && load.finish <= load.alloc_finish) - if((load.finish - load.start) / element_size == length) - found.push_back(offset); - } + cout << "Found an address!" << endl; + cout << hex << "0x" << found[0] << endl; } - cout << "found " << found.size() << " addresses" << endl; - + else + cout << "Found " << dec << found.size() << " addresses." << endl; // detach again DF->Detach(); } @@ -257,40 +295,57 @@ void searchLoopVector(DFHack::ContextManager & DFMgr, vector & ranges, uint32_t element_size) + +void searchLoopStrObjVector(DFHack::ContextManager & DFMgr, vector & ranges) { - DFMgr.Refresh(); - DFHack::Context * DF = DFMgr.getSingleContext(); - DF->Attach(); - for (int i = 0; i < ranges.size();i++) + vector found; + vector newfound; + found.reserve(100000); + newfound.reserve(100000); + cout << "search ready - insert string" << endl; + string select; + while (1) { - // can't read? range is invalid to us - if(!ranges[i].read) - continue; - char * buffah = (char *) malloc(ranges[i].end - ranges[i].start); - if(buffah) + cout << ">>"; + std::getline(cin, select); + if(select == "p") { - DF->ReadRaw(ranges[i].start,ranges[i].end - ranges[i].start, (uint8_t *) buffah); - cerr << "buffer for range " << i << " allocated and filled" << endl; - free(buffah); - cerr << "and freed" << endl; + cout << "Found vectors:" << endl; + for(int i = 0; i < found.size();i++) + { + cout << hex << "0x" << found[i] << endl; + } + } + else if(!select.empty()) + { + // refresh the list of processes, get first suitable, attach + DFMgr.Refresh(); + DFHack::Context * DF = DFMgr.getSingleContext(); + DF->Attach(); + + // clear the list of found addresses + found.clear(); + SegmentedFinder sf(ranges,DF); + sf.Find(0,4,found,newfound, vectorAll); + sf.Find(select.c_str(),4,found,newfound, vectorString); + if( found.size() == 1) + { + cout << "Found an address!" << endl; + cout << hex << "0x" << found[0] << endl; + } + else + cout << "Found " << dec << found.size() << " addresses." << endl; + // detach again + DF->Detach(); } else - cerr << "buffer for range " << i << " failed to allocate" << endl; - //loop - /* - for(uint64_t offset = ranges[i].start;offset <= ranges[i].end - sizeof(vecTriplet); offset+=4) { - DF->ReadRaw(offset, sizeof(vecTriplet), (uint8_t *) &load); - if(load.start <= load.finish && load.finish <= load.alloc_finish) - if((load.finish - load.start) / element_size == length) - found.push_back(offset); + break; } - */ } - DF->Detach(); - DFMgr.purge(); } + + inline void printRange(DFHack::t_memrange * tpr) { std::cout << std::hex << tpr->start << " - " << tpr->end << "|" << (tpr->read ? "r" : "-") << (tpr->write ? "w" : "-") << (tpr->execute ? "x" : "-") << "|" << tpr->name << std::endl; @@ -462,8 +517,7 @@ int main (void) } else if(mode == 3)// string { - mkcopy(DFMgr, selected_ranges,0); - //searchLoopString(DF, selected_ranges); + searchLoopStrObjVector(DFMgr, selected_ranges); } #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; From 08fd20c65fbeb42c716c33bc149095abba54dfbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 30 May 2010 19:44:18 +0200 Subject: [PATCH 011/122] Linux STL string search for search tool --- tools/playground/incrementalsearch.cpp | 72 ++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index a7e3e4c8d..29deb24d5 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -189,6 +189,20 @@ bool vectorAll (SegmentedFinder* s, vecTriplet *x, int ) return false; } +bool findString (SegmentedFinder* s, uint32_t *addr, const char * compare ) +{ + // read string pointer + uint32_t addrx = *addr; + // translat to local scheme + char *deref1 = (char *) s->translate(addrx); + // verify + if(!deref1) + return false; + if(strcmp(deref1, compare) == 0) + return true; + return false; +} + //TODO: lots of optimization void searchLoop(DFHack::ContextManager & DFMgr, vector & ranges, int size, int alignment) { @@ -345,6 +359,54 @@ void searchLoopStrObjVector(DFHack::ContextManager & DFMgr, vector & ranges) +{ + vector found; + vector newfound; + found.reserve(1000); + newfound.reserve(1000); + cout << "search ready - insert string" << endl; + string select; + while (1) + { + cout << ">>"; + std::getline(cin, select); + if(select == "p") + { + cout << "Found strings:" << endl; + for(int i = 0; i < found.size();i++) + { + cout << hex << "0x" << found[i] << endl; + } + } + else if(!select.empty()) + { + // refresh the list of processes, get first suitable, attach + DFMgr.Refresh(); + DFHack::Context * DF = DFMgr.getSingleContext(); + DF->Attach(); + + // clear the list of found addresses + found.clear(); + SegmentedFinder sf(ranges,DF); + sf.Find< const char * ,uint32_t>(select.c_str(),1,found,newfound, findString); + if( found.size() == 1) + { + cout << "Found a string!" << endl; + cout << hex << "0x" << found[0] << endl; + } + else + cout << "Found " << dec << found.size() << " strings." << endl; + // detach again + DF->Detach(); + } + else + { + break; + } + } +} + inline void printRange(DFHack::t_memrange * tpr) { @@ -420,7 +482,7 @@ int main (void) printRange(&(selected_ranges[i])); } try_again_type: - cout << "Select search type: 1=number(default), 2=vector, 3=string" << endl; + cout << "Select search type: 1=number(default), 2=vector, 3=vector>object>string, 4=string" << endl; cout << ">>"; std::getline(cin, select); int mode; @@ -430,7 +492,7 @@ int main (void) } else if( sscanf(select.c_str(), "%d", &mode) == 1 ) { - if(mode != 1 && mode != 2 && mode != 3) + if(mode != 1 && mode != 2 && mode != 3 && mode != 4) { goto try_again_type; } @@ -515,10 +577,14 @@ int main (void) DF->Detach(); searchLoopVector(DFMgr, selected_ranges,size); } - else if(mode == 3)// string + else if(mode == 3)// vector>object>string { searchLoopStrObjVector(DFMgr, selected_ranges); } + else if(mode == 4)// string + { + searchLoopStr(DFMgr, selected_ranges); + } #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); From ca0f7a27d14df0782cefd2693040295481f24f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 31 May 2010 02:37:28 +0200 Subject: [PATCH 012/122] Automated lang tables finder in the search tool --- output/Memory.xml | 6 +- tools/playground/incrementalsearch.cpp | 87 ++++++++++++++++++-------- 2 files changed, 65 insertions(+), 28 deletions(-) diff --git a/output/Memory.xml b/output/Memory.xml index fa97b261a..8ef8b5984 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1820,10 +1820,10 @@ map_data_1b60_offset 0x1B9c Translations ============ WORLD + 0x54E50 -
23
+
0x9324fd4
WORLD + 0x54E80 -
24
- 0x4C +
0x9324fec
+ 0x1C Constructions ============= diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index 29deb24d5..a7928f6b9 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -1,5 +1,5 @@ -// this will be an incremental search tool in the future. now it is just a memory region dump thing - +// this is an incremental search tool. It only works on Linux. +// here be dragons... and ugly code :P #include #include #include @@ -98,9 +98,9 @@ class SegmentedFinder return 0; } template - bool Find (const needleType needle, const uint8_t increment, vector &found, vector &newfound, comparator oper) + bool Find (const needleType needle, const uint8_t increment, vector &found, comparator oper) { - newfound.clear(); + vector newfound; for(int i = 0; i < segments.size(); i++) { segments[i]->Find(needle, increment, found, newfound, oper); @@ -208,9 +208,7 @@ void searchLoop(DFHack::ContextManager & DFMgr, vector & ran { uint32_t test1; vector found; - vector newfound; found.reserve(100); - newfound.reserve(100); //bool initial = 1; cout << "search ready - insert integers, 'p' for results" << endl; string select; @@ -236,13 +234,13 @@ void searchLoop(DFHack::ContextManager & DFMgr, vector & ran switch(size) { case 1: - sf.Find(test1,alignment,found,newfound, equalityP); + sf.Find(test1,alignment,found, equalityP); break; case 2: - sf.Find(test1,alignment,found,newfound, equalityP); + sf.Find(test1,alignment,found, equalityP); break; case 4: - sf.Find(test1,alignment,found,newfound, equalityP); + sf.Find(test1,alignment,found, equalityP); break; } if( found.size() == 1) @@ -263,9 +261,7 @@ void searchLoopVector(DFHack::ContextManager & DFMgr, vector found; - vector newfound; - found.reserve(100000); - newfound.reserve(100000); + found.reserve(100); //bool initial = 1; cout << "search ready - insert vector length" << endl; string select; @@ -291,8 +287,8 @@ void searchLoopVector(DFHack::ContextManager & DFMgr, vector (0,4,found,newfound, vectorAll); - sf.Find(length*element_size,4,found,newfound, vectorLength); + sf.Find(0,4,found,vectorAll); + sf.Find(length*element_size,4,found,vectorLength); if( found.size() == 1) { cout << "Found an address!" << endl; @@ -313,9 +309,6 @@ void searchLoopVector(DFHack::ContextManager & DFMgr, vector & ranges) { vector found; - vector newfound; - found.reserve(100000); - newfound.reserve(100000); cout << "search ready - insert string" << endl; string select; while (1) @@ -340,8 +333,8 @@ void searchLoopStrObjVector(DFHack::ContextManager & DFMgr, vector (0,4,found,newfound, vectorAll); - sf.Find(select.c_str(),4,found,newfound, vectorString); + sf.Find(0,4,found, vectorAll); + sf.Find(select.c_str(),4,found, vectorString); if( found.size() == 1) { cout << "Found an address!" << endl; @@ -362,9 +355,6 @@ void searchLoopStrObjVector(DFHack::ContextManager & DFMgr, vector & ranges) { vector found; - vector newfound; - found.reserve(1000); - newfound.reserve(1000); cout << "search ready - insert string" << endl; string select; while (1) @@ -389,7 +379,7 @@ void searchLoopStr(DFHack::ContextManager & DFMgr, vector & // clear the list of found addresses found.clear(); SegmentedFinder sf(ranges,DF); - sf.Find< const char * ,uint32_t>(select.c_str(),1,found,newfound, findString); + sf.Find< const char * ,uint32_t>(select.c_str(),1,found, findString); if( found.size() == 1) { cout << "Found a string!" << endl; @@ -482,7 +472,7 @@ int main (void) printRange(&(selected_ranges[i])); } try_again_type: - cout << "Select search type: 1=number(default), 2=vector, 3=vector>object>string, 4=string" << endl; + cout << "Select search type: 1=number(default), 2=vector, 3=vector>object>string, 4=string, 5=automated lang tables" << endl; cout << ">>"; std::getline(cin, select); int mode; @@ -492,7 +482,7 @@ int main (void) } else if( sscanf(select.c_str(), "%d", &mode) == 1 ) { - if(mode != 1 && mode != 2 && mode != 3 && mode != 4) + if(mode != 1 && mode != 2 && mode != 3 && mode != 4 && mode != 5) { goto try_again_type; } @@ -501,6 +491,7 @@ int main (void) { goto try_again_type; } + if(mode == 1) { // input / validation of variable size @@ -585,6 +576,52 @@ int main (void) { searchLoopStr(DFMgr, selected_ranges); } + else if(mode == 5) // find lang tables and stuff + { + vector allVectors; + vector to_filter; + uint64_t kulet_vector; + uint64_t word_table_offset; + uint64_t DWARF_vector; + uint64_t DWARF_object; + + cout << "Creating finder..." << endl; + SegmentedFinder sf(selected_ranges, DF); + // enumerate all vectors + cout << "enumerating vectors..." << endl; + sf.Find(0,4,allVectors, vectorAll); + cout << "done." << endl; + // find lang vector (neutral word table) + to_filter = allVectors; + cout << "searching for lang vector" << endl; + sf.Find("ABBEY",4,to_filter, vectorString); + uint64_t lang_addr = to_filter[0]; + cout << "lang vector: " << hex << "0x" << lang_addr << endl; + + // find dwarven language word table + to_filter = allVectors; + sf.Find("kulet",4,to_filter, vectorString); + kulet_vector = to_filter[0]; + to_filter = allVectors; + // find vector of languages + sf.Find("DWARF",4,to_filter, vectorString); + // verify + for(int i = 0; i < to_filter.size(); i++) + { + vecTriplet * vec = (vecTriplet *) sf.translate(to_filter[i]); + if(((vec->finish - vec->start) / 4) == 4) + { + // verified, print the vector address + DWARF_vector = to_filter[i]; + cout << "translation vector: " << hex << "0x" << DWARF_vector << endl; + DWARF_object = *(uint32_t *) sf.translate(vec->start); + // compute word table offset from dwarf word table and dwarf language object addresses + word_table_offset = kulet_vector - DWARF_object; + cout << "word table offset: " << hex << "0x" << word_table_offset << endl; + break; + } + } + } #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); From 61fea19e919a3bcc5f0c374377ecafc836bd1256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 31 May 2010 03:04:18 +0200 Subject: [PATCH 013/122] template madness! --- tools/playground/incrementalsearch.cpp | 63 ++++++++++++++++++-------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index a7928f6b9..715aaf124 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -109,17 +109,34 @@ class SegmentedFinder found = newfound; return !(found.empty()); } - uint8_t * translate(uint64_t address) + template + T * Translate(uint64_t address) { for(int i = 0; i < segments.size(); i++) { if(segments[i]->mr_.isInRange(address)) { - return segments[i]->mr_.buffer + address - segments[i]->mr_.start; + return (T *) (segments[i]->mr_.buffer + address - segments[i]->mr_.start); } } return 0; } + template + T Read(uint64_t address) + { + return *Translate(address); + } + template + bool Read(uint64_t address, T& target) + { + T * test = Translate(address); + if(test) + { + target = *test; + return true; + } + return false; + } private: DFHack::Context * _DF; vector segments; @@ -152,24 +169,32 @@ bool vectorString (SegmentedFinder* s, vecTriplet *x, const char *y) if(x->start <= x->finish && x->finish <= x->alloc_finish) { // deref ptr start, get ptr to firt object - uint8_t *deref1 = s->translate(x->start); + uint32_t object_ptr; + if(!s->Read(x->start,object_ptr)) + return false; + uint32_t string_ptr; + if(!s->Read(object_ptr,string_ptr)) + return false; + char * str = s->Translate(string_ptr); + /* + uint8_t *deref1 = s->Translate(x->start); if(!deref1) return false; uint32_t object_ptr = *(uint32_t *)deref1; if(!object_ptr) return false; // deref ptr to first object, get ptr to string - deref1 = s->translate(object_ptr); + deref1 = s->Translate(object_ptr); if(!deref1) return false; uint32_t string_ptr = *(uint32_t *)deref1; if(!string_ptr) return false; // get string location in our local cache - deref1 = s->translate(string_ptr); + deref1 = s->Translate(string_ptr); if(!deref1) return false; - char * str = (char *) deref1; + char * str = (char *) deref1;*/ if(!str) return false; if(strcmp(y, str) == 0) @@ -194,7 +219,7 @@ bool findString (SegmentedFinder* s, uint32_t *addr, const char * compare ) // read string pointer uint32_t addrx = *addr; // translat to local scheme - char *deref1 = (char *) s->translate(addrx); + char *deref1 = (char *) s->Translate(addrx); // verify if(!deref1) return false; @@ -584,43 +609,41 @@ int main (void) uint64_t word_table_offset; uint64_t DWARF_vector; uint64_t DWARF_object; - - cout << "Creating finder..." << endl; SegmentedFinder sf(selected_ranges, DF); + // enumerate all vectors - cout << "enumerating vectors..." << endl; sf.Find(0,4,allVectors, vectorAll); - cout << "done." << endl; + // find lang vector (neutral word table) to_filter = allVectors; - cout << "searching for lang vector" << endl; sf.Find("ABBEY",4,to_filter, vectorString); uint64_t lang_addr = to_filter[0]; - cout << "lang vector: " << hex << "0x" << lang_addr << endl; // find dwarven language word table to_filter = allVectors; sf.Find("kulet",4,to_filter, vectorString); kulet_vector = to_filter[0]; - to_filter = allVectors; + // find vector of languages + to_filter = allVectors; sf.Find("DWARF",4,to_filter, vectorString); + // verify for(int i = 0; i < to_filter.size(); i++) { - vecTriplet * vec = (vecTriplet *) sf.translate(to_filter[i]); - if(((vec->finish - vec->start) / 4) == 4) + vecTriplet * vec = sf.Translate(to_filter[i]); + if(((vec->finish - vec->start) / 4) == 4) // verified { - // verified, print the vector address DWARF_vector = to_filter[i]; - cout << "translation vector: " << hex << "0x" << DWARF_vector << endl; - DWARF_object = *(uint32_t *) sf.translate(vec->start); + DWARF_object = sf.Read(vec->start); // compute word table offset from dwarf word table and dwarf language object addresses word_table_offset = kulet_vector - DWARF_object; - cout << "word table offset: " << hex << "0x" << word_table_offset << endl; break; } } + cout << "translation vector: " << hex << "0x" << DWARF_vector << endl; + cout << "lang vector: " << hex << "0x" << lang_addr << endl; + cout << "word table offset: " << hex << "0x" << word_table_offset << endl; } #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; From b8600169ef71d2b435684f3f868cebb76b34350f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Tue, 1 Jun 2010 21:06:16 +0200 Subject: [PATCH 014/122] Minor comments and other changes --- library/include/dfhack/DFTileTypes.h | 51 ++++++++++++++------------ output/Memory.xml | 25 +++++++++---- tools/playground/incrementalsearch.cpp | 31 +++------------- 3 files changed, 51 insertions(+), 56 deletions(-) diff --git a/library/include/dfhack/DFTileTypes.h b/library/include/dfhack/DFTileTypes.h index 920c1541f..df0e3c873 100644 --- a/library/include/dfhack/DFTileTypes.h +++ b/library/include/dfhack/DFTileTypes.h @@ -29,9 +29,10 @@ distribution. namespace DFHack { + // tile class -- determines the general shape of the tile enum TileClass { - EMPTY, + EMPTY,// empty WALL, PILLAR, @@ -41,10 +42,10 @@ namespace DFHack STAIR_DOWN, STAIR_UPDOWN, - RAMP, - RAMP_TOP, + RAMP,// ramps have no direction + RAMP_TOP,// the top of a ramp. I assume it's used for path finding. - FLOOR, + FLOOR,// generic floor TREE_DEAD, TREE_OK, SAPLING_DEAD, @@ -54,29 +55,31 @@ namespace DFHack BOULDER, PEBBLES }; + // material -- what material the tile is made of enum TileMaterial { - AIR, - SOIL, - STONE, - FEATSTONE, // whatever it is - OBSIDIAN, - - VEIN, - ICE, - GRASS, - GRASS2, - GRASS_DEAD, - GRASS_DRY, - DRIFTWOOD, - HFS, - MAGMA, - CAMPFIRE, - FIRE, - ASHES, - CONSTRUCTED, - CYAN_GLOW + AIR,// empty + SOIL,// ordinary soil. material depends on geology + STONE,// ordinary layer stone. material depends on geology + FEATSTONE,// map feature stone. used for things like hell, the hell temple or adamantine tubes. material depends on local/global feature + OBSIDIAN,// cast obsidian + + VEIN,// vein stone. material depends on mineral veins present + ICE,// frozen water... not much to say. you can determine what was on the tile before it froze by looking into the 'ice vein' objects + GRASS,// grass (has 4 variants) + GRASS2,// grass (has 4 variants) + GRASS_DEAD,// dead grass (has 4 variants) + GRASS_DRY,// dry grass (has 4 variants) + DRIFTWOOD,// non-specified wood - normally on top of the local layer stone/soil. + HFS,// the stuff demon pits are made of - this makes them different from ordinary pits. + MAGMA,// material for semi-molten rock and 'magma flow' tiles + CAMPFIRE,// human armies make them when they siege. The original tile may be lost? + FIRE,// burning grass + ASHES,// what remains from a FIRE + CONSTRUCTED,// tile material depends on the construction present + CYAN_GLOW// the glowy stuff that disappears from the demon temple when you take the sword. }; + // variants are used for tiles, where there are multiple variants of the same - like grass floors enum TileVariant { VAR_1, diff --git a/output/Memory.xml b/output/Memory.xml index 8ef8b5984..d5eae8cda 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1816,6 +1816,24 @@ map_data_1b60_offset 0x1B9c 0x1A14 0xE0 0xF6 + Translations ============ @@ -1831,13 +1849,6 @@ map_data_1b60_offset 0x1B9c
0x92D0144
0x165b290 0x14 "); + recursion_level++; + subretval = hexsearch_match2(p, SKIPME, va); + recursion_level--; + //dumps("<--"); + //dump(recursion_level); + //dump(tokensprocessed); + nexthere = savenexthere; + nexttarget = savenexttarget; + if (subretval != NULL) { + // okay, we now know that the bytes starting at p + // match the remainder of the pattern. + // Nonetheless, for ease of programming, we will + // go through the motions instead of trying to + // early-out. (Basically done for HERE tokens.) + break; + } + + p++; + len--; + } + if (subretval != NULL) + { + continue; + } + // no match within nn bytes, abort. + break; + } + + // exact-match a dword. advance 4. + else if (token == DWORD_) + { + DWORD d = va_arg(va, unsigned int); + if (*(DWORD *)p != d) break; + p += 4; + tokensprocessed++; + } + + // match any dword. advance 4. + else if (token == ANYDWORD) + { + p += 4; + } + + // match any legal address in + else if (token == ADDRESS) + { + // program text. advance 4. + if (*(DWORD *)p < df_memory_start) + { + break; + } + if (*(DWORD *)p > df_memory_end) + { + break; + } + p += 4; + } + + // match any call. advance 5. + else if (token == CALL) + { + if (*p++ != 0xE8) + { + break; + } + target[nexttarget++] = *(DWORD *)p + (DWORD)p + 4; +#if 0 + if (*(DWORD *)p > DF_CODE_SIZE + && *(DWORD *)p < (DWORD)-DF_CODE_SIZE) + break; +#endif + p += 4; + } + + // match any short or near jump. + else if (token == JUMP) + { + // advance 2 or 5 respectively. + if (*p == 0xEB) + { + target[nexttarget++] = *(signed char *)(p+1) + (DWORD)p + 1; + p += 2; + continue; + } + + if (*p++ != 0xE9) + { + break; + } + + target[nexttarget++] = *(DWORD *)p + (DWORD)p + 4; +#if 0 + if (*(DWORD *)p > DF_CODE_SIZE + && *(DWORD *)p < (DWORD)-DF_CODE_SIZE) + break; +#endif + p += 4; + } + + // match a JZ instruction + else if (token == JZ) + { + if (*p == 0x74) + { + target[nexttarget++] = *(signed char *)(p+1) + (DWORD)p + 2; + p += 2; + continue; + } + else if (*p == 0x0F && *(p+1) == 0x84 + && (*(p+4) == 0x00 || *(p+4) == 0xFF) // assume dist < 64k + && (*(p+5) == 0x00 || *(p+5) == 0xFF)) + { + target[nexttarget++] = *(DWORD *)(p+2) + (DWORD)p + 6; + p += 6; + continue; + } + else break; + } + + // match a JNZ instruction + else if (token == JNZ) + { + if (*p == 0x75) { + target[nexttarget++] = *(signed char *)(p+1) + (DWORD)p + 2; + p += 2; + continue; + } + else if (*p == 0x0F && *(p+1) == 0x85 + && (*(p+4) == 0x00 || *(p+4) == 0xFF) // assume dist < 64k + && (*(p+5) == 0x00 || *(p+5) == 0xFF) + ) { + target[nexttarget++] = *(DWORD *)(p+2) + (DWORD)p + 6; + p += 6; + continue; + } + else break; + } + + // match any conditional jump + else if (token == JCC) + { + if (*p >= 0x70 && *p <= 0x7F) + { + target[nexttarget++] = *(signed char *)(p+1) + (DWORD)p + 2; + p += 2; + continue; + } + else if (*p == 0x0F && *(p+1) >= 0x80 && *(p+1) <= 0x8F + && (*(p+4) == 0x00 || *(p+4) == 0xFF) // assume dist < 64k + && (*(p+5) == 0x00 || *(p+5) == 0xFF)) + { + target[nexttarget++] = *(DWORD *)(p+2) + (DWORD)p + 6; + p += 6; + continue; + } + else break; + } + + // unknown token, abort + else + { + d_printf("unknown token: %08X\n", token); + dump(p); + dump(recursion_level); + break; + } // end of huge if-else + + } // end of while(1) + + if (!ok) + { + retval = NULL; + nexthere = savenexthere; + nexttarget = savenexttarget; + } + return (retval); +} + + +// ============================================================================ +// The name has changed because the API HAS CHANGED! +// +// Now instead of returning HERE, it always returns the start of the match. +// +// However, there is an array, here[], that is filled with the locations of +// the HERE tokens. +// (Starting at 1. here[0] is a copy of the start of the match.) +// +// The here[] array, starting at 1, is filled with the locations of the +// HERE token. +// here[0] is a copy of the start of the match. +// +// Also, the target[] array, starting at 1, is filled with the target +// addresses of all CALL, JMP, JZ, JNZ, and JCC tokens. +// +// Finally, you no longer pass it a search length. Instead, each set of +// search terms must end with an EOL. +// +// +// +// Okay, I admit this one is complicated. Treat it as a black box. +// +// Search Dwarf Fortress's code and initialized data segments for a pattern. +// (Does not search stack, heap, or thread-local memory.) +// +// Parameters: any number of search tokens, all unsigned ints. +// The last token must be EOL. +// +// 0x00 - 0xFF: Match this byte. +// EOL: End-of-list. The match succeeds when this token is reached. +// ANYBYTE: Match any byte. +// DWORD_: Followed by a dword. Exact-match the dword. +// Equivalent to 4 match-this-byte tokens. +// ANYDWORD: Match any dword. Equivalant to 4 ANYBYTEs. +// HERE: Put the current address into the here[] array. +// SKIP_UP_TO, nn: Allow up to nn bytes between the previous match +// and the next match. The next token must be a match-this-byte +// token. There is sweet, sweet backtracking. +// EITHER: Accept either of the next two tokens as a match. +// Both must be match-this-byte tokens. +// RANGE_LO, nn: Set low byte for a range comparison. DEPRECATED. +// RANGE_HI, nn: Set high byte for a range comparison, and do the +// comparison. Should immediately follow a RANGE_LO. DEPRECATED. +// BYTERANGE, nn, mm: followed by two bytes, the low and high limits +// of the range. This is the new way to do ranges. +// DWORDRANGE, nnnnnnnn, mmmmmmmm: works like BYTERANGE. +// ADDRESS: Accept any legal address in the program's text. +// DOES NOT accept pointers into heap space and such. +// CALL: Match a near call instruction to a reasonable address. +// JUMP: Match a short or near unconditional jump to a reasonable +// address. +// JZ: Match a short or long jz (jump if zero) instruction. +// JNZ: Match a short or long jnz (jump if not zero) instruction. +// JCC: Match any short or long conditional jump instruction. +// More tokens can easily be added. +// +// Returns the offset in Dwarf Fortress of the first match of the pattern. +// Also sets global variables here[] and target[]. +// +// Note: starting a pattern with ANYBYTE, ANYDWORD, SKIP_UP_TO, or EOL +// is explicitly illegal. +// +// +// implementation detail: search() uses a cached copy of the memory, so +// poke()s and patch()s will not be reflected in the searches. +// +// implementation detail: Q: why don't we discard count and always use EOL? +// A: because we need a fixed parameter to start the va_list. +// (Hmm, could we grab address of a local variable, walk the stack +// until we see &hexsearch, and use that address to init va_list?) +// (No, dummy, because &hexsearch is not on the stack. The stack +// holds the return address.) +// (Could we grab the EBP register and treat it as a stack frame?) +// (Maybe, but the compiler decides if EBP really is a stack frame, +// so that would be an implementation dependency. Don't do it.) +// +// TODO: should be a way to repeat a search in case we want the second or +// eleventh occurance. +// +// TODO: allow EITHER to accept arbitrary (sets of) tokens. +// (How would that work? Have two sub-patterns, each terminating +// with EOL?) +// +DWORD hexsearch2(DWORD token1, ...) +{ + DWORD size; + BYTE *nextoffset, *foundit; + DWORD token; + int i; + va_list va; + + for (i = 0; i < 16; i++) here[i] = 0; + for (i = 0; i < 16; i++) target[i] = 0; + + nexthere = 1; + nexttarget = 1; + + if ( token1 == ANYBYTE + || token1 == ANYDWORD + || token1 == SKIP_UP_TO + || token1 == HERE + || token1 == EOL ) + { + return 0; + } + + dump(searchmemstart); + dump(searchmemend); + dump(df_memory_start); + dump(copy_of_df_memory); + nextoffset = copy_of_df_memory; + nextoffset += (searchmemstart - df_memory_start); + dump(nextoffset); + size = searchmemend - searchmemstart; + dump(size); + + while (1) + { + // for speed, if we start with a raw byte, use a builtin function + // to skip ahead to the next actual occurance. + if (token1 <= 0xFF) + { + nextoffset = (BYTE *)memchr(nextoffset, token1, + size - (nextoffset - copy_of_df_memory)); + if (nextoffset == NULL) break; + } + + va_start(va, token1); + foundit = hexsearch_match2(nextoffset, token1, va); + va_end(va); + + if (foundit) + { + break; + } + + if ((DWORD)(++nextoffset - copy_of_df_memory - (searchmemstart - df_memory_start)) >= size) + { + break; + } + + } + + if (!foundit) + { + d_printf("hexsearch2(%X", token1); + i = 0; + va_start(va, token1); + do + { + d_printf(",%X", token = va_arg(va, DWORD)); + } while (EOL != token && i++ < 64); + va_end(va); + if (i >= 64) d_printf("..."); + d_printf(")\n"); + d_printf("search failed!\n"); + for (i = 0; i < 16; i++) + { + here[i] = 0; + target[i] = 0; + } + return 0; + } + + here[0] = (DWORD)foundit; + for (i = 0; i < 16; i++) + { + if (i < nexthere && here[i] != 0) + { + here[i] += df_memory_start - (DWORD)copy_of_df_memory; + } + else here[i] = 0; + } + for (i = 0; i < 16; i++) + { + if (i < nexttarget && target[i] != 0) + { + target[i] += df_memory_start - (DWORD)copy_of_df_memory; + } + else target[i] = 0; + } + + return df_memory_start + (foundit - copy_of_df_memory); +} + + +// ---------------------------------------------------------------------------- +void set_hexsearch2_limits(DWORD start, DWORD end) +{ + if (end < start) end = start; + + searchmemstart = start >= df_memory_start ? start : df_memory_start; + searchmemend = end >= df_memory_start && end <= df_memory_end ? + end : df_memory_end; +} + + +// ============================================================================ +// helper function for patch and verify. does the actual work. +static BOOL vpatchengine(BOOL mode, DWORD address, va_list va) +{ + // mode: TRUE == patch, FALSE == verify + DWORD next = address, a, c; + // a is token, c is helper value, b is asm instruction byte to use. + BYTE b; + BOOL ok = FALSE; + + while (1) + { + //if (length == 0) { ok = TRUE; break; } + //length--; + a = va_arg(va, unsigned int); + + if (a == EOL) + { + ok = TRUE; + break; + } + + if (a == DWORD_) + { + //if (length-- == 0) break; + c = va_arg(va, unsigned int); + if (mode ? !poked(next, c) : c != peekd(next)) break; + next += 4; + continue; + } + + if (a == CALL || a == JUMP) + { + b = (a == CALL ? 0xE8 : 0xE9); + //if (length-- == 0) break; + c = va_arg(va, unsigned int) - (next + 5); + if (mode ? !pokeb(next, b) : b != peekb(next)) break; + // do NOT merge the next++ into the previous if statement. + next++; + if (mode ? !poked(next, c) : c != peekd(next)) break; + next += 4; + continue; + } + + if (a == JZ || a == JNZ) + { + b = (a == JZ ? 0x84 : 0x85); + //if (length-- == 0) break; + c = va_arg(va, unsigned int) - (next + 6); + if (mode ? !pokeb(next, 0x0F) : 0x0F != peekb(next)) break; + next++; + if (mode ? !pokeb(next, b) : b != peekb(next)) break; + next++; + if (mode ? !poked(next, c) : c != peekd(next)) break; + next += 4; + continue; + } + + if (a <= 0xFF) + { + if (mode ? !pokeb(next, a) : a != peekb(next)) break; + next++; + continue; + } + + d_printf("vpatchengine: unsupported token: %08X\n", a); + break; // unsupported token + } + +// d_printf("vpatchengine returning %d, length is %d, next is %08X\n", +// ok, length, next); + return(ok); +} + + +// ---------------------------------------------------------------------------- +// patch() and verify() support a modified subset of hex_search() tokens: +// +// 0x00 - 0xFF: poke the byte. +// EOL: end-of-list. terminate when this token is reached. +// DWORD_: Followed by a DWORD, not a byte. Poke the DWORD. +// CALL: given an _address_; pokes near call with the proper _delta_. +// JUMP: given an _address_; pokes near jump with the proper _delta_. +// JZ: given an _address_; assembles a near (not short) jz & delta. +// JNZ: given an _address_; assembles a near jnz & delta. +// +// Particularly note that, unlike hex_search(), CALL, JUMP, JZ, and JNZ +// are followed by a dword-sized target address. +// +// Note that patch() does its own verify(), so you don't have to. +// +// TODO: doing so many individual pokes and peeks is slow. Consider +// building a copy, then doing a pokearb/peekarb. + +// Make an offset in Dwarf Fortress have certain bytes. +BOOL patch2(DWORD address, ...) +{ + va_list va; + BOOL ok; + + va_start(va, address); + ok = vpatchengine(TRUE, address, va); + va_end(va); + + va_start(va, address); + if (ok) ok = vpatchengine(FALSE, address, va); + va_end(va); + return(ok); +} + + +// ---------------------------------------------------------------------------- +// Check that an offset in Dwarf Fortress has certain bytes. +// +// See patch() documentation. +BOOL verify2(DWORD address, ...) +{ + BOOL ok; + va_list va; + va_start(va, address); + ok = vpatchengine(FALSE, address, va); + va_end(va); + return(ok); +} + +// ---------------------------------------------------------------------------- +// Get the exe name of the DF executable +static DWORD get_exe_base(DWORD pid) +{ + HANDLE snap = INVALID_HANDLE_VALUE; + PROCESSENTRY32 process = {0}; + MODULEENTRY32 module = {0}; + + do + { + snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (snap == INVALID_HANDLE_VALUE) + { + errormessage = "CreateToolhelp32Snapshot(Process) failed."; + break; + } + + // Get the process exe name + process.dwSize = sizeof(PROCESSENTRY32); + if (!Process32First(snap, &process)) + { + errormessage = "Process32First(snapshot) failed."; + break; + } + do + { + if (process.th32ProcessID == pid) + { + break; + } + else + { + //d_printf("Process: %d \"%.*s\"", process.th32ProcessID, MAX_PATH, process.szExeFile); + } + } while (Process32Next(snap, &process)); + if (process.th32ProcessID != pid) + { + errormessage = "Process32List(snapshot) Couldn't find the target process in the snapshot?"; + break; + } + + d_printf("Target Process: %d \"%.*s\"", process.th32ProcessID, MAX_PATH, process.szExeFile); + CloseHandle(snap); + + snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); + if (snap == INVALID_HANDLE_VALUE) + { + errormessage = "CreateToolhelp32Snapshot(Modules) failed."; + break; + } + + // Now find the module + module.dwSize = sizeof(MODULEENTRY32); + if (!Module32First(snap, &module)) + { + errormessage = "Module32First(snapshot) failed."; + break; + } + do + { + if (!stricmp(module.szModule, process.szExeFile)) + { + break; + } + else + { + //d_printf("Module: %08X \"%.*s\" \"%.*s\"", (DWORD)(SIZE_T)module.modBaseAddr, MAX_MODULE_NAME32 + 1, module.szModule, MAX_PATH, module.szExePath); + } + } while (Module32Next(snap, &module)); + if (stricmp(module.szModule, process.szExeFile)) + { + errormessage = "Module32List(snapshot) Couldn't find the target module in the snapshot?"; + break; + } + d_printf("Target Module: %08X \"%.*s\" \"%.*s\"", (DWORD)(SIZE_T)module.modBaseAddr, MAX_MODULE_NAME32 + 1, module.szModule, MAX_PATH, module.szExePath); + } while (0); + + if (snap != INVALID_HANDLE_VALUE) + { + CloseHandle(snap); + } + + if (errormessage != NULL && strlen(errormessage) != 0) + { + d_printf("%s\n", errormessage); + return 0; + } + + return (DWORD)(SIZE_T)module.modBaseAddr; +} + +// ============================================================================ +void cleanup(void) +{ + + if (copy_of_df_memory != NULL) + { + GlobalFree(copy_of_df_memory); + copy_of_df_memory = NULL; + } + + if (suspended) + { + if ((DWORD)-1 == ResumeThread(df_h_thread)) + { + // do what? apologise? + } + else suspended = FALSE; + } +#if 0 + // do this incase earlier runs crashed without executing the atexit handler. + // TODO: trap exceptions? + ResumeThread(df_h_thread); + ResumeThread(df_h_thread); + ResumeThread(df_h_thread); + ResumeThread(df_h_thread); + ResumeThread(df_h_thread); + ResumeThread(df_h_thread); + ResumeThread(df_h_thread); + ResumeThread(df_h_thread); + ResumeThread(df_h_thread); + ResumeThread(df_h_thread); + ResumeThread(df_h_thread); + ResumeThread(df_h_thread); +#endif + + if (df_h_thread != NULL) + { + CloseHandle(df_h_thread); + df_h_thread = NULL; + } + if (df_h_process != NULL) + { + CloseHandle(df_h_process); + df_h_process = NULL; + } +} + + +// ---------------------------------------------------------------------------- +BOOL open_dwarf_fortress(void) +{ + HANDLE df_main_wh; + char *state; + + change_page_permissions = FALSE; + + atexit(cleanup); + + df_memory_base = 0x400000; // executables start here unless + // explicitly relocated. + errormessage = ""; + + + // trigger a GPF + //*(char *)(0) = '!'; + + // trigger an invalid instruction (or DEP on newer processors). + // 0F 0B is the UD1 pseudo-instruction, explicitly reserved as an invalid + // instruction to trigger faults. + //asm(".fill 1, 1, 0x0F; .fill 1, 1, 0x0B"); + + state = "calling FindWindow()... "; + d_printf(state); + df_main_wh = FindWindow("OpenGL","Dwarf Fortress"); + d_printf("done\n"); + dump(df_main_wh); + if (df_main_wh == 0) + { + df_main_wh = FindWindow("SDL_app","Dwarf Fortress"); + if (df_main_wh == 0) + { + errormessage = "FindWindow(Dwarf Fortress) failed.\nIs the game running?"; + return FALSE; + } + } + + state = "calling GetWindowThreadProcessId()... "; + d_printf(state); + df_main_win_tid = GetWindowThreadProcessId(df_main_wh, &df_pid); + d_printf("done\n"); + dump(df_pid); + dump(df_main_win_tid); + + if (df_main_win_tid == 0) { + errormessage = + "GetWindowThreadProcessId(Dwarf Fortress) failed.\n" + "That should not have happened!"; + return FALSE; + } + + state = "calling OpenProcess()... "; + d_printf(state); + df_h_process = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_VM_OPERATION | PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION, FALSE, df_pid); + d_printf("done\n"); + dump(df_h_process); + if (df_h_process == NULL) + { + errormessage = "OpenProcess(Dwarf Fortress) failed.\n" + "Are you the same user that started the game?"; + return(FALSE); + } + + state = "calling OpenThread()... "; + d_printf(state); + df_h_thread = OpenThread(THREAD_ALL_ACCESS, FALSE, df_main_win_tid); + d_printf("done\n"); + dump(df_h_thread); + if (df_h_thread == NULL) + { + errormessage = "OpenThread(Dwarf Fortress) failed."; + return(FALSE); + } + + // TODO enum and suspend all threads? + state = "calling SuspendThread()... "; + d_printf(state); + if ((DWORD)-1 == SuspendThread(df_h_thread)) + { + errormessage = "SuspendThread(Dwarf Fortress) failed."; + return(FALSE); + } + d_printf("done\n"); + suspended = TRUE; + + // get the base of the df executable + df_memory_base = get_exe_base(df_pid); + if (!df_memory_base) + { + errormessage = "GetModuleBase(Dwarf Fortress) failed."; + return(FALSE); + } + dump(df_memory_base); + + // we could get this from the PE header, but why bother? + df_memory_start = df_memory_base + 0x1000; + dump(df_memory_start); + + // df_memory_end is based on the SizeOfImage field from the in-memory + // copy of the PE header. + df_memory_end = df_memory_base + peekd(df_memory_base+peekd(df_memory_base+0x3C)+0x50)-1; + dump(df_memory_end); + + state = "calling GlobalAlloc(huge)... "; + d_printf(state); + dump(df_memory_end - df_memory_start + 0x100); + if (NULL == (copy_of_df_memory = (BYTE *)GlobalAlloc(GPTR, df_memory_end - df_memory_start + 0x100))) + { + errormessage = "GlobalAlloc() of copy_of_df_memory failed"; + return FALSE; + } + d_printf("done\n"); + + state = "copying memory... "; + if (!peekarb(df_memory_start, copy_of_df_memory, df_memory_end-df_memory_start)) + { + d_printf("peekarb(entire program) for search()'s use failed\n"); + return FALSE; + } + + set_hexsearch2_limits(0, 0); + + return(TRUE); +} + + +// not (normally) necessary because it is done at exit time by atexit(). +// however you can call this to resume DF before putting up a dialog box. +void close_dwarf_fortress(void) +{ + cleanup(); +} + diff --git a/tools/playground/hexsearch2.h b/tools/playground/hexsearch2.h new file mode 100644 index 000000000..8cff56b90 --- /dev/null +++ b/tools/playground/hexsearch2.h @@ -0,0 +1,219 @@ +/* + * Author: Silas Dunsmore aka 0x517A5D vim:ts=4:sw=4 + * + * Released under the MIT X11 license; feel free to use some or all of this + * code, as long as you include the copyright and license statement (below) + * in all copies of the source code. In fact, I truly encourage reuse. + * + * If you do use large portions of this code, I suggest but do not require + * that you keep this code in a seperate file (such as this hexsearch.h file) + * so that it is clear that the terms of the license do not also apply to + * your code. + * + * Should you make fundamental changes, or bugfixes, to this code, I would + * appreciate it if you would give me a copy of your changes. + * + * + * Copyright (C) 2007-2008 Silas Dunsmore + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * See also: http://www.opensource.org/licenses/mit-license.php + * and http://en.wikipedia.org/wiki/MIT_License + */ + + +#ifndef HEXSEARCH_H +#define HEXSEARCH_H +#ifdef __cplusplus +extern "C" +{ +#endif + + +extern DWORD df_memory_base, df_memory_start, df_memory_end; +extern HANDLE df_h_process, df_h_thread; +extern DWORD df_pid, df_main_win_tid; + +extern DWORD here[16]; +extern DWORD target[16]; + +// ============================================================================ +// export these in case you need to work with them directly. +//extern HANDLE df_h_process, df_h_thread; +//extern DWORD df_pid, df_main_win_tid; +extern char *errormessage; + + +// ============================================================================ +// send info to KERNEL32:OutputDebugString(), useful for non-console programs. +// (you can watch this with SysInternals' DebugView.) +// http://www.microsoft.com/technet/sysinternals/Miscellaneous/DebugView.mspx +void d_printf(const char *format, ...); +// it turned out that dprintf() is semi-standard to printf to a file descriptor. + + +// ============================================================================ +// encapsulate the housekeeping. +BOOL open_dwarf_fortress(void); +void close_dwarf_fortress(void); // is not (normally) necessary because + // it is done at exit time. + + +// ============================================================================ +// memory reads and writes (peeks and pokes, in old BASIC terminology) +BOOL isvalidaddress(DWORD ea); +BOOL peekarb(DWORD ea, OUT void *data, DWORD len); +BYTE peekb(DWORD ea); +WORD peekw(DWORD ea); +DWORD peekd(DWORD ea); +char *peekstr(DWORD ea, OUT char *data, DWORD maxlen); +char *peekustr(DWORD ea, OUT char *data, DWORD maxlen); +BOOL pokearb(DWORD ea, const void *data, DWORD len); +BOOL pokeb(DWORD ea, BYTE data); +BOOL pokew(DWORD ea, WORD data); +BOOL poked(DWORD ea, DWORD data); +BOOL pokestr(DWORD ea, const BYTE *data); + + +// ============================================================================ +// The name has changed because the API HAS CHANGED! +// +// Now instead of returning HERE, it always returns the start of the match. +// +// However, there is an array, here[], that is filled with the locations of +// the HERE tokens. +// (Starting at 1. here[0] is a copy of the start of the match.) +// +// The here[] array, starting at 1, is filled with the locations of the +// HERE token. +// here[0] is a copy of the start of the match. +// +// Also, the target[] array, starting at 1, is filled with the target +// addresses of all CALL, JMP, JZ, JNZ, and JCC tokens. +// +// Finally, you no longer pass it a search length. Instead, each set of +// search terms must end with an EOL. +// +// +// +// Okay, I admit this one is complicated. Treat it as a black box. +// +// Search Dwarf Fortress's code and initialized data segments for a pattern. +// (Does not search stack, heap, or thread-local memory.) +// +// Parameters: any number of search tokens, all unsigned ints. +// The last token must be EOL. +// +// 0x00 - 0xFF: Match this byte. +// EOL: End-of-list. The match succeeds when this token is reached. +// ANYBYTE: Match any byte. +// DWORD_: Followed by a dword. Exact-match the dword. +// Equivalent to 4 match-this-byte tokens. +// ANYDWORD: Match any dword. Equivalant to 4 ANYBYTEs. +// HERE: Put the current address into the here[] array. +// SKIP_UP_TO, nn: Allow up to nn bytes between the previous match +// and the next match. The next token must be a match-this-byte +// token. There is sweet, sweet backtracking. +// EITHER: Accept either of the next two tokens as a match. +// Both must be match-this-byte tokens. +// RANGE_LO, nn: Set low byte for a range comparison. DEPRECATED. +// RANGE_HI, nn: Set high byte for a range comparison, and do the +// comparison. Should immediately follow a RANGE_LO. DEPRECATED. +// BYTERANGE, nn, mm: followed by two bytes, the low and high limits +// of the range. This is the new way to do ranges. +// DWORDRANGE, nnnnnnnn, mmmmmmmm: works like BYTERANGE. +// ADDRESS: Accept any legal address in the program's text. +// DOES NOT accept pointers into heap space and such. +// CALL: Match a near call instruction to a reasonable address. +// JUMP: Match a short or near unconditional jump to a reasonable +// address. +// JZ: Match a short or long jz (jump if zero) instruction. +// JNZ: Match a short or long jnz (jump if not zero) instruction. +// JCC: Match any short or long conditional jump instruction. +// More tokens can easily be added. +// +// Returns the offset in Dwarf Fortress of the first match of the pattern. +// Also sets global variables here[] and target[]. +// +// Note: starting a pattern with ANYBYTE, ANYDWORD, SKIP_UP_TO, or EOL +// is explicitly illegal. +// +#define EOL 0x100 +#define ANYBYTE 0x101 +//#define FF_OR_00 0x102 // deprecated +#define HERE 0x103 +#define EITHER 0x104 +#define SKIP_UP_TO 0x105 +#define RANGE_LO 0x106 // deprecated +#define RANGE_HI 0x107 // deprecated +#define DWORD_ 0x108 +#define ANYDWORD 0x109 +#define ADDRESS 0x10A +#define BYTERANGE 0x10B +#define DWORDRANGE 0x10C +#define JZ 0x174 +#define JNZ 0x175 +#define JCC 0x170 +#define CALL 0x1E8 +#define JUMP 0x1E9 + + +DWORD hexsearch2(DWORD token1, ...); + +// You can use this to limit the search to a particular part of memory. +// Use 0 for start to search from the very start of Dwarf Fortress. +// Use 0 for end to stop searching at the very end of Dwarf Fortress. +void set_hexsearch2_limits(DWORD start, DWORD end); + + +// ============================================================================ +// patch2() and verify2() support a modified subset of hex_search2() tokens: +// The names changed because the API HAS CHANGED! +// +// 0x00 - 0xFF: pokes the byte. +// EOL: End-of-list. Allows you to specify count as 10000 or so +// and terminate (with success) when this token is reached. +// DWORD_: Followed by a DWORD. Pokes the DWORD. +// CALL: given an _address_; pokes near call with the proper _delta_. +// JUMP: given an _address_; pokes near jump with the proper _delta_. +// JZ: given an _address_; assembles a near (not short) jz & delta. +// JNZ: given an _address_; assembles a near jnz & delta. +// +// Particularly note that, unlike hex_search(), CALL, JUMP, JZ, and JNZ +// are followed by a dword-sized target address. +// +// Note that patch2() does its own verify(), so you don't have to. + +// TODO: is verify() useful enough to maintain? + +// Make an offset in Dwarf Fortress have certain bytes. +BOOL patch2(DWORD offset, ...); +// Check that an offset in Dwarf Fortress has certain bytes. +BOOL verify2(DWORD offset, ...); + + + +#ifdef __cplusplus +} +#endif +#endif // HEXSEARCH_H \ No newline at end of file From 8d15e22a59fa19661d2f23d0db33454c0c282efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Wed, 2 Jun 2010 05:39:55 +0200 Subject: [PATCH 016/122] Simplified memory search tool --- tools/playground/SegmentedFinder.h | 224 ++++++++ tools/playground/incrementalsearch.cpp | 757 ++++++++----------------- 2 files changed, 476 insertions(+), 505 deletions(-) create mode 100644 tools/playground/SegmentedFinder.h diff --git a/tools/playground/SegmentedFinder.h b/tools/playground/SegmentedFinder.h new file mode 100644 index 000000000..f16152997 --- /dev/null +++ b/tools/playground/SegmentedFinder.h @@ -0,0 +1,224 @@ +#ifndef SEGMENTED_FINDER_H +#define SEGMENTED_FINDER_H + +class SegmentedFinder; +class SegmentFinder +{ + public: + SegmentFinder(DFHack::t_memrange & mr, DFHack::Context * DF, SegmentedFinder * SF) + { + _DF = DF; + mr_ = mr; + mr_.buffer = (uint8_t *)malloc (mr_.end - mr_.start); + DF->ReadRaw(mr_.start,(mr_.end - mr_.start),mr_.buffer); + _SF = SF; + } + ~SegmentFinder() + { + delete mr_.buffer; + } + template + bool Find (needleType needle, const uint8_t increment ,vector &found, vector &newfound, comparator oper) + { + if(found.empty()) + { + //loop + for(uint64_t offset = 0; offset < (mr_.end - mr_.start) - sizeof(hayType); offset += increment) + { + if( oper(_SF,(hayType *)(mr_.buffer + offset), needle) ) + newfound.push_back(mr_.start + offset); + } + } + else + { + for( uint64_t i = 0; i < found.size(); i++) + { + if(mr_.isInRange(found[i])) + { + uint64_t corrected = found[i] - mr_.start; + if( oper(_SF,(hayType *)(mr_.buffer + corrected), needle) ) + newfound.push_back(found[i]); + } + } + } + return true; + } + private: + friend class SegmentedFinder; + SegmentedFinder * _SF; + DFHack::Context * _DF; + DFHack::t_memrange mr_; +}; + +class SegmentedFinder +{ + public: + SegmentedFinder(vector & ranges, DFHack::Context * DF) + { + _DF = DF; + for(int i = 0; i < ranges.size(); i++) + { + segments.push_back(new SegmentFinder(ranges[i], DF, this)); + } + } + ~SegmentedFinder() + { + for(int i = 0; i < segments.size(); i++) + { + delete segments[i]; + } + } + SegmentFinder * getSegmentForAddress (uint64_t addr) + { + for(int i = 0; i < segments.size(); i++) + { + if(segments[i]->mr_.isInRange(addr)) + { + return segments[i]; + } + } + return 0; + } + template + bool Find (const needleType needle, const uint8_t increment, vector &found, comparator oper) + { + vector newfound; + for(int i = 0; i < segments.size(); i++) + { + segments[i]->Find(needle, increment, found, newfound, oper); + } + found.clear(); + found = newfound; + return !(found.empty()); + } + template + T * Translate(uint64_t address) + { + for(int i = 0; i < segments.size(); i++) + { + if(segments[i]->mr_.isInRange(address)) + { + return (T *) (segments[i]->mr_.buffer + address - segments[i]->mr_.start); + } + } + return 0; + } + template + T Read(uint64_t address) + { + return *Translate(address); + } + template + bool Read(uint64_t address, T& target) + { + T * test = Translate(address); + if(test) + { + target = *test; + return true; + } + return false; + } + private: + DFHack::Context * _DF; + vector segments; +}; + +template +bool equalityP (SegmentedFinder* s, T *x, T y) +{ + return (*x) == y; +} + +struct vecTriplet +{ + uint32_t start; + uint32_t finish; + uint32_t alloc_finish; +}; + +template +bool vectorLength (SegmentedFinder* s, vecTriplet *x, Needle &y) +{ + if(x->start <= x->finish && x->finish <= x->alloc_finish) + if((x->finish - x->start) == y) + return true; + return false; +} + +// find a vector of 32bit pointers, where an object pointed to has a string 'y' as the first member +bool vectorString (SegmentedFinder* s, vecTriplet *x, const char *y) +{ + uint32_t object_ptr; + uint32_t idx = x->start; + // iterato over vector of pointers + for(uint32_t idx = x->start; idx < x->finish; idx += sizeof(uint32_t)) + { + // deref ptr idx, get ptr to object + if(!s->Read(idx,object_ptr)) + { + return false; + } + // deref ptr to first object, get ptr to string + uint32_t string_ptr; + if(!s->Read(object_ptr,string_ptr)) + return false; + // get string location in our local cache + char * str = s->Translate(string_ptr); + if(!str) + return false; + if(strcmp(y, str) == 0) + return true; + } + return false; +} + +// test if the address is within a vector's array +bool vectorAddrWithin (SegmentedFinder* s, vecTriplet *x, uint32_t address) +{ + if(address < x->finish && address >= x->start) + return true; + return false; +} + +// test if an object address is within the vector of pointers +bool vectorOfPtrWithin (SegmentedFinder* s, vecTriplet *x, uint32_t address) +{ + uint32_t object_ptr; + uint32_t idx = x->start; + for(uint32_t idx = x->start; idx < x->finish; idx += sizeof(uint32_t)) + { + if(!s->Read(idx,object_ptr)) + { + return false; + } + if(object_ptr == address) + return true; + } + return false; +} + +bool vectorAll (SegmentedFinder* s, vecTriplet *x, int ) +{ + if(x->start <= x->finish && x->finish <= x->alloc_finish) + { + if(s->getSegmentForAddress(x->start) == s->getSegmentForAddress(x->finish) + && s->getSegmentForAddress(x->finish) == s->getSegmentForAddress(x->alloc_finish)) + return true; + } + return false; +} + +bool findString (SegmentedFinder* s, uint32_t *addr, const char * compare ) +{ + // read string pointer, translate to local scheme + char *str = s->Translate(*addr); + // verify + if(!str) + return false; + if(strcmp(str, compare) == 0) + return true; + return false; +} + +#endif // SEGMENTED_FINDER_H \ No newline at end of file diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index 66f0bf63d..083597ba3 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -19,395 +19,307 @@ using namespace std; #endif #include -class SegmentedFinder; -class SegmentFinder +#include "SegmentedFinder.h" + +inline void printRange(DFHack::t_memrange * tpr) { - public: - SegmentFinder(DFHack::t_memrange & mr, DFHack::Context * DF, SegmentedFinder * SF) - { - _DF = DF; - mr_ = mr; - mr_.buffer = (uint8_t *)malloc (mr_.end - mr_.start); - DF->ReadRaw(mr_.start,(mr_.end - mr_.start),mr_.buffer); - _SF = SF; - } - ~SegmentFinder() + std::cout << std::hex << tpr->start << " - " << tpr->end << "|" << (tpr->read ? "r" : "-") << (tpr->write ? "w" : "-") << (tpr->execute ? "x" : "-") << "|" << tpr->name << std::endl; +} + +bool getRanges(DFHack::Process * p, vector & selected_ranges) +{ + vector ranges; + selected_ranges.clear(); + p->getMemRanges(ranges); + cout << "Which range to search? (default is 1-4)" << endl; + for(int i = 0; i< ranges.size();i++) { - delete mr_.buffer; + cout << dec << "(" << i << ") "; + printRange(&(ranges[i])); } - template - bool Find (needleType needle, const uint8_t increment ,vector &found, vector &newfound, comparator oper) + int start, end; + while(1) { - if(found.empty()) + string select; + cout << ">>"; + std::getline(cin, select); + if(select.empty()) { - //loop - for(uint64_t offset = 0; offset < (mr_.end - mr_.start) - sizeof(hayType); offset += increment) + // empty input, assume default. observe the length of the memory range vector + // these are hardcoded values, intended for my convenience only + if(p->getDescriptor()->getOS() == DFHack::memory_info::OS_WINDOWS) { - if( oper(_SF,(hayType *)(mr_.buffer + offset), needle) ) - newfound.push_back(mr_.start + offset); + start = min(11, (int)ranges.size()); + end = min(14, (int)ranges.size()); } - } - else - { - for( uint64_t i = 0; i < found.size(); i++) + else if(p->getDescriptor()->getOS() == DFHack::memory_info::OS_LINUX) + { + start = min(11, (int)ranges.size()); + end = min(14, (int)ranges.size()); + } + else { - if(mr_.isInRange(found[i])) - { - uint64_t corrected = found[i] - mr_.start; - if( oper(_SF,(hayType *)(mr_.buffer + corrected), needle) ) - newfound.push_back(found[i]); - } + start = 1; + end = 1; } + break; } - return true; - } - private: - friend class SegmentedFinder; - SegmentedFinder * _SF; - DFHack::Context * _DF; - DFHack::t_memrange mr_; -}; - -class SegmentedFinder -{ - public: - SegmentedFinder(vector & ranges, DFHack::Context * DF) - { - _DF = DF; - for(int i = 0; i < ranges.size(); i++) + // I like the C variants here. much less object clutter + else if(sscanf(select.c_str(), "%d-%d", &start, &end) == 2) { - segments.push_back(new SegmentFinder(ranges[i], DF, this)); + start = min(start, (int)ranges.size()); + end = min(end, (int)ranges.size()); + break; } - } - ~SegmentedFinder() - { - for(int i = 0; i < segments.size(); i++) + else { - delete segments[i]; + continue; } + break; } - SegmentFinder * getSegmentForAddress (uint64_t addr) + end++; + cout << "selected ranges:" <mr_.isInRange(addr)) - { - return segments[i]; - } - } - return 0; + printRange(&(selected_ranges[i])); } - template - bool Find (const needleType needle, const uint8_t increment, vector &found, comparator oper) +} + +bool getNumber (string prompt, int & output, int def, bool pdef = true) +{ + cout << prompt; + if(pdef) + cout << " default=" << def << endl; + while (1) { - vector newfound; - for(int i = 0; i < segments.size(); i++) + string select; + cout << ">>"; + std::getline(cin, select); + if(select.empty()) { - segments[i]->Find(needle, increment, found, newfound, oper); + output = def; + break; } - found.clear(); - found = newfound; - return !(found.empty()); - } - template - T * Translate(uint64_t address) - { - for(int i = 0; i < segments.size(); i++) + else if( sscanf(select.c_str(), "%d", &output) == 1 ) { - if(segments[i]->mr_.isInRange(address)) - { - return (T *) (segments[i]->mr_.buffer + address - segments[i]->mr_.start); - } + break; } - return 0; - } - template - T Read(uint64_t address) - { - return *Translate(address); - } - template - bool Read(uint64_t address, T& target) - { - T * test = Translate(address); - if(test) + else { - target = *test; - return true; + continue; } - return false; } - private: - DFHack::Context * _DF; - vector segments; -}; - -template -bool equalityP (SegmentedFinder* s, T *x, T y) -{ - return (*x) == y; + return true; } -struct vecTriplet -{ - uint32_t start; - uint32_t finish; - uint32_t alloc_finish; -}; - -template -bool vectorLength (SegmentedFinder* s, vecTriplet *x, Needle &y) +bool getString (string prompt, string & output) { - if(x->start <= x->finish && x->finish <= x->alloc_finish) - if((x->finish - x->start) == y) - return true; - return false; -} - -bool vectorString (SegmentedFinder* s, vecTriplet *x, const char *y) -{ - if(x->start <= x->finish && x->finish <= x->alloc_finish) + cout << prompt; + cout << ">>"; + string select; + std::getline(cin, select); + if(select.empty()) { - // deref ptr start, get ptr to firt object - uint32_t object_ptr; - if(!s->Read(x->start,object_ptr)) - return false; - // deref ptr to first object, get ptr to string - uint32_t string_ptr; - if(!s->Read(object_ptr,string_ptr)) - return false; - // get string location in our local cache - char * str = s->Translate(string_ptr); - if(!str) - return false; - if(strcmp(y, str) == 0) - return true; + return false; } - return false; -} - -bool vectorAll (SegmentedFinder* s, vecTriplet *x, int ) -{ - if(x->start <= x->finish && x->finish <= x->alloc_finish) + else { - if(s->getSegmentForAddress(x->start) == s->getSegmentForAddress(x->finish) - && s->getSegmentForAddress(x->finish) == s->getSegmentForAddress(x->alloc_finish)) - return true; + output = select; + return true; } - return false; } -bool findString (SegmentedFinder* s, uint32_t *addr, const char * compare ) +template +bool Incremental ( vector &found, const char * what, T& output, + const char *singular = "address", const char *plural = "addresses" ) { - // read string pointer, translate to local scheme - char *str = s->Translate(*addr); - // verify - if(!str) + string select; + if(found.empty()) + { + cout << "search ready - insert " << what << ", 'p' for results" << endl; + } + else if( found.size() == 1) + { + cout << "Found an "<< singular <<"!" << endl; + cout << hex << "0x" << found[0] << endl; + } + else + { + cout << "Found " << dec << found.size() << " " << plural <<"." << endl; + } + incremental_more: + cout << ">>"; + std::getline(cin, select); + if(select == "p") + { + cout << "Found "<< plural <<":" << endl; + for(int i = 0; i < found.size();i++) + { + cout << hex << "0x" << found[i] << endl; + } + goto incremental_more; + } + else if(select.empty()) + { return false; - if(strcmp(str, compare) == 0) + } + else + { + stringstream ss (stringstream::in | stringstream::out); + ss << select; + ss >> output; + if(ss.fail()) + { + cout << "not a valid value for type: " << what << endl; + goto incremental_more; + } return true; - return false; + } } //TODO: lots of optimization -void searchLoop(DFHack::ContextManager & DFMgr, vector & ranges, int size, int alignment) +void searchLoop(DFHack::ContextManager & DFMgr, vector & ranges) { + // input / validation of variable size + int size; + do + { + getNumber("Select variable size (1,2,4 bytes)",size, 4); + } while (size != 1 && size != 2 && size != 4); + // input / validation of variable alignment (default is to use the same alignment as size) + int alignment; + do + { + getNumber("Select variable alignment (1,2,4 bytes)",alignment, size); + } while (alignment != 1 && alignment != 2 && alignment != 4); + uint32_t test1; vector found; found.reserve(100); - //bool initial = 1; - cout << "search ready - insert integers, 'p' for results" << endl; - string select; - while (1) + while(Incremental(found, "integer",test1)) { - cout << ">>"; - std::getline(cin, select); - if(select == "p") - { - cout << "Found addresses:" << endl; - for(int i = 0; i < found.size();i++) - { - cout << hex << "0x" << found[i] << endl; - } - } - else if(sscanf(select.c_str(),"%d", &test1) == 1) + DFMgr.Refresh(); + DFHack::Context * DF = DFMgr.getSingleContext(); + DF->Attach(); + SegmentedFinder sf(ranges,DF); + switch(size) { - // refresh the list of processes, get first suitable, attach - DFMgr.Refresh(); - DFHack::Context * DF = DFMgr.getSingleContext(); - DF->Attach(); - SegmentedFinder sf(ranges,DF); - switch(size) - { - case 1: - sf.Find(test1,alignment,found, equalityP); - break; - case 2: - sf.Find(test1,alignment,found, equalityP); - break; - case 4: - sf.Find(test1,alignment,found, equalityP); - break; - } - if( found.size() == 1) - { - cout << "Found an address!" << endl; - cout << hex << "0x" << found[0] << endl; - } - else - cout << "Found " << dec << found.size() << " addresses." << endl; - DF->Detach(); + case 1: + sf.Find(test1,alignment,found, equalityP); + break; + case 2: + sf.Find(test1,alignment,found, equalityP); + break; + case 4: + sf.Find(test1,alignment,found, equalityP); + break; } - else break; + DF->Detach(); } } -void searchLoopVector(DFHack::ContextManager & DFMgr, vector & ranges, uint32_t element_size) +void searchLoopVector(DFHack::ContextManager & DFMgr, vector & ranges ) { - vecTriplet load; + int element_size; + do + { + getNumber("Select searched vector item size in bytes",element_size, 4); + } while (element_size < 1); + uint32_t length; vector found; found.reserve(100); - //bool initial = 1; - cout << "search ready - insert vector length" << endl; - string select; - while (1) + while (Incremental(found, "vector length",length,"vector","vectors")) { - cout << ">>"; - std::getline(cin, select); - if(select == "p") - { - cout << "Found vectors:" << endl; - for(int i = 0; i < found.size();i++) - { - cout << hex << "0x" << found[i] << endl; - } - } - else if(sscanf(select.c_str(),"%d", &length) == 1) - { - // refresh the list of processes, get first suitable, attach - DFMgr.Refresh(); - DFHack::Context * DF = DFMgr.getSingleContext(); - DF->Attach(); - - // clear the list of found addresses - found.clear(); - SegmentedFinder sf(ranges,DF); - sf.Find(0,4,found,vectorAll); - sf.Find(length*element_size,4,found,vectorLength); - if( found.size() == 1) - { - cout << "Found an address!" << endl; - cout << hex << "0x" << found[0] << endl; - } - else - cout << "Found " << dec << found.size() << " addresses." << endl; - // detach again - DF->Detach(); - } - else - { - break; - } + DFMgr.Refresh(); + DFHack::Context * DF = DFMgr.getSingleContext(); + DF->Attach(); + SegmentedFinder sf(ranges,DF); + sf.Find(0,4,found,vectorAll); + sf.Find(length * element_size,4,found,vectorLength); + DF->Detach(); } } void searchLoopStrObjVector(DFHack::ContextManager & DFMgr, vector & ranges) { vector found; - cout << "search ready - insert string" << endl; string select; - while (1) + while (Incremental(found, "raw name",select,"vector","vectors")) { - cout << ">>"; - std::getline(cin, select); - if(select == "p") - { - cout << "Found vectors:" << endl; - for(int i = 0; i < found.size();i++) - { - cout << hex << "0x" << found[i] << endl; - } - } - else if(!select.empty()) - { - // refresh the list of processes, get first suitable, attach - DFMgr.Refresh(); - DFHack::Context * DF = DFMgr.getSingleContext(); - DF->Attach(); - - // clear the list of found addresses - found.clear(); - SegmentedFinder sf(ranges,DF); - sf.Find(0,4,found, vectorAll); - sf.Find(select.c_str(),4,found, vectorString); - if( found.size() == 1) - { - cout << "Found an address!" << endl; - cout << hex << "0x" << found[0] << endl; - } - else - cout << "Found " << dec << found.size() << " addresses." << endl; - // detach again - DF->Detach(); - } - else - { - break; - } + // clear the list of found addresses -- this is a one-shot + found.clear(); + DFMgr.Refresh(); + DFHack::Context * DF = DFMgr.getSingleContext(); + DF->Attach(); + SegmentedFinder sf(ranges,DF); + sf.Find(0,4,found, vectorAll); + sf.Find(select.c_str(),4,found, vectorString); + DF->Detach(); } } void searchLoopStr(DFHack::ContextManager & DFMgr, vector & ranges) { vector found; - cout << "search ready - insert string" << endl; string select; - while (1) + while (Incremental(found,"string",select,"string","strings")) { - cout << ">>"; - std::getline(cin, select); - if(select == "p") - { - cout << "Found strings:" << endl; - for(int i = 0; i < found.size();i++) - { - cout << hex << "0x" << found[i] << endl; - } - } - else if(!select.empty()) - { - // refresh the list of processes, get first suitable, attach - DFMgr.Refresh(); - DFHack::Context * DF = DFMgr.getSingleContext(); - DF->Attach(); + DFMgr.Refresh(); + DFHack::Context * DF = DFMgr.getSingleContext(); + DF->Attach(); + SegmentedFinder sf(ranges,DF); + sf.Find< const char * ,uint32_t>(select.c_str(),1,found, findString); + DF->Detach(); + } +} - // clear the list of found addresses - found.clear(); - SegmentedFinder sf(ranges,DF); - sf.Find< const char * ,uint32_t>(select.c_str(),1,found, findString); - if( found.size() == 1) - { - cout << "Found a string!" << endl; - cout << hex << "0x" << found[0] << endl; - } - else - cout << "Found " << dec << found.size() << " strings." << endl; - // detach again - DF->Detach(); - } - else +void automatedLangtables(DFHack::Context * DF, vector & ranges) +{ + vector allVectors; + vector to_filter; + uint64_t kulet_vector; + uint64_t word_table_offset; + uint64_t DWARF_vector; + uint64_t DWARF_object; + SegmentedFinder sf(ranges, DF); + + // enumerate all vectors + sf.Find(0,4,allVectors, vectorAll); + + // find lang vector (neutral word table) + to_filter = allVectors; + sf.Find("ABBEY",4,to_filter, vectorString); + uint64_t lang_addr = to_filter[0]; + + // find dwarven language word table + to_filter = allVectors; + sf.Find("kulet",4,to_filter, vectorString); + kulet_vector = to_filter[0]; + + // find vector of languages + to_filter = allVectors; + sf.Find("DWARF",4,to_filter, vectorString); + + // verify + for(int i = 0; i < to_filter.size(); i++) + { + vecTriplet * vec = sf.Translate(to_filter[i]); + if(((vec->finish - vec->start) / 4) == 4) // verified { + DWARF_vector = to_filter[i]; + DWARF_object = sf.Read(vec->start); + // compute word table offset from dwarf word table and dwarf language object addresses + word_table_offset = kulet_vector - DWARF_object; break; } } + cout << "translation vector: " << hex << "0x" << DWARF_vector << endl; + cout << "lang vector: " << hex << "0x" << lang_addr << endl; + cout << "word table offset: " << hex << "0x" << word_table_offset << endl; } - -inline void printRange(DFHack::t_memrange * tpr) -{ - std::cout << std::hex << tpr->start << " - " << tpr->end << "|" << (tpr->read ? "r" : "-") << (tpr->write ? "w" : "-") << (tpr->execute ? "x" : "-") << "|" << tpr->name << std::endl; -} int main (void) { string select; @@ -426,205 +338,40 @@ int main (void) return 1; } DFHack::Process * p = DF->getProcess(); - vector ranges; vector selected_ranges; - p->getMemRanges(ranges); - cout << "Which range to search? (default is 1-4)" << endl; - for(int i = 0; i< ranges.size();i++) - { - cout << dec << "(" << i << ") "; - printRange(&(ranges[i])); - } + getRanges(p,selected_ranges); - try_again_ranges: - cout << ">>"; - std::getline(cin, select); - int start, end; - if(select.empty()) - { - // empty input, assume default. observe the length of the memory range vector - // these are hardcoded values, intended for my convenience only - if(p->getDescriptor()->getOS() == DFHack::memory_info::OS_WINDOWS) - { - start = min(11, (int)ranges.size()); - end = min(14, (int)ranges.size()); - } - else if(p->getDescriptor()->getOS() == DFHack::memory_info::OS_LINUX) - { - start = min(11, (int)ranges.size()); - end = min(14, (int)ranges.size()); - } - else - { - start = 1; - end = 1; - } - } - // I like the C variants here. much less object clutter - else if(sscanf(select.c_str(), "%d-%d", &start, &end) == 2) - { - start = min(start, (int)ranges.size()); - end = min(end, (int)ranges.size()); - } - else - { - goto try_again_ranges; // yes, this is a goto. bite me. - } - end++; - cout << "selected ranges:" <object>string, 4=string, 5=automated lang tables" << endl; - cout << ">>"; - std::getline(cin, select); + string prompt = + "Select search type: 1=number(default), 2=vector by length, 3=vector>object>string,\n" + " 4=string, 5=automated lang tables, 6=vector by address in its array,\n" + " 7=pointer vector by address of an object, 8=vector>first object>string\n"; int mode; - if(select.empty()) - { - mode = 1; - } - else if( sscanf(select.c_str(), "%d", &mode) == 1 ) + do { - if(mode != 1 && mode != 2 && mode != 3 && mode != 4 && mode != 5) - { - goto try_again_type; - } - } - else + getNumber(prompt,mode, 1, false); + } while (mode < 1 || mode > 8 ); + switch (mode) { - goto try_again_type; - } - - if(mode == 1) - { - // input / validation of variable size - try_again_size: - cout << "Select searched variable size (1,2,4 bytes, default is 4)" << endl; - cout << ">>"; - std::getline(cin, select); - int size; - if(select.empty()) - { - size = 4; - } - else if( sscanf(select.c_str(), "%d", &size) == 1 ) - { - if(/*size != 8 &&*/ size != 4 && size != 2 && size != 1) - { - goto try_again_size; - } - } - else - { - goto try_again_size; - } - - // input / validation of variable alignment (default is to use the same alignment as size) - try_again_align: - cout << "Variable alignment (1,2,4 bytes, default is " << size << ")" << endl; - cout << ">>"; - std::getline(cin, select); - int alignment = size; - if(select.empty()) - { - alignment = size; - } - else if( sscanf(select.c_str(), "%d", &alignment) == 1 ) - { - if(/*alignment != 8 &&*/ alignment != 4 && alignment != 2 && alignment != 1) - { - goto try_again_align; - } - } - else - { - goto try_again_align; - } - // we detach, searchLoop looks for the process again. - DF->Detach(); - searchLoop(DFMgr, selected_ranges, size, alignment); - } - else if(mode == 2)// vector - { - // input / validation of variable size - try_again_vsize: - cout << "Select searched vector item size (in bytes, default is 4)" << endl; - cout << ">>"; - std::getline(cin, select); - uint32_t size; - if(select.empty()) - { - size = 4; - } - else if( sscanf(select.c_str(), "%d", &size) == 1 ) - { - if(size == 0) - { - goto try_again_vsize; - } - } - else - { - goto try_again_vsize; - } - // we detach, searchLoop looks for the process again. - DF->Detach(); - searchLoopVector(DFMgr, selected_ranges,size); - } - else if(mode == 3)// vector>object>string - { - searchLoopStrObjVector(DFMgr, selected_ranges); - } - else if(mode == 4)// string - { - searchLoopStr(DFMgr, selected_ranges); - } - else if(mode == 5) // find lang tables and stuff - { - vector allVectors; - vector to_filter; - uint64_t kulet_vector; - uint64_t word_table_offset; - uint64_t DWARF_vector; - uint64_t DWARF_object; - SegmentedFinder sf(selected_ranges, DF); - - // enumerate all vectors - sf.Find(0,4,allVectors, vectorAll); - - // find lang vector (neutral word table) - to_filter = allVectors; - sf.Find("ABBEY",4,to_filter, vectorString); - uint64_t lang_addr = to_filter[0]; - - // find dwarven language word table - to_filter = allVectors; - sf.Find("kulet",4,to_filter, vectorString); - kulet_vector = to_filter[0]; - - // find vector of languages - to_filter = allVectors; - sf.Find("DWARF",4,to_filter, vectorString); - - // verify - for(int i = 0; i < to_filter.size(); i++) - { - vecTriplet * vec = sf.Translate(to_filter[i]); - if(((vec->finish - vec->start) / 4) == 4) // verified - { - DWARF_vector = to_filter[i]; - DWARF_object = sf.Read(vec->start); - // compute word table offset from dwarf word table and dwarf language object addresses - word_table_offset = kulet_vector - DWARF_object; - break; - } - } - cout << "translation vector: " << hex << "0x" << DWARF_vector << endl; - cout << "lang vector: " << hex << "0x" << lang_addr << endl; - cout << "word table offset: " << hex << "0x" << word_table_offset << endl; + case 1:// integers + searchLoop(DFMgr, selected_ranges); + break; + case 2:// vector by length and item size + searchLoopVector(DFMgr, selected_ranges); + break; + case 3:// vector>object>string + searchLoopStrObjVector(DFMgr, selected_ranges); + break; + case 4:// string + searchLoopStr(DFMgr, selected_ranges); + break; + case 5: + automatedLangtables(DF,selected_ranges); + break; + case 6: + case 7: + case 8: + default: + cout << "not implemented :(" << endl; } #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; From 56fe1c0ebff36fa383935841f1d2f526c0d37a8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 4 Jun 2010 02:51:09 +0200 Subject: [PATCH 017/122] Search stuff sync --- tools/playground/SegmentedFinder.h | 29 +++++- tools/playground/incrementalsearch.cpp | 132 ++++++++++++++++++++----- 2 files changed, 137 insertions(+), 24 deletions(-) diff --git a/tools/playground/SegmentedFinder.h b/tools/playground/SegmentedFinder.h index f16152997..dfe365490 100644 --- a/tools/playground/SegmentedFinder.h +++ b/tools/playground/SegmentedFinder.h @@ -151,7 +151,7 @@ bool vectorString (SegmentedFinder* s, vecTriplet *x, const char *y) { uint32_t object_ptr; uint32_t idx = x->start; - // iterato over vector of pointers + // iterate over vector of pointers for(uint32_t idx = x->start; idx < x->finish; idx += sizeof(uint32_t)) { // deref ptr idx, get ptr to object @@ -173,7 +173,31 @@ bool vectorString (SegmentedFinder* s, vecTriplet *x, const char *y) return false; } -// test if the address is within a vector's array +// find a vector of 32bit pointers, where the first object pointed to has a string 'y' as the first member +bool vectorStringFirst (SegmentedFinder* s, vecTriplet *x, const char *y) +{ + uint32_t object_ptr; + uint32_t idx = x->start; + // deref ptr idx, get ptr to object + if(!s->Read(idx,object_ptr)) + { + return false; + } + // deref ptr to first object, get ptr to string + uint32_t string_ptr; + if(!s->Read(object_ptr,string_ptr)) + return false; + // get string location in our local cache + char * str = s->Translate(string_ptr); + if(!str) + return false; + if(strcmp(y, str) == 0) + return true; + return false; +} + +// test if the address is between vector.start and vector.finish +// not very useful alone, but could be a good step to filter some things bool vectorAddrWithin (SegmentedFinder* s, vecTriplet *x, uint32_t address) { if(address < x->finish && address >= x->start) @@ -182,6 +206,7 @@ bool vectorAddrWithin (SegmentedFinder* s, vecTriplet *x, uint32_t address) } // test if an object address is within the vector of pointers +// bool vectorOfPtrWithin (SegmentedFinder* s, vecTriplet *x, uint32_t address) { uint32_t object_ptr; diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index 083597ba3..1207464e9 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -137,11 +137,11 @@ bool Incremental ( vector &found, const char * what, T& output, string select; if(found.empty()) { - cout << "search ready - insert " << what << ", 'p' for results" << endl; + cout << "search ready - insert " << what << ", 'p' for results, 'p #' to limit number of results" << endl; } else if( found.size() == 1) { - cout << "Found an "<< singular <<"!" << endl; + cout << "Found single "<< singular <<"!" << endl; cout << hex << "0x" << found[0] << endl; } else @@ -151,7 +151,17 @@ bool Incremental ( vector &found, const char * what, T& output, incremental_more: cout << ">>"; std::getline(cin, select); - if(select == "p") + size_t num = 0; + if( sscanf(select.c_str(),"p %d", &num) && num > 0) + { + cout << "Found "<< plural <<":" << endl; + for(int i = 0; i < min(found.size(), num);i++) + { + cout << hex << "0x" << found[i] << endl; + } + goto incremental_more; + } + else if(select == "p") { cout << "Found "<< plural <<":" << endl; for(int i = 0; i < found.size();i++) @@ -168,18 +178,21 @@ bool Incremental ( vector &found, const char * what, T& output, { stringstream ss (stringstream::in | stringstream::out); ss << select; - ss >> output; + ss >> hex >> output; if(ss.fail()) { - cout << "not a valid value for type: " << what << endl; - goto incremental_more; + ss >> dec >> output; + if(ss.fail()) + { + cout << "not a valid value for type: " << what << endl; + goto incremental_more; + } } return true; } } -//TODO: lots of optimization -void searchLoop(DFHack::ContextManager & DFMgr, vector & ranges) +void FindIntegers(DFHack::ContextManager & DFMgr, vector & ranges) { // input / validation of variable size int size; @@ -219,7 +232,7 @@ void searchLoop(DFHack::ContextManager & DFMgr, vector & ran } } -void searchLoopVector(DFHack::ContextManager & DFMgr, vector & ranges ) +void FindVectorByLength(DFHack::ContextManager & DFMgr, vector & ranges ) { int element_size; do @@ -242,7 +255,7 @@ void searchLoopVector(DFHack::ContextManager & DFMgr, vector & ranges) +void FindVectorByObjectRawname(DFHack::ContextManager & DFMgr, vector & ranges) { vector found; string select; @@ -260,7 +273,76 @@ void searchLoopStrObjVector(DFHack::ContextManager & DFMgr, vector & ranges) +void FindVectorByFirstObjectRawname(DFHack::ContextManager & DFMgr, vector & ranges) +{ + vector found; + string select; + while (Incremental(found, "raw name",select,"vector","vectors")) + { + // clear the list of found addresses -- this is a one-shot + found.clear(); + DFMgr.Refresh(); + DFHack::Context * DF = DFMgr.getSingleContext(); + DF->Attach(); + SegmentedFinder sf(ranges,DF); + sf.Find(0,4,found, vectorAll); + sf.Find(select.c_str(),4,found, vectorStringFirst); + DF->Detach(); + } +} + +struct VectorSizeFunctor : public binary_function +{ + VectorSizeFunctor(SegmentedFinder & sf):sf_(sf){} + bool operator()( uint64_t lhs, uint64_t rhs) + { + vecTriplet* left = sf_.Translate(lhs); + vecTriplet* right = sf_.Translate(rhs); + return ((left->finish - left->start) < (right->finish - right->start)); + } + SegmentedFinder & sf_; +}; + +void FindVectorByBounds(DFHack::ContextManager & DFMgr, vector & ranges) +{ + vector found; + uint32_t select; + while (Incremental(found, "address between vector.start and vector.end",select,"vector","vectors")) + { + // clear the list of found addresses -- this is a one-shot + found.clear(); + DFMgr.Refresh(); + DFHack::Context * DF = DFMgr.getSingleContext(); + DF->Attach(); + SegmentedFinder sf(ranges,DF); + sf.Find(0,4,found, vectorAll); + sf.Find(select,4,found, vectorAddrWithin); + // sort by size of vector + std::sort(found.begin(), found.end(), VectorSizeFunctor(sf)); + DF->Detach(); + } +} + +void FindPtrVectorsByObjectAddress(DFHack::ContextManager & DFMgr, vector & ranges) +{ + vector found; + uint32_t select; + while (Incremental(found, "object address",select,"vector","vectors")) + { + // clear the list of found addresses -- this is a one-shot + found.clear(); + DFMgr.Refresh(); + DFHack::Context * DF = DFMgr.getSingleContext(); + DF->Attach(); + SegmentedFinder sf(ranges,DF); + sf.Find(0,4,found, vectorAll); + sf.Find(select,4,found, vectorOfPtrWithin); + DF->Detach(); + } +} + + +void FindStrings(DFHack::ContextManager & DFMgr, vector & ranges) { vector found; string select; @@ -290,17 +372,17 @@ void automatedLangtables(DFHack::Context * DF, vector & rang // find lang vector (neutral word table) to_filter = allVectors; - sf.Find("ABBEY",4,to_filter, vectorString); + sf.Find("ABBEY",4,to_filter, vectorStringFirst); uint64_t lang_addr = to_filter[0]; // find dwarven language word table to_filter = allVectors; - sf.Find("kulet",4,to_filter, vectorString); + sf.Find("kulet",4,to_filter, vectorStringFirst); kulet_vector = to_filter[0]; // find vector of languages to_filter = allVectors; - sf.Find("DWARF",4,to_filter, vectorString); + sf.Find("DWARF",4,to_filter, vectorStringFirst); // verify for(int i = 0; i < to_filter.size(); i++) @@ -352,24 +434,30 @@ int main (void) } while (mode < 1 || mode > 8 ); switch (mode) { - case 1:// integers - searchLoop(DFMgr, selected_ranges); + case 1: + FindIntegers(DFMgr, selected_ranges); break; - case 2:// vector by length and item size - searchLoopVector(DFMgr, selected_ranges); + case 2: + FindVectorByLength(DFMgr, selected_ranges); break; - case 3:// vector>object>string - searchLoopStrObjVector(DFMgr, selected_ranges); + case 3: + FindVectorByObjectRawname(DFMgr, selected_ranges); break; - case 4:// string - searchLoopStr(DFMgr, selected_ranges); + case 4: + FindStrings(DFMgr, selected_ranges); break; case 5: automatedLangtables(DF,selected_ranges); break; case 6: + FindVectorByBounds(DFMgr,selected_ranges); + break; case 7: + FindPtrVectorsByObjectAddress(DFMgr,selected_ranges); + break; case 8: + FindVectorByFirstObjectRawname(DFMgr, selected_ranges); + break; default: cout << "not implemented :(" << endl; } From 115e9695300dbe899dafe0ab788db343317b2e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 4 Jun 2010 03:05:38 +0200 Subject: [PATCH 018/122] Build fixes, made precompiled SHM libs --- library/CMakeLists.txt | 4 +++- library/DFProcessEnumerator.cpp | 2 +- library/modules/WindowIO_C.cpp | 3 +++ precompiled/linux/libdfconnect.so | Bin 40483 -> 36012 bytes precompiled/windows/SDL.dll | Bin 34304 -> 38400 bytes 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 15abe7cce..b9f41fda2 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -27,9 +27,11 @@ include_directories (${CMAKE_SOURCE_DIR}/library/depends/argstream/) include_directories (${CMAKE_SOURCE_DIR}/library/private/) SET(PROJECT_HDRS +private/DFMemInfoManager.h +private/ContextShared.h +private/Internal.h include/dfhack/DFError.h include/dfhack/DFMemInfo.h -include/dfhack/DFMemInfoManager.h include/dfhack/DFProcessEnumerator.h include/dfhack/DFProcess.h include/dfhack/DFTileTypes.h diff --git a/library/DFProcessEnumerator.cpp b/library/DFProcessEnumerator.cpp index 839b59e44..94eb2d804 100644 --- a/library/DFProcessEnumerator.cpp +++ b/library/DFProcessEnumerator.cpp @@ -137,8 +137,8 @@ Process *ProcessEnumerator::Private::GetProcessObject(ProcessID ID) return p3; else delete p3; - return 0; #endif + return 0; } #ifdef LINUX_BUILD diff --git a/library/modules/WindowIO_C.cpp b/library/modules/WindowIO_C.cpp index b404736ec..31c6e4739 100644 --- a/library/modules/WindowIO_C.cpp +++ b/library/modules/WindowIO_C.cpp @@ -22,6 +22,9 @@ must not be misrepresented as being the original software. distribution. */ +#include +#include +#include using namespace std; #include "dfhack/DFIntegers.h" diff --git a/precompiled/linux/libdfconnect.so b/precompiled/linux/libdfconnect.so index 633f5c5e50b67b62d44d3586925e7e7e6895f444..4b3a2a846b2c47766648309b4bb9a0ba703feeec 100755 GIT binary patch delta 17673 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 diff --git a/precompiled/windows/SDL.dll b/precompiled/windows/SDL.dll index 4b9815255b1a08265c710bc77690a96e5ed3c474..e436f4e9e4fa76d7de83f3e4bbf1b03185a985dd 100644 GIT binary patch delta 21355 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 delta 17460 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 b3>*v+3>pkt3|Kor?%LcqrJix}1*TO1tHPmS From 6b7f3e18165a979347a170e79dca9f3b19f2d613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sat, 5 Jun 2010 00:02:02 +0200 Subject: [PATCH 019/122] Big namespace cleaning --- library/DFMemInfo.cpp | 49 +++++++++++ library/include/DFHack.h | 10 ++- library/include/DFHack_C.h | 2 +- library/include/dfhack/DFMemInfo.h | 55 +------------ library/include/dfhack/DFProcess.h | 38 ++++----- library/include/dfhack/modules/Buildings.h | 2 +- library/include/dfhack/modules/Materials.h | 95 ++++++++++------------ library/modules/Buildings_C.cpp | 50 +++++------- tools/examples/buildingsdump.cpp | 34 ++++---- tools/examples/construction_dump.cpp | 9 +- tools/examples/creaturedump.cpp | 2 + tools/examples/dfitemdump.cpp | 1 + tools/examples/spatterdump.cpp | 2 +- tools/examples/treedump.cpp | 10 +-- tools/examples/veinlook.cpp | 3 +- tools/supported/probe.cpp | 60 +++++++------- 16 files changed, 208 insertions(+), 214 deletions(-) diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index 8ac0a2c94..76934b5a8 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -29,6 +29,55 @@ distribution. using namespace DFHack; +/* +* Common data types +*/ +namespace DFHack +{ + struct t_type + { + t_type(uint32_t assign, uint32_t type, std::string classname) + :classname(classname),assign(assign),type(type){}; + std::string classname; + uint32_t assign; + uint32_t type; + }; + + struct t_class + { + t_class(const t_class &old) + { + classname = old.classname; + vtable = old.vtable; + assign = old.assign; + type_offset = old.type_offset; + for(uint32_t i = 0; i < old.subs.size();i++) + { + t_type * t = new t_type (*old.subs[i]); + subs.push_back(t); + } + } + t_class () + { + vtable = 0; + assign = 0; + type_offset = 0; + } + ~t_class() + { + for(uint32_t i = 0; i < subs.size();i++) + { + delete subs[i]; + } + subs.clear(); + } + std::string classname; + uint32_t vtable; + uint32_t assign;// index to typeclass array if multiclass. return value if not. + uint32_t type_offset; // offset of type data for multiclass + std::vector subs; + }; +} /* * Private data */ diff --git a/library/include/DFHack.h b/library/include/DFHack.h index 22a332522..865b12716 100644 --- a/library/include/DFHack.h +++ b/library/include/DFHack.h @@ -1,6 +1,7 @@ #ifndef DFHACK_API_H #define DFHACK_API_H +// DFHack core classes and types #include "dfhack/DFIntegers.h" #include "dfhack/DFGlobal.h" #include "dfhack/DFError.h" @@ -10,7 +11,7 @@ #include "dfhack/DFProcess.h" #include "dfhack/DFTypes.h" - +// DFHack modules #include "dfhack/modules/Buildings.h" #include "dfhack/modules/Materials.h" #include "dfhack/modules/Position.h" @@ -22,5 +23,10 @@ #include "dfhack/modules/Vegetation.h" #include "dfhack/modules/Maps.h" -#include "dfhack/DFMiscUtils.h" +#ifdef DFHACK_WANT_MISCUTILS + #include "dfhack/DFMiscUtils.h" +#endif +#ifdef DFHACK_WANT_TILETYPES + #include "dfhack/DFTileTypes.h" +#endif #endif \ No newline at end of file diff --git a/library/include/DFHack_C.h b/library/include/DFHack_C.h index f08c31131..6c5dd004f 100644 --- a/library/include/DFHack_C.h +++ b/library/include/DFHack_C.h @@ -35,7 +35,7 @@ distribution. #include "dfhack/DFExport.h" #include "dfhack/DFIntegers.h" -using namespace std; + using namespace DFHack; typedef void DFHackObject; diff --git a/library/include/dfhack/DFMemInfo.h b/library/include/dfhack/DFMemInfo.h index 50a4aa55c..941faf6f2 100644 --- a/library/include/dfhack/DFMemInfo.h +++ b/library/include/dfhack/DFMemInfo.h @@ -27,64 +27,13 @@ distribution. #include "DFPragma.h" #include "DFExport.h" -#include -#include -#include - namespace DFHack { /* * Stubs */ - class Process; - - /* - * Common data types - */ - struct t_type - { - t_type(uint32_t assign, uint32_t type, std::string classname) - :classname(classname),assign(assign),type(type){}; - std::string classname; - uint32_t assign; - uint32_t type; - }; - - struct t_class - { - t_class(const t_class &old) - { - classname = old.classname; - vtable = old.vtable; - assign = old.assign; - type_offset = old.type_offset; - for(uint32_t i = 0; i < old.subs.size();i++) - { - t_type * t = new t_type (*old.subs[i]); - subs.push_back(t); - } - } - t_class () - { - vtable = 0; - assign = 0; - type_offset = 0; - } - ~t_class() - { - for(uint32_t i = 0; i < subs.size();i++) - { - delete subs[i]; - } - subs.clear(); - } - std::string classname; - uint32_t vtable; - uint32_t assign;// index to typeclass array if multiclass. return value if not. - uint32_t type_offset; // offset of type data for multiclass - vector subs; - }; + struct t_class; class DFHACK_EXPORT memory_info { @@ -184,7 +133,7 @@ namespace DFHack /** * Get the internal classID->classname mapping (for speed). DO NOT MANIPULATE THE VECTOR! */ - const vector * getClassIDMapping(); + const std::vector * getClassIDMapping(); }; } #endif // MEMINFO_H_INCLUDED diff --git a/library/include/dfhack/DFProcess.h b/library/include/dfhack/DFProcess.h index d2f888492..25ac51997 100644 --- a/library/include/dfhack/DFProcess.h +++ b/library/include/dfhack/DFProcess.h @@ -136,13 +136,13 @@ namespace DFHack virtual void write(uint32_t address, uint32_t length, uint8_t* buffer) = 0; /// read an STL string - virtual const string readSTLString (uint32_t offset) = 0; + virtual const std::string readSTLString (uint32_t offset) = 0; /// read an STL string virtual size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity) = 0; /// write an STL string virtual void writeSTLString(const uint32_t address, const std::string writeString) = 0; /// get class name of an object with rtti/type info - virtual string readClassName(uint32_t vptr) = 0; + virtual std::string readClassName(uint32_t vptr) = 0; /// read a null-terminated C string virtual const std::string readCString (uint32_t offset) = 0; @@ -155,9 +155,9 @@ namespace DFHack virtual bool isIdentified() = 0; /// find the thread IDs of the process - virtual bool getThreadIDs(vector & threads ) = 0; + virtual bool getThreadIDs(std::vector & threads ) = 0; /// get virtual memory ranges of the process (what is mapped where) - virtual void getMemRanges( vector & ranges ) = 0; + virtual void getMemRanges(std::vector & ranges ) = 0; /// get the flattened Memory.xml entry of this process virtual memory_info *getDescriptor() = 0; @@ -182,7 +182,7 @@ namespace DFHack private: Private * const d; public: - NormalProcess(uint32_t pid, vector & known_versions); + NormalProcess(uint32_t pid, std::vector & known_versions); ~NormalProcess(); bool attach(); bool detach(); @@ -214,11 +214,11 @@ namespace DFHack void read( uint32_t address, uint32_t length, uint8_t* buffer); void write(uint32_t address, uint32_t length, uint8_t* buffer); - const string readSTLString (uint32_t offset); + const std::string readSTLString (uint32_t offset); size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity); void writeSTLString(const uint32_t address, const std::string writeString){}; // get class name of an object with rtti/type info - string readClassName(uint32_t vptr); + std::string readClassName(uint32_t vptr); const std::string readCString (uint32_t offset); @@ -226,8 +226,8 @@ namespace DFHack bool isAttached(); bool isIdentified(); - bool getThreadIDs(vector & threads ); - void getMemRanges( vector & ranges ); + bool getThreadIDs(std::vector & threads ); + void getMemRanges(std::vector & ranges ); memory_info *getDescriptor(); int getPID(); // get module index by name and version. bool 1 = error @@ -246,7 +246,7 @@ namespace DFHack Private * const d; public: - SHMProcess(uint32_t PID, vector & known_versions); + SHMProcess(uint32_t PID, std::vector & known_versions); ~SHMProcess(); // Set up stuff so we can read memory bool attach(); @@ -279,11 +279,11 @@ namespace DFHack void read( uint32_t address, uint32_t length, uint8_t* buffer); void write(uint32_t address, uint32_t length, uint8_t* buffer); - const string readSTLString (uint32_t offset); + const std::string readSTLString (uint32_t offset); size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity); void writeSTLString(const uint32_t address, const std::string writeString); // get class name of an object with rtti/type info - string readClassName(uint32_t vptr); + std::string readClassName(uint32_t vptr); const std::string readCString (uint32_t offset); @@ -291,8 +291,8 @@ namespace DFHack bool isAttached(); bool isIdentified(); - bool getThreadIDs(vector & threads ); - void getMemRanges( vector & ranges ); + bool getThreadIDs(std::vector & threads ); + void getMemRanges(std::vector & ranges ); memory_info *getDescriptor(); int getPID(); // get module index by name and version. bool 1 = error @@ -311,7 +311,7 @@ namespace DFHack Private * const d; public: - WineProcess(uint32_t pid, vector & known_versions); + WineProcess(uint32_t pid, std::vector & known_versions); ~WineProcess(); bool attach(); bool detach(); @@ -343,11 +343,11 @@ namespace DFHack void read( uint32_t address, uint32_t length, uint8_t* buffer); void write(uint32_t address, uint32_t length, uint8_t* buffer); - const string readSTLString (uint32_t offset); + const std::string readSTLString (uint32_t offset); size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity); void writeSTLString(const uint32_t address, const std::string writeString){}; // get class name of an object with rtti/type info - string readClassName(uint32_t vptr); + std::string readClassName(uint32_t vptr); const std::string readCString (uint32_t offset); @@ -355,8 +355,8 @@ namespace DFHack bool isAttached(); bool isIdentified(); - bool getThreadIDs(vector & threads ); - void getMemRanges( vector & ranges ); + bool getThreadIDs(std::vector & threads ); + void getMemRanges(std::vector & ranges ); memory_info *getDescriptor(); int getPID(); // get module index by name and version. bool 1 = error diff --git a/library/include/dfhack/modules/Buildings.h b/library/include/dfhack/modules/Buildings.h index a9dc04494..4f8332ac6 100644 --- a/library/include/dfhack/modules/Buildings.h +++ b/library/include/dfhack/modules/Buildings.h @@ -37,7 +37,7 @@ namespace DFHack bool Finish(); // read a vector of names - bool ReadCustomWorkshopTypes(map & btypes); + bool ReadCustomWorkshopTypes(std::map & btypes); // returns -1 on error, >= 0 for real value int32_t GetCustomWorkshopType(t_building & building); diff --git a/library/include/dfhack/modules/Materials.h b/library/include/dfhack/modules/Materials.h index af2e16941..4cec9cecc 100644 --- a/library/include/dfhack/modules/Materials.h +++ b/library/include/dfhack/modules/Materials.h @@ -84,81 +84,70 @@ namespace DFHack struct t_matglossOther { - char rawname[128]; + char rawname[128]; }; struct t_creatureextract { - char rawname[128]; + char rawname[128]; }; // this doesn't transfer well across the shm gap... struct t_creaturetype { char rawname[128]; - std::vector castes; - std::vector extract; - uint8_t tile_character; - struct - { - uint16_t fore; - uint16_t back; - uint16_t bright; - } tilecolor; + std::vector castes; + std::vector extract; + uint8_t tile_character; + struct + { + uint16_t fore; + uint16_t back; + uint16_t bright; + } tilecolor; }; // this structure describes what are things made of in the DF world struct t_material { - int16_t itemType; - int16_t subType; - int16_t subIndex; - int32_t index; - uint32_t flags; + int16_t itemType; + int16_t subType; + int16_t subIndex; + int32_t index; + uint32_t flags; }; class DFHACK_EXPORT Materials { - public: - Materials(DFHack::DFContextShared * _d); - ~Materials(); + public: + Materials(DFHack::DFContextShared * _d); + ~Materials(); - std::vector inorganic; - std::vector organic; - std::vector tree; - std::vector plant; - std::vector race; - std::vector raceEx; - std::vector color; - std::vector other; - std::vector alldesc; + std::vector inorganic; + std::vector organic; + std::vector tree; + std::vector plant; + std::vector race; + std::vector raceEx; + std::vector color; + std::vector other; + std::vector alldesc; - bool ReadInorganicMaterials (void); - bool ReadOrganicMaterials (void); - bool ReadWoodMaterials (void); - bool ReadPlantMaterials (void); - bool ReadCreatureTypes (void); - bool ReadCreatureTypesEx (void); - bool ReadDescriptorColors(void); - bool ReadOthers (void); + bool ReadInorganicMaterials (void); + bool ReadOrganicMaterials (void); + bool ReadWoodMaterials (void); + bool ReadPlantMaterials (void); + bool ReadCreatureTypes (void); + bool ReadCreatureTypesEx (void); + bool ReadDescriptorColors(void); + bool ReadOthers (void); - void ReadAllMaterials(void); + void ReadAllMaterials(void); - std::string getDescription(t_material & mat); - /* - bool ReadInorganicMaterials (std::vector & output); - bool ReadOrganicMaterials (std::vector & output); - bool ReadWoodMaterials (std::vector & output); - bool ReadPlantMaterials (std::vector & output); - - // TODO: maybe move to creatures? - bool ReadCreatureTypes (std::vector & output); - bool ReadCreatureTypesEx (vector & creatures); - bool ReadDescriptorColors(std::vector & output); - */ - private: - class Private; - Private* d; - }; + std::string getDescription(t_material & mat); + private: + class Private; + Private* d; + }; } #endif diff --git a/library/modules/Buildings_C.cpp b/library/modules/Buildings_C.cpp index 7eaaa48a6..d7b7d940e 100644 --- a/library/modules/Buildings_C.cpp +++ b/library/modules/Buildings_C.cpp @@ -23,7 +23,7 @@ distribution. */ #include "dfhack-c/modules/Buildings_C.h" - +using namespace std; #ifdef __cplusplus extern "C" { #endif @@ -70,33 +70,27 @@ int Buildings_GetCustomWorkshopType(DFHackObject* b_Ptr, t_building* building) int Buildings_ReadCustomWorkshopTypes(DFHackObject* b_Ptr, void* (*t_customWorkshop_buffer_create)(uint32_t)) { - if(b_Ptr != NULL) - { - int i; - t_customWorkshop* cw_Ptr; - map bTypes; - map::iterator bIter; - - bool result = ((DFHack::Buildings*)b_Ptr)->ReadCustomWorkshopTypes(bTypes); - - if(!result) - return 0; - - cw_Ptr = (t_customWorkshop*)((*t_customWorkshop_buffer_create)(bTypes.size())); - - for(i = 0, bIter = bTypes.begin(); bIter != bTypes.end(); bIter++, i++) - { - cw_Ptr[i].index = (*bIter).first; - - size_t length = (*bIter).second.copy(cw_Ptr[i].name, 256); - - cw_Ptr[i].name[length] = '\0'; - } - - return 1; - } - - return -1; + if(b_Ptr != NULL) + { + int i; + t_customWorkshop* cw_Ptr; + std::map bTypes; + map::iterator bIter; + + if(!((DFHack::Buildings*)b_Ptr)->ReadCustomWorkshopTypes(bTypes)) + return 0; + + cw_Ptr = (t_customWorkshop*)((*t_customWorkshop_buffer_create)(bTypes.size())); + for(i = 0, bIter = bTypes.begin(); bIter != bTypes.end(); bIter++, i++) + { + cw_Ptr[i].index = (*bIter).first; + size_t length = (*bIter).second.copy(cw_Ptr[i].name, 256); + cw_Ptr[i].name[length] = '\0'; + } + return 1; + } + + return -1; } #ifdef __cplusplus diff --git a/tools/examples/buildingsdump.cpp b/tools/examples/buildingsdump.cpp index 1f0be6fc7..bfb747685 100644 --- a/tools/examples/buildingsdump.cpp +++ b/tools/examples/buildingsdump.cpp @@ -5,8 +5,10 @@ #include #include #include -using namespace std; +#include +//using namespace std; +#define DFHACK_WANT_MISCUTILS #include int main (int argc,const char* argv[]) @@ -27,14 +29,14 @@ int main (int argc,const char* argv[]) } else if(argc == 3) { - string s = argv[2]; //blah. I don't care - istringstream ins; // Declare an input string stream. + std::string s = argv[2]; //blah. I don't care + std::istringstream ins; // Declare an input string stream. ins.str(s); // Specify string to read. ins >> lines; // Reads the integers from the string. mode = 1; } - map custom_workshop_types; + std::map custom_workshop_types; DFHack::ContextManager DFMgr ("Memory.xml"); DFHack::Context *DF; @@ -43,9 +45,9 @@ int main (int argc,const char* argv[]) DF = DFMgr.getSingleContext(); DF->Attach(); } - catch (exception& e) + catch (std::exception& e) { - cerr << e.what() << endl; + std::cerr << e.what() << std::endl; #ifndef LINUX_BUILD cin.ignore(); #endif @@ -62,17 +64,17 @@ int main (int argc,const char* argv[]) Bld->ReadCustomWorkshopTypes(custom_workshop_types); if(mode) { - cout << numBuildings << endl; - vector < uint32_t > addresses; + std::cout << numBuildings << std::endl; + std::vector < uint32_t > addresses; for(uint32_t i = 0; i < numBuildings; i++) { DFHack::t_building temp; Bld->Read(i, temp); if(temp.type != 0xFFFFFFFF) // check if type isn't invalid { - string typestr; + std::string typestr; mem->resolveClassIDToClassname(temp.type, typestr); - cout << typestr << endl; + std::cout << typestr << std::endl; if(typestr == argv[1]) { //cout << buildingtypes[temp.type] << " 0x" << hex << temp.origin << endl; @@ -83,7 +85,7 @@ int main (int argc,const char* argv[]) else { // couldn't translate type, print out the vtable - cout << "unknown vtable: " << temp.vtable << endl; + std::cout << "unknown vtable: " << temp.vtable << std::endl; } } interleave_hex(DF,addresses,lines / 4); @@ -105,7 +107,7 @@ int main (int argc,const char* argv[]) && (uint32_t)z == temp.z ) { - string typestr; + std::string typestr; mem->resolveClassIDToClassname(temp.type, typestr); printf("Address 0x%x, type %d (%s), %d/%d/%d\n",temp.origin, temp.type, typestr.c_str(), temp.x1,temp.y1,temp.z); printf("Material %d %d\n", temp.material.type, temp.material.index); @@ -120,12 +122,12 @@ int main (int argc,const char* argv[]) } else { - cout << numBuildings << endl; + std::cout << numBuildings << std::endl; for(uint32_t i = 0; i < numBuildings; i++) { DFHack::t_building temp; Bld->Read(i, temp); - string typestr; + std::string typestr; mem->resolveClassIDToClassname(temp.type, typestr); printf("Address 0x%x, type %d (%s), %d/%d/%d\n",temp.origin, temp.type, typestr.c_str(), temp.x1,temp.y1,temp.z); } @@ -135,12 +137,12 @@ int main (int argc,const char* argv[]) } else { - cerr << "buildings not supported for this DF version" << endl; + std::cerr << "buildings not supported for this DF version" << std::endl; } DF->Detach(); #ifndef LINUX_BUILD - cout << "Done. Press any key to continue" << endl; + std::cout << "Done. Press any key to continue" << std::endl; cin.ignore(); #endif return 0; diff --git a/tools/examples/construction_dump.cpp b/tools/examples/construction_dump.cpp index a48b4e6a9..26bbef35d 100644 --- a/tools/examples/construction_dump.cpp +++ b/tools/examples/construction_dump.cpp @@ -7,8 +7,9 @@ #include #include #include -using namespace std; +#include +#define DFHACK_WANT_MISCUTILS #include using namespace DFHack; @@ -21,9 +22,9 @@ int main (int numargs, const char ** args) DF = DFMgr.getSingleContext(); DF->Attach(); } - catch (exception& e) + catch (std::exception& e) { - cerr << e.what() << endl; + std::cerr << e.what() << std::endl; #ifndef LINUX_BUILD cin.ignore(); #endif @@ -51,7 +52,7 @@ int main (int numargs, const char ** args) printf("Construction %d/%d/%d @ 0x%x\n", con.x, con.y, con.z,con.origin); // inorganic stuff - we can recognize that printf("Material: form %d, type %d, index %d\n",con.form, con.mat_type, con.mat_idx); - string matstr = "unknown"; + std::string matstr = "unknown"; if(con.mat_type == 0) { if(con.mat_idx != 0xffffffff) diff --git a/tools/examples/creaturedump.cpp b/tools/examples/creaturedump.cpp index f8b63b51f..8c2667c20 100644 --- a/tools/examples/creaturedump.cpp +++ b/tools/examples/creaturedump.cpp @@ -4,8 +4,10 @@ #include #include #include +#include using namespace std; +#define DFHACK_WANT_MISCUTILS #include enum likeType diff --git a/tools/examples/dfitemdump.cpp b/tools/examples/dfitemdump.cpp index 0ed6413b2..cf1778326 100644 --- a/tools/examples/dfitemdump.cpp +++ b/tools/examples/dfitemdump.cpp @@ -11,6 +11,7 @@ using namespace std; #include +#include DFHack::Materials * Materials; diff --git a/tools/examples/spatterdump.cpp b/tools/examples/spatterdump.cpp index 3d3b92102..3a2ba82b2 100644 --- a/tools/examples/spatterdump.cpp +++ b/tools/examples/spatterdump.cpp @@ -8,7 +8,7 @@ #include #include using namespace std; - +#define DFHACK_WANT_MISCUTILS #include using namespace DFHack; diff --git a/tools/examples/treedump.cpp b/tools/examples/treedump.cpp index 7e54db674..71b386220 100644 --- a/tools/examples/treedump.cpp +++ b/tools/examples/treedump.cpp @@ -9,6 +9,7 @@ #include using namespace std; +#define DFHACK_WANT_MISCUTILS #include int main (int numargs, const char ** args) @@ -34,18 +35,17 @@ int main (int numargs, const char ** args) #endif return 1; } - + DFHack::Process* p = DF->getProcess(); DFHack::memory_info* mem = DF->getMemoryInfo(); DFHack::Position * pos = DF->getPosition(); DFHack::Vegetation * v = DF->getVegetation(); DFHack::Materials * mat = DF->getMaterials(); mat->ReadOrganicMaterials(); - + int32_t x,y,z; pos->getCursorCoords(x,y,z); - - + uint32_t numVegs = 0; v->Start(numVegs); if(x == -30000) @@ -89,7 +89,7 @@ int main (int numargs, const char ** args) } } v->Finish(); - + #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); diff --git a/tools/examples/veinlook.cpp b/tools/examples/veinlook.cpp index 63ad703bf..e0fc79004 100644 --- a/tools/examples/veinlook.cpp +++ b/tools/examples/veinlook.cpp @@ -15,8 +15,9 @@ using namespace std; #include #include +#define DFHACK_WANT_MISCUTILS +#define DFHACK_WANT_TILETYPES #include -#include using namespace DFHack; diff --git a/tools/supported/probe.cpp b/tools/supported/probe.cpp index 4353d48ba..832562dc5 100644 --- a/tools/supported/probe.cpp +++ b/tools/supported/probe.cpp @@ -7,10 +7,10 @@ #include #include #include -using namespace std; +#define DFHACK_WANT_MISCUTILS +#define DFHACK_WANT_TILETYPES #include -#include using namespace DFHack; int main (int numargs, const char ** args) @@ -22,9 +22,9 @@ int main (int numargs, const char ** args) { DF->Attach(); } - catch (exception& e) + catch (std::exception& e) { - cerr << e.what() << endl; + std::cerr << e.what() << std::endl; #ifndef LINUX_BUILD cin.ignore(); #endif @@ -68,59 +68,59 @@ int main (int numargs, const char ** args) int16_t tiletype = block.tiletypes[tileX][tileY]; naked_designation &des = block.designation[tileX][tileY].bits; uint32_t &desw = block.designation[tileX][tileY].whole; - print_bits(block.designation[tileX][tileY].whole,cout); - cout << endl; - print_bits(block.occupancy[tileX][tileY].whole,cout); - cout << endl; + print_bits(block.designation[tileX][tileY].whole,std::cout); + std::cout << endl; + print_bits(block.occupancy[tileX][tileY].whole,std::cout); + std::cout << endl; // tiletype - cout <<"tiletype: " << tiletype; + std::cout <<"tiletype: " << tiletype; if(tileTypeTable[tiletype].name) - cout << " = " << tileTypeTable[tiletype].name; - cout << endl; + std::cout << " = " << tileTypeTable[tiletype].name; + std::cout << std::endl; - cout <<"temperature1: " << tmpb1[tileX][tileY] << " U" << endl; - cout <<"temperature2: " << tmpb2[tileX][tileY] << " U" << endl; + std::cout <<"temperature1: " << tmpb1[tileX][tileY] << " U" << std::endl; + std::cout <<"temperature2: " << tmpb2[tileX][tileY] << " U" << std::endl; // biome, geolayer - cout << "biome: " << des.biome << endl; - cout << "geolayer: " << des.geolayer_index << endl; + std::cout << "biome: " << des.biome << std::endl; + std::cout << "geolayer: " << des.geolayer_index << std::endl; // liquids if(des.flow_size) { if(des.liquid_type == DFHack::liquid_magma) - cout <<"magma: "; - else cout <<"water: "; - cout << des.flow_size << endl; + std::cout <<"magma: "; + else std::cout <<"water: "; + std::cout << des.flow_size << std::endl; } if(des.flow_forbid) - cout << "flow forbid" << endl; + std::cout << "flow forbid" << std::endl; if(des.pile) - cout << "stockpile?" << endl; + std::cout << "stockpile?" << std::endl; if(des.rained) - cout << "rained?" << endl; + std::cout << "rained?" << std::endl; if(des.smooth) - cout << "smooth?" << endl; + std::cout << "smooth?" << std::endl; uint32_t designato = block.origin + designatus + (tileX * 16 + tileY) * sizeof(t_designation); printf("designation offset: 0x%x\n", designato); if(des.light) - cout << "Light "; + std::cout << "Light "; else - cout << " "; + std::cout << " "; if(des.skyview) - cout << "SkyView "; + std::cout << "SkyView "; else - cout << " "; + std::cout << " "; if(des.subterranean) - cout << "Underground "; + std::cout << "Underground "; else - cout << " "; - cout << endl; + std::cout << " "; + std::cout << std::endl; } } #ifndef LINUX_BUILD - cout << "Done. Press any key to continue" << endl; + std::cout << "Done. Press any key to continue" << std::endl; cin.ignore(); #endif return 0; From 1645df7088bbcea12173459cd5356418fa81e7ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 6 Jun 2010 00:56:09 +0200 Subject: [PATCH 020/122] Some offsets for 0.31.04, bugfixes --- library/DFProcess-linux-SHM.cpp | 4 +- library/DFProcess-linux-wine.cpp | 9 +- library/DFProcess-linux.cpp | 2 +- library/DFProcess-windows-SHM.cpp | 4 +- library/include/DFHack.h | 8 +- library/include/dfhack/DFMiscUtils.h | 6 +- library/modules/Translation.cpp | 2 +- library/modules/World.cpp | 14 +- output/Memory.xml | 268 +++++++++++++------------ tools/examples/processenum.cpp | 9 +- tools/playground/incrementalsearch.cpp | 202 ++++++++++++++++++- 11 files changed, 372 insertions(+), 156 deletions(-) diff --git a/library/DFProcess-linux-SHM.cpp b/library/DFProcess-linux-SHM.cpp index d4f90db93..9c8d9aab1 100644 --- a/library/DFProcess-linux-SHM.cpp +++ b/library/DFProcess-linux-SHM.cpp @@ -714,7 +714,7 @@ float SHMProcess::readFloat (const uint32_t offset) D_SHMHDR->address = offset; gcc_barrier d->SetAndWait(CORE_READ_DWORD); - return D_SHMHDR->value; + return reinterpret_cast (D_SHMHDR->value); } void SHMProcess::readFloat (const uint32_t offset, float &val) { @@ -723,7 +723,7 @@ void SHMProcess::readFloat (const uint32_t offset, float &val) D_SHMHDR->address = offset; gcc_barrier d->SetAndWait(CORE_READ_DWORD); - val = D_SHMHDR->value; + val = reinterpret_cast (D_SHMHDR->value); } /* diff --git a/library/DFProcess-linux-wine.cpp b/library/DFProcess-linux-wine.cpp index b9ef2339b..6f288a078 100644 --- a/library/DFProcess-linux-wine.cpp +++ b/library/DFProcess-linux-wine.cpp @@ -367,9 +367,11 @@ void WineProcess::read (const uint32_t offset, const uint32_t size, uint8_t *tar if(size == 0) return; ssize_t result; - result = pread(d->memFileHandle, target,size,offset); - if(result != size) + ssize_t total = 0; + ssize_t remaining = size; + while (total != size) { + result = pread(d->memFileHandle, target + total ,remaining,offset + total); if(result == -1) { cerr << "pread failed: can't read " << size << " bytes at addres " << offset << endl; @@ -379,7 +381,8 @@ void WineProcess::read (const uint32_t offset, const uint32_t size, uint8_t *tar } else { - read(offset + result, size - result, target + result); + total += result; + remaining -= result; } } } diff --git a/library/DFProcess-linux.cpp b/library/DFProcess-linux.cpp index 343985a3d..2402609e1 100644 --- a/library/DFProcess-linux.cpp +++ b/library/DFProcess-linux.cpp @@ -86,7 +86,7 @@ NormalProcess::NormalProcess(uint32_t pid, vector< memory_info* >& known_version target_name[target_result] = 0; // is this the regular linux DF? - if (strstr(target_name, "dwarfort.exe") != NULL) + if (strstr(target_name, "dwarfort.exe") != 0 || strstr(target_name,"Dwarf_Fortress") != 0) { // create linux process, add it to the vector d->identified = d->validate(target_name,pid,mem_name,known_versions ); diff --git a/library/DFProcess-windows-SHM.cpp b/library/DFProcess-windows-SHM.cpp index 9a8bd8d4f..f9a7cad26 100644 --- a/library/DFProcess-windows-SHM.cpp +++ b/library/DFProcess-windows-SHM.cpp @@ -756,7 +756,7 @@ float SHMProcess::readFloat (const uint32_t offset) D_SHMHDR->address = offset; full_barrier d->SetAndWait(CORE_READ_DWORD); - return (float) D_SHMHDR->value; + return reinterpret_cast (D_SHMHDR->value); } void SHMProcess::readFloat (const uint32_t offset, float &val) { @@ -765,7 +765,7 @@ void SHMProcess::readFloat (const uint32_t offset, float &val) D_SHMHDR->address = offset; full_barrier d->SetAndWait(CORE_READ_DWORD); - val = (float) D_SHMHDR->value; + val = reinterpret_cast (D_SHMHDR->value); } uint64_t SHMProcess::readQuad (const uint32_t offset) { diff --git a/library/include/DFHack.h b/library/include/DFHack.h index 865b12716..a5f40e896 100644 --- a/library/include/DFHack.h +++ b/library/include/DFHack.h @@ -23,10 +23,16 @@ #include "dfhack/modules/Vegetation.h" #include "dfhack/modules/Maps.h" +/* + * This is a header full of ugly, volatile things. + * Only for use of official DFHack tools! + */ #ifdef DFHACK_WANT_MISCUTILS #include "dfhack/DFMiscUtils.h" #endif + +// define this to get the static tiletype->properties mapping #ifdef DFHACK_WANT_TILETYPES #include "dfhack/DFTileTypes.h" #endif -#endif \ No newline at end of file +#endif diff --git a/library/include/dfhack/DFMiscUtils.h b/library/include/dfhack/DFMiscUtils.h index 14f192e6a..04676a769 100644 --- a/library/include/dfhack/DFMiscUtils.h +++ b/library/include/dfhack/DFMiscUtils.h @@ -8,17 +8,13 @@ #include #include #include + using namespace std; #include #include #include -/* - * This is a header full of ugly, volatile things. - * Only for use of official DFHack tools! - */ - void DumpObjStr0Vector (const char * name, DFHack::Process *p, uint32_t addr) { cout << "----==== " << name << " ====----" << endl; diff --git a/library/modules/Translation.cpp b/library/modules/Translation.cpp index 80412c690..ae0c8b7ed 100644 --- a/library/modules/Translation.cpp +++ b/library/modules/Translation.cpp @@ -72,6 +72,7 @@ bool Translation::Start() if(!d->Inited) return false; Process * p = d->d->p; + Finish(); DfVector genericVec (p, d->genericAddress); DfVector transVec (p, d->transAddress); DFDict & translations = d->dicts.translations; @@ -92,7 +93,6 @@ bool Translation::Start() for (uint32_t i = 0; i < transVec.size();i++) { uint32_t transPtr = transVec.at(i); - DfVector trans_names_vec (p, transPtr + d->word_table_offset); for (uint32_t j = 0;j < trans_names_vec.size();j++) { diff --git a/library/modules/World.cpp b/library/modules/World.cpp index 47f4d200d..92c8606d4 100644 --- a/library/modules/World.cpp +++ b/library/modules/World.cpp @@ -95,12 +95,22 @@ uint32_t World::ReadCurrentTick() return 0; } +// FIX'D according to this: +/* +World::ReadCurrentMonth and World::ReadCurrentDay +« Sent to: peterix on: June 04, 2010, 04:44:30 » +« You have forwarded or responded to this message. » +ReplyQuoteRemove +Shouldn't these be /28 and %28 instead of 24? There're 28 days in a DF month. +Using 28 and doing the calculation on the value stored at the memory location +specified by memory.xml gets me the current month/date. +*/ uint32_t World::ReadCurrentMonth() { - return this->ReadCurrentTick() / 1200 / 24; + return this->ReadCurrentTick() / 1200 / 28; } uint32_t World::ReadCurrentDay() { - return ((this->ReadCurrentTick() / 1200) % 24) + 1; + return ((this->ReadCurrentTick() / 1200) % 28) + 1; } diff --git a/output/Memory.xml b/output/Memory.xml index d5eae8cda..dbeb589b0 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1621,115 +1621,52 @@ map_data_1b60_offset 0x1B9c - - 1d759a11af258263ef5c139d6d9a3e15 + Basic things ============ - 0xC - 0x0 - 0x4 - - - -
0x92D00C0
0x0165B188 + 0xC VERIFIED + 0x0 VERIFIED + 0x4 VERIFIED - Position and window dimensions - ============================== -
0x8cd3b18
0xe32798 -
0x8cd3b1c
0xe60838 -
0x8cd3b20
0xe60814 -
0x8b17370
0xae82cc - -
0x9464d6c
0x17f5ab8 - GUI State - ========= -
0x92c971c
0x146e45f - - Map stuff - ========= -
0x9322d20
WORLD + 0x52C60 - 0x08 - 0x20 - 0x24 - 0x006A - 0x026C - 0x066c - 0x156c - 0x176c - 0x1D6C - 0x0D6c - - Map Features - ============ - WORLD + 0x5487C -
0x932493C
- 0x94 - 0x28 - 0x2C - WORLD + 0x548F4 -
0x93249B4
- 0x24 - 0x28 + MAP BLOCK OFFSETS + ================= + 0x08 VERIFIED + 0x20 VERIFIED + 0x24 VERIFIED + 0x006A VERIFIED + 0x026C VERIFIED + 0x066c VERIFIED + 0x156c VERIFIED + 0x176c VERIFIED + 0x1D6C VERIFIED + 0x0D6c VERIFIED + + MAP FEATURE OFFSETS + =================== + 0x94 VERIFIED + 0x28 VERIFIED + 0x2C VERIFIED + + 0x24 VERIFIED + 0x28 VERIFIED - * map size in blocks * -
0x9322d34
0x016ad738 -
0x9322d38
0x016ad73C -
0x9322d3C
0x016ad740 - - * map size in tiles * -
0x9322d40
0x016ad744 -
0x9322d44
0x016ad748 -
0x9322d48
0x016ad74C - - * region coords * - WORLD + 0x525C8 -
0x9322d4C
0x016ad750 - WORLD + 0x525CC -
0x9322d50
0x016ad754 - WORLD + 0x525D0 -
0x9322d54
0x016ad758 - - * World size * (WORDs) - WORLD + 0x542E0 -
0x93243A0
0x016AEDD4 - WORLD + 0x542E2 -
0x93243A2
0x016AEDD6 - WORLD + 0x54894 -
0x9324954
FIX 0x16AF52C - WORLD + 0x548B8 -
0x9324978
FIX 0x16AF574 - values for the region structure =============================== - 0x58 0x64 FIX - 0x54 0x60 FIX + 0x58 VERIFIED + 0x54 VERIFIED geoblock offsets ================ - 0x4 vector - 0x4 vector + 0x4 VERIFIED + 0x4 VERIFIED Name struct =========== - 0x0 - 0x4 - 0x8 - - Creatures - ========= -
0x092E3AA0
-
0x092CB608
-
0x092CB5FC
+ 0x0 VERIFIED + 0x4 VERIFIED + 0x8 VERIFIED + + Creature offsets + ================ 0x0 0x6c 0x3c * @@ -1794,6 +1731,102 @@ map_data_1b60_offset 0x1B9c 0x4 subtype ? 0x8 index of material (for example, 2 is for silver) 0x18 set only for shell / bone mood requirements ? + + Creature type offsets + ===================== + 0x138 + 0x1A14 + 0xE0 + 0xF6 + + + Color descriptors + ================= + 0x0 VERIFIED + 0x1C VERIFIED + 0x24 VERIFIED + 0x28 VERIFIED + 0x2C VERIFIED + + Language tables + =============== + 0x1C + + Constructions + ============= + 0x14 +
+ + + 1d759a11af258263ef5c139d6d9a3e15 + +
0x92D00C0
+ + Position and window dimensions + ============================== +
0x8cd3b18
+
0x8cd3b1c
+
0x8cd3b20
+
0x8b17370
+
0x9464d6c
+ + GUI State + ========= +
0x92c971c
+ + Map data + ========= +
0x9322d20
WORLD + 0x52C60 + + Map Features + ============ + WORLD + 0x5487C +
0x932493C
+ WORLD + 0x548F4 +
0x93249B4
+ + * map size in blocks * +
0x9322d34
+
0x9322d38
+
0x9322d3C
+ + * map size in tiles * +
0x9322d40
+
0x9322d44
+
0x9322d48
+ + * region coords * + WORLD + 0x525C8 +
0x9322d4C
+ WORLD + 0x525CC +
0x9322d50
+ WORLD + 0x525D0 +
0x9322d54
+ + * World size * (WORDs) + WORLD + 0x542E0 +
0x93243A0
+ WORLD + 0x542E2 +
0x93243A2
+ WORLD + 0x54894 +
0x9324954
+ WORLD + 0x548B8 +
0x9324978
+ + Creatures + ========= +
0x092E3AA0
+
0x092CB608
+
0x092CB5FC
Materials ========= @@ -1812,42 +1845,30 @@ map_data_1b60_offset 0x1B9c creature types actually used for creatures,
0x09324F14
- 0x138 - 0x1A14 - 0xE0 - 0xF6 + Color descriptors + ================= +
0x9329378
VERIFIED +
0x9329390
VERIFIED Translations ============ WORLD + 0x54E50
0x9324fd4
WORLD + 0x54E80
0x9324fec
- 0x1C Constructions ============= WORLD + 0x84
0x92D0144
0x165b290 - 0x14 + + Time + ==== +
0x92C9680
+
0x92C9688
- Time - ==== -
0x92C9688
-
0x92C9680
+
+ + fea3801a26538b1741f3cc9294139fca diff --git a/tools/examples/processenum.cpp b/tools/examples/processenum.cpp index 1910ca733..50b0df0a1 100644 --- a/tools/examples/processenum.cpp +++ b/tools/examples/processenum.cpp @@ -88,15 +88,16 @@ int main (void) } // next test ContextManager and BadContexts { - cout << "Testing ProcessEnumerator" << endl; + cout << "Testing ContextManager" << endl; ContextManager Cman("Memory.xml"); memory_info * mem; do { - // make the ProcessEnumerator update its list of Processes + // make the ContextManager update its list of Contexts // by passing the pointer to 'inval', we make it export expired - // processes instead of destroying them outright - // (processes expire when the OS kills them for whatever reason) + // contexts instead of destroying them outright + // (contexts expire when the OS kills their process for whatever + // reason) BadContexts inval; Cman.Refresh(&inval); int nCont = Cman.size(); diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index 1207464e9..764c1d956 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -26,6 +26,31 @@ inline void printRange(DFHack::t_memrange * tpr) std::cout << std::hex << tpr->start << " - " << tpr->end << "|" << (tpr->read ? "r" : "-") << (tpr->write ? "w" : "-") << (tpr->execute ? "x" : "-") << "|" << tpr->name << std::endl; } +string rdWinString( char * offset, SegmentedFinder & sf ) +{ + char * start_offset = offset + 4; + uint32_t length = *(uint32_t *)(offset + 20); + uint32_t capacity = *(uint32_t *)(offset + 24); + char * temp = new char[capacity+1]; + + // read data from inside the string structure + if(capacity < 16) + { + memcpy(temp, start_offset,capacity); + //read(start_offset, capacity, (uint8_t *)temp); + } + else // read data from what the offset + 4 dword points to + { + start_offset = sf.Translate(*(uint32_t*)start_offset); + memcpy(temp, start_offset,capacity); + } + + temp[length] = 0; + string ret = temp; + delete temp; + return ret; +} + bool getRanges(DFHack::Process * p, vector & selected_ranges) { vector ranges; @@ -79,10 +104,17 @@ bool getRanges(DFHack::Process * p, vector & selected_ranges } end++; cout << "selected ranges:" <::iterator it; + it = ranges.begin() + start; + while (it != ranges.begin() + end) { - printRange(&(selected_ranges[i])); + // check if readable + if((*it).read) + { + selected_ranges.push_back(*it); + printRange(&*it); + } + it++; } } @@ -357,31 +389,109 @@ void FindStrings(DFHack::ContextManager & DFMgr, vector & ra } } +void printFound(vector &found, const char * what) +{ + cout << what << ":" << endl; + for(int i = 0; i < found.size();i++) + { + cout << hex << "0x" << found[i] << endl; + } +} + +void printFoundStrVec(vector &found, const char * what, SegmentedFinder & s) +{ + cout << what << ":" << endl; + for(int i = 0; i < found.size();i++) + { + cout << hex << "0x" << found[i] << endl; + cout << "--------------------------" << endl; + vecTriplet * vt = s.Translate(found[i]); + if(vt) + { + int j = 0; + for(uint32_t idx = vt->start; idx < vt->finish; idx += sizeof(uint32_t)) + { + uint32_t object_ptr; + // deref ptr idx, get ptr to object + if(!s.Read(idx,object_ptr)) + { + cout << "BAD!" << endl; + break; + } + // deref ptr to first object, get ptr to string + uint32_t string_ptr; + if(!s.Read(object_ptr,string_ptr)) + { + cout << "BAD!" << endl; + break; + } + // get string location in our local cache + char * str = s.Translate(string_ptr); + if(!str) + { + cout << "BAD!" << endl; + break; + } + cout << dec << j << ": " << str << endl; + j++; + } + } + else + { + cout << "BAD!" << endl; + break; + } + cout << "--------------------------" << endl; + } +} + + void automatedLangtables(DFHack::Context * DF, vector & ranges) { vector allVectors; + vector filtVectors; vector to_filter; + + cout << "stealing memory..." << endl; + SegmentedFinder sf(ranges, DF); + cout << "looking for vectors..." << endl; + sf.Find(0,4,allVectors, vectorAll); + + // trim vectors. anything with > 10000 entries is not interesting + for(uint64_t i = 0; i < allVectors.size();i++) + { + vecTriplet* vtrip = sf.Translate(allVectors[i]); + if(vtrip) + { + uint64_t length = (vtrip->finish - vtrip->start) / 4; + if(length < 10000 ) + { + filtVectors.push_back(allVectors[i]); + } + } + } + + cout << "-------------------" << endl; + cout << "!!LANGUAGE TABLES!!" << endl; + cout << "-------------------" << endl; + uint64_t kulet_vector; uint64_t word_table_offset; uint64_t DWARF_vector; uint64_t DWARF_object; - SegmentedFinder sf(ranges, DF); - - // enumerate all vectors - sf.Find(0,4,allVectors, vectorAll); // find lang vector (neutral word table) - to_filter = allVectors; + to_filter = filtVectors; sf.Find("ABBEY",4,to_filter, vectorStringFirst); uint64_t lang_addr = to_filter[0]; // find dwarven language word table - to_filter = allVectors; + to_filter = filtVectors; sf.Find("kulet",4,to_filter, vectorStringFirst); kulet_vector = to_filter[0]; // find vector of languages - to_filter = allVectors; + to_filter = filtVectors; sf.Find("DWARF",4,to_filter, vectorStringFirst); // verify @@ -400,6 +510,76 @@ void automatedLangtables(DFHack::Context * DF, vector & rang cout << "translation vector: " << hex << "0x" << DWARF_vector << endl; cout << "lang vector: " << hex << "0x" << lang_addr << endl; cout << "word table offset: " << hex << "0x" << word_table_offset << endl; + + cout << "-------------" << endl; + cout << "!!MATERIALS!!" << endl; + cout << "-------------" << endl; + // inorganics vector + to_filter = filtVectors; + //sf.Find(257 * 4,4,to_filter,vectorLength); + sf.Find("IRON",4,to_filter, vectorStringFirst); + sf.Find("RAW_ADAMANTINE",4,to_filter, vectorString); + sf.Find("BLOODSTONE",4,to_filter, vectorString); + printFound(to_filter,"inorganics"); + + // organics vector + to_filter = filtVectors; + sf.Find(52 * 4,4,to_filter,vectorLength); + sf.Find("MUSHROOM_HELMET_PLUMP",4,to_filter, vectorStringFirst); + printFound(to_filter,"organics"); + + // tree vector + to_filter = filtVectors; + sf.Find(31 * 4,4,to_filter,vectorLength); + sf.Find("MANGROVE",4,to_filter, vectorStringFirst); + printFound(to_filter,"trees"); + + // plant vector + to_filter = filtVectors; + sf.Find(21 * 4,4,to_filter,vectorLength); + sf.Find("MUSHROOM_HELMET_PLUMP",4,to_filter, vectorStringFirst); + printFound(to_filter,"plants"); + + // color descriptors + //AMBER, 112 + to_filter = filtVectors; + sf.Find(112 * 4,4,to_filter,vectorLength); + sf.Find("AMBER",4,to_filter, vectorStringFirst); + printFound(to_filter,"color descriptors"); + if(!to_filter.empty()) + { + uint64_t vec = to_filter[0]; + vecTriplet *vtColors = sf.Translate(vec); + uint32_t colorObj = sf.Read(vtColors->start); + cout << "Amber color:" << hex << "0x" << colorObj << endl; + // TODO: find string 'amber', the floats + } + + // all descriptors + //AMBER, 338 + to_filter = filtVectors; + sf.Find(338 * 4,4,to_filter,vectorLength); + sf.Find("AMBER",4,to_filter, vectorStringFirst); + printFound(to_filter,"all descriptors"); + + // creature type + //ELEPHANT, ?? (demons abound) + to_filter = filtVectors; + //sf.Find(338 * 4,4,to_filter,vectorLength); + sf.Find("ELEPHANT",4,to_filter, vectorString); + sf.Find("CAT",4,to_filter, vectorString); + sf.Find("DWARF",4,to_filter, vectorString); + sf.Find("WAMBLER_FLUFFY",4,to_filter, vectorString); + sf.Find("TOAD",4,to_filter, vectorString); + sf.Find("DEMON_1",4,to_filter, vectorString); + + vector toad_first = to_filter; + vector elephant_first = to_filter; + sf.Find("TOAD",4,toad_first, vectorStringFirst); + sf.Find("ELEPHANT",4,elephant_first, vectorStringFirst); + printFound(toad_first,"toad-first creature types"); + printFound(elephant_first,"elephant-first creature types"); + printFound(to_filter,"all creature types"); } int main (void) @@ -425,7 +605,7 @@ int main (void) string prompt = "Select search type: 1=number(default), 2=vector by length, 3=vector>object>string,\n" - " 4=string, 5=automated lang tables, 6=vector by address in its array,\n" + " 4=string, 5=automated offset search, 6=vector by address in its array,\n" " 7=pointer vector by address of an object, 8=vector>first object>string\n"; int mode; do From f1e06b0c226c4efb928475e5b3d8f236beaa2161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 6 Jun 2010 01:33:18 +0200 Subject: [PATCH 021/122] Fix number input in search tool --- output/Memory.xml | 19 +++++++++++++++++++ tools/playground/incrementalsearch.cpp | 21 ++++++++++----------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/output/Memory.xml b/output/Memory.xml index dbeb589b0..c9a2ec837 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1975,6 +1975,25 @@ map_data_1b60_offset 0x1B9c
fea3801a26538b1741f3cc9294139fca + +
0x92D00C0
BOGUS! + + Position and window dimensions + ============================== +
0x8b0d36c
BOGUS! +
0x8b0d370
BOGUS! +
0x8b0d374
BOGUS! +
0x8b0d36c
VERIFIED +
0x8b0d370
BOGUS! + GUI State + ========= +
0x92bf73c
VERIFIED + + Map data + ======== + WORLD + 0x52C60? +
0x9322d20
diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index 764c1d956..540d90194 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -208,19 +208,18 @@ bool Incremental ( vector &found, const char * what, T& output, } else { - stringstream ss (stringstream::in | stringstream::out); - ss << select; - ss >> hex >> output; - if(ss.fail()) + if( sscanf(select.c_str(),"0x%x", &output) == 1 ) { - ss >> dec >> output; - if(ss.fail()) - { - cout << "not a valid value for type: " << what << endl; - goto incremental_more; - } + cout << dec << output << endl; + return true; } - return true; + if( sscanf(select.c_str(),"%d", &output) == 1 ) + { + cout << dec << output << endl; + return true; + } + cout << "not a valid value for type: " << what << endl; + goto incremental_more; } } From 9f86f50369be6f00a67595221744dc9db255f258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 6 Jun 2010 02:07:01 +0200 Subject: [PATCH 022/122] 0.31.05 Maps support on Linux --- output/Memory.xml | 81 +++++++++++++++++++++++--- tools/playground/incrementalsearch.cpp | 4 +- 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/output/Memory.xml b/output/Memory.xml index c9a2ec837..cc3dd1461 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1845,14 +1845,12 @@ map_data_1b60_offset 0x1B9c creature types actually used for creatures,
0x09324F14
- Color descriptors =================
0x9329378
VERIFIED
0x9329390
VERIFIED + Translations ============ WORLD + 0x54E50 @@ -1977,15 +1975,15 @@ map_data_1b60_offset 0x1B9c fea3801a26538b1741f3cc9294139fca -
0x92D00C0
BOGUS! +
0x92C60E0
MOST PROBABLY BOGUS! Position and window dimensions ============================== -
0x8b0d36c
BOGUS! -
0x8b0d370
BOGUS! -
0x8b0d374
BOGUS! +
0x8cc9b38
VERIFIED +
0x8cc9b3c
VERIFIED +
0x8cc9b40
VERIFIED
0x8b0d36c
VERIFIED -
0x8b0d370
BOGUS! +
0x945ad8c
VERIFIED GUI State =========
0x92bf73c
VERIFIED @@ -1993,7 +1991,72 @@ map_data_1b60_offset 0x1B9c Map data ======== WORLD + 0x52C60? -
0x9322d20
+
0x9318D40
+ + Map Features + ============ + WORLD + 0x5487C? +
0x931A95C
+ WORLD + 0x548F4? +
0x931A9D4
+ + * map size in blocks * +
0x9318D54
VERIFIED +
0x9318D58
VERIFIED +
0x9318D5C
VERIFIED + + * map size in tiles * +
0x9318D60
VERIFIED +
0x9318D64
VERIFIED +
0x9318D68
VERIFIED + + * region coords * + WORLD + 0x525C8 +
0x9318D6C
VERIFIED + WORLD + 0x525CC +
0x9318D70
VERIFIED + WORLD + 0x525D0 +
0x9318D74
VERIFIED (old = 0x9322d54) + + * World size * (WORDs) + WORLD + 0x542E0 +
0x931A3C0
old = 0x93243A0 + WORLD + 0x542E2 +
0x931A3C2
old = 0x93243A2 + WORLD + 0x54894 +
0x931A974
old = 0x9324954 + WORLD + 0x548B8 +
0x931A998
old = 0x9324978 + + Materials + ========= + soil, stone, metal + inorganics vector +
0x931ae88
+ + wood and plant matter +
0x931ae94
+ + plant matter +
0x931aea0
+ + just wood +
0x931aeb8
+ + creature types actually used for creatures, +
0x931af34
+ + Color descriptors + ================= +
0x931f398
VERIFIED +
0x931f3b0
VERIFIED + + Translations + ============ + WORLD + 0x54E50 +
0x931aff4
+ WORLD + 0x54E80 +
0x931b00c
diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index 540d90194..1c03398d8 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -210,12 +210,12 @@ bool Incremental ( vector &found, const char * what, T& output, { if( sscanf(select.c_str(),"0x%x", &output) == 1 ) { - cout << dec << output << endl; + //cout << dec << output << endl; return true; } if( sscanf(select.c_str(),"%d", &output) == 1 ) { - cout << dec << output << endl; + //cout << dec << output << endl; return true; } cout << "not a valid value for type: " << what << endl; From 67bddfdad4b1c298c1e92552858d763ee105fe6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 6 Jun 2010 04:36:39 +0200 Subject: [PATCH 023/122] 0.31.05 Windows support --- output/Memory.xml | 87 +++++++++++++++++++++----- tools/playground/incrementalsearch.cpp | 25 +++++++- 2 files changed, 95 insertions(+), 17 deletions(-) diff --git a/output/Memory.xml b/output/Memory.xml index cc3dd1461..791c753a7 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1597,6 +1597,65 @@ map_data_1b60_offset 0x1B9c 0x0 Why do i have to redefine this ??? + + 394ff63fc00fedd5df0b36e4beb589bc + 0x4c091569 +
0x1678704
CHMOD +
0x014abee4
CHMOD +
0x1471FB0
BOGUS! + + + + + +
0xE80780
LOOKS O.K. +
0xEB2878
LOOKS O.K. + +
0x180b10c
LOOKS O.K. +
0xe6c0dc
VERIFIED +
0xe9a1b0
VERIFIED +
0xe9a18c
VERIFIED +
0xaf12cc
VERIFIED + + 0x0 Why do i have to redefine this ??? + ... what? +
.-"""-. ' \ @@ -1734,7 +1793,7 @@ map_data_1b60_offset 0x1B9c Creature type offsets ===================== - 0x138 + 0x60 VERIFIED 0x1A14 0xE0 0xF6 @@ -1758,7 +1817,7 @@ map_data_1b60_offset 0x1B9c Language tables =============== - 0x1C + 0x1C VERIFIED Constructions ============= @@ -1991,14 +2050,14 @@ map_data_1b60_offset 0x1B9c Map data ======== WORLD + 0x52C60? -
0x9318D40
+
0x9318D40
VERIFIED Map Features ============ WORLD + 0x5487C? -
0x931A95C
+
0x931A95C
VERIFIED WORLD + 0x548F4? -
0x931A9D4
+
0x931A9D4
VERIFIED * map size in blocks *
0x9318D54
VERIFIED @@ -2020,31 +2079,31 @@ map_data_1b60_offset 0x1B9c * World size * (WORDs) WORLD + 0x542E0 -
0x931A3C0
old = 0x93243A0 +
0x931A3C0
VERIFIED WORLD + 0x542E2 -
0x931A3C2
old = 0x93243A2 +
0x931A3C2
VERIFIED WORLD + 0x54894 -
0x931A974
old = 0x9324954 +
0x931A974
VERIFIED WORLD + 0x548B8 -
0x931A998
old = 0x9324978 +
0x931A998
VERIFIED Materials ========= soil, stone, metal inorganics vector -
0x931ae88
+
0x931ae88
VERIFIED wood and plant matter -
0x931ae94
+
0x931ae94
VERIFIED plant matter -
0x931aea0
+
0x931aea0
VERIFIED just wood -
0x931aeb8
+
0x931aeb8
VERIFIED creature types actually used for creatures, -
0x931af34
+
0x931af34
VERIFIED Color descriptors ================= diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index 1c03398d8..8eab76fa8 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -218,6 +218,14 @@ bool Incremental ( vector &found, const char * what, T& output, //cout << dec << output << endl; return true; } + + stringstream ss (stringstream::in | stringstream::out); + ss << select; + ss >> output; + if(!ss.fail()) + { + return true; + } cout << "not a valid value for type: " << what << endl; goto incremental_more; } @@ -431,7 +439,7 @@ void printFoundStrVec(vector &found, const char * what, SegmentedFind cout << "BAD!" << endl; break; } - cout << dec << j << ": " << str << endl; + cout << dec << j << ":" << hex << "0x" << object_ptr << " : " << str << endl; j++; } } @@ -516,7 +524,8 @@ void automatedLangtables(DFHack::Context * DF, vector & rang // inorganics vector to_filter = filtVectors; //sf.Find(257 * 4,4,to_filter,vectorLength); - sf.Find("IRON",4,to_filter, vectorStringFirst); + sf.Find("IRON",4,to_filter, vectorString); + sf.Find("ONYX",4,to_filter, vectorString); sf.Find("RAW_ADAMANTINE",4,to_filter, vectorString); sf.Find("BLOODSTONE",4,to_filter, vectorString); printFound(to_filter,"inorganics"); @@ -576,7 +585,7 @@ void automatedLangtables(DFHack::Context * DF, vector & rang vector elephant_first = to_filter; sf.Find("TOAD",4,toad_first, vectorStringFirst); sf.Find("ELEPHANT",4,elephant_first, vectorStringFirst); - printFound(toad_first,"toad-first creature types"); + printFoundStrVec(toad_first,"toad-first creature types",sf); printFound(elephant_first,"elephant-first creature types"); printFound(to_filter,"all creature types"); } @@ -602,6 +611,9 @@ int main (void) vector selected_ranges; getRanges(p,selected_ranges); + DFHack::memory_info *minfo = DF->getMemoryInfo(); + DFHack::memory_info::OSType os = minfo->getOS(); + string prompt = "Select search type: 1=number(default), 2=vector by length, 3=vector>object>string,\n" " 4=string, 5=automated offset search, 6=vector by address in its array,\n" @@ -614,27 +626,34 @@ int main (void) switch (mode) { case 1: + DF->Detach(); FindIntegers(DFMgr, selected_ranges); break; case 2: + DF->Detach(); FindVectorByLength(DFMgr, selected_ranges); break; case 3: + DF->Detach(); FindVectorByObjectRawname(DFMgr, selected_ranges); break; case 4: + DF->Detach(); FindStrings(DFMgr, selected_ranges); break; case 5: automatedLangtables(DF,selected_ranges); break; case 6: + DF->Detach(); FindVectorByBounds(DFMgr,selected_ranges); break; case 7: + DF->Detach(); FindPtrVectorsByObjectAddress(DFMgr,selected_ranges); break; case 8: + DF->Detach(); FindVectorByFirstObjectRawname(DFMgr, selected_ranges); break; default: From 319e37b9b0f9904d3cf2cf1b97e7d38c8cb91051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 6 Jun 2010 16:00:01 +0200 Subject: [PATCH 024/122] Update README --- README | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README b/README index 56c5c4d7d..338ce1fe2 100644 --- a/README +++ b/README @@ -32,10 +32,12 @@ OSX is also not supported due to lack of developers with a Mac. Currently supported Dwarf Fortress versions: * Windows - 0.31.01 - 0.31.03 + 0.31.01 - 0.31.03 legacy + 0.31.04 - 0.31.05 SDL * Linux - wine together with the Windows versions + 0.31.04 - 0.31.05 native. There are missing offsets but Map tools should be OK. + All Windows versions through wine. Using the library as a developer -------------------------------- @@ -162,6 +164,8 @@ be useful and are cross-platform just like the library itself. - dfvdig : Designates a whole vein for digging. Point the cursor at a vein and run this thing :) + - dfflows : A tool for checking how many liquid tiles are actively checked + for flows. - Your tool here: Write one ;) From 9d143d8afb07f7d4fffa895829621b5ab97de791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 7 Jun 2010 01:54:40 +0200 Subject: [PATCH 025/122] Fix creature vector on windows --- output/Memory.xml | 2 +- tools/examples/construction_dump.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/output/Memory.xml b/output/Memory.xml index 791c753a7..39df9cbd0 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1600,7 +1600,7 @@ map_data_1b60_offset 0x1B9c 394ff63fc00fedd5df0b36e4beb589bc 0x4c091569 -
0x1678704
CHMOD +
0x014abee4
CHMOD
0x1471FB0
BOGUS!
0x014abee4
CHMOD
0x1471FB0
BOGUS! +
0x180b10c
LOOKS O.K. +
0xe6c0dc
VERIFIED +
0xe9a1b0
VERIFIED +
0xe9a18c
VERIFIED +
0xaf12cc
VERIFIED +
0xE80780
LOOKS O.K. +
0xEB2878
LOOKS O.K. -
0xE80780
LOOKS O.K. -
0xEB2878
LOOKS O.K. -
0x180b10c
LOOKS O.K. -
0xe6c0dc
VERIFIED -
0xe9a1b0
VERIFIED -
0xe9a18c
VERIFIED -
0xaf12cc
VERIFIED - 0x0 Why do i have to redefine this ??? ... what?
- + + c4b7e37dafa2716e31d29110968ac64e + 0x4c0f83d5 +
0xaf12d0
+[addresses] +translation_vector = 0x016c53dc +language_vector = 0x016c53ac +creature_vector = 0x0168071c +dwarf_race_index = 0x014abef4 +
+ .-"""-. ' \ |,. ,-. | _________________________ @@ -2117,6 +2126,9 @@ map_data_1b60_offset 0x1B9c WORLD + 0x54E80
0x931b00c
+ + 13a1c19e8f59b74e307e094e2a0f28c3 + diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index 8eab76fa8..3c3014dca 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -463,7 +463,7 @@ void automatedLangtables(DFHack::Context * DF, vector & rang SegmentedFinder sf(ranges, DF); cout << "looking for vectors..." << endl; sf.Find(0,4,allVectors, vectorAll); - +/* // trim vectors. anything with > 10000 entries is not interesting for(uint64_t i = 0; i < allVectors.size();i++) { @@ -477,7 +477,8 @@ void automatedLangtables(DFHack::Context * DF, vector & rang } } } - +*/ + filtVectors = allVectors; cout << "-------------------" << endl; cout << "!!LANGUAGE TABLES!!" << endl; cout << "-------------------" << endl; From 45031a3724df02ba19abf3fa41184af18519abc1 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Thu, 10 Jun 2010 16:53:25 +0100 Subject: [PATCH 028/122] Added levels done (unless issues) --- library/DFMemInfo.cpp | 30 ++++++++++++++++++++++++++++++ library/DFMemInfoManager.cpp | 10 +++++++++- library/include/dfhack/DFMemInfo.h | 10 +++++++++- library/include/dfhack/DFTypes.h | 8 ++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index 76934b5a8..ff748b738 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -27,6 +27,8 @@ distribution. #include "dfhack/DFError.h" #include "dfhack/DFProcess.h" +//Inital amount of space in levels vector (since we usually know the number, efficent!) +#define NUM_RESERVE_LVLS 20 using namespace DFHack; /* @@ -92,6 +94,7 @@ class memory_info::Private vector professions; vector jobs; vector skills; + vector levels; vector< vector > traits; map labors; @@ -120,6 +123,7 @@ memory_info::memory_info() d->base = 0; d->p = 0; d->classindex = 0; + d->levels.reserve(NUM_RESERVE_LVLS); } // copy constructor @@ -146,6 +150,7 @@ memory_info::memory_info(const memory_info &old) d->skills = old.d->skills; d->traits = old.d->traits; d->labors = old.d->labors; + d->levels = old.d->levels; } void memory_info::setParentProcess(Process * _p) { @@ -300,6 +305,22 @@ void memory_info::setSkill (const string & key, const string & value) d->skills[keyInt] = value; } +void memory_info::setLevel(const std::string &nLevel, + const std::string &nName, + const std::string &nMin_xp, + const std::string &nMax_xp) +{ + uint32_t keyInt = strtol(nLevel.c_str(), NULL, 10); + + if(d->skills.size() <= keyInt) + d->skills.resize(keyInt+1); + + d->levels[keyInt].level = keyInt; + d->levels[keyInt].name = nName; + d->levels[keyInt].min_xp = strtol(nMin_xp.c_str(), NULL, 10); + d->levels[keyInt].max_xp = strtol(nMax_xp.c_str(), NULL, 10); +} + void memory_info::setTrait(const string & key, const string & value, const string & zero, @@ -628,6 +649,15 @@ string memory_info::getSkill (const uint32_t key) const throw Error::MissingMemoryDefinition("skill", key); } +DFHack::t_level memory_info::getLevelInfo(const uint32_t level) const +{ + if(d->levels.size() > level) + { + return d->levels[level]; + } + throw Error::MissingMemoryDefinition("Level", level); +} + // FIXME: ugly hack that needs to die int absolute (int number) { diff --git a/library/DFMemInfoManager.cpp b/library/DFMemInfoManager.cpp index a2c0140ce..021e909b7 100644 --- a/library/DFMemInfoManager.cpp +++ b/library/DFMemInfoManager.cpp @@ -152,8 +152,12 @@ void MemInfoManager::ParseEntry (TiXmlElement* entry, memory_info* mem, map Value(); - const char *cstr_name = pMemEntry->Attribute("name"); + const char *cstr_name = pMemEntry->Attribute("name"); const char *cstr_value = pMemEntry->GetText(); + + if(!cstr_value) + cstr_value = pMemEntry->Attribute("id"); + // check for missing parts string type, name, value; type = cstr_type; @@ -203,6 +207,10 @@ void MemInfoManager::ParseEntry (TiXmlElement* entry, memory_info* mem, map setLabor(value,name); + } + else if (type == "Level") + { + mem->setLevel(value, name, pMemEntry->Attribute("min_xp"), pMemEntry->Attribute("max_xp")); } else { diff --git a/library/include/dfhack/DFMemInfo.h b/library/include/dfhack/DFMemInfo.h index 941faf6f2..a5aa5284c 100644 --- a/library/include/dfhack/DFMemInfo.h +++ b/library/include/dfhack/DFMemInfo.h @@ -27,6 +27,8 @@ distribution. #include "DFPragma.h" #include "DFExport.h" +#include "dfhack/DFTypes.h" + namespace DFHack { /* @@ -72,6 +74,8 @@ namespace DFHack std::string getTraitName(const uint32_t) const; std::string getLabor (const uint32_t); + DFHack::t_level getLevelInfo(const uint32_t level) const; + void setVersion(const char *); void setVersion(const std::string&); std::string getVersion(); @@ -98,8 +102,12 @@ namespace DFHack void setProfession(const std::string &, const std::string &); void setJob(const std::string &, const std::string &); void setSkill(const std::string &, const std::string &); - void setTrait(const std::string &,const std::string &,const std::string &,const std::string &,const std::string &,const std::string &,const std::string &,const std::string &); + void setTrait(const std::string &, const std::string &, const std::string &, + const std::string &, const std::string &, + const std::string &, const std::string &, const std::string &); void setLabor(const std::string &, const std::string &); + void setLevel(const std::string &nLevel, const std::string &nName, + const std::string &nMin_xp, const std::string &nMax_xp); void RebaseVTable(const int32_t offset); void setParentProcess(Process * _p); diff --git a/library/include/dfhack/DFTypes.h b/library/include/dfhack/DFTypes.h index 95ab11ccd..bcf15432b 100644 --- a/library/include/dfhack/DFTypes.h +++ b/library/include/dfhack/DFTypes.h @@ -211,5 +211,13 @@ struct t_attrib uint32_t field_18; }; +struct t_level +{ + uint32_t level; + std::string name; + uint32_t min_xp; + uint32_t max_xp; +}; + }// namespace DFHack #endif // TYPES_H_INCLUDED From 69417e557d8df55c6d244954a948f75a1204fc6a Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Thu, 10 Jun 2010 17:20:41 +0100 Subject: [PATCH 029/122] Forgot to commit the updated memory.xml --- output/Memory.xml | 154 ++++++++-------------------------------------- 1 file changed, 26 insertions(+), 128 deletions(-) diff --git a/output/Memory.xml b/output/Memory.xml index 2dc0a3d3d..4b3934f1f 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -4,6 +4,7 @@ 0x0 + ==================================================================== T R A I T S ==================================================================== @@ -217,6 +218,7 @@ level_2="Often does the first thing that comes to mind" level_1="Acts impulsively" level_0="Always acts without considering alternatives or thinking through possibilities">29 + ==================================================================== P R O F E S S I O N S ==================================================================== @@ -322,6 +324,7 @@ 88 89 90 + ==================================================================== J O B S ==================================================================== @@ -792,137 +795,32 @@ size=212 62 63 64 - + ==================================================================== L E V E L S ==================================================================== - - 0 - Dabbling - 1 - 499 - - - 1 - Novice - 500 - 1099 - - - 2 - Adequate - 1100 - 1799 - - - 3 - Competent - 1800 - 2599 - - - 4 - Skilled - 2600 - 3499 - - - 5 - Proficient - 3500 - 4499 - - - 6 - Talented - 4500 - 5599 - - - 7 - Adept - 5600 - 6799 - - - 8 - Expert - 6800 - 8099 - - - 9 - Professional - 8100 - 9499 - - - 10 - Accomplished - 9500 - 10999 - - - 11 - Great - 11000 - 12599 - - - 12 - Master - 12600 - 14299 - - - 13 - High Master - 14300 - 16099 - - - 14 - Grand Master - 16100 - 17999 - - - 15 - Legendary - 18000 - 19999 - - - 16 - Legendary+1 - 20000 - 22099 - - - 17 - Legendary+2 - 22100 - 24299 - - - 18 - Legendary+3 - 24300 - 26599 - - - 19 - Legendary+4 - 26600 - 28999 - - - 20 - Legendary+5 - 29000 - 30000 - - + + + + + + + + + + + + + + + + + TODO verify level 16 and up's existence in DF2010 + + + + No max xp on last level but 30000 is nice and round + ==================================================================== L A B O R S ==================================================================== From 8987111cfe2c88d558c7278517d67003c3bdeb41 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Thu, 10 Jun 2010 17:31:09 +0100 Subject: [PATCH 030/122] Stupid mistake was stupid --- library/DFMemInfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index ff748b738..22969a56c 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -312,8 +312,8 @@ void memory_info::setLevel(const std::string &nLevel, { uint32_t keyInt = strtol(nLevel.c_str(), NULL, 10); - if(d->skills.size() <= keyInt) - d->skills.resize(keyInt+1); + if(d->levels.size() <= keyInt) + d->levels.resize(keyInt+1); d->levels[keyInt].level = keyInt; d->levels[keyInt].name = nName; From ec7b6edeb39ea902e59bc3fbc883421b3691cb0f Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Thu, 10 Jun 2010 07:57:27 +0800 Subject: [PATCH 031/122] Levels added to Memory.xml --- output/Memory.xml | 130 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/output/Memory.xml b/output/Memory.xml index 32fc15e16..dda91d4e5 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -792,6 +792,136 @@ size=212 62 63 64 + + ==================================================================== + L E V E L S + ==================================================================== + + 0 + Dabbling + 1 + 499 + + + 1 + Novice + 500 + 1099 + + + 2 + Adequate + 1100 + 1799 + + + 3 + Competent + 1800 + 2599 + + + 4 + Skilled + 2600 + 3499 + + + 5 + Proficient + 3500 + 4499 + + + 6 + Talented + 4500 + 5599 + + + 7 + Adept + 5600 + 6799 + + + 8 + Expert + 6800 + 8099 + + + 9 + Professional + 8100 + 9499 + + + 10 + Accomplished + 9500 + 10999 + + + 11 + Great + 11000 + 12599 + + + 12 + Master + 12600 + 14299 + + + 13 + High Master + 14300 + 16099 + + + 14 + Grand Master + 16100 + 17999 + + + 15 + Legendary + 18000 + 19999 + + + 16 + Legendary+1 + 20000 + 22099 + + + 17 + Legendary+2 + 22100 + 24299 + + + 18 + Legendary+3 + 24300 + 26599 + + + 19 + Legendary+4 + 26600 + 28999 + + + 20 + Legendary+5 + 29000 + 30000 + ==================================================================== L A B O R S From a89fd106e22d15caf5d9c015261da2df0ddd62f8 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Thu, 10 Jun 2010 23:53:25 +0800 Subject: [PATCH 032/122] Added levels done (unless issues) --- library/DFMemInfo.cpp | 30 ++++++++++++++++++++++++++++++ library/DFMemInfoManager.cpp | 10 +++++++++- library/include/dfhack/DFMemInfo.h | 10 +++++++++- library/include/dfhack/DFTypes.h | 8 ++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index 76934b5a8..ff748b738 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -27,6 +27,8 @@ distribution. #include "dfhack/DFError.h" #include "dfhack/DFProcess.h" +//Inital amount of space in levels vector (since we usually know the number, efficent!) +#define NUM_RESERVE_LVLS 20 using namespace DFHack; /* @@ -92,6 +94,7 @@ class memory_info::Private vector professions; vector jobs; vector skills; + vector levels; vector< vector > traits; map labors; @@ -120,6 +123,7 @@ memory_info::memory_info() d->base = 0; d->p = 0; d->classindex = 0; + d->levels.reserve(NUM_RESERVE_LVLS); } // copy constructor @@ -146,6 +150,7 @@ memory_info::memory_info(const memory_info &old) d->skills = old.d->skills; d->traits = old.d->traits; d->labors = old.d->labors; + d->levels = old.d->levels; } void memory_info::setParentProcess(Process * _p) { @@ -300,6 +305,22 @@ void memory_info::setSkill (const string & key, const string & value) d->skills[keyInt] = value; } +void memory_info::setLevel(const std::string &nLevel, + const std::string &nName, + const std::string &nMin_xp, + const std::string &nMax_xp) +{ + uint32_t keyInt = strtol(nLevel.c_str(), NULL, 10); + + if(d->skills.size() <= keyInt) + d->skills.resize(keyInt+1); + + d->levels[keyInt].level = keyInt; + d->levels[keyInt].name = nName; + d->levels[keyInt].min_xp = strtol(nMin_xp.c_str(), NULL, 10); + d->levels[keyInt].max_xp = strtol(nMax_xp.c_str(), NULL, 10); +} + void memory_info::setTrait(const string & key, const string & value, const string & zero, @@ -628,6 +649,15 @@ string memory_info::getSkill (const uint32_t key) const throw Error::MissingMemoryDefinition("skill", key); } +DFHack::t_level memory_info::getLevelInfo(const uint32_t level) const +{ + if(d->levels.size() > level) + { + return d->levels[level]; + } + throw Error::MissingMemoryDefinition("Level", level); +} + // FIXME: ugly hack that needs to die int absolute (int number) { diff --git a/library/DFMemInfoManager.cpp b/library/DFMemInfoManager.cpp index a2c0140ce..021e909b7 100644 --- a/library/DFMemInfoManager.cpp +++ b/library/DFMemInfoManager.cpp @@ -152,8 +152,12 @@ void MemInfoManager::ParseEntry (TiXmlElement* entry, memory_info* mem, map Value(); - const char *cstr_name = pMemEntry->Attribute("name"); + const char *cstr_name = pMemEntry->Attribute("name"); const char *cstr_value = pMemEntry->GetText(); + + if(!cstr_value) + cstr_value = pMemEntry->Attribute("id"); + // check for missing parts string type, name, value; type = cstr_type; @@ -203,6 +207,10 @@ void MemInfoManager::ParseEntry (TiXmlElement* entry, memory_info* mem, map setLabor(value,name); + } + else if (type == "Level") + { + mem->setLevel(value, name, pMemEntry->Attribute("min_xp"), pMemEntry->Attribute("max_xp")); } else { diff --git a/library/include/dfhack/DFMemInfo.h b/library/include/dfhack/DFMemInfo.h index 941faf6f2..a5aa5284c 100644 --- a/library/include/dfhack/DFMemInfo.h +++ b/library/include/dfhack/DFMemInfo.h @@ -27,6 +27,8 @@ distribution. #include "DFPragma.h" #include "DFExport.h" +#include "dfhack/DFTypes.h" + namespace DFHack { /* @@ -72,6 +74,8 @@ namespace DFHack std::string getTraitName(const uint32_t) const; std::string getLabor (const uint32_t); + DFHack::t_level getLevelInfo(const uint32_t level) const; + void setVersion(const char *); void setVersion(const std::string&); std::string getVersion(); @@ -98,8 +102,12 @@ namespace DFHack void setProfession(const std::string &, const std::string &); void setJob(const std::string &, const std::string &); void setSkill(const std::string &, const std::string &); - void setTrait(const std::string &,const std::string &,const std::string &,const std::string &,const std::string &,const std::string &,const std::string &,const std::string &); + void setTrait(const std::string &, const std::string &, const std::string &, + const std::string &, const std::string &, + const std::string &, const std::string &, const std::string &); void setLabor(const std::string &, const std::string &); + void setLevel(const std::string &nLevel, const std::string &nName, + const std::string &nMin_xp, const std::string &nMax_xp); void RebaseVTable(const int32_t offset); void setParentProcess(Process * _p); diff --git a/library/include/dfhack/DFTypes.h b/library/include/dfhack/DFTypes.h index 95ab11ccd..bcf15432b 100644 --- a/library/include/dfhack/DFTypes.h +++ b/library/include/dfhack/DFTypes.h @@ -211,5 +211,13 @@ struct t_attrib uint32_t field_18; }; +struct t_level +{ + uint32_t level; + std::string name; + uint32_t min_xp; + uint32_t max_xp; +}; + }// namespace DFHack #endif // TYPES_H_INCLUDED From fdd61f399e06058c375210a58c2b56eafed1abbb Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Fri, 11 Jun 2010 00:20:41 +0800 Subject: [PATCH 033/122] Forgot to commit the updated memory.xml --- output/Memory.xml | 154 ++++++++-------------------------------------- 1 file changed, 26 insertions(+), 128 deletions(-) diff --git a/output/Memory.xml b/output/Memory.xml index dda91d4e5..919e7dda9 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -4,6 +4,7 @@ 0x0 + ==================================================================== T R A I T S ==================================================================== @@ -217,6 +218,7 @@ level_2="Often does the first thing that comes to mind" level_1="Acts impulsively" level_0="Always acts without considering alternatives or thinking through possibilities">29 + ==================================================================== P R O F E S S I O N S ==================================================================== @@ -322,6 +324,7 @@ 88 89 90 + ==================================================================== J O B S ==================================================================== @@ -792,137 +795,32 @@ size=212 62 63 64 - + ==================================================================== L E V E L S ==================================================================== - - 0 - Dabbling - 1 - 499 - - - 1 - Novice - 500 - 1099 - - - 2 - Adequate - 1100 - 1799 - - - 3 - Competent - 1800 - 2599 - - - 4 - Skilled - 2600 - 3499 - - - 5 - Proficient - 3500 - 4499 - - - 6 - Talented - 4500 - 5599 - - - 7 - Adept - 5600 - 6799 - - - 8 - Expert - 6800 - 8099 - - - 9 - Professional - 8100 - 9499 - - - 10 - Accomplished - 9500 - 10999 - - - 11 - Great - 11000 - 12599 - - - 12 - Master - 12600 - 14299 - - - 13 - High Master - 14300 - 16099 - - - 14 - Grand Master - 16100 - 17999 - - - 15 - Legendary - 18000 - 19999 - - - 16 - Legendary+1 - 20000 - 22099 - - - 17 - Legendary+2 - 22100 - 24299 - - - 18 - Legendary+3 - 24300 - 26599 - - - 19 - Legendary+4 - 26600 - 28999 - - - 20 - Legendary+5 - 29000 - 30000 - - + + + + + + + + + + + + + + + + + TODO verify level 16 and up's existence in DF2010 + + + + No max xp on last level but 30000 is nice and round + ==================================================================== L A B O R S ==================================================================== From 38718f4865f36c3fc5cd0e92f310c8bf706352f7 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Fri, 11 Jun 2010 00:31:09 +0800 Subject: [PATCH 034/122] Stupid mistake was stupid --- library/DFMemInfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index ff748b738..22969a56c 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -312,8 +312,8 @@ void memory_info::setLevel(const std::string &nLevel, { uint32_t keyInt = strtol(nLevel.c_str(), NULL, 10); - if(d->skills.size() <= keyInt) - d->skills.resize(keyInt+1); + if(d->levels.size() <= keyInt) + d->levels.resize(keyInt+1); d->levels[keyInt].level = keyInt; d->levels[keyInt].name = nName; From afd22d05f41ea6e4c1c2b2ef35be2b07362ce2d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Thu, 10 Jun 2010 19:01:32 +0200 Subject: [PATCH 035/122] Fix linux 31.06 (at least a bit). README update. --- README | 4 ++-- output/Memory.xml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README b/README index 338ce1fe2..9e513ef31 100644 --- a/README +++ b/README @@ -33,10 +33,10 @@ OSX is also not supported due to lack of developers with a Mac. Currently supported Dwarf Fortress versions: * Windows 0.31.01 - 0.31.03 legacy - 0.31.04 - 0.31.05 SDL + 0.31.04 - 0.31.06 SDL * Linux - 0.31.04 - 0.31.05 native. There are missing offsets but Map tools should be OK. + 0.31.04 - 0.31.06 native. There are missing offsets but Map tools should be OK. All Windows versions through wine. Using the library as a developer diff --git a/output/Memory.xml b/output/Memory.xml index 32fc15e16..1d37e857c 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -2126,8 +2126,9 @@ dwarf_race_index = 0x014abef4 WORLD + 0x54E80
0x931b00c
- + 13a1c19e8f59b74e307e094e2a0f28c3 +
0x8b0b328
VERIFIED
From 0562ce980257fd48d89574a80b02641d17a71fe1 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Fri, 11 Jun 2010 00:00:21 +0100 Subject: [PATCH 036/122] Ok fixed level data to work from 0 to xp needed for next level. Due to xp starting from 0 for each level, getting the level based on xp had to be removed so now you can only get level data by level, which returns a struct containing level, name and xp need to next level. --- library/DFMemInfo.cpp | 6 ++--- library/DFMemInfoManager.cpp | 2 +- library/include/dfhack/DFMemInfo.h | 2 +- library/include/dfhack/DFTypes.h | 3 +-- output/Memory.xml | 42 +++++++++++++++--------------- 5 files changed, 26 insertions(+), 29 deletions(-) diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index 22969a56c..6b3fa0ffe 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -307,8 +307,7 @@ void memory_info::setSkill (const string & key, const string & value) void memory_info::setLevel(const std::string &nLevel, const std::string &nName, - const std::string &nMin_xp, - const std::string &nMax_xp) + const std::string &nXp) { uint32_t keyInt = strtol(nLevel.c_str(), NULL, 10); @@ -317,8 +316,7 @@ void memory_info::setLevel(const std::string &nLevel, d->levels[keyInt].level = keyInt; d->levels[keyInt].name = nName; - d->levels[keyInt].min_xp = strtol(nMin_xp.c_str(), NULL, 10); - d->levels[keyInt].max_xp = strtol(nMax_xp.c_str(), NULL, 10); + d->levels[keyInt].xpNxtLvl = strtol(nXp.c_str(), NULL, 10); } void memory_info::setTrait(const string & key, diff --git a/library/DFMemInfoManager.cpp b/library/DFMemInfoManager.cpp index 021e909b7..bc34e877a 100644 --- a/library/DFMemInfoManager.cpp +++ b/library/DFMemInfoManager.cpp @@ -210,7 +210,7 @@ void MemInfoManager::ParseEntry (TiXmlElement* entry, memory_info* mem, map setLevel(value, name, pMemEntry->Attribute("min_xp"), pMemEntry->Attribute("max_xp")); + mem->setLevel(value, name, pMemEntry->Attribute("xpNxtLvl")); } else { diff --git a/library/include/dfhack/DFMemInfo.h b/library/include/dfhack/DFMemInfo.h index a5aa5284c..d3370fc5b 100644 --- a/library/include/dfhack/DFMemInfo.h +++ b/library/include/dfhack/DFMemInfo.h @@ -107,7 +107,7 @@ namespace DFHack const std::string &, const std::string &, const std::string &); void setLabor(const std::string &, const std::string &); void setLevel(const std::string &nLevel, const std::string &nName, - const std::string &nMin_xp, const std::string &nMax_xp); + const std::string &nXp); void RebaseVTable(const int32_t offset); void setParentProcess(Process * _p); diff --git a/library/include/dfhack/DFTypes.h b/library/include/dfhack/DFTypes.h index bcf15432b..748bf9381 100644 --- a/library/include/dfhack/DFTypes.h +++ b/library/include/dfhack/DFTypes.h @@ -215,8 +215,7 @@ struct t_level { uint32_t level; std::string name; - uint32_t min_xp; - uint32_t max_xp; + uint32_t xpNxtLvl; }; }// namespace DFHack diff --git a/output/Memory.xml b/output/Memory.xml index c1611e926..ff63b1861 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -799,27 +799,27 @@ size=212 ==================================================================== L E V E L S ==================================================================== - - - - - - - - - - - - - - - - - TODO verify level 16 and up's existence in DF2010 - - - - No max xp on last level but 30000 is nice and round + + + + + + + + + + + + + + + + + TODO verify level 16 and up's existence in DF2010 + + + + -1 for no cap ==================================================================== L A B O R S From 3f099f8928bc37df012579b8da83453294625f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 11 Jun 2010 19:53:28 +0200 Subject: [PATCH 037/122] LARGE_INTEGER replacement --- library/DFProcessEnumerator.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/library/DFProcessEnumerator.cpp b/library/DFProcessEnumerator.cpp index 94eb2d804..ef5c35d75 100644 --- a/library/DFProcessEnumerator.cpp +++ b/library/DFProcessEnumerator.cpp @@ -203,23 +203,33 @@ bool EnableDebugPriv() return bRET; } +typedef union +{ + struct + { + uint32_t LowDword; + uint32_t HighDword; + }; + uint64_t Quad; +} TWO_DWORDS; + // Convert Windows FileTime structs to POSIX timestamp // from http://frenk.wordpress.com/2009/12/14/convert-filetime-to-unix-timestamp/ uint64_t FileTime_to_POSIX(FILETIME ft) { // takes the last modified date - LARGE_INTEGER date, adjust; - date.HighPart = ft.dwHighDateTime; - date.LowPart = ft.dwLowDateTime; + TWO_DWORDS date, adjust; + date.HighDword = ft.dwHighDateTime; + date.LowDword = ft.dwLowDateTime; // 100-nanoseconds = milliseconds * 10000 - adjust.QuadPart = 11644473600000 * 10000; + adjust.Quad = 11644473600000 * 10000; // removes the diff between 1970 and 1601 - date.QuadPart -= adjust.QuadPart; + date.Quad -= adjust.Quad; // converts back from 100-nanoseconds to seconds - return date.QuadPart / 10000000; + return date.Quad / 10000000; } void ProcessEnumerator::Private::EnumPIDs (vector &PIDs) From b732e63673de5f41f5c7597683d1aa1e1c79dcc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 11 Jun 2010 20:13:37 +0200 Subject: [PATCH 038/122] long long --- library/DFProcessEnumerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/DFProcessEnumerator.cpp b/library/DFProcessEnumerator.cpp index ef5c35d75..c060d2182 100644 --- a/library/DFProcessEnumerator.cpp +++ b/library/DFProcessEnumerator.cpp @@ -223,13 +223,13 @@ uint64_t FileTime_to_POSIX(FILETIME ft) date.LowDword = ft.dwLowDateTime; // 100-nanoseconds = milliseconds * 10000 - adjust.Quad = 11644473600000 * 10000; + adjust.Quad = 11644473600000LL * 10000LL; // removes the diff between 1970 and 1601 date.Quad -= adjust.Quad; // converts back from 100-nanoseconds to seconds - return date.Quad / 10000000; + return date.Quad / 10000000LL; } void ProcessEnumerator::Private::EnumPIDs (vector &PIDs) From 1b63a4e64d02e4f75b403e50b9ea84111dda93c7 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Tue, 15 Jun 2010 00:59:18 +0100 Subject: [PATCH 039/122] Happiness writing function added and tested. Seems ok so far --- library/include/dfhack/DFTypes.h | 2 +- library/include/dfhack/modules/Creatures.h | 743 +++++++++++---------- library/modules/Creatures.cpp | 33 +- 3 files changed, 397 insertions(+), 381 deletions(-) diff --git a/library/include/dfhack/DFTypes.h b/library/include/dfhack/DFTypes.h index 748bf9381..52c7826b7 100644 --- a/library/include/dfhack/DFTypes.h +++ b/library/include/dfhack/DFTypes.h @@ -203,7 +203,7 @@ struct t_settlement struct t_attrib { uint32_t level; - uint32_t field_4; + uint32_t field_4; // offset from beginning, purpose unknown uint32_t field_8; uint32_t field_C; uint32_t leveldiff; diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 7e0d48cb5..1f08b1aa4 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -6,377 +6,384 @@ #include "dfhack/DFExport.h" namespace DFHack { - /* - bits: - - 0 Can the dwarf move or are they waiting for their movement timer - 1 Dead (might also be set for incoming/leaving critters that are alive) - 2 Currently in mood - 3 Had a mood - 4 "marauder" -- wide class of invader/inside creature attackers - 5 Drowning - 6 Active merchant - 7 "forest" (used for units no longer linked to merchant/diplomacy, they just try to leave mostly) - 8 Left (left the map) - 9 Rider - 10 Incoming - 11 Diplomat - 12 Zombie - 13 Skeleton - 14 Can swap tiles during movement (prevents multiple swaps) - 15 On the ground (can be conscious) - 16 Projectile - 17 Active invader (for organized ones) - 18 Hidden in ambush - 19 Invader origin (could be inactive and fleeing) - 20 Will flee if invasion turns around - 21 Active marauder/invader moving inward - 22 Marauder resident/invader moving in all the way - 23 Check against flows next time you get a chance - 24 Ridden - 25 Caged - 26 Tame - 27 Chained - 28 Royal guard - 29 Fortress guard - 30 Suppress wield for beatings/etc - 31 Is an important historical figure - */ - - struct naked_creaturflags1 - { - unsigned int move_state : 1; // Can the dwarf move or are they waiting for their movement timer - unsigned int dead : 1; // might also be set for incoming/leaving critters that are alive - unsigned int has_mood : 1; // Currently in mood - unsigned int had_mood : 1; // Had a mood - - unsigned int marauder : 1; // wide class of invader/inside creature attackers - unsigned int drowning : 1; - unsigned int merchant : 1; // active merchant - unsigned int forest : 1; // used for units no longer linked to merchant/diplomacy, they just try to leave mostly - - unsigned int left : 1; // left the map - unsigned int rider : 1; - unsigned int incoming : 1; - unsigned int diplomat : 1; - - unsigned int zombie : 1; - unsigned int skeleton : 1; - unsigned int can_swap : 1; // Can swap tiles during movement (prevents multiple swaps) - unsigned int on_ground : 1; // can be conscious - - unsigned int projectile : 1; - unsigned int active_invader : 1; // for organized ones - unsigned int hidden_in_ambush : 1; - unsigned int invader_origin : 1; // could be inactive and fleeing - - unsigned int coward : 1; // Will flee if invasion turns around - unsigned int hidden_ambusher : 1; // maybe - unsigned int invades : 1; // Active marauder/invader moving inward - unsigned int check_flows : 1; // Check against flows next time you get a chance - - // 0100 0000 - 8000 0000 - unsigned int ridden : 1; - unsigned int caged : 1; - unsigned int tame : 1; - unsigned int chained : 1; - - unsigned int royal_guard : 1; - unsigned int fortress_guard : 1; - unsigned int suppress_wield : 1; // Suppress wield for beatings/etc - unsigned int important_historical_figure : 1; // Is an important historical figure - }; - - union t_creaturflags1 - { - uint32_t whole; - naked_creaturflags1 bits; - }; - - /* - bits: - - 0 Swimming - 1 Play combat for sparring - 2 Do not notify about level gains (for embark etc) - 3 Unused - - 4 Nerves calculated - 5 Body part info calculated - 6 Is important historical figure (slight variation) - 7 Has been killed by kill function (slightly different from dead, not necessarily violent death) - - 8 Must be forgotten by forget function (just cleanup) - 9 Must be deleted (cleanup) - 10 Recently forgotten (cleanup) - 11 Offered for trade - - 12 Trade resolved - 13 Has breaks - 14 Gutted - 15 Circulatory spray - - 16 Locked in for trading (it's a projectile on the other set of flags, might be what the flying was) - 17 Marked for slaughter - 18 Underworld creature - 19 Current resident - - 20 Marked for special cleanup as unused load from unit block on disk - 21 Insulation from clothing calculated - 22 Uninvited guest - 23 Visitor - - 24 Inventory order calculated - 25 Vision -- have good part - 26 Vision -- have damaged part - 27 Vision -- have missing part - - 28 Breathing -- have good part - 29 Breathing -- having a problem - 30 Roaming wilderness population source - 31 Roaming wilderness population source -- not a map feature - */ - struct naked_creaturflags2 - { - unsigned int swimming : 1; - unsigned int sparring : 1; - unsigned int no_notify : 1; // Do not notify about level gains (for embark etc) - unsigned int unused : 1; - - unsigned int calculated_nerves : 1; - unsigned int calculated_bodyparts : 1; - unsigned int important_historical_figure : 1; // slight variation - unsigned int killed : 1; // killed by kill() function - - unsigned int cleanup_1 : 1; // Must be forgotten by forget function (just cleanup) - unsigned int cleanup_2 : 1; // Must be deleted (cleanup) - unsigned int cleanup_3 : 1; // Recently forgotten (cleanup) - unsigned int for_trade : 1; // Offered for trade - - unsigned int trade_resolved : 1; - unsigned int has_breaks : 1; - unsigned int gutted : 1; - unsigned int circulatory_spray : 1; - - unsigned int locked_in_for_trading : 1; - unsigned int slaughter : 1; // marked for slaughter - unsigned int underworld : 1; // Underworld creature - unsigned int resident : 1; // Current resident - - unsigned int cleanup_4 : 1; // Marked for special cleanup as unused load from unit block on disk - unsigned int calculated_insulation : 1; // Insulation from clothing calculated - unsigned int visitor_uninvited : 1; // Uninvited guest - unsigned int visitor : 1; // visitor - - unsigned int calculated_inventory : 1; // Inventory order calculated - unsigned int vision_good : 1; // Vision -- have good part - unsigned int vision_damaged : 1; // Vision -- have damaged part - unsigned int vision_missing : 1; // Vision -- have missing part - - unsigned int breathing_good : 1; // Breathing -- have good part - unsigned int breathing_problem : 1; // Breathing -- having a problem - unsigned int roaming_wilderness_population_source : 1; - unsigned int roaming_wilderness_population_source_not_a_map_feature : 1; - }; - - union t_creaturflags2 - { - uint32_t whole; - naked_creaturflags2 bits; - }; - - /* - struct t_labor - { - string name; - uint8_t value; - t_labor() { - value =0; - } - t_labor(const t_labor & b){ - name=b.name; - value=b.value; - } - t_labor & operator=(const t_labor &b){ - name=b.name; - value=b.value; - return *this; - } - }; - struct t_skill - { - string name; - uint16_t id; - uint32_t experience; - uint16_t rating; - t_skill(){ - id=rating=0; - experience=0; - } - t_skill(const t_skill & b) - { - name=b.name; - id=b.id; - experience=b.experience; - rating=b.rating; - } - t_skill & operator=(const t_skill &b) - { - name=b.name; - id=b.id; - experience=b.experience; - rating=b.rating; - return *this; - } - }; - - struct t_trait - { - uint16_t value; - string displayTxt; - string name; - t_trait(){ - value=0; - } - t_trait(const t_trait &b) - { - name=b.name; - displayTxt=b.displayTxt; - value=b.value; - } - t_trait & operator=(const t_trait &b) - { - name=b.name; - displayTxt=b.displayTxt; - value=b.value; - return *this; - } - }; - */ - - struct t_skill - { - uint16_t id; - uint32_t experience; - uint16_t rating; - }; - struct t_job - { - bool active; - uint32_t jobId; - uint8_t jobType; + /* + bits: + + 0 Can the dwarf move or are they waiting for their movement timer + 1 Dead (might also be set for incoming/leaving critters that are alive) + 2 Currently in mood + 3 Had a mood + 4 "marauder" -- wide class of invader/inside creature attackers + 5 Drowning + 6 Active merchant + 7 "forest" (used for units no longer linked to merchant/diplomacy, they just try to leave mostly) + 8 Left (left the map) + 9 Rider + 10 Incoming + 11 Diplomat + 12 Zombie + 13 Skeleton + 14 Can swap tiles during movement (prevents multiple swaps) + 15 On the ground (can be conscious) + 16 Projectile + 17 Active invader (for organized ones) + 18 Hidden in ambush + 19 Invader origin (could be inactive and fleeing) + 20 Will flee if invasion turns around + 21 Active marauder/invader moving inward + 22 Marauder resident/invader moving in all the way + 23 Check against flows next time you get a chance + 24 Ridden + 25 Caged + 26 Tame + 27 Chained + 28 Royal guard + 29 Fortress guard + 30 Suppress wield for beatings/etc + 31 Is an important historical figure + */ + + struct naked_creaturflags1 + { + unsigned int move_state : 1; // Can the dwarf move or are they waiting for their movement timer + unsigned int dead : 1; // might also be set for incoming/leaving critters that are alive + unsigned int has_mood : 1; // Currently in mood + unsigned int had_mood : 1; // Had a mood + + unsigned int marauder : 1; // wide class of invader/inside creature attackers + unsigned int drowning : 1; + unsigned int merchant : 1; // active merchant + unsigned int forest : 1; // used for units no longer linked to merchant/diplomacy, they just try to leave mostly + + unsigned int left : 1; // left the map + unsigned int rider : 1; + unsigned int incoming : 1; + unsigned int diplomat : 1; + + unsigned int zombie : 1; + unsigned int skeleton : 1; + unsigned int can_swap : 1; // Can swap tiles during movement (prevents multiple swaps) + unsigned int on_ground : 1; // can be conscious + + unsigned int projectile : 1; + unsigned int active_invader : 1; // for organized ones + unsigned int hidden_in_ambush : 1; + unsigned int invader_origin : 1; // could be inactive and fleeing + + unsigned int coward : 1; // Will flee if invasion turns around + unsigned int hidden_ambusher : 1; // maybe + unsigned int invades : 1; // Active marauder/invader moving inward + unsigned int check_flows : 1; // Check against flows next time you get a chance + + // 0100 0000 - 8000 0000 + unsigned int ridden : 1; + unsigned int caged : 1; + unsigned int tame : 1; + unsigned int chained : 1; + + unsigned int royal_guard : 1; + unsigned int fortress_guard : 1; + unsigned int suppress_wield : 1; // Suppress wield for beatings/etc + unsigned int important_historical_figure : 1; // Is an important historical figure + }; + + union t_creaturflags1 + { + uint32_t whole; + naked_creaturflags1 bits; + }; + + /* + bits: + + 0 Swimming + 1 Play combat for sparring + 2 Do not notify about level gains (for embark etc) + 3 Unused + + 4 Nerves calculated + 5 Body part info calculated + 6 Is important historical figure (slight variation) + 7 Has been killed by kill function (slightly different from dead, not necessarily violent death) + + 8 Must be forgotten by forget function (just cleanup) + 9 Must be deleted (cleanup) + 10 Recently forgotten (cleanup) + 11 Offered for trade + + 12 Trade resolved + 13 Has breaks + 14 Gutted + 15 Circulatory spray + + 16 Locked in for trading (it's a projectile on the other set of flags, might be what the flying was) + 17 Marked for slaughter + 18 Underworld creature + 19 Current resident + + 20 Marked for special cleanup as unused load from unit block on disk + 21 Insulation from clothing calculated + 22 Uninvited guest + 23 Visitor + + 24 Inventory order calculated + 25 Vision -- have good part + 26 Vision -- have damaged part + 27 Vision -- have missing part + + 28 Breathing -- have good part + 29 Breathing -- having a problem + 30 Roaming wilderness population source + 31 Roaming wilderness population source -- not a map feature + */ + struct naked_creaturflags2 + { + unsigned int swimming : 1; + unsigned int sparring : 1; + unsigned int no_notify : 1; // Do not notify about level gains (for embark etc) + unsigned int unused : 1; + + unsigned int calculated_nerves : 1; + unsigned int calculated_bodyparts : 1; + unsigned int important_historical_figure : 1; // slight variation + unsigned int killed : 1; // killed by kill() function + + unsigned int cleanup_1 : 1; // Must be forgotten by forget function (just cleanup) + unsigned int cleanup_2 : 1; // Must be deleted (cleanup) + unsigned int cleanup_3 : 1; // Recently forgotten (cleanup) + unsigned int for_trade : 1; // Offered for trade + + unsigned int trade_resolved : 1; + unsigned int has_breaks : 1; + unsigned int gutted : 1; + unsigned int circulatory_spray : 1; + + unsigned int locked_in_for_trading : 1; + unsigned int slaughter : 1; // marked for slaughter + unsigned int underworld : 1; // Underworld creature + unsigned int resident : 1; // Current resident + + unsigned int cleanup_4 : 1; // Marked for special cleanup as unused load from unit block on disk + unsigned int calculated_insulation : 1; // Insulation from clothing calculated + unsigned int visitor_uninvited : 1; // Uninvited guest + unsigned int visitor : 1; // visitor + + unsigned int calculated_inventory : 1; // Inventory order calculated + unsigned int vision_good : 1; // Vision -- have good part + unsigned int vision_damaged : 1; // Vision -- have damaged part + unsigned int vision_missing : 1; // Vision -- have missing part + + unsigned int breathing_good : 1; // Breathing -- have good part + unsigned int breathing_problem : 1; // Breathing -- having a problem + unsigned int roaming_wilderness_population_source : 1; + unsigned int roaming_wilderness_population_source_not_a_map_feature : 1; + }; + + union t_creaturflags2 + { + uint32_t whole; + naked_creaturflags2 bits; + }; + + /* + struct t_labor + { + string name; + uint8_t value; + t_labor() { + value =0; + } + t_labor(const t_labor & b){ + name=b.name; + value=b.value; + } + t_labor & operator=(const t_labor &b){ + name=b.name; + value=b.value; + return *this; + } + }; + struct t_skill + { + string name; + uint16_t id; + uint32_t experience; + uint16_t rating; + t_skill(){ + id=rating=0; + experience=0; + } + t_skill(const t_skill & b) + { + name=b.name; + id=b.id; + experience=b.experience; + rating=b.rating; + } + t_skill & operator=(const t_skill &b) + { + name=b.name; + id=b.id; + experience=b.experience; + rating=b.rating; + return *this; + } + }; + + struct t_trait + { + uint16_t value; + string displayTxt; + string name; + t_trait(){ + value=0; + } + t_trait(const t_trait &b) + { + name=b.name; + displayTxt=b.displayTxt; + value=b.value; + } + t_trait & operator=(const t_trait &b) + { + name=b.name; + displayTxt=b.displayTxt; + value=b.value; + return *this; + } + }; + */ + + struct t_skill + { + uint16_t id; + uint32_t experience; + uint16_t rating; + }; + struct t_job + { + bool active; + uint32_t jobId; + uint8_t jobType; uint32_t occupationPtr; - }; - struct t_like - { - int16_t type; - int16_t itemClass; - int16_t itemIndex; - t_matglossPair material; - bool active; - }; - - - // FIXME: define in Memory.xml instead? - #define NUM_CREATURE_TRAITS 30 - #define NUM_CREATURE_LABORS 102 - - struct t_soul - { - uint8_t numSkills; - t_skill skills[256]; - /* - uint8_t numLikes; - t_like likes[32]; - */ - uint16_t traits[NUM_CREATURE_TRAITS]; - t_attrib analytical_ability; - t_attrib focus; - t_attrib willpower; - t_attrib creativity; - t_attrib intuition; - t_attrib patience; - t_attrib memory; - t_attrib linguistic_ability; - t_attrib spatial_sense; - t_attrib musicality; - t_attrib kinesthetic_sense; - t_attrib empathy; - t_attrib social_awareness; - }; + }; + struct t_like + { + int16_t type; + int16_t itemClass; + int16_t itemIndex; + t_matglossPair material; + bool active; + }; + + + // FIXME: define in Memory.xml instead? +#define NUM_CREATURE_TRAITS 30 +#define NUM_CREATURE_LABORS 102 + + struct t_soul + { + uint8_t numSkills; + t_skill skills[256]; + /* + uint8_t numLikes; + t_like likes[32]; + */ + uint16_t traits[NUM_CREATURE_TRAITS]; + t_attrib analytical_ability; + t_attrib focus; + t_attrib willpower; + t_attrib creativity; + t_attrib intuition; + t_attrib patience; + t_attrib memory; + t_attrib linguistic_ability; + t_attrib spatial_sense; + t_attrib musicality; + t_attrib kinesthetic_sense; + t_attrib empathy; + t_attrib social_awareness; + }; #define MAX_COLORS 15 - struct t_creature - { - uint32_t origin; - uint16_t x; - uint16_t y; - uint16_t z; - uint32_t race; - int32_t civ; - - t_creaturflags1 flags1; - t_creaturflags2 flags2; - - t_name name; - - int16_t mood; - int16_t mood_skill; - t_name artifact_name; - - uint8_t profession; - char custom_profession[128]; - - // enabled labors - uint8_t labors[NUM_CREATURE_LABORS]; - t_job current_job; - - uint32_t happiness; - uint32_t id; - t_attrib strength; - t_attrib agility; - t_attrib toughness; - t_attrib endurance; - t_attrib recuperation; - t_attrib disease_resistance; - int32_t squad_leader_id; - uint8_t sex; - uint16_t caste; - uint32_t pregnancy_timer; //Countdown timer to giving birth - bool has_default_soul; - t_soul defaultSoul; - uint32_t nbcolors; - uint32_t color[MAX_COLORS]; - - uint32_t birth_year; - uint32_t birth_time; - }; - - class DFContextShared; - struct t_creature; - class DFHACK_EXPORT Creatures - { - public: - Creatures(DFHack::DFContextShared * d); - ~Creatures(); - bool Start( uint32_t & numCreatures); - bool Finish(); - - // Read creatures in a box, starting with index. Returns -1 if no more creatures - // found. Call repeatedly do get all creatures in a specified box (uses tile coords) - int32_t ReadCreatureInBox(const int32_t index, t_creature & furball, - const uint16_t x1, const uint16_t y1,const uint16_t z1, - const uint16_t x2, const uint16_t y2,const uint16_t z2); - bool ReadCreature(const int32_t index, t_creature & furball); - /// write labors of a creature (for Dwarf Therapist) - bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); - uint32_t GetDwarfRaceIndex ( void ); - int32_t GetDwarfCivId ( void ); - bool ReadJob(const t_creature * furball, std::vector & mat); - private: - struct Private; - Private *d; - }; + struct t_creature + { + uint32_t origin; + uint16_t x; + uint16_t y; + uint16_t z; + uint32_t race; + int32_t civ; + + t_creaturflags1 flags1; + t_creaturflags2 flags2; + + t_name name; + + int16_t mood; + int16_t mood_skill; + t_name artifact_name; + + uint8_t profession; + char custom_profession[128]; + + // enabled labors + uint8_t labors[NUM_CREATURE_LABORS]; + t_job current_job; + + uint32_t happiness; + uint32_t id; + t_attrib strength; + t_attrib agility; + t_attrib toughness; + t_attrib endurance; + t_attrib recuperation; + t_attrib disease_resistance; + int32_t squad_leader_id; + uint8_t sex; + uint16_t caste; + uint32_t pregnancy_timer; //Countdown timer to giving birth + bool has_default_soul; + t_soul defaultSoul; + uint32_t nbcolors; + uint32_t color[MAX_COLORS]; + + uint32_t birth_year; + uint32_t birth_time; + }; + + class DFContextShared; + struct t_creature; + class DFHACK_EXPORT Creatures + { + public: + Creatures(DFHack::DFContextShared * d); + ~Creatures(); + bool Start( uint32_t & numCreatures); + bool Finish(); + + /* Read Functions */ + // Read creatures in a box, starting with index. Returns -1 if no more creatures + // found. Call repeatedly do get all creatures in a specified box (uses tile coords) + int32_t ReadCreatureInBox(const int32_t index, t_creature & furball, + const uint16_t x1, const uint16_t y1,const uint16_t z1, + const uint16_t x2, const uint16_t y2,const uint16_t z2); + bool ReadCreature(const int32_t index, t_creature & furball); + bool ReadJob(const t_creature * furball, std::vector & mat); + + /* Getters */ + uint32_t GetDwarfRaceIndex ( void ); + int32_t GetDwarfCivId ( void ); + + /* Write Functions */ + // write labors of a creature (for Dwarf Therapist) + bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); + bool WriteHappiness(const uint32_t index, const uint32_t happinessValue); + + private: + struct Private; + Private *d; + }; } #endif diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index b7e39a95f..d882e1d7f 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -346,20 +346,29 @@ int32_t Creatures::ReadCreatureInBox (int32_t index, t_creature & furball, } } - - bool Creatures::WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]) { - if(!d->Started) return false; - uint32_t temp = d->p_cre->at (index); - Process * p = d->owner; - - p->write(temp + d->creatures.labors_offset, NUM_CREATURE_LABORS, labors); - uint32_t pickup_equip; - p->readDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); - pickup_equip |= 1u; - p->writeDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); - return true; + if(!d->Started) return false; + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + + p->write(temp + d->creatures.labors_offset, NUM_CREATURE_LABORS, labors); + uint32_t pickup_equip; + p->readDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); + pickup_equip |= 1u; + p->writeDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); + return true; +} + +bool Creatures::WriteHappiness(const uint32_t index, const uint32_t happinessValue) +{ + if(!d->Started) + return false; + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + p->writeDWord (temp + d->creatures.happiness_offset, happinessValue); + return true; } uint32_t Creatures::GetDwarfRaceIndex() From 2ad6bcb9cc9966d5ec3b9be25c4a0c3af064ee64 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Tue, 15 Jun 2010 17:28:05 +0100 Subject: [PATCH 040/122] Flag writing function added --- library/include/dfhack/modules/Creatures.h | 3 ++- library/modules/Creatures.cpp | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 1f08b1aa4..2e27ff3b9 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -379,7 +379,8 @@ namespace DFHack /* Write Functions */ // write labors of a creature (for Dwarf Therapist) bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); - bool WriteHappiness(const uint32_t index, const uint32_t happinessValue); + bool WriteHappiness(const uint32_t index, const uint32_t happinessValue); + bool WriteFlags(const uint32_t index, const uint32_t flags1, const uint32_t flags2); private: struct Private; diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index d882e1d7f..e9193e9dc 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -371,6 +371,20 @@ bool Creatures::WriteHappiness(const uint32_t index, const uint32_t happinessVal return true; } +bool Creatures::WriteFlags(const uint32_t index, + const uint32_t flags1, + const uint32_t flags2) +{ + if(!d->Started) + return false; + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + p->writeDWord (temp + d->creatures.flags1_offset, flags1); + p->writeDWord (temp + d->creatures.flags2_offset, flags1); + return true; +} + uint32_t Creatures::GetDwarfRaceIndex() { if(!d->Inited) return 0; From aa0f45b8acebcccc6f614edc6c353d37606d4e41 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Tue, 15 Jun 2010 22:23:24 +0100 Subject: [PATCH 041/122] Skill writing added --- library/include/dfhack/modules/Creatures.h | 1 + library/modules/Creatures.cpp | 24 ++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 2e27ff3b9..07d457d1b 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -381,6 +381,7 @@ namespace DFHack bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); bool WriteHappiness(const uint32_t index, const uint32_t happinessValue); bool WriteFlags(const uint32_t index, const uint32_t flags1, const uint32_t flags2); + bool WriteSkills(const uint32_t index, t_soul &soul); private: struct Private; diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index e9193e9dc..467ddcd15 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -385,6 +385,30 @@ bool Creatures::WriteFlags(const uint32_t index, return true; } +bool Creatures::WriteSkills(const uint32_t index, t_soul &soul) +{ + if(!d->Started) + return false; + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + uint32_t souloff = p->readDWord(temp + d->creatures.default_soul_offset); + + if(!souloff) + return false; + + DfVector skills(p, souloff + d->creatures.soul_skills_vector_offset); + + for (uint32_t i=0; iwriteByte(temp2 + 4, soul.skills[i].rating); + p->writeWord(temp2 + 8, soul.skills[i].experience); + } + + return true; +} + uint32_t Creatures::GetDwarfRaceIndex() { if(!d->Inited) return 0; From cc05fd4a70daebdc99afcc1931abb883f27a8962 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Wed, 16 Jun 2010 00:19:19 +0100 Subject: [PATCH 042/122] Attribute writing added --- library/include/dfhack/modules/Creatures.h | 7 ++-- library/modules/Creatures.cpp | 39 ++++++++++++++++++---- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 07d457d1b..9d58ec12d 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -256,9 +256,9 @@ namespace DFHack struct t_skill { - uint16_t id; + uint32_t id; uint32_t experience; - uint16_t rating; + uint32_t rating; }; struct t_job { @@ -381,7 +381,8 @@ namespace DFHack bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); bool WriteHappiness(const uint32_t index, const uint32_t happinessValue); bool WriteFlags(const uint32_t index, const uint32_t flags1, const uint32_t flags2); - bool WriteSkills(const uint32_t index, t_soul &soul); + bool WriteSkills(const uint32_t index, const t_soul &soul); + bool WriteAttributes(const uint32_t index, const t_creature &creature); private: struct Private; diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index 467ddcd15..c47201ffc 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -261,10 +261,10 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) for (uint32_t i = 0; i < furball.defaultSoul.numSkills;i++) { uint32_t temp2 = skills[i]; - // a byte: this gives us 256 skills maximum. - furball.defaultSoul.skills[i].id = p->readByte (temp2); - furball.defaultSoul.skills[i].rating = p->readByte (temp2 + 4); - furball.defaultSoul.skills[i].experience = p->readWord (temp2 + 8); + // a byte: this gives us 256 skills maximum. ??? + furball.defaultSoul.skills[i].id = p->readDWord (temp2); + furball.defaultSoul.skills[i].rating = p->readDWord (temp2 + 4); + furball.defaultSoul.skills[i].experience = p->readDWord (temp2 + 8); } // mental attributes are part of the soul p->read(soul + offs.soul_mental_offset, sizeof(t_attrib) * 13, (uint8_t *)&furball.defaultSoul.analytical_ability); @@ -385,7 +385,7 @@ bool Creatures::WriteFlags(const uint32_t index, return true; } -bool Creatures::WriteSkills(const uint32_t index, t_soul &soul) +bool Creatures::WriteSkills(const uint32_t index, const t_soul &soul) { if(!d->Started) return false; @@ -402,13 +402,38 @@ bool Creatures::WriteSkills(const uint32_t index, t_soul &soul) for (uint32_t i=0; iwriteByte(temp2 + 4, soul.skills[i].rating); - p->writeWord(temp2 + 8, soul.skills[i].experience); + p->writeDWord(temp2 + 4, soul.skills[i].rating); + p->writeDWord(temp2 + 8, soul.skills[i].experience); } return true; } +bool Creatures::WriteAttributes(const uint32_t index, const t_creature &creature) +{ + if(!d->Started) + return false; + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + uint32_t souloff = p->readDWord(temp + d->creatures.default_soul_offset); + + if(!souloff) + return false; + + // physical attributes + p->write(temp + d->creatures.physical_offset, + sizeof(t_attrib) * 6, + (uint8_t *)&creature.strength); + + // mental attributes are part of the soul + p->write(souloff + d->creatures.soul_mental_offset, + sizeof(t_attrib) * 13, + (uint8_t *)&creature.defaultSoul.analytical_ability); + + return true; +} + uint32_t Creatures::GetDwarfRaceIndex() { if(!d->Inited) return 0; From b95efc22fe96c81c84ffd22dadf55b45ffb34c16 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Tue, 15 Jun 2010 07:59:18 +0800 Subject: [PATCH 043/122] Happiness writing function added and tested. Seems ok so far --- library/include/dfhack/DFTypes.h | 2 +- library/include/dfhack/modules/Creatures.h | 743 +++++++++++---------- library/modules/Creatures.cpp | 33 +- 3 files changed, 397 insertions(+), 381 deletions(-) diff --git a/library/include/dfhack/DFTypes.h b/library/include/dfhack/DFTypes.h index 748bf9381..52c7826b7 100644 --- a/library/include/dfhack/DFTypes.h +++ b/library/include/dfhack/DFTypes.h @@ -203,7 +203,7 @@ struct t_settlement struct t_attrib { uint32_t level; - uint32_t field_4; + uint32_t field_4; // offset from beginning, purpose unknown uint32_t field_8; uint32_t field_C; uint32_t leveldiff; diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 7e0d48cb5..1f08b1aa4 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -6,377 +6,384 @@ #include "dfhack/DFExport.h" namespace DFHack { - /* - bits: - - 0 Can the dwarf move or are they waiting for their movement timer - 1 Dead (might also be set for incoming/leaving critters that are alive) - 2 Currently in mood - 3 Had a mood - 4 "marauder" -- wide class of invader/inside creature attackers - 5 Drowning - 6 Active merchant - 7 "forest" (used for units no longer linked to merchant/diplomacy, they just try to leave mostly) - 8 Left (left the map) - 9 Rider - 10 Incoming - 11 Diplomat - 12 Zombie - 13 Skeleton - 14 Can swap tiles during movement (prevents multiple swaps) - 15 On the ground (can be conscious) - 16 Projectile - 17 Active invader (for organized ones) - 18 Hidden in ambush - 19 Invader origin (could be inactive and fleeing) - 20 Will flee if invasion turns around - 21 Active marauder/invader moving inward - 22 Marauder resident/invader moving in all the way - 23 Check against flows next time you get a chance - 24 Ridden - 25 Caged - 26 Tame - 27 Chained - 28 Royal guard - 29 Fortress guard - 30 Suppress wield for beatings/etc - 31 Is an important historical figure - */ - - struct naked_creaturflags1 - { - unsigned int move_state : 1; // Can the dwarf move or are they waiting for their movement timer - unsigned int dead : 1; // might also be set for incoming/leaving critters that are alive - unsigned int has_mood : 1; // Currently in mood - unsigned int had_mood : 1; // Had a mood - - unsigned int marauder : 1; // wide class of invader/inside creature attackers - unsigned int drowning : 1; - unsigned int merchant : 1; // active merchant - unsigned int forest : 1; // used for units no longer linked to merchant/diplomacy, they just try to leave mostly - - unsigned int left : 1; // left the map - unsigned int rider : 1; - unsigned int incoming : 1; - unsigned int diplomat : 1; - - unsigned int zombie : 1; - unsigned int skeleton : 1; - unsigned int can_swap : 1; // Can swap tiles during movement (prevents multiple swaps) - unsigned int on_ground : 1; // can be conscious - - unsigned int projectile : 1; - unsigned int active_invader : 1; // for organized ones - unsigned int hidden_in_ambush : 1; - unsigned int invader_origin : 1; // could be inactive and fleeing - - unsigned int coward : 1; // Will flee if invasion turns around - unsigned int hidden_ambusher : 1; // maybe - unsigned int invades : 1; // Active marauder/invader moving inward - unsigned int check_flows : 1; // Check against flows next time you get a chance - - // 0100 0000 - 8000 0000 - unsigned int ridden : 1; - unsigned int caged : 1; - unsigned int tame : 1; - unsigned int chained : 1; - - unsigned int royal_guard : 1; - unsigned int fortress_guard : 1; - unsigned int suppress_wield : 1; // Suppress wield for beatings/etc - unsigned int important_historical_figure : 1; // Is an important historical figure - }; - - union t_creaturflags1 - { - uint32_t whole; - naked_creaturflags1 bits; - }; - - /* - bits: - - 0 Swimming - 1 Play combat for sparring - 2 Do not notify about level gains (for embark etc) - 3 Unused - - 4 Nerves calculated - 5 Body part info calculated - 6 Is important historical figure (slight variation) - 7 Has been killed by kill function (slightly different from dead, not necessarily violent death) - - 8 Must be forgotten by forget function (just cleanup) - 9 Must be deleted (cleanup) - 10 Recently forgotten (cleanup) - 11 Offered for trade - - 12 Trade resolved - 13 Has breaks - 14 Gutted - 15 Circulatory spray - - 16 Locked in for trading (it's a projectile on the other set of flags, might be what the flying was) - 17 Marked for slaughter - 18 Underworld creature - 19 Current resident - - 20 Marked for special cleanup as unused load from unit block on disk - 21 Insulation from clothing calculated - 22 Uninvited guest - 23 Visitor - - 24 Inventory order calculated - 25 Vision -- have good part - 26 Vision -- have damaged part - 27 Vision -- have missing part - - 28 Breathing -- have good part - 29 Breathing -- having a problem - 30 Roaming wilderness population source - 31 Roaming wilderness population source -- not a map feature - */ - struct naked_creaturflags2 - { - unsigned int swimming : 1; - unsigned int sparring : 1; - unsigned int no_notify : 1; // Do not notify about level gains (for embark etc) - unsigned int unused : 1; - - unsigned int calculated_nerves : 1; - unsigned int calculated_bodyparts : 1; - unsigned int important_historical_figure : 1; // slight variation - unsigned int killed : 1; // killed by kill() function - - unsigned int cleanup_1 : 1; // Must be forgotten by forget function (just cleanup) - unsigned int cleanup_2 : 1; // Must be deleted (cleanup) - unsigned int cleanup_3 : 1; // Recently forgotten (cleanup) - unsigned int for_trade : 1; // Offered for trade - - unsigned int trade_resolved : 1; - unsigned int has_breaks : 1; - unsigned int gutted : 1; - unsigned int circulatory_spray : 1; - - unsigned int locked_in_for_trading : 1; - unsigned int slaughter : 1; // marked for slaughter - unsigned int underworld : 1; // Underworld creature - unsigned int resident : 1; // Current resident - - unsigned int cleanup_4 : 1; // Marked for special cleanup as unused load from unit block on disk - unsigned int calculated_insulation : 1; // Insulation from clothing calculated - unsigned int visitor_uninvited : 1; // Uninvited guest - unsigned int visitor : 1; // visitor - - unsigned int calculated_inventory : 1; // Inventory order calculated - unsigned int vision_good : 1; // Vision -- have good part - unsigned int vision_damaged : 1; // Vision -- have damaged part - unsigned int vision_missing : 1; // Vision -- have missing part - - unsigned int breathing_good : 1; // Breathing -- have good part - unsigned int breathing_problem : 1; // Breathing -- having a problem - unsigned int roaming_wilderness_population_source : 1; - unsigned int roaming_wilderness_population_source_not_a_map_feature : 1; - }; - - union t_creaturflags2 - { - uint32_t whole; - naked_creaturflags2 bits; - }; - - /* - struct t_labor - { - string name; - uint8_t value; - t_labor() { - value =0; - } - t_labor(const t_labor & b){ - name=b.name; - value=b.value; - } - t_labor & operator=(const t_labor &b){ - name=b.name; - value=b.value; - return *this; - } - }; - struct t_skill - { - string name; - uint16_t id; - uint32_t experience; - uint16_t rating; - t_skill(){ - id=rating=0; - experience=0; - } - t_skill(const t_skill & b) - { - name=b.name; - id=b.id; - experience=b.experience; - rating=b.rating; - } - t_skill & operator=(const t_skill &b) - { - name=b.name; - id=b.id; - experience=b.experience; - rating=b.rating; - return *this; - } - }; - - struct t_trait - { - uint16_t value; - string displayTxt; - string name; - t_trait(){ - value=0; - } - t_trait(const t_trait &b) - { - name=b.name; - displayTxt=b.displayTxt; - value=b.value; - } - t_trait & operator=(const t_trait &b) - { - name=b.name; - displayTxt=b.displayTxt; - value=b.value; - return *this; - } - }; - */ - - struct t_skill - { - uint16_t id; - uint32_t experience; - uint16_t rating; - }; - struct t_job - { - bool active; - uint32_t jobId; - uint8_t jobType; + /* + bits: + + 0 Can the dwarf move or are they waiting for their movement timer + 1 Dead (might also be set for incoming/leaving critters that are alive) + 2 Currently in mood + 3 Had a mood + 4 "marauder" -- wide class of invader/inside creature attackers + 5 Drowning + 6 Active merchant + 7 "forest" (used for units no longer linked to merchant/diplomacy, they just try to leave mostly) + 8 Left (left the map) + 9 Rider + 10 Incoming + 11 Diplomat + 12 Zombie + 13 Skeleton + 14 Can swap tiles during movement (prevents multiple swaps) + 15 On the ground (can be conscious) + 16 Projectile + 17 Active invader (for organized ones) + 18 Hidden in ambush + 19 Invader origin (could be inactive and fleeing) + 20 Will flee if invasion turns around + 21 Active marauder/invader moving inward + 22 Marauder resident/invader moving in all the way + 23 Check against flows next time you get a chance + 24 Ridden + 25 Caged + 26 Tame + 27 Chained + 28 Royal guard + 29 Fortress guard + 30 Suppress wield for beatings/etc + 31 Is an important historical figure + */ + + struct naked_creaturflags1 + { + unsigned int move_state : 1; // Can the dwarf move or are they waiting for their movement timer + unsigned int dead : 1; // might also be set for incoming/leaving critters that are alive + unsigned int has_mood : 1; // Currently in mood + unsigned int had_mood : 1; // Had a mood + + unsigned int marauder : 1; // wide class of invader/inside creature attackers + unsigned int drowning : 1; + unsigned int merchant : 1; // active merchant + unsigned int forest : 1; // used for units no longer linked to merchant/diplomacy, they just try to leave mostly + + unsigned int left : 1; // left the map + unsigned int rider : 1; + unsigned int incoming : 1; + unsigned int diplomat : 1; + + unsigned int zombie : 1; + unsigned int skeleton : 1; + unsigned int can_swap : 1; // Can swap tiles during movement (prevents multiple swaps) + unsigned int on_ground : 1; // can be conscious + + unsigned int projectile : 1; + unsigned int active_invader : 1; // for organized ones + unsigned int hidden_in_ambush : 1; + unsigned int invader_origin : 1; // could be inactive and fleeing + + unsigned int coward : 1; // Will flee if invasion turns around + unsigned int hidden_ambusher : 1; // maybe + unsigned int invades : 1; // Active marauder/invader moving inward + unsigned int check_flows : 1; // Check against flows next time you get a chance + + // 0100 0000 - 8000 0000 + unsigned int ridden : 1; + unsigned int caged : 1; + unsigned int tame : 1; + unsigned int chained : 1; + + unsigned int royal_guard : 1; + unsigned int fortress_guard : 1; + unsigned int suppress_wield : 1; // Suppress wield for beatings/etc + unsigned int important_historical_figure : 1; // Is an important historical figure + }; + + union t_creaturflags1 + { + uint32_t whole; + naked_creaturflags1 bits; + }; + + /* + bits: + + 0 Swimming + 1 Play combat for sparring + 2 Do not notify about level gains (for embark etc) + 3 Unused + + 4 Nerves calculated + 5 Body part info calculated + 6 Is important historical figure (slight variation) + 7 Has been killed by kill function (slightly different from dead, not necessarily violent death) + + 8 Must be forgotten by forget function (just cleanup) + 9 Must be deleted (cleanup) + 10 Recently forgotten (cleanup) + 11 Offered for trade + + 12 Trade resolved + 13 Has breaks + 14 Gutted + 15 Circulatory spray + + 16 Locked in for trading (it's a projectile on the other set of flags, might be what the flying was) + 17 Marked for slaughter + 18 Underworld creature + 19 Current resident + + 20 Marked for special cleanup as unused load from unit block on disk + 21 Insulation from clothing calculated + 22 Uninvited guest + 23 Visitor + + 24 Inventory order calculated + 25 Vision -- have good part + 26 Vision -- have damaged part + 27 Vision -- have missing part + + 28 Breathing -- have good part + 29 Breathing -- having a problem + 30 Roaming wilderness population source + 31 Roaming wilderness population source -- not a map feature + */ + struct naked_creaturflags2 + { + unsigned int swimming : 1; + unsigned int sparring : 1; + unsigned int no_notify : 1; // Do not notify about level gains (for embark etc) + unsigned int unused : 1; + + unsigned int calculated_nerves : 1; + unsigned int calculated_bodyparts : 1; + unsigned int important_historical_figure : 1; // slight variation + unsigned int killed : 1; // killed by kill() function + + unsigned int cleanup_1 : 1; // Must be forgotten by forget function (just cleanup) + unsigned int cleanup_2 : 1; // Must be deleted (cleanup) + unsigned int cleanup_3 : 1; // Recently forgotten (cleanup) + unsigned int for_trade : 1; // Offered for trade + + unsigned int trade_resolved : 1; + unsigned int has_breaks : 1; + unsigned int gutted : 1; + unsigned int circulatory_spray : 1; + + unsigned int locked_in_for_trading : 1; + unsigned int slaughter : 1; // marked for slaughter + unsigned int underworld : 1; // Underworld creature + unsigned int resident : 1; // Current resident + + unsigned int cleanup_4 : 1; // Marked for special cleanup as unused load from unit block on disk + unsigned int calculated_insulation : 1; // Insulation from clothing calculated + unsigned int visitor_uninvited : 1; // Uninvited guest + unsigned int visitor : 1; // visitor + + unsigned int calculated_inventory : 1; // Inventory order calculated + unsigned int vision_good : 1; // Vision -- have good part + unsigned int vision_damaged : 1; // Vision -- have damaged part + unsigned int vision_missing : 1; // Vision -- have missing part + + unsigned int breathing_good : 1; // Breathing -- have good part + unsigned int breathing_problem : 1; // Breathing -- having a problem + unsigned int roaming_wilderness_population_source : 1; + unsigned int roaming_wilderness_population_source_not_a_map_feature : 1; + }; + + union t_creaturflags2 + { + uint32_t whole; + naked_creaturflags2 bits; + }; + + /* + struct t_labor + { + string name; + uint8_t value; + t_labor() { + value =0; + } + t_labor(const t_labor & b){ + name=b.name; + value=b.value; + } + t_labor & operator=(const t_labor &b){ + name=b.name; + value=b.value; + return *this; + } + }; + struct t_skill + { + string name; + uint16_t id; + uint32_t experience; + uint16_t rating; + t_skill(){ + id=rating=0; + experience=0; + } + t_skill(const t_skill & b) + { + name=b.name; + id=b.id; + experience=b.experience; + rating=b.rating; + } + t_skill & operator=(const t_skill &b) + { + name=b.name; + id=b.id; + experience=b.experience; + rating=b.rating; + return *this; + } + }; + + struct t_trait + { + uint16_t value; + string displayTxt; + string name; + t_trait(){ + value=0; + } + t_trait(const t_trait &b) + { + name=b.name; + displayTxt=b.displayTxt; + value=b.value; + } + t_trait & operator=(const t_trait &b) + { + name=b.name; + displayTxt=b.displayTxt; + value=b.value; + return *this; + } + }; + */ + + struct t_skill + { + uint16_t id; + uint32_t experience; + uint16_t rating; + }; + struct t_job + { + bool active; + uint32_t jobId; + uint8_t jobType; uint32_t occupationPtr; - }; - struct t_like - { - int16_t type; - int16_t itemClass; - int16_t itemIndex; - t_matglossPair material; - bool active; - }; - - - // FIXME: define in Memory.xml instead? - #define NUM_CREATURE_TRAITS 30 - #define NUM_CREATURE_LABORS 102 - - struct t_soul - { - uint8_t numSkills; - t_skill skills[256]; - /* - uint8_t numLikes; - t_like likes[32]; - */ - uint16_t traits[NUM_CREATURE_TRAITS]; - t_attrib analytical_ability; - t_attrib focus; - t_attrib willpower; - t_attrib creativity; - t_attrib intuition; - t_attrib patience; - t_attrib memory; - t_attrib linguistic_ability; - t_attrib spatial_sense; - t_attrib musicality; - t_attrib kinesthetic_sense; - t_attrib empathy; - t_attrib social_awareness; - }; + }; + struct t_like + { + int16_t type; + int16_t itemClass; + int16_t itemIndex; + t_matglossPair material; + bool active; + }; + + + // FIXME: define in Memory.xml instead? +#define NUM_CREATURE_TRAITS 30 +#define NUM_CREATURE_LABORS 102 + + struct t_soul + { + uint8_t numSkills; + t_skill skills[256]; + /* + uint8_t numLikes; + t_like likes[32]; + */ + uint16_t traits[NUM_CREATURE_TRAITS]; + t_attrib analytical_ability; + t_attrib focus; + t_attrib willpower; + t_attrib creativity; + t_attrib intuition; + t_attrib patience; + t_attrib memory; + t_attrib linguistic_ability; + t_attrib spatial_sense; + t_attrib musicality; + t_attrib kinesthetic_sense; + t_attrib empathy; + t_attrib social_awareness; + }; #define MAX_COLORS 15 - struct t_creature - { - uint32_t origin; - uint16_t x; - uint16_t y; - uint16_t z; - uint32_t race; - int32_t civ; - - t_creaturflags1 flags1; - t_creaturflags2 flags2; - - t_name name; - - int16_t mood; - int16_t mood_skill; - t_name artifact_name; - - uint8_t profession; - char custom_profession[128]; - - // enabled labors - uint8_t labors[NUM_CREATURE_LABORS]; - t_job current_job; - - uint32_t happiness; - uint32_t id; - t_attrib strength; - t_attrib agility; - t_attrib toughness; - t_attrib endurance; - t_attrib recuperation; - t_attrib disease_resistance; - int32_t squad_leader_id; - uint8_t sex; - uint16_t caste; - uint32_t pregnancy_timer; //Countdown timer to giving birth - bool has_default_soul; - t_soul defaultSoul; - uint32_t nbcolors; - uint32_t color[MAX_COLORS]; - - uint32_t birth_year; - uint32_t birth_time; - }; - - class DFContextShared; - struct t_creature; - class DFHACK_EXPORT Creatures - { - public: - Creatures(DFHack::DFContextShared * d); - ~Creatures(); - bool Start( uint32_t & numCreatures); - bool Finish(); - - // Read creatures in a box, starting with index. Returns -1 if no more creatures - // found. Call repeatedly do get all creatures in a specified box (uses tile coords) - int32_t ReadCreatureInBox(const int32_t index, t_creature & furball, - const uint16_t x1, const uint16_t y1,const uint16_t z1, - const uint16_t x2, const uint16_t y2,const uint16_t z2); - bool ReadCreature(const int32_t index, t_creature & furball); - /// write labors of a creature (for Dwarf Therapist) - bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); - uint32_t GetDwarfRaceIndex ( void ); - int32_t GetDwarfCivId ( void ); - bool ReadJob(const t_creature * furball, std::vector & mat); - private: - struct Private; - Private *d; - }; + struct t_creature + { + uint32_t origin; + uint16_t x; + uint16_t y; + uint16_t z; + uint32_t race; + int32_t civ; + + t_creaturflags1 flags1; + t_creaturflags2 flags2; + + t_name name; + + int16_t mood; + int16_t mood_skill; + t_name artifact_name; + + uint8_t profession; + char custom_profession[128]; + + // enabled labors + uint8_t labors[NUM_CREATURE_LABORS]; + t_job current_job; + + uint32_t happiness; + uint32_t id; + t_attrib strength; + t_attrib agility; + t_attrib toughness; + t_attrib endurance; + t_attrib recuperation; + t_attrib disease_resistance; + int32_t squad_leader_id; + uint8_t sex; + uint16_t caste; + uint32_t pregnancy_timer; //Countdown timer to giving birth + bool has_default_soul; + t_soul defaultSoul; + uint32_t nbcolors; + uint32_t color[MAX_COLORS]; + + uint32_t birth_year; + uint32_t birth_time; + }; + + class DFContextShared; + struct t_creature; + class DFHACK_EXPORT Creatures + { + public: + Creatures(DFHack::DFContextShared * d); + ~Creatures(); + bool Start( uint32_t & numCreatures); + bool Finish(); + + /* Read Functions */ + // Read creatures in a box, starting with index. Returns -1 if no more creatures + // found. Call repeatedly do get all creatures in a specified box (uses tile coords) + int32_t ReadCreatureInBox(const int32_t index, t_creature & furball, + const uint16_t x1, const uint16_t y1,const uint16_t z1, + const uint16_t x2, const uint16_t y2,const uint16_t z2); + bool ReadCreature(const int32_t index, t_creature & furball); + bool ReadJob(const t_creature * furball, std::vector & mat); + + /* Getters */ + uint32_t GetDwarfRaceIndex ( void ); + int32_t GetDwarfCivId ( void ); + + /* Write Functions */ + // write labors of a creature (for Dwarf Therapist) + bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); + bool WriteHappiness(const uint32_t index, const uint32_t happinessValue); + + private: + struct Private; + Private *d; + }; } #endif diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index b7e39a95f..d882e1d7f 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -346,20 +346,29 @@ int32_t Creatures::ReadCreatureInBox (int32_t index, t_creature & furball, } } - - bool Creatures::WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]) { - if(!d->Started) return false; - uint32_t temp = d->p_cre->at (index); - Process * p = d->owner; - - p->write(temp + d->creatures.labors_offset, NUM_CREATURE_LABORS, labors); - uint32_t pickup_equip; - p->readDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); - pickup_equip |= 1u; - p->writeDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); - return true; + if(!d->Started) return false; + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + + p->write(temp + d->creatures.labors_offset, NUM_CREATURE_LABORS, labors); + uint32_t pickup_equip; + p->readDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); + pickup_equip |= 1u; + p->writeDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); + return true; +} + +bool Creatures::WriteHappiness(const uint32_t index, const uint32_t happinessValue) +{ + if(!d->Started) + return false; + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + p->writeDWord (temp + d->creatures.happiness_offset, happinessValue); + return true; } uint32_t Creatures::GetDwarfRaceIndex() From 2254f3dfe581b241df1ed735451433c7d7cb1ad9 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Wed, 16 Jun 2010 00:28:05 +0800 Subject: [PATCH 044/122] Flag writing function added --- library/include/dfhack/modules/Creatures.h | 3 ++- library/modules/Creatures.cpp | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 1f08b1aa4..2e27ff3b9 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -379,7 +379,8 @@ namespace DFHack /* Write Functions */ // write labors of a creature (for Dwarf Therapist) bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); - bool WriteHappiness(const uint32_t index, const uint32_t happinessValue); + bool WriteHappiness(const uint32_t index, const uint32_t happinessValue); + bool WriteFlags(const uint32_t index, const uint32_t flags1, const uint32_t flags2); private: struct Private; diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index d882e1d7f..e9193e9dc 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -371,6 +371,20 @@ bool Creatures::WriteHappiness(const uint32_t index, const uint32_t happinessVal return true; } +bool Creatures::WriteFlags(const uint32_t index, + const uint32_t flags1, + const uint32_t flags2) +{ + if(!d->Started) + return false; + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + p->writeDWord (temp + d->creatures.flags1_offset, flags1); + p->writeDWord (temp + d->creatures.flags2_offset, flags1); + return true; +} + uint32_t Creatures::GetDwarfRaceIndex() { if(!d->Inited) return 0; From 8fb05f24db6aadfae786c541e33a8464cbae19cd Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Wed, 16 Jun 2010 05:23:24 +0800 Subject: [PATCH 045/122] Skill writing added --- library/include/dfhack/modules/Creatures.h | 1 + library/modules/Creatures.cpp | 24 ++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 2e27ff3b9..07d457d1b 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -381,6 +381,7 @@ namespace DFHack bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); bool WriteHappiness(const uint32_t index, const uint32_t happinessValue); bool WriteFlags(const uint32_t index, const uint32_t flags1, const uint32_t flags2); + bool WriteSkills(const uint32_t index, t_soul &soul); private: struct Private; diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index e9193e9dc..467ddcd15 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -385,6 +385,30 @@ bool Creatures::WriteFlags(const uint32_t index, return true; } +bool Creatures::WriteSkills(const uint32_t index, t_soul &soul) +{ + if(!d->Started) + return false; + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + uint32_t souloff = p->readDWord(temp + d->creatures.default_soul_offset); + + if(!souloff) + return false; + + DfVector skills(p, souloff + d->creatures.soul_skills_vector_offset); + + for (uint32_t i=0; iwriteByte(temp2 + 4, soul.skills[i].rating); + p->writeWord(temp2 + 8, soul.skills[i].experience); + } + + return true; +} + uint32_t Creatures::GetDwarfRaceIndex() { if(!d->Inited) return 0; From 77d234374275d5b5cac573030c12f7b9a54b38e9 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Wed, 16 Jun 2010 07:19:19 +0800 Subject: [PATCH 046/122] Attribute writing added --- library/include/dfhack/modules/Creatures.h | 7 ++-- library/modules/Creatures.cpp | 39 ++++++++++++++++++---- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 07d457d1b..9d58ec12d 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -256,9 +256,9 @@ namespace DFHack struct t_skill { - uint16_t id; + uint32_t id; uint32_t experience; - uint16_t rating; + uint32_t rating; }; struct t_job { @@ -381,7 +381,8 @@ namespace DFHack bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); bool WriteHappiness(const uint32_t index, const uint32_t happinessValue); bool WriteFlags(const uint32_t index, const uint32_t flags1, const uint32_t flags2); - bool WriteSkills(const uint32_t index, t_soul &soul); + bool WriteSkills(const uint32_t index, const t_soul &soul); + bool WriteAttributes(const uint32_t index, const t_creature &creature); private: struct Private; diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index 467ddcd15..c47201ffc 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -261,10 +261,10 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) for (uint32_t i = 0; i < furball.defaultSoul.numSkills;i++) { uint32_t temp2 = skills[i]; - // a byte: this gives us 256 skills maximum. - furball.defaultSoul.skills[i].id = p->readByte (temp2); - furball.defaultSoul.skills[i].rating = p->readByte (temp2 + 4); - furball.defaultSoul.skills[i].experience = p->readWord (temp2 + 8); + // a byte: this gives us 256 skills maximum. ??? + furball.defaultSoul.skills[i].id = p->readDWord (temp2); + furball.defaultSoul.skills[i].rating = p->readDWord (temp2 + 4); + furball.defaultSoul.skills[i].experience = p->readDWord (temp2 + 8); } // mental attributes are part of the soul p->read(soul + offs.soul_mental_offset, sizeof(t_attrib) * 13, (uint8_t *)&furball.defaultSoul.analytical_ability); @@ -385,7 +385,7 @@ bool Creatures::WriteFlags(const uint32_t index, return true; } -bool Creatures::WriteSkills(const uint32_t index, t_soul &soul) +bool Creatures::WriteSkills(const uint32_t index, const t_soul &soul) { if(!d->Started) return false; @@ -402,13 +402,38 @@ bool Creatures::WriteSkills(const uint32_t index, t_soul &soul) for (uint32_t i=0; iwriteByte(temp2 + 4, soul.skills[i].rating); - p->writeWord(temp2 + 8, soul.skills[i].experience); + p->writeDWord(temp2 + 4, soul.skills[i].rating); + p->writeDWord(temp2 + 8, soul.skills[i].experience); } return true; } +bool Creatures::WriteAttributes(const uint32_t index, const t_creature &creature) +{ + if(!d->Started) + return false; + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + uint32_t souloff = p->readDWord(temp + d->creatures.default_soul_offset); + + if(!souloff) + return false; + + // physical attributes + p->write(temp + d->creatures.physical_offset, + sizeof(t_attrib) * 6, + (uint8_t *)&creature.strength); + + // mental attributes are part of the soul + p->write(souloff + d->creatures.soul_mental_offset, + sizeof(t_attrib) * 13, + (uint8_t *)&creature.defaultSoul.analytical_ability); + + return true; +} + uint32_t Creatures::GetDwarfRaceIndex() { if(!d->Inited) return 0; From 00cd96884e9441cb5a7f3c7881383fe5b892ad40 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Wed, 16 Jun 2010 00:55:12 +0100 Subject: [PATCH 047/122] Magic number cleaning --- library/include/dfhack/modules/Creatures.h | 2 ++ library/modules/Creatures.cpp | 29 +++++++++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 9d58ec12d..670e37cff 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -280,6 +280,8 @@ namespace DFHack // FIXME: define in Memory.xml instead? #define NUM_CREATURE_TRAITS 30 #define NUM_CREATURE_LABORS 102 +#define NUM_CREATURE_MENTAL_ATTRIBUTES 13 +#define NUM_CREATURE_PHYSICAL_ATTRIBUTES 6 struct t_soul { diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index c47201ffc..53a9060c9 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -195,7 +195,9 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) p->readDWord (temp + offs.flags2_offset, furball.flags2.whole); // physical attributes - p->read(temp + offs.physical_offset, sizeof(t_attrib) * 6, (uint8_t *)&furball.strength); + p->read(temp + offs.physical_offset, + sizeof(t_attrib) * NUM_CREATURE_PHYSICAL_ATTRIBUTES, + (uint8_t *)&furball.strength); // mood stuff furball.mood = (int16_t) p->readWord (temp + offs.mood_offset); @@ -252,25 +254,34 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) */ uint32_t soul = p->readDWord(temp + offs.default_soul_offset); furball.has_default_soul = false; + if(soul) { furball.has_default_soul = true; // get first soul's skills DfVector skills(p, soul + offs.soul_skills_vector_offset); furball.defaultSoul.numSkills = skills.size(); + for (uint32_t i = 0; i < furball.defaultSoul.numSkills;i++) { uint32_t temp2 = skills[i]; // a byte: this gives us 256 skills maximum. ??? furball.defaultSoul.skills[i].id = p->readDWord (temp2); - furball.defaultSoul.skills[i].rating = p->readDWord (temp2 + 4); - furball.defaultSoul.skills[i].experience = p->readDWord (temp2 + 8); + furball.defaultSoul.skills[i].rating = + p->readDWord (temp2 + offsetof(t_skill, rating)); + furball.defaultSoul.skills[i].experience = + p->readDWord (temp2 + offsetof(t_skill, experience)); } + // mental attributes are part of the soul - p->read(soul + offs.soul_mental_offset, sizeof(t_attrib) * 13, (uint8_t *)&furball.defaultSoul.analytical_ability); + p->read(soul + offs.soul_mental_offset, + sizeof(t_attrib) * NUM_CREATURE_MENTAL_ATTRIBUTES, + (uint8_t *)&furball.defaultSoul.analytical_ability); // traits as well - p->read(soul + offs.soul_traits_offset, sizeof (uint16_t) * NUM_CREATURE_TRAITS, (uint8_t *) &furball.defaultSoul.traits); + p->read(soul + offs.soul_traits_offset, + sizeof (uint16_t) * NUM_CREATURE_TRAITS, + (uint8_t *) &furball.defaultSoul.traits); } DfVector app(p, temp + offs.appearance_vector_offset); @@ -402,8 +413,8 @@ bool Creatures::WriteSkills(const uint32_t index, const t_soul &soul) for (uint32_t i=0; iwriteDWord(temp2 + 4, soul.skills[i].rating); - p->writeDWord(temp2 + 8, soul.skills[i].experience); + p->writeDWord(temp2 + offsetof(t_skill, rating), soul.skills[i].rating); + p->writeDWord(temp2 + offsetof(t_skill, experiance), soul.skills[i].experience); } return true; @@ -423,12 +434,12 @@ bool Creatures::WriteAttributes(const uint32_t index, const t_creature &creature // physical attributes p->write(temp + d->creatures.physical_offset, - sizeof(t_attrib) * 6, + sizeof(t_attrib) * NUM_CREATURE_PHYSICAL_ATTRIBUTES, (uint8_t *)&creature.strength); // mental attributes are part of the soul p->write(souloff + d->creatures.soul_mental_offset, - sizeof(t_attrib) * 13, + sizeof(t_attrib) * NUM_CREATURE_MENTAL_ATTRIBUTES, (uint8_t *)&creature.defaultSoul.analytical_ability); return true; From ba9d2d14c2e96ace7816ad51811addabcc7c79f7 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Wed, 16 Jun 2010 07:55:12 +0800 Subject: [PATCH 048/122] Magic number cleaning --- library/include/dfhack/modules/Creatures.h | 2 ++ library/modules/Creatures.cpp | 29 +++++++++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 9d58ec12d..670e37cff 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -280,6 +280,8 @@ namespace DFHack // FIXME: define in Memory.xml instead? #define NUM_CREATURE_TRAITS 30 #define NUM_CREATURE_LABORS 102 +#define NUM_CREATURE_MENTAL_ATTRIBUTES 13 +#define NUM_CREATURE_PHYSICAL_ATTRIBUTES 6 struct t_soul { diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index c47201ffc..53a9060c9 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -195,7 +195,9 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) p->readDWord (temp + offs.flags2_offset, furball.flags2.whole); // physical attributes - p->read(temp + offs.physical_offset, sizeof(t_attrib) * 6, (uint8_t *)&furball.strength); + p->read(temp + offs.physical_offset, + sizeof(t_attrib) * NUM_CREATURE_PHYSICAL_ATTRIBUTES, + (uint8_t *)&furball.strength); // mood stuff furball.mood = (int16_t) p->readWord (temp + offs.mood_offset); @@ -252,25 +254,34 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) */ uint32_t soul = p->readDWord(temp + offs.default_soul_offset); furball.has_default_soul = false; + if(soul) { furball.has_default_soul = true; // get first soul's skills DfVector skills(p, soul + offs.soul_skills_vector_offset); furball.defaultSoul.numSkills = skills.size(); + for (uint32_t i = 0; i < furball.defaultSoul.numSkills;i++) { uint32_t temp2 = skills[i]; // a byte: this gives us 256 skills maximum. ??? furball.defaultSoul.skills[i].id = p->readDWord (temp2); - furball.defaultSoul.skills[i].rating = p->readDWord (temp2 + 4); - furball.defaultSoul.skills[i].experience = p->readDWord (temp2 + 8); + furball.defaultSoul.skills[i].rating = + p->readDWord (temp2 + offsetof(t_skill, rating)); + furball.defaultSoul.skills[i].experience = + p->readDWord (temp2 + offsetof(t_skill, experience)); } + // mental attributes are part of the soul - p->read(soul + offs.soul_mental_offset, sizeof(t_attrib) * 13, (uint8_t *)&furball.defaultSoul.analytical_ability); + p->read(soul + offs.soul_mental_offset, + sizeof(t_attrib) * NUM_CREATURE_MENTAL_ATTRIBUTES, + (uint8_t *)&furball.defaultSoul.analytical_ability); // traits as well - p->read(soul + offs.soul_traits_offset, sizeof (uint16_t) * NUM_CREATURE_TRAITS, (uint8_t *) &furball.defaultSoul.traits); + p->read(soul + offs.soul_traits_offset, + sizeof (uint16_t) * NUM_CREATURE_TRAITS, + (uint8_t *) &furball.defaultSoul.traits); } DfVector app(p, temp + offs.appearance_vector_offset); @@ -402,8 +413,8 @@ bool Creatures::WriteSkills(const uint32_t index, const t_soul &soul) for (uint32_t i=0; iwriteDWord(temp2 + 4, soul.skills[i].rating); - p->writeDWord(temp2 + 8, soul.skills[i].experience); + p->writeDWord(temp2 + offsetof(t_skill, rating), soul.skills[i].rating); + p->writeDWord(temp2 + offsetof(t_skill, experiance), soul.skills[i].experience); } return true; @@ -423,12 +434,12 @@ bool Creatures::WriteAttributes(const uint32_t index, const t_creature &creature // physical attributes p->write(temp + d->creatures.physical_offset, - sizeof(t_attrib) * 6, + sizeof(t_attrib) * NUM_CREATURE_PHYSICAL_ATTRIBUTES, (uint8_t *)&creature.strength); // mental attributes are part of the soul p->write(souloff + d->creatures.soul_mental_offset, - sizeof(t_attrib) * 13, + sizeof(t_attrib) * NUM_CREATURE_MENTAL_ATTRIBUTES, (uint8_t *)&creature.defaultSoul.analytical_ability); return true; From 5e105c95710c3f5f401a39d4450a033bc35f1f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Wed, 16 Jun 2010 02:03:37 +0200 Subject: [PATCH 049/122] fix typo --- library/modules/Creatures.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index 53a9060c9..1b9fcbdc2 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -414,7 +414,7 @@ bool Creatures::WriteSkills(const uint32_t index, const t_soul &soul) { uint32_t temp2 = skills[i]; p->writeDWord(temp2 + offsetof(t_skill, rating), soul.skills[i].rating); - p->writeDWord(temp2 + offsetof(t_skill, experiance), soul.skills[i].experience); + p->writeDWord(temp2 + offsetof(t_skill, experience), soul.skills[i].experience); } return true; From 9a15f00c8dad35e634fbeb09fd804c59c0e4cd19 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Wed, 16 Jun 2010 20:47:05 +0100 Subject: [PATCH 050/122] bug fix, sex writing (seems to work ok), trait writing(untested) --- library/DFMemInfo.cpp | 5 ++++ library/include/dfhack/DFMemInfo.h | 1 + library/include/dfhack/modules/Creatures.h | 6 +++-- library/modules/Creatures.cpp | 29 ++++++++++++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index 6b3fa0ffe..5c329ff8d 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -698,6 +698,11 @@ string memory_info::getTraitName(const uint32_t traitIdx) const throw Error::MissingMemoryDefinition("traitname", traitIdx); } +std::vector< std::vector> const& memory_info::getAllTraits() +{ + return d->traits; +} + string memory_info::getLabor (const uint32_t laborIdx) { if(d->labors.count(laborIdx)) diff --git a/library/include/dfhack/DFMemInfo.h b/library/include/dfhack/DFMemInfo.h index d3370fc5b..84b76da69 100644 --- a/library/include/dfhack/DFMemInfo.h +++ b/library/include/dfhack/DFMemInfo.h @@ -73,6 +73,7 @@ namespace DFHack std::string getTrait (const uint32_t, const uint32_t) const; std::string getTraitName(const uint32_t) const; std::string getLabor (const uint32_t); + std::vector< std::vector> const& getAllTraits(); DFHack::t_level getLevelInfo(const uint32_t level) const; diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 670e37cff..99db5853e 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -256,9 +256,9 @@ namespace DFHack struct t_skill { - uint32_t id; - uint32_t experience; + uint32_t id; uint32_t rating; + uint32_t experience; }; struct t_job { @@ -385,6 +385,8 @@ namespace DFHack bool WriteFlags(const uint32_t index, const uint32_t flags1, const uint32_t flags2); bool WriteSkills(const uint32_t index, const t_soul &soul); bool WriteAttributes(const uint32_t index, const t_creature &creature); + bool WriteSex(const uint32_t index, const uint8_t sex); + bool WriteTraits(const uint32_t index, const t_soul &soul); private: struct Private; diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index 1b9fcbdc2..55cc15ccb 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -445,6 +445,35 @@ bool Creatures::WriteAttributes(const uint32_t index, const t_creature &creature return true; } +bool Creatures::WriteSex(const uint32_t index, const uint8_t sex) +{ + if(!d->Started) + return false; + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + p->writeByte (temp + d->creatures.sex_offset, sex); +} + +bool Creatures::WriteTraits(const uint32_t index, const t_soul &soul) +{ + if(!d->Started) + return false; + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + uint32_t souloff = p->readDWord(temp + d->creatures.default_soul_offset); + + if(!souloff) + return false; + + p->write(souloff + d->creatures.soul_traits_offset, + sizeof (uint16_t) * NUM_CREATURE_TRAITS, + (uint8_t *) &soul.traits); + + return true; +} + uint32_t Creatures::GetDwarfRaceIndex() { if(!d->Inited) return 0; From c53b6438860985f10d3d5412b4e7e18a1d526190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Thu, 17 Jun 2010 06:46:20 +0200 Subject: [PATCH 051/122] Fix liquids bug, added status checks to Maps (still not the real thing, but better) --- library/include/dfhack/DFError.h | 10 ++++ library/modules/Maps.cpp | 29 +++++++-- tools/playground/CMakeLists.txt | 2 +- tools/playground/incrementalsearch.cpp | 81 ++++++++++++++++++++++++++ tools/playground/typeblocks.cpp | 43 ++++++++++++++ tools/supported/liquids.cpp | 4 +- 6 files changed, 162 insertions(+), 7 deletions(-) create mode 100644 tools/playground/typeblocks.cpp diff --git a/library/include/dfhack/DFError.h b/library/include/dfhack/DFError.h index d838c5623..79823a9fa 100644 --- a/library/include/dfhack/DFError.h +++ b/library/include/dfhack/DFError.h @@ -297,6 +297,16 @@ namespace DFHack return "SHM ATTACH FAILURE"; } }; + class DFHACK_EXPORT ModuleNotInitialized : public std::exception + { + public: + ModuleNotInitialized() {} + virtual ~ModuleNotInitialized() throw(){}; + virtual const char* what() const throw() + { + return "Programmer error: module not initialized!"; + } + }; } } diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index af0a8be9b..b14b7f062 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -37,7 +37,7 @@ distribution. #define SHMCMD(num) ((shm_cmd *)d->d->shm_start)[num]->pingpong #define SHMHDR ((shm_core_hdr *)d->d->shm_start) #define SHMDATA(type) ((type *)(d->d->shm_start + SHM_HEADER)) - +#define MAPS_GUARD if(!d->Started) throw DFHack::Error::ModuleNotInitialized(); using namespace DFHack; struct Maps::Private @@ -101,9 +101,6 @@ Maps::Maps(DFContextShared* _d) off.world_size_x = mem->getAddress ("world_size_x"); off.world_size_y = mem->getAddress ("world_size_y"); - - - // these can fail and will be found when looking at the actual veins later // basically a cache off.vein_ice_vptr = 0; @@ -193,6 +190,7 @@ bool Maps::Start() // getter for map size void Maps::getSize (uint32_t& x, uint32_t& y, uint32_t& z) { + MAPS_GUARD x = d->x_block_count; y = d->y_block_count; z = d->z_block_count; @@ -216,6 +214,7 @@ bool Maps::Finish() bool Maps::isValidBlock (uint32_t x, uint32_t y, uint32_t z) { + MAPS_GUARD if ( x >= d->x_block_count || y >= d->y_block_count || z >= d->z_block_count) return false; return d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z] != 0; @@ -223,6 +222,7 @@ bool Maps::isValidBlock (uint32_t x, uint32_t y, uint32_t z) uint32_t Maps::getBlockPtr (uint32_t x, uint32_t y, uint32_t z) { + MAPS_GUARD if ( x >= d->x_block_count || y >= d->y_block_count || z >= d->z_block_count) return 0; return d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; @@ -230,6 +230,7 @@ uint32_t Maps::getBlockPtr (uint32_t x, uint32_t y, uint32_t z) bool Maps::ReadBlock40d(uint32_t x, uint32_t y, uint32_t z, mapblock40d * buffer) { + MAPS_GUARD Process *p = d->owner; if(d->d->shm_start && d->maps_module) // ACCELERATE! { @@ -268,6 +269,7 @@ bool Maps::ReadBlock40d(uint32_t x, uint32_t y, uint32_t z, mapblock40d * buffer bool Maps::ReadTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buffer) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -279,6 +281,7 @@ bool Maps::ReadTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buff bool Maps::WriteTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buffer) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -294,6 +297,7 @@ bool Maps::WriteTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buf bool Maps::ReadDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool &dirtybit) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if(addr) { @@ -307,6 +311,7 @@ bool Maps::ReadDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool &dirtybit) bool Maps::WriteDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool dirtybit) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -324,6 +329,7 @@ bool Maps::WriteDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool dirtybit) /// read/write the block flags bool Maps::ReadBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags &blockflags) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if(addr) { @@ -336,6 +342,7 @@ bool Maps::ReadBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags &bloc } bool Maps::WriteBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags blockflags) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -353,6 +360,7 @@ bool Maps::WriteBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags bloc bool Maps::ReadDesignations (uint32_t x, uint32_t y, uint32_t z, designations40d *buffer) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -364,6 +372,7 @@ bool Maps::ReadDesignations (uint32_t x, uint32_t y, uint32_t z, designations40d bool Maps::WriteDesignations (uint32_t x, uint32_t y, uint32_t z, designations40d *buffer) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -379,6 +388,7 @@ bool Maps::WriteDesignations (uint32_t x, uint32_t y, uint32_t z, designations40 bool Maps::ReadOccupancy (uint32_t x, uint32_t y, uint32_t z, occupancies40d *buffer) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -390,6 +400,7 @@ bool Maps::ReadOccupancy (uint32_t x, uint32_t y, uint32_t z, occupancies40d *bu bool Maps::WriteOccupancy (uint32_t x, uint32_t y, uint32_t z, occupancies40d *buffer) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -404,6 +415,7 @@ bool Maps::WriteOccupancy (uint32_t x, uint32_t y, uint32_t z, occupancies40d *b */ bool Maps::ReadTemperatures(uint32_t x, uint32_t y, uint32_t z, t_temperatures *temp1, t_temperatures *temp2) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -417,6 +429,7 @@ bool Maps::ReadTemperatures(uint32_t x, uint32_t y, uint32_t z, t_temperatures * } bool Maps::WriteTemperatures (uint32_t x, uint32_t y, uint32_t z, t_temperatures *temp1, t_temperatures *temp2) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -434,6 +447,7 @@ bool Maps::WriteTemperatures (uint32_t x, uint32_t y, uint32_t z, t_temperatures */ bool Maps::ReadRegionOffsets (uint32_t x, uint32_t y, uint32_t z, biome_indices40d *buffer) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -445,6 +459,7 @@ bool Maps::ReadRegionOffsets (uint32_t x, uint32_t y, uint32_t z, biome_indices4 bool Maps::ReadFeatures(uint32_t x, uint32_t y, uint32_t z, int16_t & local, int16_t & global) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -458,6 +473,7 @@ bool Maps::ReadFeatures(uint32_t x, uint32_t y, uint32_t z, int16_t & local, int bool Maps::WriteLocalFeature(uint32_t x, uint32_t y, uint32_t z, int16_t local) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -470,6 +486,7 @@ bool Maps::WriteLocalFeature(uint32_t x, uint32_t y, uint32_t z, int16_t local) bool Maps::WriteGlobalFeature(uint32_t x, uint32_t y, uint32_t z, int16_t global) { + MAPS_GUARD uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { @@ -485,6 +502,7 @@ bool Maps::WriteGlobalFeature(uint32_t x, uint32_t y, uint32_t z, int16_t global */ bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector * veins, vector * ices, vector *splatter) { + MAPS_GUARD t_vein v; t_frozenliquidvein fv; t_spattervein sv; @@ -625,6 +643,7 @@ __int16 __userpurge GetGeologicalRegion(__int16 block_X, int X, __i */ bool Maps::ReadGeology (vector < vector >& assign) { + MAPS_GUARD memory_info * minfo = d->d->offset_descriptor; Process *p = d->owner; // get needed addresses and offsets. Now this is what I call crazy. @@ -694,6 +713,7 @@ bool Maps::ReadGeology (vector < vector >& assign) bool Maps::ReadLocalFeatures( std::map > & local_features ) { + MAPS_GUARD // can't be used without a map! if(!d->block) return false; @@ -792,6 +812,7 @@ bool Maps::ReadLocalFeatures( std::map > & bool Maps::ReadGlobalFeatures( std::vector & features) { + MAPS_GUARD // can't be used without a map! if(!d->block) return false; diff --git a/tools/playground/CMakeLists.txt b/tools/playground/CMakeLists.txt index ee43d8c20..749922a5a 100644 --- a/tools/playground/CMakeLists.txt +++ b/tools/playground/CMakeLists.txt @@ -55,4 +55,4 @@ TARGET_LINK_LIBRARIES(dfcatsplosion dfhack) # df directly # Author: belal #ADD_EXECUTABLE(dfrenamer renamer.cpp) -#TARGET_LINK_LIBRARIES(dfrenamer dfhack) \ No newline at end of file +#TARGET_LINK_LIBRARIES(dfrenamer dfhack) diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index 3c3014dca..ff3f5b592 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -20,6 +20,87 @@ using namespace std; #include #include "SegmentedFinder.h" +template +class holder +{ + public: + vector values; + SegmentedFinder & sf; + holder(SegmentedFinder& sff):sf(sff){}; + bool isValid(size_t idx) + { + + }; +}; + +class address +{ + public: + uint64_t addr_; + unsigned int valid : 1; + virtual void print(SegmentedFinder& sff) + { + cout << hex << "0x" << addr_ << endl; + }; + address(const uint64_t addr) + { + addr_ = addr; + valid = false; + } + address & operator=(const uint64_t in) + { + addr_ = in; + valid = false; + return *this; + } + bool isValid(SegmentedFinder& sff) + { + if(valid) return true; + if(sff.getSegmentForAddress(addr_)) + { + valid = 1; + } + } +}; + +class Cstr: public address +{ + void print(SegmentedFinder & sf) + { + cout << hex << "0x" << addr_ << ": \"" << sf.Translate(addr_) << "\"" << endl; + } +}; +// STL STRING +#ifdef LINUX_BUILD +class STLstr: public address +{ + +}; +#endif +#ifndef LINUX_BUILD +class STLstr: public address +{ + +}; +#endif + +// STL VECTOR +#ifdef LINUX_BUILD +class Vector: public address +{ + +}; +#endif +#ifndef LINUX_BUILD +class Vector: public address +{ + +}; +#endif +class Int64: public address{}; +class Int32: public address{}; +class Int16: public address{}; +class Int8: public address{}; inline void printRange(DFHack::t_memrange * tpr) { diff --git a/tools/playground/typeblocks.cpp b/tools/playground/typeblocks.cpp new file mode 100644 index 000000000..3a0b88f31 --- /dev/null +++ b/tools/playground/typeblocks.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +#include +using namespace DFHack; + +namespace TBlocks +{ + +} + +int main (int numargs, const char ** args) +{ + DFHack::ContextManager DFMgr("Memory.xml"); + DFHack::Context * DF; + try + { + DF = DFMgr.getSingleContext(); + DF->Attach(); + } + catch (exception& e) + { + cerr << e.what() << endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + + // DO STUFF HERE + + #ifndef LINUX_BUILD + cout << "Done. Press any key to continue" << endl; + cin.ignore(); + #endif + return 0; +} diff --git a/tools/supported/liquids.cpp b/tools/supported/liquids.cpp index d125c7ad1..b93c6cc29 100644 --- a/tools/supported/liquids.cpp +++ b/tools/supported/liquids.cpp @@ -26,6 +26,8 @@ int main (void) DF=DFMgr.getSingleContext(); DF->Attach(); Maps = DF->getMaps(); + Maps->Start(); + Maps->getSize(x_max,y_max,z_max); Position = DF->getPosition(); } catch (exception& e) @@ -44,7 +46,6 @@ int main (void) int amount = 7; while(!end) { - Maps->getSize(x_max,y_max,z_max); DF->Resume(); string command = ""; cout <<"[" << mode << ":" << amount << ":" << flowmode << "]# "; @@ -71,7 +72,6 @@ int main (void) << endl << "Usage: point the DF cursor at a tile you want to modify" << endl << "and use the commands available :)" << endl; - } else if(command == "m") { From 061108c6855455bdc361d78321754f9dc1fb67f4 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Thu, 17 Jun 2010 19:24:18 +0100 Subject: [PATCH 052/122] weird skill reading byte alignment fix (reverted to how it was original minus the offsetof change) --- library/modules/Creatures.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index 55cc15ccb..e1250f01b 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -265,12 +265,12 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) for (uint32_t i = 0; i < furball.defaultSoul.numSkills;i++) { uint32_t temp2 = skills[i]; - // a byte: this gives us 256 skills maximum. ??? - furball.defaultSoul.skills[i].id = p->readDWord (temp2); - furball.defaultSoul.skills[i].rating = - p->readDWord (temp2 + offsetof(t_skill, rating)); + // a byte: this gives us 256 skills maximum. + furball.defaultSoul.skills[i].id = p->readByte (temp2); + furball.defaultSoul.skills[i].rating = + p->readByte (temp2 + offsetof(t_skill, rating)); furball.defaultSoul.skills[i].experience = - p->readDWord (temp2 + offsetof(t_skill, experience)); + p->readWord (temp2 + offsetof(t_skill, experience)); } // mental attributes are part of the soul @@ -413,8 +413,8 @@ bool Creatures::WriteSkills(const uint32_t index, const t_soul &soul) for (uint32_t i=0; iwriteDWord(temp2 + offsetof(t_skill, rating), soul.skills[i].rating); - p->writeDWord(temp2 + offsetof(t_skill, experience), soul.skills[i].experience); + p->writeByte(temp2 + offsetof(t_skill, rating), soul.skills[i].rating); + p->writeWord(temp2 + offsetof(t_skill, experience), soul.skills[i].experience); } return true; From d58260740f6d993c06aeb412f62fa71b5fe08ce0 Mon Sep 17 00:00:00 2001 From: doomchild Date: Thu, 17 Jun 2010 15:29:29 -0500 Subject: [PATCH 053/122] moved the old Python/C stuff to python/deprecated renamed "c api" to "pydfhack" --- library/python/c api/gui.py | 25 -- library/python/c api/materials.py | 141 -------- library/python/c api/position.py | 43 --- library/python/c api/pydftypes.py | 315 ---------------- library/python/c api/vegetation.py | 25 -- .../python/{ => deprecated}/CMakeLists.txt | 0 library/python/{ => deprecated}/DF_API.cpp | 0 .../python/{ => deprecated}/DF_Buildings.cpp | 0 .../{ => deprecated}/DF_Constructions.cpp | 0 .../{ => deprecated}/DF_CreatureManager.cpp | 0 .../{ => deprecated}/DF_CreatureType.cpp | 0 library/python/{ => deprecated}/DF_GUI.cpp | 0 .../python/{ => deprecated}/DF_Helpers.cpp | 0 .../python/{ => deprecated}/DF_Imports.cpp | 0 library/python/{ => deprecated}/DF_Maps.cpp | 0 .../python/{ => deprecated}/DF_Material.cpp | 0 .../python/{ => deprecated}/DF_MemInfo.cpp | 0 .../python/{ => deprecated}/DF_Position.cpp | 0 .../python/{ => deprecated}/DF_Translate.cpp | 0 .../python/{ => deprecated}/DF_Vegetation.cpp | 0 library/python/{ => deprecated}/build-linux | 0 library/python/{ => deprecated}/build.bat | 0 .../{ => deprecated}/dfhack_api_ctypes.py | 0 .../{ => deprecated}/examples/attachtest.py | 0 .../{ => deprecated}/examples/miscutils.py | 0 .../{ => deprecated}/examples/position.py | 0 .../examples/settlementdump.py | 0 .../{ => deprecated}/examples/suspendtest.py | 0 .../{ => deprecated}/examples/treedump.py | 0 library/python/{ => deprecated}/ez_setup.py | 0 library/python/{ => deprecated}/linsetup.py | 0 library/python/{ => deprecated}/pydfhack.cpp | 0 .../{ => deprecated}/pydfhack/__init__.py | 0 .../{ => deprecated}/pydfhack/blocks.py | 0 .../{ => deprecated}/pydfhack/construction.py | 0 .../{ => deprecated}/pydfhack/creature.py | 0 .../{ => deprecated}/pydfhack/decorators.py | 0 library/python/deprecated/pydfhack/gui.py | 25 ++ .../python/{ => deprecated}/pydfhack/map.py | 0 .../python/deprecated/pydfhack/materials.py | 42 +++ .../{ => deprecated}/pydfhack/meminfo.py | 0 .../{ => deprecated}/pydfhack/mixins.py | 0 .../python/deprecated/pydfhack/position.py | 42 +++ .../{ => deprecated}/pydfhack/pydfapi.py | 0 .../pydfhack}/pydfhackflags.py | 27 +- .../python/deprecated/pydfhack/pydftypes.py | 50 +++ .../{ => deprecated}/pydfhack/translation.py | 0 .../python/deprecated/pydfhack/vegetation.py | 18 + library/python/{ => deprecated}/setup.py | 0 library/python/{ => deprecated}/test.py | 0 .../python/{ => deprecated}/tools/shell.py | 0 .../python/{ => deprecated}/tools/trees.py | 0 .../python/{c api => pydfhack}/buildings.py | 0 .../{c api => pydfhack}/constructions.py | 0 library/python/{c api => pydfhack}/context.py | 0 .../python/{c api => pydfhack}/creatures.py | 0 .../{c api => pydfhack}/dfhack_api_ctypes.py | 0 library/python/{c api => pydfhack}/enum.py | 0 library/python/pydfhack/gui.py | 46 +-- library/python/{c api => pydfhack}/items.py | 0 library/python/{c api => pydfhack}/maps.py | 0 library/python/pydfhack/materials.py | 183 +++++++--- library/python/pydfhack/position.py | 77 ++-- library/python/pydfhack/pydfhackflags.py | 27 +- library/python/pydfhack/pydftypes.py | 335 ++++++++++++++++-- library/python/{c api => pydfhack}/util.py | 0 library/python/pydfhack/vegetation.py | 39 +- 67 files changed, 730 insertions(+), 730 deletions(-) delete mode 100644 library/python/c api/gui.py delete mode 100644 library/python/c api/materials.py delete mode 100644 library/python/c api/position.py delete mode 100644 library/python/c api/pydftypes.py delete mode 100644 library/python/c api/vegetation.py rename library/python/{ => deprecated}/CMakeLists.txt (100%) rename library/python/{ => deprecated}/DF_API.cpp (100%) rename library/python/{ => deprecated}/DF_Buildings.cpp (100%) rename library/python/{ => deprecated}/DF_Constructions.cpp (100%) rename library/python/{ => deprecated}/DF_CreatureManager.cpp (100%) rename library/python/{ => deprecated}/DF_CreatureType.cpp (100%) rename library/python/{ => deprecated}/DF_GUI.cpp (100%) rename library/python/{ => deprecated}/DF_Helpers.cpp (100%) rename library/python/{ => deprecated}/DF_Imports.cpp (100%) rename library/python/{ => deprecated}/DF_Maps.cpp (100%) rename library/python/{ => deprecated}/DF_Material.cpp (100%) rename library/python/{ => deprecated}/DF_MemInfo.cpp (100%) rename library/python/{ => deprecated}/DF_Position.cpp (100%) rename library/python/{ => deprecated}/DF_Translate.cpp (100%) rename library/python/{ => deprecated}/DF_Vegetation.cpp (100%) rename library/python/{ => deprecated}/build-linux (100%) rename library/python/{ => deprecated}/build.bat (100%) rename library/python/{ => deprecated}/dfhack_api_ctypes.py (100%) rename library/python/{ => deprecated}/examples/attachtest.py (100%) rename library/python/{ => deprecated}/examples/miscutils.py (100%) rename library/python/{ => deprecated}/examples/position.py (100%) rename library/python/{ => deprecated}/examples/settlementdump.py (100%) rename library/python/{ => deprecated}/examples/suspendtest.py (100%) rename library/python/{ => deprecated}/examples/treedump.py (100%) rename library/python/{ => deprecated}/ez_setup.py (100%) rename library/python/{ => deprecated}/linsetup.py (100%) rename library/python/{ => deprecated}/pydfhack.cpp (100%) rename library/python/{ => deprecated}/pydfhack/__init__.py (100%) rename library/python/{ => deprecated}/pydfhack/blocks.py (100%) rename library/python/{ => deprecated}/pydfhack/construction.py (100%) rename library/python/{ => deprecated}/pydfhack/creature.py (100%) rename library/python/{ => deprecated}/pydfhack/decorators.py (100%) create mode 100644 library/python/deprecated/pydfhack/gui.py rename library/python/{ => deprecated}/pydfhack/map.py (100%) create mode 100644 library/python/deprecated/pydfhack/materials.py rename library/python/{ => deprecated}/pydfhack/meminfo.py (100%) rename library/python/{ => deprecated}/pydfhack/mixins.py (100%) create mode 100644 library/python/deprecated/pydfhack/position.py rename library/python/{ => deprecated}/pydfhack/pydfapi.py (100%) rename library/python/{c api => deprecated/pydfhack}/pydfhackflags.py (91%) create mode 100644 library/python/deprecated/pydfhack/pydftypes.py rename library/python/{ => deprecated}/pydfhack/translation.py (100%) create mode 100644 library/python/deprecated/pydfhack/vegetation.py rename library/python/{ => deprecated}/setup.py (100%) rename library/python/{ => deprecated}/test.py (100%) rename library/python/{ => deprecated}/tools/shell.py (100%) rename library/python/{ => deprecated}/tools/trees.py (100%) rename library/python/{c api => pydfhack}/buildings.py (100%) rename library/python/{c api => pydfhack}/constructions.py (100%) rename library/python/{c api => pydfhack}/context.py (100%) rename library/python/{c api => pydfhack}/creatures.py (100%) rename library/python/{c api => pydfhack}/dfhack_api_ctypes.py (100%) rename library/python/{c api => pydfhack}/enum.py (100%) rename library/python/{c api => pydfhack}/items.py (100%) rename library/python/{c api => pydfhack}/maps.py (100%) rename library/python/{c api => pydfhack}/util.py (100%) diff --git a/library/python/c api/gui.py b/library/python/c api/gui.py deleted file mode 100644 index 09a7c5c94..000000000 --- a/library/python/c api/gui.py +++ /dev/null @@ -1,25 +0,0 @@ -from ctypes import * -from pydfhack import libdfhack, ViewScreen - -libdfhack.Gui_ReadViewScreen.argtypes = [ c_void_p, c_void_p ] - -class Gui(object): - def __init__(self, ptr): - self._gui_ptr = ptr - - def start(self): - return libdfhack.Gui_Start(self._gui_ptr) - - def finish(self): - return libdfhack.Gui_Finish(self._gui_ptr) - - def read_pause_state(self): - return libdfhack.Gui_ReadPauseState(self._pos_ptr) > 0 - - def read_view_screen(self): - s = ViewScreen() - - if libdfhack.Gui_ReadViewScreen(self._gui_ptr, byref(s)) > 0: - return s - else: - return None diff --git a/library/python/c api/materials.py b/library/python/c api/materials.py deleted file mode 100644 index 04d82fddb..000000000 --- a/library/python/c api/materials.py +++ /dev/null @@ -1,141 +0,0 @@ -from ctypes import * -from pydftypes import libdfhack -from util import * - -_get_arg_types = [ c_void_p, _arr_create_func ] - -libdfhack.Materials_getInorganic.argtypes = _get_arg_types -libdfhack.Materials_getOrganic.argtypes = _get_arg_types -libdfhack.Materials_getTree.argtypes = _get_arg_types -libdfhack.Materials_getPlant.argtypes = _get_arg_types -libdfhack.Materials_getRace.argtypes = _get_arg_types -#libdfhack.Materials_getRaceEx.argtypes = _get_arg_types -libdfhack.Materials_getColor.argtypes = _get_arg_types -libdfhack.Materials_getOther.argtypes = _get_arg_types - -class Materials(object): - def __init__(self, ptr): - self._mat_ptr = ptr - - self.inorganic = None - self.organic = None - self.tree = None - self.plant = None - self.race = None - self.race_ex = None - self.color = None - self.other = None - - def read_inorganic(self): - return libdfhack.Materials_ReadInorganicMaterials(self._mat_ptr) - - def read_organic(self): - return libdfhack.Materials_ReadOrganicMaterials(self._mat_ptr) - - def read_wood(self): - return libdfhack.Materials_ReadWoodMaterials(self._mat_ptr) - - def read_plant(self): - return libdfhack.Materials_ReadPlantMaterials(self._mat_ptr) - - def read_creature_types(self): - return libdfhack.Materials_ReadCreatureTypes(self._mat_ptr) - - def read_creature_types_ex(self): - return libdfhack.Materials_ReadCreatureTypesEx(self._mat_ptr) - - def read_descriptor_colors(self): - return libdfhack.Materials_ReadDescriptorColors(self._mat_ptr) - - def read_others(self): - return libdfhack.Materials_ReadOthers(self._mat_ptr) - - def read_all(self): - libdfhack.Materials_ReadAllMaterials(self._mat_ptr) - - def get_description(self, material): - return libdfhack.Materials_getDescription(self._mat_ptr, byref(material)) - - def update_inorganic_cache(self): - def update_callback(count): - allocated = _allocate_array(Matgloss, count) - - self.inorganic = allocated[0] - - return allocated[1] - - callback = _arr_create_func(update_callback) - - return libdfhack.Materials_getInorganic(self._mat_ptr, callback) - - def update_organic_cache(self): - def update_callback(count): - allocated = _allocate_array(Matgloss, count) - - self.organic = allocated[0] - - return allocated[1] - - callback = _arr_create_func(update_callback) - - return libdfhack.Materials_getOrganic(self._mat_ptr, callback) - - def update_tree_cache(self): - def update_callback(count): - allocated = _allocate_array(Matgloss, count) - - self.tree = allocated[0] - - return allocated[1] - - callback = _arr_create_func(update_callback) - - return libdfhack.Materials_getTree(self._mat_ptr, callback) - - def update_plant_cache(self): - def update_callback(count): - allocated = _allocate_array(Matgloss, count) - - self.plant = allocated[0] - - return allocated[1] - - callback = _arr_create_func(update_callback) - - return libdfhack.Materials_getPlant(self._mat_ptr, callback) - - def update_race_cache(self): - def update_callback(count): - allocated = _allocate_array(Matgloss, count) - - self.race = allocated[0] - - return allocated[1] - - callback = _arr_create_func(update_callback) - - return libdfhack.Materials_getRace(self._mat_ptr, callback) - - def update_color_cache(self): - def update_callback(count): - allocated = _allocate_array(DescriptorColor, count) - - self.color = allocated[0] - - return allocated[1] - - callback = _arr_create_func(update_callback) - - return libdfhack.Materials_getColor(self._mat_ptr, callback) - - def update_other_cache(self): - def update_callback(count): - allocated = _allocate_array(MatglossOther, count) - - self.other = allocated[0] - - return allocated[1] - - callback = _arr_create_func(update_callback) - - return libdfhack.Materials_getOther(self._mat_ptr, callback) diff --git a/library/python/c api/position.py b/library/python/c api/position.py deleted file mode 100644 index ffa758150..000000000 --- a/library/python/c api/position.py +++ /dev/null @@ -1,43 +0,0 @@ -from ctypes import * -from pydftypes import libdfhack - -class Position(object): - def __init__(self, ptr): - self._pos_ptr = ptr - - self._vx, self._vy, self._vz = c_int(), c_int(), c_int() - self._cx, self._cy, self._cz = c_int(), c_int(), c_int() - self._ww, self._wh = c_int(), c_int() - - def get_view_coords(self): - if libdfhack.Position_getViewCoords(self._pos_ptr, byref(self._vx), byref(self._vy), byref(self._vz)) > 0: - return (self._vx.value, self._vy.value, self._vz.value) - else: - return (-1, -1, -1) - - def set_view_coords(self, v_coords): - self._vx.value, self._vy.value, self._vz.value = v_coords - - libdfhack.Position_setViewCoords(self._pos_ptr, self._vx, self._vy, self._vz) - - view_coords = property(get_view_coords, set_view_coords) - - def get_cursor_coords(self): - if libdfhack.Position_getCursorCoords(self._pos_ptr, byref(self._cx), byref(self._cy), byref(self._cz)) > 0: - return (self._cx.value, self._cy.value, self._cz.value) - else: - return (-1, -1, -1) - - def set_cursor_coords(self, c_coords): - self._cx.value, self._cy.value, self_cz.value = c_coords - - libdfhack.Position_setCursorCoords(self._pos_ptr, self._cx, self._cy, self._cz) - - cursor_coords = property(get_cursor_coords, set_cursor_coords) - - @property - def window_size(self): - if libdfhack.Position_getWindowSize(self._pos_ptr, byref(self._ww), byref(self._wh)) > 0: - return (self._ww.value, self._wh.value) - else: - return (-1, -1) diff --git a/library/python/c api/pydftypes.py b/library/python/c api/pydftypes.py deleted file mode 100644 index 376d99238..000000000 --- a/library/python/c api/pydftypes.py +++ /dev/null @@ -1,315 +0,0 @@ -from ctypes import * -from pydfhackflags import * -from enum import * -from util import * - -libdfhack = cdll.libdfhack - -libdfhack.alloc_byte_buffer_callback = alloc_byte_buffer -libdfhack.alloc_ubyte_buffer_callback = alloc_ubyte_buffer -libdfhack.alloc_short_buffer_callback = alloc_short_buffer -libdfhack.alloc_ushort_buffer_callback = alloc_ushort_buffer -libdfhack.alloc_int_buffer_callback = alloc_int_buffer -libdfhack.alloc_uint_buffer_callback = alloc_uint_buffer -libdfhack.alloc_char_buffer_callback = alloc_char_buffer - -int_ptr = POINTER(c_int) -uint_ptr = POINTER(c_uint) - -_arr_create_func = CFUNCTYPE(c_void_p, c_int) - -TileTypes40d = ((c_int * 16) * 16) -BiomeIndices40d = c_ubyte * 16 -Temperatures = ((c_ushort * 16) * 16) -Designations40d = ((DesignationFlags * 16) * 16) -Occupancies40d = ((OccupancyFlags * 16) * 16) - -class Position2D(Structure): - _fields_ = [("x", c_ushort), - ("y", c_ushort)] - -class PlaneCoord(Union): - _fields_ = [("xy", c_uint), - ("dim", Position2D)] - - def __cmp__(self, other): - if isinstance(other, PlaneCoord): - return self.xy - other.xy - else: - raise TypeError("argument must be of type %s" % type(self)) - -class Feature(Structure): - _fields_ = [("type", FeatureType), - ("main_material", c_short), - ("sub_material", c_short), - ("discovered", c_byte), - ("origin", c_uint)] - -class Vein(Structure): - _fields_ = [("vtable", c_uint), - ("type", c_int), - ("assignment", c_short * 16), - ("flags", c_uint), - ("address_of", c_uint)] - -class FrozenLiquidVein(Structure): - _fields_ = [("vtable", c_uint), - ("tiles", TileTypes40d), - ("address_of", c_uint)] - -class SpatterVein(Structure): - _fields_ = [("vtable", c_uint), - ("mat1", c_ushort), - ("unk1", c_ushort), - ("mat2", c_uint), - ("mat3", c_ushort), - ("intensity", ((c_ubyte * 16) * 16)), - ("address_of", c_uint)] - -class MapBlock40d(Structure): - _fields_ = [("tiletypes", TileTypes40d), - ("designation", Designations40d), - ("occupancy", Occupancies40d), - ("biome_indices", BiomeIndices40d), - ("origin", c_uint), - ("blockflags", BlockFlags), - ("global_feature", c_short), - ("local_feature", c_short)] - - -class ViewScreen(Structure): - _fields_ = [("type", c_int)] - -class Matgloss(Structure): - _fields_ = [("id", c_char * 128), - ("fore", c_byte), - ("back", c_byte), - ("bright", c_byte), - ("name", c_char * 128)] - -def _alloc_matgloss_buffer_callback(ptr, count): - allocated = _allocate_array(Matgloss, count) - - ptr = addressof(allocated[0]) - - return 1 - -_matgloss_functype = CFUNCTYPE(c_int, POINTER(Matgloss), c_uint) -libdfhack.alloc_matgloss_buffer_callback = _matgloss_functype(_alloc_matgloss_buffer_callback) - -class MatglossPair(Structure): - _fields_ = [("type", c_short), - ("index", c_int)] - -class DescriptorColor(Structure): - _fields_ = [("id", c_char * 128), - ("r", c_float), - ("v", c_float), - ("b", c_float), - ("name", c_char * 128)] - -def _alloc_descriptor_buffer_callback(ptr, count): - allocated = _allocate_array(DescriptorColor, count) - - ptr = addressof(allocated[0]) - - return 1 - -_descriptor_functype = CFUNCTYPE(c_int, POINTER(DescriptorColor), c_uint) -libdfhack.alloc_descriptor_buffer_callback = _descriptor_functype(_alloc_descriptor_buffer_callback) - -class MatglossOther(Structure): - _fields_ = [("rawname", c_char * 128)] - -def _alloc_matgloss_other_buffer_callback(count): - allocated = _allocate_array(MatglossOther, count) - - ptr = addressof(allocated[0]) - - return 1 - -_matgloss_other_functype = CFUNCTYPE(c_int, POINTER(MatglossOther), c_uint) -libdfhack.alloc_matgloss_other_buffer_callback = _matgloss_other_functype(_alloc_matgloss_other_buffer_callback) - -class Building(Structure): - _fields_ = [("origin", c_uint), - ("vtable", c_uint), - ("x1", c_uint), - ("y1", c_uint), - ("x2", c_uint), - ("y2", c_uint), - ("z", c_uint), - ("material", MatglossPair), - ("type", c_uint)] - -class CustomWorkshop(Structure): - _fields_ = [("index", c_uint), - ("name", c_char * 256)] - -class Construction(Structure): - _fields_ = [("x", c_ushort), - ("y", c_ushort), - ("z", c_ushort), - ("form", c_ushort), - ("unk_8", c_ushort), - ("mat_type", c_ushort), - ("mat_idx", c_ushort), - ("unk3", c_ushort), - ("unk4", c_ushort), - ("unk5", c_ushort), - ("unk6", c_uint), - ("origin", c_uint)] - -class Tree(Structure): - _fields_ = [("type", c_ushort), - ("material", c_ushort), - ("x", c_ushort), - ("y", c_ushort), - ("z", c_ushort), - ("address", c_uint)] - -class Material(Structure): - _fields_ = [("itemType", c_short), - ("subType", c_short), - ("subIndex", c_short), - ("index", c_int), - ("flags", c_uint)] - -class Skill(Structure): - _fields_ = [("id", c_ushort), - ("experience", c_uint), - ("rating", c_ushort)] - -class Job(Structure): - _fields_ = [("active", c_byte), - ("jobId", c_uint), - ("jobType", c_ubyte), - ("occupationPtr", c_uint)] - -class Like(Structure): - _fields_ = [("type", c_short), - ("itemClass", c_short), - ("itemIndex", c_short), - ("material", MatglossPair), - ("active", c_byte)] - -class Attribute(Structure): - _fields_ = [("level", c_uint), - ("field_4", c_uint), - ("field_8", c_uint), - ("field_C", c_uint), - ("leveldiff", c_uint), - ("field_14", c_uint), - ("field_18", c_uint)] - -class Name(Structure): - _fields_ = [("first_name", (c_char * 128)), - ("nickname", (c_char * 128)), - ("words", (c_int * 7)), - ("parts_of_speech", (c_ushort * 7)), - ("language", c_uint), - ("has_name", c_byte)] - -class Note(Structure): - _fields_ = [("symbol", c_char), - ("foreground", c_ushort), - ("background", c_ushort), - ("name", (c_char * 128)), - ("x", c_ushort), - ("y", c_ushort), - ("z", c_ushort)] - -class Settlement(Structure): - _fields_ = [("origin", c_uint), - ("name", Name), - ("world_x", c_short), - ("world_y", c_short), - ("local_x1", c_short), - ("local_x2", c_short), - ("local_y1", c_short), - ("local_y2", c_short)] - -_NUM_CREATURE_TRAITS = 30 -_NUM_CREATURE_LABORS = 102 - -class Soul(Structure): - _fields_ = [("numSkills", c_ubyte), - ("skills", (Skill * 256)), - ("traits", (c_ushort * _NUM_CREATURE_TRAITS)), - ("analytical_ability", Attribute), - ("focus", Attribute), - ("willpower", Attribute), - ("creativity", Attribute), - ("intuition", Attribute), - ("patience", Attribute), - ("memory", Attribute), - ("linguistic_ability", Attribute), - ("spatial_sense", Attribute), - ("musicality", Attribute), - ("kinesthetic_sense", Attribute), - ("empathy", Attribute), - ("social_awareness", Attribute)] - -_MAX_COLORS = 15 - -class Creature(Structure): - _fields_ = [("origin", c_uint), - ("x", c_ushort), - ("y", c_ushort), - ("z", c_ushort), - ("race", c_uint), - ("civ", c_int), - ("flags1", CreatureFlags1), - ("flags2", CreatureFlags2), - ("name", Name), - ("mood", c_short), - ("mood_skill", c_short), - ("artifact_name", Name), - ("profession", c_ubyte), - ("custom_profession", (c_char * 128)), - ("labors", (c_ubyte * _NUM_CREATURE_LABORS)), - ("current_job", Job), - ("happiness", c_uint), - ("id", c_uint), - ("strength", Attribute), - ("agility", Attribute), - ("toughness", Attribute), - ("endurance", Attribute), - ("recuperation", Attribute), - ("disease_resistance", Attribute), - ("squad_leader_id", c_int), - ("sex", c_ubyte), - ("caste", c_ushort), - ("pregnancy_timer", c_uint), - ("has_default_soul", c_byte), - ("defaultSoul", Soul), - ("nbcolors", c_uint), - ("color", (c_uint * _MAX_COLORS))] - -class CreatureExtract(Structure): - _fields_ = [("rawname", (c_char * 128))] - -class BodyPart(Structure): - _fields_ = [("id", (c_char * 128)), - ("category", (c_char * 128)), - ("single", (c_char * 128)), - ("plural", (c_char * 128))] - -class ColorModifier(Structure): - _fields_ = [("part", (c_char * 128)), - ("colorlist", POINTER(c_uint)), - ("colorlistLength", c_uint)] - - def __init__(self): - self.part[0] = '\0' - self.colorlistLength = 0 - -ColorModifierPtr = POINTER(ColorModifier) - -def _alloc_empty_colormodifier_callback(ptr): - ptr = ColorModifierPtr(ColorModifier()) - - return 1 - -_empty_colormodifier_functype = CFUNCTYPE(c_int, ColorModifierPtr) -libdfhack.alloc_empty_colormodifier_callback = _empty_colormodifier_functype(_alloc_empty_colormodifier_callback) diff --git a/library/python/c api/vegetation.py b/library/python/c api/vegetation.py deleted file mode 100644 index 0c22d26b5..000000000 --- a/library/python/c api/vegetation.py +++ /dev/null @@ -1,25 +0,0 @@ -from ctypes import * -from pydftypes import libdfhack, Tree - -class Vegetation(object): - def __init__(self, ptr): - self._v_ptr = ptr - - def start(self): - n = c_uint(0) - - if libdfhack.Vegetation_Start(self._v_ptr, byref(n)) > 0: - return int(n.value) - else: - return -1 - - def finish(self): - return libdfhack.Vegetation_Finish(self._v_ptr) > 0 - - def read(self, index): - t = Tree() - - if libdfhack.Vegetation_Read(self._v_ptr, c_uint(index), byref(t)) > 0: - return t - else: - return None diff --git a/library/python/CMakeLists.txt b/library/python/deprecated/CMakeLists.txt similarity index 100% rename from library/python/CMakeLists.txt rename to library/python/deprecated/CMakeLists.txt diff --git a/library/python/DF_API.cpp b/library/python/deprecated/DF_API.cpp similarity index 100% rename from library/python/DF_API.cpp rename to library/python/deprecated/DF_API.cpp diff --git a/library/python/DF_Buildings.cpp b/library/python/deprecated/DF_Buildings.cpp similarity index 100% rename from library/python/DF_Buildings.cpp rename to library/python/deprecated/DF_Buildings.cpp diff --git a/library/python/DF_Constructions.cpp b/library/python/deprecated/DF_Constructions.cpp similarity index 100% rename from library/python/DF_Constructions.cpp rename to library/python/deprecated/DF_Constructions.cpp diff --git a/library/python/DF_CreatureManager.cpp b/library/python/deprecated/DF_CreatureManager.cpp similarity index 100% rename from library/python/DF_CreatureManager.cpp rename to library/python/deprecated/DF_CreatureManager.cpp diff --git a/library/python/DF_CreatureType.cpp b/library/python/deprecated/DF_CreatureType.cpp similarity index 100% rename from library/python/DF_CreatureType.cpp rename to library/python/deprecated/DF_CreatureType.cpp diff --git a/library/python/DF_GUI.cpp b/library/python/deprecated/DF_GUI.cpp similarity index 100% rename from library/python/DF_GUI.cpp rename to library/python/deprecated/DF_GUI.cpp diff --git a/library/python/DF_Helpers.cpp b/library/python/deprecated/DF_Helpers.cpp similarity index 100% rename from library/python/DF_Helpers.cpp rename to library/python/deprecated/DF_Helpers.cpp diff --git a/library/python/DF_Imports.cpp b/library/python/deprecated/DF_Imports.cpp similarity index 100% rename from library/python/DF_Imports.cpp rename to library/python/deprecated/DF_Imports.cpp diff --git a/library/python/DF_Maps.cpp b/library/python/deprecated/DF_Maps.cpp similarity index 100% rename from library/python/DF_Maps.cpp rename to library/python/deprecated/DF_Maps.cpp diff --git a/library/python/DF_Material.cpp b/library/python/deprecated/DF_Material.cpp similarity index 100% rename from library/python/DF_Material.cpp rename to library/python/deprecated/DF_Material.cpp diff --git a/library/python/DF_MemInfo.cpp b/library/python/deprecated/DF_MemInfo.cpp similarity index 100% rename from library/python/DF_MemInfo.cpp rename to library/python/deprecated/DF_MemInfo.cpp diff --git a/library/python/DF_Position.cpp b/library/python/deprecated/DF_Position.cpp similarity index 100% rename from library/python/DF_Position.cpp rename to library/python/deprecated/DF_Position.cpp diff --git a/library/python/DF_Translate.cpp b/library/python/deprecated/DF_Translate.cpp similarity index 100% rename from library/python/DF_Translate.cpp rename to library/python/deprecated/DF_Translate.cpp diff --git a/library/python/DF_Vegetation.cpp b/library/python/deprecated/DF_Vegetation.cpp similarity index 100% rename from library/python/DF_Vegetation.cpp rename to library/python/deprecated/DF_Vegetation.cpp diff --git a/library/python/build-linux b/library/python/deprecated/build-linux similarity index 100% rename from library/python/build-linux rename to library/python/deprecated/build-linux diff --git a/library/python/build.bat b/library/python/deprecated/build.bat similarity index 100% rename from library/python/build.bat rename to library/python/deprecated/build.bat diff --git a/library/python/dfhack_api_ctypes.py b/library/python/deprecated/dfhack_api_ctypes.py similarity index 100% rename from library/python/dfhack_api_ctypes.py rename to library/python/deprecated/dfhack_api_ctypes.py diff --git a/library/python/examples/attachtest.py b/library/python/deprecated/examples/attachtest.py similarity index 100% rename from library/python/examples/attachtest.py rename to library/python/deprecated/examples/attachtest.py diff --git a/library/python/examples/miscutils.py b/library/python/deprecated/examples/miscutils.py similarity index 100% rename from library/python/examples/miscutils.py rename to library/python/deprecated/examples/miscutils.py diff --git a/library/python/examples/position.py b/library/python/deprecated/examples/position.py similarity index 100% rename from library/python/examples/position.py rename to library/python/deprecated/examples/position.py diff --git a/library/python/examples/settlementdump.py b/library/python/deprecated/examples/settlementdump.py similarity index 100% rename from library/python/examples/settlementdump.py rename to library/python/deprecated/examples/settlementdump.py diff --git a/library/python/examples/suspendtest.py b/library/python/deprecated/examples/suspendtest.py similarity index 100% rename from library/python/examples/suspendtest.py rename to library/python/deprecated/examples/suspendtest.py diff --git a/library/python/examples/treedump.py b/library/python/deprecated/examples/treedump.py similarity index 100% rename from library/python/examples/treedump.py rename to library/python/deprecated/examples/treedump.py diff --git a/library/python/ez_setup.py b/library/python/deprecated/ez_setup.py similarity index 100% rename from library/python/ez_setup.py rename to library/python/deprecated/ez_setup.py diff --git a/library/python/linsetup.py b/library/python/deprecated/linsetup.py similarity index 100% rename from library/python/linsetup.py rename to library/python/deprecated/linsetup.py diff --git a/library/python/pydfhack.cpp b/library/python/deprecated/pydfhack.cpp similarity index 100% rename from library/python/pydfhack.cpp rename to library/python/deprecated/pydfhack.cpp diff --git a/library/python/pydfhack/__init__.py b/library/python/deprecated/pydfhack/__init__.py similarity index 100% rename from library/python/pydfhack/__init__.py rename to library/python/deprecated/pydfhack/__init__.py diff --git a/library/python/pydfhack/blocks.py b/library/python/deprecated/pydfhack/blocks.py similarity index 100% rename from library/python/pydfhack/blocks.py rename to library/python/deprecated/pydfhack/blocks.py diff --git a/library/python/pydfhack/construction.py b/library/python/deprecated/pydfhack/construction.py similarity index 100% rename from library/python/pydfhack/construction.py rename to library/python/deprecated/pydfhack/construction.py diff --git a/library/python/pydfhack/creature.py b/library/python/deprecated/pydfhack/creature.py similarity index 100% rename from library/python/pydfhack/creature.py rename to library/python/deprecated/pydfhack/creature.py diff --git a/library/python/pydfhack/decorators.py b/library/python/deprecated/pydfhack/decorators.py similarity index 100% rename from library/python/pydfhack/decorators.py rename to library/python/deprecated/pydfhack/decorators.py diff --git a/library/python/deprecated/pydfhack/gui.py b/library/python/deprecated/pydfhack/gui.py new file mode 100644 index 000000000..07192f67c --- /dev/null +++ b/library/python/deprecated/pydfhack/gui.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +""" +Python class for DF_Hack::GUI +""" +from ._pydfhack import _GUIManager +class GUI(_GUIManager): + api = None + started = False + def __init__(self, api, *args, **kwds): + _GUIManager.__init__(self, args, kwds) + self.api = api + + def prepare(self): + """ + Enforce Suspend/Start + """ + if self.api.prepare(): + if not self.started: + self.started = self.Start() + return self.started + else: + return False + + + diff --git a/library/python/pydfhack/map.py b/library/python/deprecated/pydfhack/map.py similarity index 100% rename from library/python/pydfhack/map.py rename to library/python/deprecated/pydfhack/map.py diff --git a/library/python/deprecated/pydfhack/materials.py b/library/python/deprecated/pydfhack/materials.py new file mode 100644 index 000000000..13e02c682 --- /dev/null +++ b/library/python/deprecated/pydfhack/materials.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +""" +Python class for DF_Hack::Materials +""" +from ._pydfhack import _MaterialsManager +from .mixins import NoStart +from .decorators import suspend + +class Materials(NoStart, _MaterialsManager): + api = None + cls = _MaterialsManager + def __init__(self, api, *args, **kwds): + cls.__init__(self, args, kwds) + self.api = api + + @suspend + def Read_Wood_Materials(self, *args, **kw): + return self.cls.Read_Wood_Materials(self, *args, **kw) + + @suspend + def Read_Plant_Materials(self, *args, **kw): + return self.cls.Read_Plant_Materials(self, *args, **kw) + + @suspend + def Read_Inorganic_Materials(self, *args, **kw): + return self.cls.Read_Inorganic_Materials(self, *args, **kw) + + @suspend + def Read_Descriptor_Colors(self, *args, **kw): + return self.cls.Read_Descriptor_Colors(self, *args, **kw) + + @suspend + def Read_Creature_Types(self, *args, **kw): + return self.cls.Read_Creature_Types(self, *args, **kw) + + @suspend + def Read_Organic_Materials(self, *args, **kw): + return self.cls.Read_Organic_Materials(self, *args, **kw) + + @suspend + def Read_Creature_Types_Ex(self, *args, **kw): + return self.cls.Read_Creature_Types_Ex(self, *args, **kw) diff --git a/library/python/pydfhack/meminfo.py b/library/python/deprecated/pydfhack/meminfo.py similarity index 100% rename from library/python/pydfhack/meminfo.py rename to library/python/deprecated/pydfhack/meminfo.py diff --git a/library/python/pydfhack/mixins.py b/library/python/deprecated/pydfhack/mixins.py similarity index 100% rename from library/python/pydfhack/mixins.py rename to library/python/deprecated/pydfhack/mixins.py diff --git a/library/python/deprecated/pydfhack/position.py b/library/python/deprecated/pydfhack/position.py new file mode 100644 index 000000000..7956ea812 --- /dev/null +++ b/library/python/deprecated/pydfhack/position.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +""" +Python class for DF_Hack::Position +""" +from ._pydfhack import _PositionManager +from .blocks import Point, Block +from .mixins import NoStart +from .decorators import suspend + +class Position(NoStart, _PositionManager): + api = None + cls = _PositionManager + def __init__(self, api, *args, **kwds): + self.cls.__init__(self, args, kwds) + self.api = api + + @suspend + def get_cursor(self): + coords = self.cursor_coords + if coords: + return Point(*coords) + else: + return None + + @suspend + def get_window_size(self): + wsize = self.window_size + return wsize + + @suspend + def get_view_coords(self): + coords = self.view_coords + return Point(*coords) + + @suspend + def get_cursor_tile(self): + point = self.get_cursor() + if point: + tile = self.api.maps.get_tile(point=point) + return tile + else: + return None diff --git a/library/python/pydfhack/pydfapi.py b/library/python/deprecated/pydfhack/pydfapi.py similarity index 100% rename from library/python/pydfhack/pydfapi.py rename to library/python/deprecated/pydfhack/pydfapi.py diff --git a/library/python/c api/pydfhackflags.py b/library/python/deprecated/pydfhack/pydfhackflags.py similarity index 91% rename from library/python/c api/pydfhackflags.py rename to library/python/deprecated/pydfhack/pydfhackflags.py index 645bba659..f8c15bef7 100644 --- a/library/python/c api/pydfhackflags.py +++ b/library/python/deprecated/pydfhack/pydfhackflags.py @@ -1,11 +1,10 @@ # -*- coding: utf-8 -*- from ctypes import Structure, Union, c_uint -from enum import * class DesignationStruct(Structure): _fields_ = [("flow_size", c_uint, 3), ("pile", c_uint, 1), - ("dig", DesignationType, 3), + ("dig", c_uint, 3), ("smooth", c_uint, 2), ("hidden", c_uint, 1), ("geolayer_index", c_uint, 4), @@ -182,16 +181,30 @@ class ItemFlags(Union): def __int__(self): return self.whole +dig_types = { "no" : 0, + "default" : 1, + "ud_stair" : 2, + "channel" : 3, + "ramp" : 4, + "d_stair" : 5, + "u_stair" : 6, + "whatever" : 7 } + +traffic_types = { "normal" : 0, + "low" : 1, + "high" : 2, + "restricted" : 3 } + class BlockFlagStruct(Structure): _fields_ = [("designated", c_uint, 1), - ("unk_1", c_uint, 1), - ("liquid_1", c_uint, 1), - ("liquid_2", c_uint, 1), - ("unk_2", c_uint, 28)] + ("unk_1", c_uint, 1), + ("liquid_1", c_uint, 1), + ("liquid_2", c_uint, 1), + ("unk_2", c_uint, 28)] class BlockFlags(Union): _fields_ = [("whole", c_uint, 32), - ("bits", BlockFlagStruct)] + ("bits", BlockFlagStruct)] def __init__(self, inital = 0): self.whole = initial diff --git a/library/python/deprecated/pydfhack/pydftypes.py b/library/python/deprecated/pydfhack/pydftypes.py new file mode 100644 index 000000000..eadef49c4 --- /dev/null +++ b/library/python/deprecated/pydfhack/pydftypes.py @@ -0,0 +1,50 @@ +from ctypes import * +from collections import namedtuple + +Position2D = namedtuple("Position2D", "x, y") +Position3D = namedtuple("Position3D", "x, y, z") +Rectangle = namedtuple("Rectangle", "x1, y1, x2, y2") +Note = namedtuple("Note", "symbol, foreground, background, name, position") +Construction = namedtuple("Construction", "position, form, unk_8, mat_type, mat_idx, unk3, unk4, unk5, unk6, origin") +Vein = namedtuple("Vein", "vtable, type, flags, address, assignment") +FrozenLiquidVein = namedtuple("FrozenLiquidVein", "vtable, address, tiles") +SpatterVein = namedtuple("SpatterVein", "vtable, address, mat1, unk1, mat2, mat3, intensity") +Settlement = namedtuple("Settlement", "origin, name, world_pos, local_pos") +Attribute = namedtuple("Attribute", "level, field_4, field_8, field_C, leveldiff, field_14, field_18"); +Skill = namedtuple("Skill", "id, experience, rating") +Tree = namedtuple("Tree", "type, material, position, address") +CreatureCaste = namedtuple("CreatureCaste", "rawname, singular, plural, adjective") +CreatureTypeEx = namedtuple("CreatureTypeEx", "rawname, castes, tile_character, tilecolor") +TileColor = namedtuple("TileColor", "fore, back, bright") +Name = namedtuple("Name", "first_name, nickname, language, has_name, words, parts_of_speech") + +char_array = c_char * 128 + +class Soul(object): + def __init__(self, *args, **kwds): + if kwds: + for k, v in kwds.iteritems(): + self.__dict__[k] = v + +class MapBlock40d(object): + pass + +class ViewScreen(Structure): + _fields_ = [("type", c_int)] + +class Matgloss(Structure): + _fields_ = [("id", char_array), + ("fore", c_byte), + ("back", c_byte), + ("bright", c_byte), + ("name", char_array)] + +class Descriptor_Color(Structure): + _fields_ = [("id", char_array), + ("r", c_float), + ("v", c_float), + ("b", c_float), + ("name", char_array)] + +class MatglossOther(Structure): + _fields_ = [("rawname", char_array)] diff --git a/library/python/pydfhack/translation.py b/library/python/deprecated/pydfhack/translation.py similarity index 100% rename from library/python/pydfhack/translation.py rename to library/python/deprecated/pydfhack/translation.py diff --git a/library/python/deprecated/pydfhack/vegetation.py b/library/python/deprecated/pydfhack/vegetation.py new file mode 100644 index 000000000..ce1262a13 --- /dev/null +++ b/library/python/deprecated/pydfhack/vegetation.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +""" +Python class for DF_Hack::Vegetation +""" +from ._pydfhack import _VegetationManager +from .mixins import NeedsStart +from .decorators import suspend + +class Vegetation(NeedsStart, _VegetationManager): + api = None + cls = _VegetationManager + def __init__(self, api, *args, **kwds): + self.cls.__init__(self, args, kwds) + self.api = api + + @suspend + def Read(self, *args, **kw): + return self.cls.Read(self, *args, **kw) diff --git a/library/python/setup.py b/library/python/deprecated/setup.py similarity index 100% rename from library/python/setup.py rename to library/python/deprecated/setup.py diff --git a/library/python/test.py b/library/python/deprecated/test.py similarity index 100% rename from library/python/test.py rename to library/python/deprecated/test.py diff --git a/library/python/tools/shell.py b/library/python/deprecated/tools/shell.py similarity index 100% rename from library/python/tools/shell.py rename to library/python/deprecated/tools/shell.py diff --git a/library/python/tools/trees.py b/library/python/deprecated/tools/trees.py similarity index 100% rename from library/python/tools/trees.py rename to library/python/deprecated/tools/trees.py diff --git a/library/python/c api/buildings.py b/library/python/pydfhack/buildings.py similarity index 100% rename from library/python/c api/buildings.py rename to library/python/pydfhack/buildings.py diff --git a/library/python/c api/constructions.py b/library/python/pydfhack/constructions.py similarity index 100% rename from library/python/c api/constructions.py rename to library/python/pydfhack/constructions.py diff --git a/library/python/c api/context.py b/library/python/pydfhack/context.py similarity index 100% rename from library/python/c api/context.py rename to library/python/pydfhack/context.py diff --git a/library/python/c api/creatures.py b/library/python/pydfhack/creatures.py similarity index 100% rename from library/python/c api/creatures.py rename to library/python/pydfhack/creatures.py diff --git a/library/python/c api/dfhack_api_ctypes.py b/library/python/pydfhack/dfhack_api_ctypes.py similarity index 100% rename from library/python/c api/dfhack_api_ctypes.py rename to library/python/pydfhack/dfhack_api_ctypes.py diff --git a/library/python/c api/enum.py b/library/python/pydfhack/enum.py similarity index 100% rename from library/python/c api/enum.py rename to library/python/pydfhack/enum.py diff --git a/library/python/pydfhack/gui.py b/library/python/pydfhack/gui.py index 07192f67c..09a7c5c94 100644 --- a/library/python/pydfhack/gui.py +++ b/library/python/pydfhack/gui.py @@ -1,25 +1,25 @@ -# -*- coding: utf-8 -*- -""" -Python class for DF_Hack::GUI -""" -from ._pydfhack import _GUIManager -class GUI(_GUIManager): - api = None - started = False - def __init__(self, api, *args, **kwds): - _GUIManager.__init__(self, args, kwds) - self.api = api +from ctypes import * +from pydfhack import libdfhack, ViewScreen - def prepare(self): - """ - Enforce Suspend/Start - """ - if self.api.prepare(): - if not self.started: - self.started = self.Start() - return self.started - else: - return False - - +libdfhack.Gui_ReadViewScreen.argtypes = [ c_void_p, c_void_p ] + +class Gui(object): + def __init__(self, ptr): + self._gui_ptr = ptr + + def start(self): + return libdfhack.Gui_Start(self._gui_ptr) + + def finish(self): + return libdfhack.Gui_Finish(self._gui_ptr) + def read_pause_state(self): + return libdfhack.Gui_ReadPauseState(self._pos_ptr) > 0 + + def read_view_screen(self): + s = ViewScreen() + + if libdfhack.Gui_ReadViewScreen(self._gui_ptr, byref(s)) > 0: + return s + else: + return None diff --git a/library/python/c api/items.py b/library/python/pydfhack/items.py similarity index 100% rename from library/python/c api/items.py rename to library/python/pydfhack/items.py diff --git a/library/python/c api/maps.py b/library/python/pydfhack/maps.py similarity index 100% rename from library/python/c api/maps.py rename to library/python/pydfhack/maps.py diff --git a/library/python/pydfhack/materials.py b/library/python/pydfhack/materials.py index 13e02c682..04d82fddb 100644 --- a/library/python/pydfhack/materials.py +++ b/library/python/pydfhack/materials.py @@ -1,42 +1,141 @@ -# -*- coding: utf-8 -*- -""" -Python class for DF_Hack::Materials -""" -from ._pydfhack import _MaterialsManager -from .mixins import NoStart -from .decorators import suspend - -class Materials(NoStart, _MaterialsManager): - api = None - cls = _MaterialsManager - def __init__(self, api, *args, **kwds): - cls.__init__(self, args, kwds) - self.api = api - - @suspend - def Read_Wood_Materials(self, *args, **kw): - return self.cls.Read_Wood_Materials(self, *args, **kw) - - @suspend - def Read_Plant_Materials(self, *args, **kw): - return self.cls.Read_Plant_Materials(self, *args, **kw) - - @suspend - def Read_Inorganic_Materials(self, *args, **kw): - return self.cls.Read_Inorganic_Materials(self, *args, **kw) - - @suspend - def Read_Descriptor_Colors(self, *args, **kw): - return self.cls.Read_Descriptor_Colors(self, *args, **kw) - - @suspend - def Read_Creature_Types(self, *args, **kw): - return self.cls.Read_Creature_Types(self, *args, **kw) - - @suspend - def Read_Organic_Materials(self, *args, **kw): - return self.cls.Read_Organic_Materials(self, *args, **kw) - - @suspend - def Read_Creature_Types_Ex(self, *args, **kw): - return self.cls.Read_Creature_Types_Ex(self, *args, **kw) +from ctypes import * +from pydftypes import libdfhack +from util import * + +_get_arg_types = [ c_void_p, _arr_create_func ] + +libdfhack.Materials_getInorganic.argtypes = _get_arg_types +libdfhack.Materials_getOrganic.argtypes = _get_arg_types +libdfhack.Materials_getTree.argtypes = _get_arg_types +libdfhack.Materials_getPlant.argtypes = _get_arg_types +libdfhack.Materials_getRace.argtypes = _get_arg_types +#libdfhack.Materials_getRaceEx.argtypes = _get_arg_types +libdfhack.Materials_getColor.argtypes = _get_arg_types +libdfhack.Materials_getOther.argtypes = _get_arg_types + +class Materials(object): + def __init__(self, ptr): + self._mat_ptr = ptr + + self.inorganic = None + self.organic = None + self.tree = None + self.plant = None + self.race = None + self.race_ex = None + self.color = None + self.other = None + + def read_inorganic(self): + return libdfhack.Materials_ReadInorganicMaterials(self._mat_ptr) + + def read_organic(self): + return libdfhack.Materials_ReadOrganicMaterials(self._mat_ptr) + + def read_wood(self): + return libdfhack.Materials_ReadWoodMaterials(self._mat_ptr) + + def read_plant(self): + return libdfhack.Materials_ReadPlantMaterials(self._mat_ptr) + + def read_creature_types(self): + return libdfhack.Materials_ReadCreatureTypes(self._mat_ptr) + + def read_creature_types_ex(self): + return libdfhack.Materials_ReadCreatureTypesEx(self._mat_ptr) + + def read_descriptor_colors(self): + return libdfhack.Materials_ReadDescriptorColors(self._mat_ptr) + + def read_others(self): + return libdfhack.Materials_ReadOthers(self._mat_ptr) + + def read_all(self): + libdfhack.Materials_ReadAllMaterials(self._mat_ptr) + + def get_description(self, material): + return libdfhack.Materials_getDescription(self._mat_ptr, byref(material)) + + def update_inorganic_cache(self): + def update_callback(count): + allocated = _allocate_array(Matgloss, count) + + self.inorganic = allocated[0] + + return allocated[1] + + callback = _arr_create_func(update_callback) + + return libdfhack.Materials_getInorganic(self._mat_ptr, callback) + + def update_organic_cache(self): + def update_callback(count): + allocated = _allocate_array(Matgloss, count) + + self.organic = allocated[0] + + return allocated[1] + + callback = _arr_create_func(update_callback) + + return libdfhack.Materials_getOrganic(self._mat_ptr, callback) + + def update_tree_cache(self): + def update_callback(count): + allocated = _allocate_array(Matgloss, count) + + self.tree = allocated[0] + + return allocated[1] + + callback = _arr_create_func(update_callback) + + return libdfhack.Materials_getTree(self._mat_ptr, callback) + + def update_plant_cache(self): + def update_callback(count): + allocated = _allocate_array(Matgloss, count) + + self.plant = allocated[0] + + return allocated[1] + + callback = _arr_create_func(update_callback) + + return libdfhack.Materials_getPlant(self._mat_ptr, callback) + + def update_race_cache(self): + def update_callback(count): + allocated = _allocate_array(Matgloss, count) + + self.race = allocated[0] + + return allocated[1] + + callback = _arr_create_func(update_callback) + + return libdfhack.Materials_getRace(self._mat_ptr, callback) + + def update_color_cache(self): + def update_callback(count): + allocated = _allocate_array(DescriptorColor, count) + + self.color = allocated[0] + + return allocated[1] + + callback = _arr_create_func(update_callback) + + return libdfhack.Materials_getColor(self._mat_ptr, callback) + + def update_other_cache(self): + def update_callback(count): + allocated = _allocate_array(MatglossOther, count) + + self.other = allocated[0] + + return allocated[1] + + callback = _arr_create_func(update_callback) + + return libdfhack.Materials_getOther(self._mat_ptr, callback) diff --git a/library/python/pydfhack/position.py b/library/python/pydfhack/position.py index 7956ea812..ffa758150 100644 --- a/library/python/pydfhack/position.py +++ b/library/python/pydfhack/position.py @@ -1,42 +1,43 @@ -# -*- coding: utf-8 -*- -""" -Python class for DF_Hack::Position -""" -from ._pydfhack import _PositionManager -from .blocks import Point, Block -from .mixins import NoStart -from .decorators import suspend - -class Position(NoStart, _PositionManager): - api = None - cls = _PositionManager - def __init__(self, api, *args, **kwds): - self.cls.__init__(self, args, kwds) - self.api = api - - @suspend - def get_cursor(self): - coords = self.cursor_coords - if coords: - return Point(*coords) - else: - return None +from ctypes import * +from pydftypes import libdfhack + +class Position(object): + def __init__(self, ptr): + self._pos_ptr = ptr - @suspend - def get_window_size(self): - wsize = self.window_size - return wsize + self._vx, self._vy, self._vz = c_int(), c_int(), c_int() + self._cx, self._cy, self._cz = c_int(), c_int(), c_int() + self._ww, self._wh = c_int(), c_int() - @suspend def get_view_coords(self): - coords = self.view_coords - return Point(*coords) - - @suspend - def get_cursor_tile(self): - point = self.get_cursor() - if point: - tile = self.api.maps.get_tile(point=point) - return tile + if libdfhack.Position_getViewCoords(self._pos_ptr, byref(self._vx), byref(self._vy), byref(self._vz)) > 0: + return (self._vx.value, self._vy.value, self._vz.value) + else: + return (-1, -1, -1) + + def set_view_coords(self, v_coords): + self._vx.value, self._vy.value, self._vz.value = v_coords + + libdfhack.Position_setViewCoords(self._pos_ptr, self._vx, self._vy, self._vz) + + view_coords = property(get_view_coords, set_view_coords) + + def get_cursor_coords(self): + if libdfhack.Position_getCursorCoords(self._pos_ptr, byref(self._cx), byref(self._cy), byref(self._cz)) > 0: + return (self._cx.value, self._cy.value, self._cz.value) + else: + return (-1, -1, -1) + + def set_cursor_coords(self, c_coords): + self._cx.value, self._cy.value, self_cz.value = c_coords + + libdfhack.Position_setCursorCoords(self._pos_ptr, self._cx, self._cy, self._cz) + + cursor_coords = property(get_cursor_coords, set_cursor_coords) + + @property + def window_size(self): + if libdfhack.Position_getWindowSize(self._pos_ptr, byref(self._ww), byref(self._wh)) > 0: + return (self._ww.value, self._wh.value) else: - return None + return (-1, -1) diff --git a/library/python/pydfhack/pydfhackflags.py b/library/python/pydfhack/pydfhackflags.py index f8c15bef7..645bba659 100644 --- a/library/python/pydfhack/pydfhackflags.py +++ b/library/python/pydfhack/pydfhackflags.py @@ -1,10 +1,11 @@ # -*- coding: utf-8 -*- from ctypes import Structure, Union, c_uint +from enum import * class DesignationStruct(Structure): _fields_ = [("flow_size", c_uint, 3), ("pile", c_uint, 1), - ("dig", c_uint, 3), + ("dig", DesignationType, 3), ("smooth", c_uint, 2), ("hidden", c_uint, 1), ("geolayer_index", c_uint, 4), @@ -181,30 +182,16 @@ class ItemFlags(Union): def __int__(self): return self.whole -dig_types = { "no" : 0, - "default" : 1, - "ud_stair" : 2, - "channel" : 3, - "ramp" : 4, - "d_stair" : 5, - "u_stair" : 6, - "whatever" : 7 } - -traffic_types = { "normal" : 0, - "low" : 1, - "high" : 2, - "restricted" : 3 } - class BlockFlagStruct(Structure): _fields_ = [("designated", c_uint, 1), - ("unk_1", c_uint, 1), - ("liquid_1", c_uint, 1), - ("liquid_2", c_uint, 1), - ("unk_2", c_uint, 28)] + ("unk_1", c_uint, 1), + ("liquid_1", c_uint, 1), + ("liquid_2", c_uint, 1), + ("unk_2", c_uint, 28)] class BlockFlags(Union): _fields_ = [("whole", c_uint, 32), - ("bits", BlockFlagStruct)] + ("bits", BlockFlagStruct)] def __init__(self, inital = 0): self.whole = initial diff --git a/library/python/pydfhack/pydftypes.py b/library/python/pydfhack/pydftypes.py index eadef49c4..376d99238 100644 --- a/library/python/pydfhack/pydftypes.py +++ b/library/python/pydfhack/pydftypes.py @@ -1,50 +1,315 @@ from ctypes import * -from collections import namedtuple - -Position2D = namedtuple("Position2D", "x, y") -Position3D = namedtuple("Position3D", "x, y, z") -Rectangle = namedtuple("Rectangle", "x1, y1, x2, y2") -Note = namedtuple("Note", "symbol, foreground, background, name, position") -Construction = namedtuple("Construction", "position, form, unk_8, mat_type, mat_idx, unk3, unk4, unk5, unk6, origin") -Vein = namedtuple("Vein", "vtable, type, flags, address, assignment") -FrozenLiquidVein = namedtuple("FrozenLiquidVein", "vtable, address, tiles") -SpatterVein = namedtuple("SpatterVein", "vtable, address, mat1, unk1, mat2, mat3, intensity") -Settlement = namedtuple("Settlement", "origin, name, world_pos, local_pos") -Attribute = namedtuple("Attribute", "level, field_4, field_8, field_C, leveldiff, field_14, field_18"); -Skill = namedtuple("Skill", "id, experience, rating") -Tree = namedtuple("Tree", "type, material, position, address") -CreatureCaste = namedtuple("CreatureCaste", "rawname, singular, plural, adjective") -CreatureTypeEx = namedtuple("CreatureTypeEx", "rawname, castes, tile_character, tilecolor") -TileColor = namedtuple("TileColor", "fore, back, bright") -Name = namedtuple("Name", "first_name, nickname, language, has_name, words, parts_of_speech") - -char_array = c_char * 128 - -class Soul(object): - def __init__(self, *args, **kwds): - if kwds: - for k, v in kwds.iteritems(): - self.__dict__[k] = v - -class MapBlock40d(object): - pass +from pydfhackflags import * +from enum import * +from util import * + +libdfhack = cdll.libdfhack + +libdfhack.alloc_byte_buffer_callback = alloc_byte_buffer +libdfhack.alloc_ubyte_buffer_callback = alloc_ubyte_buffer +libdfhack.alloc_short_buffer_callback = alloc_short_buffer +libdfhack.alloc_ushort_buffer_callback = alloc_ushort_buffer +libdfhack.alloc_int_buffer_callback = alloc_int_buffer +libdfhack.alloc_uint_buffer_callback = alloc_uint_buffer +libdfhack.alloc_char_buffer_callback = alloc_char_buffer + +int_ptr = POINTER(c_int) +uint_ptr = POINTER(c_uint) + +_arr_create_func = CFUNCTYPE(c_void_p, c_int) + +TileTypes40d = ((c_int * 16) * 16) +BiomeIndices40d = c_ubyte * 16 +Temperatures = ((c_ushort * 16) * 16) +Designations40d = ((DesignationFlags * 16) * 16) +Occupancies40d = ((OccupancyFlags * 16) * 16) + +class Position2D(Structure): + _fields_ = [("x", c_ushort), + ("y", c_ushort)] + +class PlaneCoord(Union): + _fields_ = [("xy", c_uint), + ("dim", Position2D)] + + def __cmp__(self, other): + if isinstance(other, PlaneCoord): + return self.xy - other.xy + else: + raise TypeError("argument must be of type %s" % type(self)) + +class Feature(Structure): + _fields_ = [("type", FeatureType), + ("main_material", c_short), + ("sub_material", c_short), + ("discovered", c_byte), + ("origin", c_uint)] + +class Vein(Structure): + _fields_ = [("vtable", c_uint), + ("type", c_int), + ("assignment", c_short * 16), + ("flags", c_uint), + ("address_of", c_uint)] + +class FrozenLiquidVein(Structure): + _fields_ = [("vtable", c_uint), + ("tiles", TileTypes40d), + ("address_of", c_uint)] + +class SpatterVein(Structure): + _fields_ = [("vtable", c_uint), + ("mat1", c_ushort), + ("unk1", c_ushort), + ("mat2", c_uint), + ("mat3", c_ushort), + ("intensity", ((c_ubyte * 16) * 16)), + ("address_of", c_uint)] + +class MapBlock40d(Structure): + _fields_ = [("tiletypes", TileTypes40d), + ("designation", Designations40d), + ("occupancy", Occupancies40d), + ("biome_indices", BiomeIndices40d), + ("origin", c_uint), + ("blockflags", BlockFlags), + ("global_feature", c_short), + ("local_feature", c_short)] + class ViewScreen(Structure): _fields_ = [("type", c_int)] class Matgloss(Structure): - _fields_ = [("id", char_array), + _fields_ = [("id", c_char * 128), ("fore", c_byte), ("back", c_byte), ("bright", c_byte), - ("name", char_array)] + ("name", c_char * 128)] -class Descriptor_Color(Structure): - _fields_ = [("id", char_array), +def _alloc_matgloss_buffer_callback(ptr, count): + allocated = _allocate_array(Matgloss, count) + + ptr = addressof(allocated[0]) + + return 1 + +_matgloss_functype = CFUNCTYPE(c_int, POINTER(Matgloss), c_uint) +libdfhack.alloc_matgloss_buffer_callback = _matgloss_functype(_alloc_matgloss_buffer_callback) + +class MatglossPair(Structure): + _fields_ = [("type", c_short), + ("index", c_int)] + +class DescriptorColor(Structure): + _fields_ = [("id", c_char * 128), ("r", c_float), ("v", c_float), ("b", c_float), - ("name", char_array)] + ("name", c_char * 128)] + +def _alloc_descriptor_buffer_callback(ptr, count): + allocated = _allocate_array(DescriptorColor, count) + + ptr = addressof(allocated[0]) + + return 1 + +_descriptor_functype = CFUNCTYPE(c_int, POINTER(DescriptorColor), c_uint) +libdfhack.alloc_descriptor_buffer_callback = _descriptor_functype(_alloc_descriptor_buffer_callback) class MatglossOther(Structure): - _fields_ = [("rawname", char_array)] + _fields_ = [("rawname", c_char * 128)] + +def _alloc_matgloss_other_buffer_callback(count): + allocated = _allocate_array(MatglossOther, count) + + ptr = addressof(allocated[0]) + + return 1 + +_matgloss_other_functype = CFUNCTYPE(c_int, POINTER(MatglossOther), c_uint) +libdfhack.alloc_matgloss_other_buffer_callback = _matgloss_other_functype(_alloc_matgloss_other_buffer_callback) + +class Building(Structure): + _fields_ = [("origin", c_uint), + ("vtable", c_uint), + ("x1", c_uint), + ("y1", c_uint), + ("x2", c_uint), + ("y2", c_uint), + ("z", c_uint), + ("material", MatglossPair), + ("type", c_uint)] + +class CustomWorkshop(Structure): + _fields_ = [("index", c_uint), + ("name", c_char * 256)] + +class Construction(Structure): + _fields_ = [("x", c_ushort), + ("y", c_ushort), + ("z", c_ushort), + ("form", c_ushort), + ("unk_8", c_ushort), + ("mat_type", c_ushort), + ("mat_idx", c_ushort), + ("unk3", c_ushort), + ("unk4", c_ushort), + ("unk5", c_ushort), + ("unk6", c_uint), + ("origin", c_uint)] + +class Tree(Structure): + _fields_ = [("type", c_ushort), + ("material", c_ushort), + ("x", c_ushort), + ("y", c_ushort), + ("z", c_ushort), + ("address", c_uint)] + +class Material(Structure): + _fields_ = [("itemType", c_short), + ("subType", c_short), + ("subIndex", c_short), + ("index", c_int), + ("flags", c_uint)] + +class Skill(Structure): + _fields_ = [("id", c_ushort), + ("experience", c_uint), + ("rating", c_ushort)] + +class Job(Structure): + _fields_ = [("active", c_byte), + ("jobId", c_uint), + ("jobType", c_ubyte), + ("occupationPtr", c_uint)] + +class Like(Structure): + _fields_ = [("type", c_short), + ("itemClass", c_short), + ("itemIndex", c_short), + ("material", MatglossPair), + ("active", c_byte)] + +class Attribute(Structure): + _fields_ = [("level", c_uint), + ("field_4", c_uint), + ("field_8", c_uint), + ("field_C", c_uint), + ("leveldiff", c_uint), + ("field_14", c_uint), + ("field_18", c_uint)] + +class Name(Structure): + _fields_ = [("first_name", (c_char * 128)), + ("nickname", (c_char * 128)), + ("words", (c_int * 7)), + ("parts_of_speech", (c_ushort * 7)), + ("language", c_uint), + ("has_name", c_byte)] + +class Note(Structure): + _fields_ = [("symbol", c_char), + ("foreground", c_ushort), + ("background", c_ushort), + ("name", (c_char * 128)), + ("x", c_ushort), + ("y", c_ushort), + ("z", c_ushort)] + +class Settlement(Structure): + _fields_ = [("origin", c_uint), + ("name", Name), + ("world_x", c_short), + ("world_y", c_short), + ("local_x1", c_short), + ("local_x2", c_short), + ("local_y1", c_short), + ("local_y2", c_short)] + +_NUM_CREATURE_TRAITS = 30 +_NUM_CREATURE_LABORS = 102 + +class Soul(Structure): + _fields_ = [("numSkills", c_ubyte), + ("skills", (Skill * 256)), + ("traits", (c_ushort * _NUM_CREATURE_TRAITS)), + ("analytical_ability", Attribute), + ("focus", Attribute), + ("willpower", Attribute), + ("creativity", Attribute), + ("intuition", Attribute), + ("patience", Attribute), + ("memory", Attribute), + ("linguistic_ability", Attribute), + ("spatial_sense", Attribute), + ("musicality", Attribute), + ("kinesthetic_sense", Attribute), + ("empathy", Attribute), + ("social_awareness", Attribute)] + +_MAX_COLORS = 15 + +class Creature(Structure): + _fields_ = [("origin", c_uint), + ("x", c_ushort), + ("y", c_ushort), + ("z", c_ushort), + ("race", c_uint), + ("civ", c_int), + ("flags1", CreatureFlags1), + ("flags2", CreatureFlags2), + ("name", Name), + ("mood", c_short), + ("mood_skill", c_short), + ("artifact_name", Name), + ("profession", c_ubyte), + ("custom_profession", (c_char * 128)), + ("labors", (c_ubyte * _NUM_CREATURE_LABORS)), + ("current_job", Job), + ("happiness", c_uint), + ("id", c_uint), + ("strength", Attribute), + ("agility", Attribute), + ("toughness", Attribute), + ("endurance", Attribute), + ("recuperation", Attribute), + ("disease_resistance", Attribute), + ("squad_leader_id", c_int), + ("sex", c_ubyte), + ("caste", c_ushort), + ("pregnancy_timer", c_uint), + ("has_default_soul", c_byte), + ("defaultSoul", Soul), + ("nbcolors", c_uint), + ("color", (c_uint * _MAX_COLORS))] + +class CreatureExtract(Structure): + _fields_ = [("rawname", (c_char * 128))] + +class BodyPart(Structure): + _fields_ = [("id", (c_char * 128)), + ("category", (c_char * 128)), + ("single", (c_char * 128)), + ("plural", (c_char * 128))] + +class ColorModifier(Structure): + _fields_ = [("part", (c_char * 128)), + ("colorlist", POINTER(c_uint)), + ("colorlistLength", c_uint)] + + def __init__(self): + self.part[0] = '\0' + self.colorlistLength = 0 + +ColorModifierPtr = POINTER(ColorModifier) + +def _alloc_empty_colormodifier_callback(ptr): + ptr = ColorModifierPtr(ColorModifier()) + + return 1 + +_empty_colormodifier_functype = CFUNCTYPE(c_int, ColorModifierPtr) +libdfhack.alloc_empty_colormodifier_callback = _empty_colormodifier_functype(_alloc_empty_colormodifier_callback) diff --git a/library/python/c api/util.py b/library/python/pydfhack/util.py similarity index 100% rename from library/python/c api/util.py rename to library/python/pydfhack/util.py diff --git a/library/python/pydfhack/vegetation.py b/library/python/pydfhack/vegetation.py index ce1262a13..0c22d26b5 100644 --- a/library/python/pydfhack/vegetation.py +++ b/library/python/pydfhack/vegetation.py @@ -1,18 +1,25 @@ -# -*- coding: utf-8 -*- -""" -Python class for DF_Hack::Vegetation -""" -from ._pydfhack import _VegetationManager -from .mixins import NeedsStart -from .decorators import suspend +from ctypes import * +from pydftypes import libdfhack, Tree -class Vegetation(NeedsStart, _VegetationManager): - api = None - cls = _VegetationManager - def __init__(self, api, *args, **kwds): - self.cls.__init__(self, args, kwds) - self.api = api +class Vegetation(object): + def __init__(self, ptr): + self._v_ptr = ptr + + def start(self): + n = c_uint(0) - @suspend - def Read(self, *args, **kw): - return self.cls.Read(self, *args, **kw) + if libdfhack.Vegetation_Start(self._v_ptr, byref(n)) > 0: + return int(n.value) + else: + return -1 + + def finish(self): + return libdfhack.Vegetation_Finish(self._v_ptr) > 0 + + def read(self, index): + t = Tree() + + if libdfhack.Vegetation_Read(self._v_ptr, c_uint(index), byref(t)) > 0: + return t + else: + return None From fa8238af0886063ad596cdcfa90825e739b47e98 Mon Sep 17 00:00:00 2001 From: doomchild Date: Thu, 17 Jun 2010 15:38:48 -0500 Subject: [PATCH 054/122] removed reveal and force_suspend to examples --- library/python/pydfhack/context.py | 37 +----------------------------- 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/library/python/pydfhack/context.py b/library/python/pydfhack/context.py index eed236b09..0afc2cf25 100644 --- a/library/python/pydfhack/context.py +++ b/library/python/pydfhack/context.py @@ -167,39 +167,4 @@ class Context(object): if self._tran_obj is None: self._tran_obj = translation.Translation(libdfhack.Context_getTranslation(self._c_ptr)) - return self._tran_obj - -def reveal(): - df_cm = ContextManager("Memory.xml") - df = df_cm.get_single_context() - - df.attach() - - m = df.maps - - m.start() - - m_x, m_y, m_z = m.size - - for x in xrange(m_x): - for y in xrange(m_y): - for z in xrange(m_z): - if m.is_valid_block(x, y, z): - d = m.read_designations(x, y, z) - - for i in d: - for j in i: - j.bits.hidden = 0 - - m.write_designations(x, y, z, d) - - m.finish() - df.detach() - -def resume(): - df_cm = ContextManager("Memory.xml") - df = df_cm.get_single_context() - - df.attach() - df.force_resume() - df.detach() + return self._tran_obj \ No newline at end of file From 5b71ac7dae0c622a843a116cd58590dccf9d2d17 Mon Sep 17 00:00:00 2001 From: doomchild Date: Thu, 17 Jun 2010 16:26:53 -0500 Subject: [PATCH 055/122] add __init__ file renamed flags and types --- library/python/pydfhack/__init__.py | 14 ++++++++++++++ .../python/pydfhack/{pydftypes.py => dftypes.py} | 0 .../python/pydfhack/{pydfhackflags.py => flags.py} | 0 3 files changed, 14 insertions(+) create mode 100644 library/python/pydfhack/__init__.py rename library/python/pydfhack/{pydftypes.py => dftypes.py} (100%) rename library/python/pydfhack/{pydfhackflags.py => flags.py} (100%) diff --git a/library/python/pydfhack/__init__.py b/library/python/pydfhack/__init__.py new file mode 100644 index 000000000..99cf04305 --- /dev/null +++ b/library/python/pydfhack/__init__.py @@ -0,0 +1,14 @@ +import context + +__all__ = [ "buildings", + "constructions", + "context", + "creatures", + "dftypes", + "flags", + "gui", + "items", + "maps", + "materials", + "position" + "vegetation" ] \ No newline at end of file diff --git a/library/python/pydfhack/pydftypes.py b/library/python/pydfhack/dftypes.py similarity index 100% rename from library/python/pydfhack/pydftypes.py rename to library/python/pydfhack/dftypes.py diff --git a/library/python/pydfhack/pydfhackflags.py b/library/python/pydfhack/flags.py similarity index 100% rename from library/python/pydfhack/pydfhackflags.py rename to library/python/pydfhack/flags.py From 96c774629ac6f11ec6110a0591239a3bd150d974 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Thu, 17 Jun 2010 23:18:01 +0100 Subject: [PATCH 056/122] Added mood writing. Mood only, not skill or anything. Seems to work ok --- library/include/dfhack/modules/Creatures.h | 1 + library/modules/Creatures.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 99db5853e..062319f9f 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -387,6 +387,7 @@ namespace DFHack bool WriteAttributes(const uint32_t index, const t_creature &creature); bool WriteSex(const uint32_t index, const uint8_t sex); bool WriteTraits(const uint32_t index, const t_soul &soul); + bool WriteMood(const uint32_t index, const uint16_t mood); private: struct Private; diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index e1250f01b..ff2fbc6b8 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -474,6 +474,17 @@ bool Creatures::WriteTraits(const uint32_t index, const t_soul &soul) return true; } +bool Creatures::WriteMood(const uint32_t index, const uint16_t mood) +{ + if(!d->Started) + return false; + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + p->writeWord(temp + d->creatures.mood_offset, mood); + return true; +} + uint32_t Creatures::GetDwarfRaceIndex() { if(!d->Inited) return 0; From 893deb73dfbd5cdfbaa155c57f390994e1917438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 18 Jun 2010 01:07:54 +0200 Subject: [PATCH 057/122] derp --- tools/playground/incrementalsearch.cpp | 74 ++++++++++++++++++-------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index ff3f5b592..e4d46dab5 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -36,40 +36,68 @@ class holder class address { public: - uint64_t addr_; - unsigned int valid : 1; - virtual void print(SegmentedFinder& sff) - { - cout << hex << "0x" << addr_ << endl; - }; - address(const uint64_t addr) - { - addr_ = addr; - valid = false; - } - address & operator=(const uint64_t in) - { - addr_ = in; - valid = false; - return *this; - } - bool isValid(SegmentedFinder& sff) + uint64_t addr_; + unsigned int valid : 1; + virtual void print(SegmentedFinder& sff) + { + cout << hex << "0x" << addr_ << endl; + }; + address(const uint64_t addr) + { + addr_ = addr; + valid = false; + } + virtual address & operator=(const uint64_t in) + { + addr_ = in; + valid = false; + return *this; + } + virtual bool isValid(SegmentedFinder& sff) + { + if(valid) return true; + if(sff.getSegmentForAddress(addr_)) { - if(valid) return true; - if(sff.getSegmentForAddress(addr_)) - { - valid = 1; - } + valid = 1; } + } + virtual bool equals (SegmentedFinder & sf, address & rhs) + { + return rhs.addr_ == addr_; + } }; +// pointer to a null-terminated byte string class Cstr: public address { void print(SegmentedFinder & sf) { cout << hex << "0x" << addr_ << ": \"" << sf.Translate(addr_) << "\"" << endl; } + bool equals(SegmentedFinder & sf,const char * rhs) + { + uint32_t addr2 = *(sf.Translate(addr_)); + return strcmp(sf.Translate(addr2), rhs) == 0; + } + template + bool equalsP(SegmentedFinder & sf,inType rhs) + { + return Predicate(addr_, sf, rhs); + } + bool isValid(SegmentedFinder& sf) + { + if (address::isValid(sf)) + { + // read the pointer + uint32_t addr2 = *(sf.Translate(addr_)); + // is it a real pointer? a pretty weak test, but whatever. + if(sf.getSegmentForAddress(addr2)) + return true; + } + return false; + } }; + // STL STRING #ifdef LINUX_BUILD class STLstr: public address From d3e7701bc8a7d9e763f08386647f3b67e02403e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 18 Jun 2010 01:10:03 +0200 Subject: [PATCH 058/122] Fix template brackets --- library/DFMemInfo.cpp | 2 +- library/include/dfhack/DFMemInfo.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index 5c329ff8d..8d397e6a9 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -698,7 +698,7 @@ string memory_info::getTraitName(const uint32_t traitIdx) const throw Error::MissingMemoryDefinition("traitname", traitIdx); } -std::vector< std::vector> const& memory_info::getAllTraits() +std::vector< std::vector > const& memory_info::getAllTraits() { return d->traits; } diff --git a/library/include/dfhack/DFMemInfo.h b/library/include/dfhack/DFMemInfo.h index 84b76da69..6c116fc2b 100644 --- a/library/include/dfhack/DFMemInfo.h +++ b/library/include/dfhack/DFMemInfo.h @@ -73,7 +73,7 @@ namespace DFHack std::string getTrait (const uint32_t, const uint32_t) const; std::string getTraitName(const uint32_t) const; std::string getLabor (const uint32_t); - std::vector< std::vector> const& getAllTraits(); + std::vector< std::vector > const& getAllTraits(); DFHack::t_level getLevelInfo(const uint32_t level) const; From 41f3432d1cc1d0b47c2fb44c2b0a1b071142db1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 18 Jun 2010 01:17:46 +0200 Subject: [PATCH 059/122] whitespace --- library/modules/Creatures.cpp | 223 +++++++++++++++++++--------------- 1 file changed, 122 insertions(+), 101 deletions(-) diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index ff2fbc6b8..2ec257f39 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -92,19 +92,19 @@ Creatures::Creatures(DFContextShared* _d) creatures.mood_offset = minfo->getOffset("creature_mood"); creatures.mood_skill_offset = minfo->getOffset("creature_mood_skill"); creatures.pickup_equipment_bit = minfo->getOffset("creature_pickup_equipment_bit"); - creatures.current_job_offset = minfo->getOffset("creature_current_job"); + creatures.current_job_offset = minfo->getOffset("creature_current_job"); // soul offsets creatures.soul_skills_vector_offset = minfo->getOffset("soul_skills_vector"); creatures.soul_mental_offset = minfo->getOffset("soul_mental"); creatures.soul_traits_offset = minfo->getOffset("soul_traits"); - + // appearance creatures.appearance_vector_offset = minfo->getOffset("creature_appearance_vector"); //birth creatures.birth_year_offset = minfo->getOffset("creature_birth_year"); creatures.birth_time_offset = minfo->getOffset("creature_birth_time"); - + // name offsets for the creature module creatures.name_firstname_offset = minfo->getOffset("name_firstname"); creatures.name_nickname_offset = minfo->getOffset("name_nickname"); @@ -172,17 +172,17 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) */ // non-SHM slow path memory_info * minfo = d->d->offset_descriptor; - + // read pointer from vector at position uint32_t temp = d->p_cre->at (index); furball.origin = temp; Creatures2010::creature_offsets &offs = d->creatures; - + //read creature from memory - + // name d->d->readName(furball.name,temp + offs.name_offset); - + // basic stuff p->readDWord (temp + offs.happiness_offset, furball.happiness); p->readDWord (temp + offs.id_offset, furball.id); @@ -193,24 +193,24 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) p->readWord (temp + offs.caste_offset, furball.caste); p->readDWord (temp + offs.flags1_offset, furball.flags1.whole); p->readDWord (temp + offs.flags2_offset, furball.flags2.whole); - + // physical attributes p->read(temp + offs.physical_offset, - sizeof(t_attrib) * NUM_CREATURE_PHYSICAL_ATTRIBUTES, - (uint8_t *)&furball.strength); - + sizeof(t_attrib) * NUM_CREATURE_PHYSICAL_ATTRIBUTES, + (uint8_t *)&furball.strength); + // mood stuff furball.mood = (int16_t) p->readWord (temp + offs.mood_offset); furball.mood_skill = p->readWord (temp + offs.mood_skill_offset); d->d->readName(furball.artifact_name, temp + offs.artifact_name_offset); - + // custom profession p->readSTLString(temp + offs.custom_profession_offset, furball.custom_profession, sizeof(furball.custom_profession)); //fill_char_buf (furball.custom_profession, p->readSTLString (temp + offs.custom_profession_offset)); // labors p->read (temp + offs.labors_offset, NUM_CREATURE_LABORS, furball.labors); - + // profession furball.profession = p->readByte (temp + offs.profession_offset); @@ -268,20 +268,20 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) // a byte: this gives us 256 skills maximum. furball.defaultSoul.skills[i].id = p->readByte (temp2); furball.defaultSoul.skills[i].rating = - p->readByte (temp2 + offsetof(t_skill, rating)); + p->readByte (temp2 + offsetof(t_skill, rating)); furball.defaultSoul.skills[i].experience = - p->readWord (temp2 + offsetof(t_skill, experience)); + p->readWord (temp2 + offsetof(t_skill, experience)); } // mental attributes are part of the soul p->read(soul + offs.soul_mental_offset, - sizeof(t_attrib) * NUM_CREATURE_MENTAL_ATTRIBUTES, - (uint8_t *)&furball.defaultSoul.analytical_ability); - + sizeof(t_attrib) * NUM_CREATURE_MENTAL_ATTRIBUTES, + (uint8_t *)&furball.defaultSoul.analytical_ability); + // traits as well p->read(soul + offs.soul_traits_offset, - sizeof (uint16_t) * NUM_CREATURE_TRAITS, - (uint8_t *) &furball.defaultSoul.traits); + sizeof (uint16_t) * NUM_CREATURE_TRAITS, + (uint8_t *) &furball.defaultSoul.traits); } DfVector app(p, temp + offs.appearance_vector_offset); @@ -312,7 +312,7 @@ int32_t Creatures::ReadCreatureInBox (int32_t index, t_creature & furball, { if (!d->Started) return -1; - + Process *p = d->owner; /* if(d->creature_module) @@ -359,130 +359,151 @@ int32_t Creatures::ReadCreatureInBox (int32_t index, t_creature & furball, bool Creatures::WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]) { - if(!d->Started) return false; - uint32_t temp = d->p_cre->at (index); - Process * p = d->owner; - - p->write(temp + d->creatures.labors_offset, NUM_CREATURE_LABORS, labors); - uint32_t pickup_equip; - p->readDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); - pickup_equip |= 1u; - p->writeDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); - return true; + if(!d->Started) + { + return false; + } + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + + p->write(temp + d->creatures.labors_offset, NUM_CREATURE_LABORS, labors); + uint32_t pickup_equip; + p->readDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); + pickup_equip |= 1u; + p->writeDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); + return true; } bool Creatures::WriteHappiness(const uint32_t index, const uint32_t happinessValue) { - if(!d->Started) - return false; - - uint32_t temp = d->p_cre->at (index); - Process * p = d->owner; - p->writeDWord (temp + d->creatures.happiness_offset, happinessValue); - return true; + if(!d->Started) + { + return false; + } + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + p->writeDWord (temp + d->creatures.happiness_offset, happinessValue); + return true; } bool Creatures::WriteFlags(const uint32_t index, - const uint32_t flags1, - const uint32_t flags2) + const uint32_t flags1, + const uint32_t flags2) { - if(!d->Started) - return false; - - uint32_t temp = d->p_cre->at (index); - Process * p = d->owner; - p->writeDWord (temp + d->creatures.flags1_offset, flags1); - p->writeDWord (temp + d->creatures.flags2_offset, flags1); - return true; + if(!d->Started) + { + return false; + } + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + p->writeDWord (temp + d->creatures.flags1_offset, flags1); + p->writeDWord (temp + d->creatures.flags2_offset, flags1); + return true; } bool Creatures::WriteSkills(const uint32_t index, const t_soul &soul) { - if(!d->Started) - return false; - - uint32_t temp = d->p_cre->at (index); - Process * p = d->owner; - uint32_t souloff = p->readDWord(temp + d->creatures.default_soul_offset); - - if(!souloff) - return false; - + if(!d->Started) + { + return false; + } + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + uint32_t souloff = p->readDWord(temp + d->creatures.default_soul_offset); + + if(!souloff) + { + return false; + } + DfVector skills(p, souloff + d->creatures.soul_skills_vector_offset); - for (uint32_t i=0; iwriteByte(temp2 + offsetof(t_skill, rating), soul.skills[i].rating); - p->writeWord(temp2 + offsetof(t_skill, experience), soul.skills[i].experience); + p->writeByte(temp2 + offsetof(t_skill, rating), soul.skills[i].rating); + p->writeWord(temp2 + offsetof(t_skill, experience), soul.skills[i].experience); } - return true; + return true; } bool Creatures::WriteAttributes(const uint32_t index, const t_creature &creature) { - if(!d->Started) - return false; + if(!d->Started) + { + return false; + } - uint32_t temp = d->p_cre->at (index); - Process * p = d->owner; - uint32_t souloff = p->readDWord(temp + d->creatures.default_soul_offset); + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + uint32_t souloff = p->readDWord(temp + d->creatures.default_soul_offset); - if(!souloff) - return false; + if(!souloff) + { + return false; + } - // physical attributes - p->write(temp + d->creatures.physical_offset, - sizeof(t_attrib) * NUM_CREATURE_PHYSICAL_ATTRIBUTES, - (uint8_t *)&creature.strength); + // physical attributes + p->write(temp + d->creatures.physical_offset, + sizeof(t_attrib) * NUM_CREATURE_PHYSICAL_ATTRIBUTES, + (uint8_t *)&creature.strength); - // mental attributes are part of the soul - p->write(souloff + d->creatures.soul_mental_offset, - sizeof(t_attrib) * NUM_CREATURE_MENTAL_ATTRIBUTES, - (uint8_t *)&creature.defaultSoul.analytical_ability); + // mental attributes are part of the soul + p->write(souloff + d->creatures.soul_mental_offset, + sizeof(t_attrib) * NUM_CREATURE_MENTAL_ATTRIBUTES, + (uint8_t *)&creature.defaultSoul.analytical_ability); - return true; + return true; } bool Creatures::WriteSex(const uint32_t index, const uint8_t sex) { - if(!d->Started) - return false; + if(!d->Started) + { + return false; + } - uint32_t temp = d->p_cre->at (index); - Process * p = d->owner; - p->writeByte (temp + d->creatures.sex_offset, sex); + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + p->writeByte (temp + d->creatures.sex_offset, sex); } bool Creatures::WriteTraits(const uint32_t index, const t_soul &soul) { - if(!d->Started) - return false; + if(!d->Started) + { + return false; + } + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + uint32_t souloff = p->readDWord(temp + d->creatures.default_soul_offset); - uint32_t temp = d->p_cre->at (index); - Process * p = d->owner; - uint32_t souloff = p->readDWord(temp + d->creatures.default_soul_offset); + if(!souloff) + { + return false; + } - if(!souloff) - return false; + p->write(souloff + d->creatures.soul_traits_offset, + sizeof (uint16_t) * NUM_CREATURE_TRAITS, + (uint8_t *) &soul.traits); - p->write(souloff + d->creatures.soul_traits_offset, - sizeof (uint16_t) * NUM_CREATURE_TRAITS, - (uint8_t *) &soul.traits); - - return true; + return true; } bool Creatures::WriteMood(const uint32_t index, const uint16_t mood) { - if(!d->Started) - return false; + if(!d->Started) + { + return false; + } - uint32_t temp = d->p_cre->at (index); - Process * p = d->owner; - p->writeWord(temp + d->creatures.mood_offset, mood); - return true; + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + p->writeWord(temp + d->creatures.mood_offset, mood); + return true; } uint32_t Creatures::GetDwarfRaceIndex() From 5fd94efb10979fbf3b686170ad0e5ff20bde232d Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Fri, 18 Jun 2010 01:17:19 +0100 Subject: [PATCH 060/122] Added moods to memory.xml --- library/DFMemInfo.cpp | 22 ++++++++++++++++++++++ library/DFMemInfoManager.cpp | 4 ++++ library/include/dfhack/DFMemInfo.h | 2 ++ output/Memory.xml | 12 +++++++++++- 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index 5c329ff8d..582a225db 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -29,6 +29,7 @@ distribution. //Inital amount of space in levels vector (since we usually know the number, efficent!) #define NUM_RESERVE_LVLS 20 +#define NUM_RESERVE_MOODS 6 using namespace DFHack; /* @@ -96,6 +97,7 @@ class memory_info::Private vector skills; vector levels; vector< vector > traits; + vector moods; map labors; // storage for class and multiclass @@ -124,6 +126,7 @@ memory_info::memory_info() d->p = 0; d->classindex = 0; d->levels.reserve(NUM_RESERVE_LVLS); + d->moods.reserve(NUM_RESERVE_MOODS); } // copy constructor @@ -151,6 +154,7 @@ memory_info::memory_info(const memory_info &old) d->traits = old.d->traits; d->labors = old.d->labors; d->levels = old.d->levels; + d->moods = old.d->moods; } void memory_info::setParentProcess(Process * _p) { @@ -319,6 +323,16 @@ void memory_info::setLevel(const std::string &nLevel, d->levels[keyInt].xpNxtLvl = strtol(nXp.c_str(), NULL, 10); } +void memory_info::setMood(const std::string &id, const std::string &mood) +{ + uint32_t keyInt = strtol(id.c_str(), NULL, 10); + + if(d->moods.size() <= keyInt) + d->moods.resize(keyInt+1); + + d->moods[keyInt] = mood; +} + void memory_info::setTrait(const string & key, const string & value, const string & zero, @@ -712,3 +726,11 @@ string memory_info::getLabor (const uint32_t laborIdx) throw Error::MissingMemoryDefinition("labor", laborIdx); } +std::string memory_info::getMood(const uint32_t moodID) +{ + if(d->moods.size() > moodID) + { + return d->moods[moodID]; + } + throw Error::MissingMemoryDefinition("Mood", moodID); +} diff --git a/library/DFMemInfoManager.cpp b/library/DFMemInfoManager.cpp index bc34e877a..48ea3f8a2 100644 --- a/library/DFMemInfoManager.cpp +++ b/library/DFMemInfoManager.cpp @@ -212,6 +212,10 @@ void MemInfoManager::ParseEntry (TiXmlElement* entry, memory_info* mem, map setLevel(value, name, pMemEntry->Attribute("xpNxtLvl")); } + else if (type == "Mood") + { + mem->setMood(value, name); + } else { throw Error::MemoryXmlUnknownType(type.c_str()); diff --git a/library/include/dfhack/DFMemInfo.h b/library/include/dfhack/DFMemInfo.h index 84b76da69..400dc5765 100644 --- a/library/include/dfhack/DFMemInfo.h +++ b/library/include/dfhack/DFMemInfo.h @@ -66,6 +66,7 @@ namespace DFHack uint32_t getAddress (const char *); uint32_t getHexValue (const char *); + std::string getMood(const uint32_t moodID); std::string getString (const std::string&); std::string getProfession(const uint32_t) const; std::string getJob(const uint32_t) const; @@ -109,6 +110,7 @@ namespace DFHack void setLabor(const std::string &, const std::string &); void setLevel(const std::string &nLevel, const std::string &nName, const std::string &nXp); + void setMood(const std::string &id, const std::string &mood); void RebaseVTable(const int32_t offset); void setParentProcess(Process * _p); diff --git a/output/Memory.xml b/output/Memory.xml index ff63b1861..fe0a539f3 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -218,7 +218,17 @@ level_2="Often does the first thing that comes to mind" level_1="Acts impulsively" level_0="Always acts without considering alternatives or thinking through possibilities">29 - + + ==================================================================== + M O O D S + ==================================================================== + + + + + + + ==================================================================== P R O F E S S I O N S ==================================================================== From b867a9cef5004ebea8c781c0acb7a8c7ef4a9a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 18 Jun 2010 03:50:30 +0200 Subject: [PATCH 061/122] some minor offsets --- output/Memory.xml | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/output/Memory.xml b/output/Memory.xml index ff63b1861..47b2712db 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1455,6 +1455,8 @@ map_data_1b60_offset 0x1B9c 0x288 0x298 0x29C + 0x390 + 0x394 the skill that will be increased at the end of the mood (or not) 0x464 - 0x390 - 0x394 the skill that will be increased at the end of the mood (or not) 0x604 0x6D4 0x774 @@ -2153,10 +2153,31 @@ dwarf_race_index = 0x014abef4
0x931aff4
WORLD + 0x54E80
0x931b00c
+ + Creatures + ========= +
0x92D9AC0
+
0x92C1628
0x092CB608 +
0x92C161C
0x092CB5FC + + Time + ==== +
0x92BF6A0
+
0x92BF6A8
+ YEAR 0x92BF6A0, WORLD - 0x6A40 + TICKS 0x92BF6A8, WORLD - 0x6A40 + 0x08 +
13a1c19e8f59b74e307e094e2a0f28c3
0x8b0b328
VERIFIED + WORLD = 0x92C4000 + Creatures + ========= + WORLD + 0x139E0 + 0x92d79d4 + 0x92d79e0 = real one? seems like it + 0x92d7a10
From 0b9605e08a450d7a5b9f217cc94b26a22f03e7ef Mon Sep 17 00:00:00 2001 From: doomchild Date: Fri, 18 Jun 2010 10:39:40 -0500 Subject: [PATCH 062/122] changed def to class (durrrr) --- library/python/pydfhack/buildings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/python/pydfhack/buildings.py b/library/python/pydfhack/buildings.py index c61fd9f2b..32c330201 100644 --- a/library/python/pydfhack/buildings.py +++ b/library/python/pydfhack/buildings.py @@ -4,7 +4,7 @@ import util libdfhack.Buildings_GetCustomWorkshopType.argtypes = [ c_void_p, POINTER(CustomWorkshop) ] -def Buildings(object): +class Buildings(object): def __init__(self, ptr): self._b_ptr = ptr From bbb29fe3d5e39196e61effe63a361803c3e7788d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sat, 19 Jun 2010 03:47:09 +0200 Subject: [PATCH 063/122] Find, Filter, FindInRange and Incremental search methods --- library/include/dfhack/DFMemInfo.h | 18 +++--- library/modules/Materials.cpp | 20 ++++-- output/Memory.xml | 7 ++ tools/playground/SegmentedFinder.h | 89 ++++++++++++++++++++------ tools/playground/incrementalsearch.cpp | 82 +++++++++++------------- 5 files changed, 137 insertions(+), 79 deletions(-) diff --git a/library/include/dfhack/DFMemInfo.h b/library/include/dfhack/DFMemInfo.h index 6eafee7a3..77b28ccd0 100644 --- a/library/include/dfhack/DFMemInfo.h +++ b/library/include/dfhack/DFMemInfo.h @@ -41,7 +41,7 @@ namespace DFHack { private: class Private; - Private * d; + Private * d; public: enum OSType { @@ -66,7 +66,7 @@ namespace DFHack uint32_t getAddress (const char *); uint32_t getHexValue (const char *); - std::string getMood(const uint32_t moodID); + std::string getMood(const uint32_t moodID); std::string getString (const std::string&); std::string getProfession(const uint32_t) const; std::string getJob(const uint32_t) const; @@ -74,9 +74,9 @@ namespace DFHack std::string getTrait (const uint32_t, const uint32_t) const; std::string getTraitName(const uint32_t) const; std::string getLabor (const uint32_t); - std::vector< std::vector > const& getAllTraits(); + std::vector< std::vector > const& getAllTraits(); - DFHack::t_level getLevelInfo(const uint32_t level) const; + DFHack::t_level getLevelInfo(const uint32_t level) const; void setVersion(const char *); void setVersion(const std::string&); @@ -105,12 +105,12 @@ namespace DFHack void setJob(const std::string &, const std::string &); void setSkill(const std::string &, const std::string &); void setTrait(const std::string &, const std::string &, const std::string &, - const std::string &, const std::string &, - const std::string &, const std::string &, const std::string &); + const std::string &, const std::string &, + const std::string &, const std::string &, const std::string &); void setLabor(const std::string &, const std::string &); - void setLevel(const std::string &nLevel, const std::string &nName, - const std::string &nXp); - void setMood(const std::string &id, const std::string &mood); + void setLevel(const std::string &nLevel, const std::string &nName, + const std::string &nXp); + void setMood(const std::string &id, const std::string &mood); void RebaseVTable(const int32_t offset); void setParentProcess(Process * _p); diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index 3567bb0d0..c3e358b69 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -301,8 +301,8 @@ bool Materials::ReadCreatureTypesEx (void) uint32_t bodypart_id_offset = mem->getOffset ("bodypart_id"); uint32_t bodypart_category_offset = mem->getOffset ("bodypart_category"); uint32_t bodypart_layers_offset = mem->getOffset ("bodypart_layers_vector"); - uint32_t bodypart_singular_offset = mem->getOffset ("bodypart_singular_vector"); - uint32_t bodypart_plural_offset = mem->getOffset ("bodypart_plural_vector"); + uint32_t bodypart_singular_offset = mem->getOffset ("bodypart_singular_vector"); // unused + uint32_t bodypart_plural_offset = mem->getOffset ("bodypart_plural_vector"); // unused uint32_t color_modifier_part_offset = mem->getOffset ("color_modifier_part"); uint32_t color_modifier_startdate_offset = mem->getOffset ("color_modifier_startdate"); uint32_t color_modifier_enddate_offset = mem->getOffset ("color_modifier_enddate"); @@ -318,7 +318,18 @@ bool Materials::ReadCreatureTypesEx (void) for (uint32_t i = 0; i < size;i++) { t_creaturetype mat; + // FROM race READ + // std::string rawname AT 0, + // char tile_character AT tile_offset, + // word tilecolor.fore : tile_color_offset, + // word tilecolor.back : tile_color_offset + 2, + // word tilecolor.bright : tile_color_offset + 4 p->readSTLString (p_races[i], mat.rawname, sizeof(mat.rawname)); + mat.tile_character = p->readByte( p_races[i] + tile_offset ); + mat.tilecolor.fore = p->readWord( p_races[i] + tile_color_offset ); + 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 p_castes(p, p_races[i] + castes_vector_offset); sizecas = p_castes.size(); for (uint32_t j = 0; j < sizecas;j++) @@ -364,11 +375,6 @@ bool Materials::ReadCreatureTypesEx (void) mat.castes.push_back(caste); } - mat.tile_character = p->readByte( p_races[i] + tile_offset ); - mat.tilecolor.fore = p->readWord( p_races[i] + tile_color_offset ); - 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 p_extract(p, p_races[i] + extract_vector_offset); for(uint32_t j = 0; j < p_extract.size(); j++) { diff --git a/output/Memory.xml b/output/Memory.xml index bf2b1c8f0..5d036c0e0 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1844,6 +1844,13 @@ dwarf_race_index = 0x014abef4 0x1A14 0xE0 0xF6 + +
0x014abee4
CHMOD
0x1471FB0
BOGUS!
0x180b10c
LOOKS O.K. @@ -1648,48 +1647,6 @@ map_data_1b60_offset 0x1B9c
0xaf12cc
VERIFIED
0xE80780
LOOKS O.K.
0xEB2878
LOOKS O.K. - - - - - - 0x0 Why do i have to redefine this ??? ... what? @@ -1697,12 +1654,19 @@ map_data_1b60_offset 0x1B9c c4b7e37dafa2716e31d29110968ac64e 0x4c0f83d5
0xaf12d0
-[addresses] -translation_vector = 0x016c53dc -language_vector = 0x016c53ac -creature_vector = 0x0168071c -dwarf_race_index = 0x014abef4 + + 1c0b5254af1b8ff9a34b51c3f6609da3 + 0x4c0f83d5 +
0xaf32d8
0xaf12d0 +
0x180d11c
0x180b10c +
0xe6e0ec
+
0xe9c1c0
+
0xe9c19c
+ map size X: 0x16c4b10 + map size Y: 0x16c4b14 +
+ .-"""-. ' \ From 6c50b99050ad171458a117d073cf87c2ffb986f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 20 Jun 2010 01:11:09 +0200 Subject: [PATCH 067/122] Now with 100% more PE timestamp --- output/Memory.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/output/Memory.xml b/output/Memory.xml index cc68f956f..7fdc7ac61 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1657,7 +1657,7 @@ map_data_1b60_offset 0x1B9c 1c0b5254af1b8ff9a34b51c3f6609da3 - 0x4c0f83d5 + 0x4c1cbe4b
0xaf32d8
0xaf12d0
0x180d11c
0x180b10c
0xe6e0ec
From 31167475decbe08a98b96b821cba6401d4980cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 20 Jun 2010 02:50:37 +0200 Subject: [PATCH 068/122] Tool for dumping the effective addresses/offsets of a running DF instance --- library/DFMemInfo.cpp | 16 +++++++++++++ library/include/dfhack/DFMemInfo.h | 5 ++++ tools/playground/CMakeLists.txt | 4 ++++ tools/playground/dumpoffsets.cpp | 38 ++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 tools/playground/dumpoffsets.cpp diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index 8c0b1f864..4d6149e77 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -734,3 +734,19 @@ std::string memory_info::getMood(const uint32_t moodID) } throw Error::MissingMemoryDefinition("Mood", moodID); } + +std::string memory_info::PrintOffsets() +{ + ostringstream ss; + map::const_iterator iter; + for(iter = d->addresses.begin(); iter != d->addresses.end(); iter++) + { + ss << "address " << (*iter).first << " : " << hex << "0x" << (*iter).second << endl; + } + map::const_iterator iter2; + for(iter2 = d->offsets.begin(); iter2 != d->offsets.end(); iter2++) + { + ss << "offset " << (*iter2).first << " : " << hex << "0x" << (*iter2).second << endl; + } + return ss.str(); +} \ No newline at end of file diff --git a/library/include/dfhack/DFMemInfo.h b/library/include/dfhack/DFMemInfo.h index 77b28ccd0..e40ecbf11 100644 --- a/library/include/dfhack/DFMemInfo.h +++ b/library/include/dfhack/DFMemInfo.h @@ -145,6 +145,11 @@ namespace DFHack * Get the internal classID->classname mapping (for speed). DO NOT MANIPULATE THE VECTOR! */ const std::vector * getClassIDMapping(); + + /** + * Get a string with all addresses and offsets + */ + std::string PrintOffsets(); }; } #endif // MEMINFO_H_INCLUDED diff --git a/tools/playground/CMakeLists.txt b/tools/playground/CMakeLists.txt index 749922a5a..eff712d97 100644 --- a/tools/playground/CMakeLists.txt +++ b/tools/playground/CMakeLists.txt @@ -13,6 +13,10 @@ TARGET_LINK_LIBRARIES(dfmoodump dfhack) ADD_EXECUTABLE(dftest test.cpp) TARGET_LINK_LIBRARIES(dftest dfhack) +# just dump offsets of the current version +ADD_EXECUTABLE(dfdoffsets dumpoffsets.cpp) +TARGET_LINK_LIBRARIES(dfdoffsets dfhack) + # bauxite - turn all mechanisms into bauxite mechanisms # Author: Alex Legg #ADD_EXECUTABLE(dfbauxite dfbauxite.cpp) diff --git a/tools/playground/dumpoffsets.cpp b/tools/playground/dumpoffsets.cpp new file mode 100644 index 000000000..2257ca1de --- /dev/null +++ b/tools/playground/dumpoffsets.cpp @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +#include +using namespace DFHack; + +int main (int numargs, const char ** args) +{ + DFHack::ContextManager DFMgr("Memory.xml"); + DFHack::Context * DF; + try + { + DF = DFMgr.getSingleContext(); + DF->Attach(); + } + catch (exception& e) + { + cerr << e.what() << endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + memory_info * minfo = DF->getMemoryInfo(); + if(minfo) + cout << minfo->PrintOffsets(); + #ifndef LINUX_BUILD + cout << "Done. Press any key to continue" << endl; + cin.ignore(); + #endif + return 0; +} From 8d0700167415dabbcde21c4c623c45ef8023642a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 20 Jun 2010 19:20:10 +0200 Subject: [PATCH 069/122] 0.31.08 Windows SDL --- library/DFMemInfo.cpp | 16 ++++++++++++++++ output/Memory.xml | 14 +++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index 4d6149e77..8b2e11833 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -738,6 +738,22 @@ std::string memory_info::getMood(const uint32_t moodID) std::string memory_info::PrintOffsets() { ostringstream ss; + ss << "version: " << getVersion(); + switch (getOS()) + { + case OS_LINUX: + ss << " LINUX" << endl; + ss << "md5 hash: " << getString("md5") << endl; + break; + case OS_WINDOWS: + ss << " WINDOWS" << endl; + ss << "PE timestamp: " << hex << "0x" << getHexValue("pe_timestamp") << endl; + ss << "md5 hash: " << getString("md5") << endl; + break; + default: + ss << " UNKNOWN" << endl; + } + map::const_iterator iter; for(iter = d->addresses.begin(); iter != d->addresses.end(); iter++) { diff --git a/output/Memory.xml b/output/Memory.xml index 7fdc7ac61..ca36ef311 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1666,7 +1666,19 @@ map_data_1b60_offset 0x1B9c map size X: 0x16c4b10 map size Y: 0x16c4b14
- + + a83e6b21307cf41fb54c315fa40dec86 + 0x4c1d69fe + + .-"""-. ' \ From f3d75a6070da2217f823b7842c1cafd489487991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 20 Jun 2010 23:38:50 +0200 Subject: [PATCH 070/122] Linux versions update --- README | 7 ++++--- output/Memory.xml | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README b/README index 9e513ef31..cc6e7c9ef 100644 --- a/README +++ b/README @@ -33,11 +33,12 @@ OSX is also not supported due to lack of developers with a Mac. Currently supported Dwarf Fortress versions: * Windows 0.31.01 - 0.31.03 legacy - 0.31.04 - 0.31.06 SDL + 0.31.04 - 0.31.08 SDL * Linux - 0.31.04 - 0.31.06 native. There are missing offsets but Map tools should be OK. - All Windows versions through wine. + 0.31.04 - 0.31.08 native. + There are missing offsets but Map tools should be OK. Linux support is a bit lacking, I'm working on it. + All supported Windows versions running in wine can be used with DFHack. Using the library as a developer -------------------------------- diff --git a/output/Memory.xml b/output/Memory.xml index ca36ef311..33430714c 100755 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -2172,6 +2172,12 @@ map_data_1b60_offset 0x1B9c 0x92d79e0 = real one? seems like it 0x92d7a10 + + b31979551782e89c049b11db8d2d86d7 + + + e37750890350d7b9d8203879aff8fa5c + From c5a4172a36f99395b0a896cdc075889b065cdd70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 21 Jun 2010 00:31:43 +0200 Subject: [PATCH 071/122] Sorting in prospector tool --- tools/supported/prospector.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/tools/supported/prospector.cpp b/tools/supported/prospector.cpp index 514be1e3e..e7e0e9237 100644 --- a/tools/supported/prospector.cpp +++ b/tools/supported/prospector.cpp @@ -13,11 +13,32 @@ #include #include #include +#include using namespace std; #include #include +template