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 literal 36012 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 literal 40483 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 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