From 9cf69164ed4062250d6cb3278fc9ca0650883cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sat, 30 Jul 2011 16:47:49 +0200 Subject: [PATCH] BitArray implementation, now used in Maps for the flags. --- library/CMakeLists.txt | 4 +- library/include/dfhack/BitArray.h | 136 ++++++++++++++++++ library/include/dfhack/Types.h | 195 +++++++++++--------------- library/include/dfhack/modules/Maps.h | 5 +- library/modules/Maps.cpp | 32 ++--- plugins/CMakeLists.txt | 4 +- plugins/kittens.cpp | 61 +++++++- 7 files changed, 293 insertions(+), 144 deletions(-) create mode 100644 library/include/dfhack/BitArray.h diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index f3d9eb302..b124d2d8c 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -120,8 +120,8 @@ ADD_DEFINITIONS(-DBUILD_DFHACK_LIB) IF(UNIX) add_definitions(-DLINUX_BUILD) SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall") - SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -m32") - SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32") + SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -m32 -std=c++0x") + SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32 -std=c++0x") SET(PROJECT_LIBS rt ) ELSE() diff --git a/library/include/dfhack/BitArray.h b/library/include/dfhack/BitArray.h new file mode 100644 index 000000000..dffdddb4d --- /dev/null +++ b/library/include/dfhack/BitArray.h @@ -0,0 +1,136 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#pragma once +#include "dfhack/Pragma.h" +#include "dfhack/Export.h" +#include +#include +#include +//#include +namespace DFHack +{ + class BitArray + { + public: + BitArray() + { + bits = NULL; + size = 0; + } + ~BitArray() + { + if(bits) + delete [] bits; + } + void clear_all ( void ) + { + if(bits) + memset(bits, 0, size); + } + void set (uint32_t index, bool value = true) + { + if(!value) + { + clear(index); + return; + } + uint32_t byte = index / 8; + if(byte < size) + { + uint8_t bit = 1 << (index % 8); + bits[byte] |= bit; + } + } + void clear (uint32_t index) + { + uint32_t byte = index / 8; + if(byte < size) + { + uint8_t bit = 1 << (index % 8); + bits[byte] &= ~bit; + } + } + void toggle (uint32_t index) + { + uint32_t byte = index / 8; + if(byte < size) + { + uint8_t bit = 1 << (index % 8); + bits[byte] ^= bit; + } + } + bool is_set (uint32_t index) + { + uint32_t byte = index / 8; + if(byte < size) + { + uint8_t bit = 1 << (index % 8); + return bit & bits[byte]; + } + else return false; + } + /// WARNING: this can truncate long bit arrays + operator uint32_t () + { + if(!bits) + return 0; + if(size >= 4) + return *(uint32_t *)bits; + uint32_t target = 0; + memcpy (&target, bits,size); + return target; + } + /// WARNING: this can be truncated / only overwrite part of the data + bool operator =(uint32_t data) + { + if(!bits) + return false; + if (size >= 4) + { + (*(uint32_t *)bits) = data; + return true; + } + memcpy(bits, &data, size); + return true; + } + friend std::ostream& operator<< (std::ostream &out, BitArray &ba); + //private: + uint8_t * bits; + uint32_t size; + }; + inline std::ostream& operator<< (std::ostream &out, BitArray &ba) + { + std::stringstream sstr; + for (int i = 0; i < ba.size * 8; i++) + { + if(ba.is_set(i)) + sstr << "1 "; + else + sstr << "0 "; + } + out << sstr.str(); + return out; + } +} \ No newline at end of file diff --git a/library/include/dfhack/Types.h b/library/include/dfhack/Types.h index 5dc92f749..2ec35692f 100644 --- a/library/include/dfhack/Types.h +++ b/library/include/dfhack/Types.h @@ -25,120 +25,91 @@ distribution. #pragma once -#ifndef TYPES_H_INCLUDED -#define TYPES_H_INCLUDED - #include "dfhack/Pragma.h" #include "dfhack/Export.h" -#ifdef __cplusplus namespace DFHack { -#endif - -struct t_matglossPair -{ - int16_t type; - int32_t index; -}; - -// DF effects, by darius from the bay12 forum - -template -struct junk_fill -{ - uint8_t data[SIZE]; -}; - -struct df_name -{ - std::string first_name; - std::string nick_name; - int32_t words[7]; - int16_t parts_of_speech[7]; - int32_t language; - int16_t unknown; - int16_t has_name; -}; - -enum EFFECT_TYPE -{ - EFF_MIASMA=0, - EFF_WATER, - EFF_WATER2, - EFF_BLOOD, - EFF_DUST, - EFF_MAGMA, - EFF_SMOKE, - EFF_DRAGONFIRE, - EFF_FIRE, - EFF_WEBING, - EFF_BOILING, // uses matgloss - EFF_OCEANWAVE -}; - -struct t_effect_df40d //size 40 -{ - uint16_t type; - t_matglossPair material; - int16_t lifetime; - uint16_t x; - uint16_t y; - uint16_t z; //14 - int16_t x_direction; - int16_t y_direction; - junk_fill <12> unk4; - uint8_t canCreateNew;//?? - uint8_t isHidden; -}; - -/* - dword vtable; - int minx; - int miny; - int centerx; - int maxx; - int maxy; - int centery; - int z; - dword height_not_used; - word mattype; - word matgloss; - word type; // NOTE: the actual field is in a different place -*/ - -//#pragma pack(push,4) - -struct t_name -{ - char first_name[128]; - char nickname[128]; - int32_t words[7]; - uint16_t parts_of_speech[7]; - uint32_t language; - bool has_name; -}; - -struct t_attrib -{ - uint32_t level; - uint32_t field_4; // offset from beginning, purpose unknown - uint32_t field_8; - uint32_t field_C; - uint32_t leveldiff; - uint32_t field_14; - uint32_t field_18; -}; - -#ifdef __cplusplus -struct t_level -{ - uint32_t level; - std::string name; - uint32_t xpNxtLvl; -}; - -}// namespace DFHack -#endif - -#endif // TYPES_H_INCLUDED + struct t_matglossPair + { + int16_t type; + int32_t index; + }; + + template + struct junk_fill + { + uint8_t data[SIZE]; + }; + + struct df_name + { + std::string first_name; + std::string nick_name; + int32_t words[7]; + int16_t parts_of_speech[7]; + int32_t language; + int16_t unknown; + int16_t has_name; + }; + + // DF effects, by darius from the bay12 forum + enum EFFECT_TYPE + { + EFF_MIASMA=0, + EFF_WATER, + EFF_WATER2, + EFF_BLOOD, + EFF_DUST, + EFF_MAGMA, + EFF_SMOKE, + EFF_DRAGONFIRE, + EFF_FIRE, + EFF_WEBING, + EFF_BOILING, // uses matgloss + EFF_OCEANWAVE + }; + + struct t_effect_df40d //size 40 + { + uint16_t type; + t_matglossPair material; + int16_t lifetime; + uint16_t x; + uint16_t y; + uint16_t z; //14 + int16_t x_direction; + int16_t y_direction; + junk_fill <12> unk4; + uint8_t canCreateNew;//?? + uint8_t isHidden; + }; + + struct t_name + { + char first_name[128]; + char nickname[128]; + int32_t words[7]; + uint16_t parts_of_speech[7]; + uint32_t language; + bool has_name; + }; + + struct t_attrib + { + uint32_t level; + uint32_t field_4; // offset from beginning, purpose unknown + uint32_t field_8; + uint32_t field_C; + uint32_t leveldiff; + uint32_t field_14; + uint32_t field_18; + }; + + struct t_level + { + uint32_t level; + std::string name; + uint32_t xpNxtLvl; + }; +}// namespace DFHack \ No newline at end of file diff --git a/library/include/dfhack/modules/Maps.h b/library/include/dfhack/modules/Maps.h index d549bd4c8..aa05d7645 100644 --- a/library/include/dfhack/modules/Maps.h +++ b/library/include/dfhack/modules/Maps.h @@ -35,6 +35,7 @@ distribution. #include "dfhack/modules/Vegetation.h" #include #include "dfhack/Virtual.h" +#include /** * \defgroup grp_maps Maps module and its types @@ -534,9 +535,7 @@ namespace DFHack // one of the vector is the 'effects' vector. another should be item id/index vector struct df_block { - // FIXME: wrap the flag array! - unsigned char * flagarray; - unsigned long flagarray_slots; + BitArray flags; // how to handle this virtual mess? std::vector block_events; // no idea what these are diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index 0f2a909ce..887e8c754 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -295,7 +295,8 @@ bool Maps::ReadBlock40d(uint32_t x, uint32_t y, uint32_t z, mapblock40d * buffer // FIXME: not 64-bit safe buffer->origin = (uint32_t) █ //uint32_t addr_of_struct = p->readDWord(addr); - buffer->blockflags.whole = *(uint32_t*) block->flagarray; + // FIXME: maybe truncates + buffer->blockflags.whole = block->flags; return true; } return false; @@ -324,7 +325,6 @@ bool Maps::WriteTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buf if (block) { memcpy(block->tiletype, buffer, sizeof(tiletypes40d)); - //d->owner->write (addr + d->offsets.tile_type_offset, sizeof (tiletypes40d), (uint8_t *) buffer); return true; } return false; @@ -333,65 +333,53 @@ bool Maps::WriteTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buf /* * Dirty bit */ -//FIXME: this is bullshit bool Maps::ReadDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool &dirtybit) { MAPS_GUARD df_block * block = getBlock(x,y,z); if (block) { - if(!block->flagarray) - return false; - dirtybit = ((t_blockflags *)block->flagarray)->bits.designated; + dirtybit = block->flags.is_set(1); return true; } return false; } -//FIXME: this is bullshit + bool Maps::WriteDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool dirtybit) { MAPS_GUARD df_block * block = getBlock(x,y,z); if (block) { - if(!block->flagarray) - return false; - t_blockflags & flagz = (*(t_blockflags *)block->flagarray); - flagz.bits.designated = dirtybit; + block->flags.set(1,dirtybit); return true; } return false; } - +/* /* * Block flags */ -//FIXME: this is bullshit +// FIXME: maybe truncates, still bullshit bool Maps::ReadBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags &blockflags) { MAPS_GUARD df_block * block = getBlock(x,y,z); if (block) { - if(!block->flagarray) - return false; - blockflags = *(t_blockflags *) block->flagarray; + blockflags.whole = block->flags; return true; } return false; } -//FIXME: this is bullshit +//FIXME: maybe truncated, still bullshit bool Maps::WriteBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags blockflags) { MAPS_GUARD df_block * block = getBlock(x,y,z); if (block) { - if(!block->flagarray) - return false; - t_blockflags & bf = *(t_blockflags *) block->flagarray; - bf.whole = blockflags.whole; - return true; + return (block->flags = blockflags.whole); } return false; } diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 1bdaec094..9915cc9dd 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -2,8 +2,8 @@ IF(UNIX) add_definitions(-DLINUX_BUILD) SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall") - SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -m32") - SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32") + SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -m32 -std=c++0x") + SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32 -std=c++0x") ENDIF() include_directories("${dfhack_SOURCE_DIR}/library/include") diff --git a/plugins/kittens.cpp b/plugins/kittens.cpp index f41137b8b..80e2f412b 100644 --- a/plugins/kittens.cpp +++ b/plugins/kittens.cpp @@ -5,6 +5,8 @@ #include #include #include "dfhack/extra/stopwatch.h" +#include "dfhack/modules/Maps.h" +#include using std::vector; using std::string; @@ -17,6 +19,7 @@ uint64_t timeLast = 0; DFhackCExport command_result kittens (Core * c, vector & parameters); DFhackCExport command_result ktimer (Core * c, vector & parameters); +DFhackCExport command_result bflags (Core * c, vector & parameters); DFhackCExport const char * plugin_name ( void ) { @@ -27,7 +30,8 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector { commands.clear(); commands.push_back(PluginCommand("nyan","NYAN CAT INVASION!",kittens)); - commands.push_back(PluginCommand("ktimer","Time events...",ktimer)); + commands.push_back(PluginCommand("ktimer","Measure time between game updates and console lag.",ktimer)); + commands.push_back(PluginCommand("blockflags","Look up block flags",bflags)); return CR_OK; } @@ -41,8 +45,6 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) return CR_OK; } - - DFhackCExport command_result plugin_onupdate ( Core * c ) { if(timering == true) @@ -57,6 +59,59 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) return CR_OK; } +DFhackCExport command_result bflags (Core * c, vector & parameters) +{ + c->Suspend(); + Gui * g = c-> getGui(); + Maps* m = c->getMaps(); + if(!m->Start()) + { + c->con.printerr("No map to probe\n"); + return CR_FAILURE; + } + int32_t cx,cy,cz; + g->getCursorCoords(cx,cy,cz); + if(cx == -30000) + { + // get map size in blocks + uint32_t sx,sy,sz; + m->getSize(sx,sy,sz); + std::map counts; + // for each block + for(size_t x = 0; x < sx; x++) + for(size_t y = 0; y < sx; y++) + for(size_t z = 0; z < sx; z++) + { + df_block * b = m->getBlock(x,y,z); + if(!b) continue; + auto iter = counts.find(b->flags.size); + if(iter == counts.end()) + { + counts[b->flags.bits[0]] = b; + } + } + for(auto iter = counts.begin(); iter != counts.end(); iter++) + { + c->con.print("%2x : 0x%x\n",iter->first, iter->second); + } + } + else + { + df_block * b = m->getBlock(cx/16,cy/16,cz); + if(b) + { + c->con << "Block flags:" << b->flags << std::endl; + } + else + { + c->con.printerr("No block here\n"); + return CR_FAILURE; + } + } + c->Resume(); + return CR_OK; +} + DFhackCExport command_result ktimer (Core * c, vector & parameters) { if(timering)