BitArray implementation, now used in Maps for the flags.

develop
Petr Mrázek 2011-07-30 16:47:49 +02:00
parent a9a3a3ff5f
commit 9cf69164ed
7 changed files with 293 additions and 144 deletions

@ -120,8 +120,8 @@ ADD_DEFINITIONS(-DBUILD_DFHACK_LIB)
IF(UNIX) IF(UNIX)
add_definitions(-DLINUX_BUILD) add_definitions(-DLINUX_BUILD)
SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall") SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall")
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -m32") SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -m32 -std=c++0x")
SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32") SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32 -std=c++0x")
SET(PROJECT_LIBS rt ) SET(PROJECT_LIBS rt )
ELSE() ELSE()

@ -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 <stdint.h>
#include <string.h>
#include <sstream>
//#include <ostream>
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;
}
}

@ -25,120 +25,91 @@ distribution.
#pragma once #pragma once
#ifndef TYPES_H_INCLUDED
#define TYPES_H_INCLUDED
#include "dfhack/Pragma.h" #include "dfhack/Pragma.h"
#include "dfhack/Export.h" #include "dfhack/Export.h"
#ifdef __cplusplus
namespace DFHack namespace DFHack
{ {
#endif struct t_matglossPair
{
struct t_matglossPair int16_t type;
{ int32_t index;
int16_t type; };
int32_t index;
}; template <int SIZE>
struct junk_fill
// DF effects, by darius from the bay12 forum {
uint8_t data[SIZE];
template <int SIZE> };
struct junk_fill
{ struct df_name
uint8_t data[SIZE]; {
}; std::string first_name;
std::string nick_name;
struct df_name int32_t words[7];
{ int16_t parts_of_speech[7];
std::string first_name; int32_t language;
std::string nick_name; int16_t unknown;
int32_t words[7]; int16_t has_name;
int16_t parts_of_speech[7]; };
int32_t language;
int16_t unknown; // DF effects, by darius from the bay12 forum
int16_t has_name; enum EFFECT_TYPE
}; {
EFF_MIASMA=0,
enum EFFECT_TYPE EFF_WATER,
{ EFF_WATER2,
EFF_MIASMA=0, EFF_BLOOD,
EFF_WATER, EFF_DUST,
EFF_WATER2, EFF_MAGMA,
EFF_BLOOD, EFF_SMOKE,
EFF_DUST, EFF_DRAGONFIRE,
EFF_MAGMA, EFF_FIRE,
EFF_SMOKE, EFF_WEBING,
EFF_DRAGONFIRE, EFF_BOILING, // uses matgloss
EFF_FIRE, EFF_OCEANWAVE
EFF_WEBING, };
EFF_BOILING, // uses matgloss
EFF_OCEANWAVE struct t_effect_df40d //size 40
}; {
uint16_t type;
struct t_effect_df40d //size 40 t_matglossPair material;
{ int16_t lifetime;
uint16_t type; uint16_t x;
t_matglossPair material; uint16_t y;
int16_t lifetime; uint16_t z; //14
uint16_t x; int16_t x_direction;
uint16_t y; int16_t y_direction;
uint16_t z; //14 junk_fill <12> unk4;
int16_t x_direction; uint8_t canCreateNew;//??
int16_t y_direction; uint8_t isHidden;
junk_fill <12> unk4; };
uint8_t canCreateNew;//??
uint8_t isHidden; struct t_name
}; {
char first_name[128];
/* char nickname[128];
dword vtable; int32_t words[7];
int minx; uint16_t parts_of_speech[7];
int miny; uint32_t language;
int centerx; bool has_name;
int maxx; };
int maxy;
int centery; struct t_attrib
int z; {
dword height_not_used; uint32_t level;
word mattype; uint32_t field_4; // offset from beginning, purpose unknown
word matgloss; uint32_t field_8;
word type; // NOTE: the actual field is in a different place uint32_t field_C;
*/ uint32_t leveldiff;
uint32_t field_14;
//#pragma pack(push,4) uint32_t field_18;
};
struct t_name
{ struct t_level
char first_name[128]; {
char nickname[128]; uint32_t level;
int32_t words[7]; std::string name;
uint16_t parts_of_speech[7]; uint32_t xpNxtLvl;
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 }// namespace DFHack
#endif
#endif // TYPES_H_INCLUDED

@ -35,6 +35,7 @@ distribution.
#include "dfhack/modules/Vegetation.h" #include "dfhack/modules/Vegetation.h"
#include <vector> #include <vector>
#include "dfhack/Virtual.h" #include "dfhack/Virtual.h"
#include <dfhack/BitArray.h>
/** /**
* \defgroup grp_maps Maps module and its types * \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 // one of the vector is the 'effects' vector. another should be item id/index vector
struct df_block struct df_block
{ {
// FIXME: wrap the flag array! BitArray flags;
unsigned char * flagarray;
unsigned long flagarray_slots;
// how to handle this virtual mess? // how to handle this virtual mess?
std::vector <t_virtual *> block_events; std::vector <t_virtual *> block_events;
// no idea what these are // no idea what these are

@ -295,7 +295,8 @@ bool Maps::ReadBlock40d(uint32_t x, uint32_t y, uint32_t z, mapblock40d * buffer
// FIXME: not 64-bit safe // FIXME: not 64-bit safe
buffer->origin = (uint32_t) &block; buffer->origin = (uint32_t) &block;
//uint32_t addr_of_struct = p->readDWord(addr); //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 true;
} }
return false; return false;
@ -324,7 +325,6 @@ bool Maps::WriteTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buf
if (block) if (block)
{ {
memcpy(block->tiletype, buffer, sizeof(tiletypes40d)); memcpy(block->tiletype, buffer, sizeof(tiletypes40d));
//d->owner->write (addr + d->offsets.tile_type_offset, sizeof (tiletypes40d), (uint8_t *) buffer);
return true; return true;
} }
return false; return false;
@ -333,65 +333,53 @@ bool Maps::WriteTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buf
/* /*
* Dirty bit * Dirty bit
*/ */
//FIXME: this is bullshit
bool Maps::ReadDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool &dirtybit) bool Maps::ReadDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool &dirtybit)
{ {
MAPS_GUARD MAPS_GUARD
df_block * block = getBlock(x,y,z); df_block * block = getBlock(x,y,z);
if (block) if (block)
{ {
if(!block->flagarray) dirtybit = block->flags.is_set(1);
return false;
dirtybit = ((t_blockflags *)block->flagarray)->bits.designated;
return true; return true;
} }
return false; return false;
} }
//FIXME: this is bullshit
bool Maps::WriteDirtyBit(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 MAPS_GUARD
df_block * block = getBlock(x,y,z); df_block * block = getBlock(x,y,z);
if (block) if (block)
{ {
if(!block->flagarray) block->flags.set(1,dirtybit);
return false;
t_blockflags & flagz = (*(t_blockflags *)block->flagarray);
flagz.bits.designated = dirtybit;
return true; return true;
} }
return false; return false;
} }
/*
/* /*
* Block flags * 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) bool Maps::ReadBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags &blockflags)
{ {
MAPS_GUARD MAPS_GUARD
df_block * block = getBlock(x,y,z); df_block * block = getBlock(x,y,z);
if (block) if (block)
{ {
if(!block->flagarray) blockflags.whole = block->flags;
return false;
blockflags = *(t_blockflags *) block->flagarray;
return true; return true;
} }
return false; 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) bool Maps::WriteBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags blockflags)
{ {
MAPS_GUARD MAPS_GUARD
df_block * block = getBlock(x,y,z); df_block * block = getBlock(x,y,z);
if (block) if (block)
{ {
if(!block->flagarray) return (block->flags = blockflags.whole);
return false;
t_blockflags & bf = *(t_blockflags *) block->flagarray;
bf.whole = blockflags.whole;
return true;
} }
return false; return false;
} }

@ -2,8 +2,8 @@
IF(UNIX) IF(UNIX)
add_definitions(-DLINUX_BUILD) add_definitions(-DLINUX_BUILD)
SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall") SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall")
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -m32") SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -m32 -std=c++0x")
SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32") SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32 -std=c++0x")
ENDIF() ENDIF()
include_directories("${dfhack_SOURCE_DIR}/library/include") include_directories("${dfhack_SOURCE_DIR}/library/include")

@ -5,6 +5,8 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include "dfhack/extra/stopwatch.h" #include "dfhack/extra/stopwatch.h"
#include "dfhack/modules/Maps.h"
#include <dfhack/modules/Gui.h>
using std::vector; using std::vector;
using std::string; using std::string;
@ -17,6 +19,7 @@ uint64_t timeLast = 0;
DFhackCExport command_result kittens (Core * c, vector <string> & parameters); DFhackCExport command_result kittens (Core * c, vector <string> & parameters);
DFhackCExport command_result ktimer (Core * c, vector <string> & parameters); DFhackCExport command_result ktimer (Core * c, vector <string> & parameters);
DFhackCExport command_result bflags (Core * c, vector <string> & parameters);
DFhackCExport const char * plugin_name ( void ) DFhackCExport const char * plugin_name ( void )
{ {
@ -27,7 +30,8 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand("nyan","NYAN CAT INVASION!",kittens)); 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; return CR_OK;
} }
@ -41,8 +45,6 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_onupdate ( Core * c ) DFhackCExport command_result plugin_onupdate ( Core * c )
{ {
if(timering == true) if(timering == true)
@ -57,6 +59,59 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
return CR_OK; return CR_OK;
} }
DFhackCExport command_result bflags (Core * c, vector <string> & 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 <uint8_t, df_block *> 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 <string> & parameters) DFhackCExport command_result ktimer (Core * c, vector <string> & parameters)
{ {
if(timering) if(timering)