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)
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()

@ -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
#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 <int SIZE>
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;
};
struct t_matglossPair
{
int16_t type;
int32_t index;
};
template <int SIZE>
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
#endif
#endif // TYPES_H_INCLUDED

@ -35,6 +35,7 @@ distribution.
#include "dfhack/modules/Vegetation.h"
#include <vector>
#include "dfhack/Virtual.h"
#include <dfhack/BitArray.h>
/**
* \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 <t_virtual *> block_events;
// 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
buffer->origin = (uint32_t) &block;
//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;
}

@ -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")

@ -5,6 +5,8 @@
#include <vector>
#include <string>
#include "dfhack/extra/stopwatch.h"
#include "dfhack/modules/Maps.h"
#include <dfhack/modules/Gui.h>
using std::vector;
using std::string;
@ -17,6 +19,7 @@ uint64_t timeLast = 0;
DFhackCExport command_result kittens (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 )
{
@ -27,7 +30,8 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
{
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 <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)
{
if(timering)