SHM rework, stage 2

develop
Petr Mrázek 2010-03-05 00:05:01 +01:00
parent 088028cc5f
commit c86464502c
15 changed files with 396 additions and 146 deletions

@ -47,9 +47,7 @@ int main (int numargs, char** args)
uint32_t x_max,y_max,z_max; uint32_t x_max,y_max,z_max;
uint32_t num_blocks = 0; uint32_t num_blocks = 0;
uint64_t bytes_read = 0; uint64_t bytes_read = 0;
uint16_t tiletypes[16][16]; DFHack::mapblock40d Block;
DFHack::t_designation designations[16][16];
DFHack::t_occupancy occupancies[16][16];
DFHack::API DF("Memory.xml"); DFHack::API DF("Memory.xml");
if(!DF.Attach()) if(!DF.Attach())
@ -76,11 +74,9 @@ int main (int numargs, char** args)
{ {
if(DF.isValidBlock(x,y,z)) if(DF.isValidBlock(x,y,z))
{ {
DF.ReadTileTypes(x,y,z, (uint16_t *) tiletypes); DF.ReadBlock40d(x, y, z, &Block);
DF.ReadDesignations(x,y,z, (uint32_t *) designations);
DF.ReadOccupancy(x,y,z, (uint32_t *) occupancies);
num_blocks ++; num_blocks ++;
bytes_read += sizeof(tiletypes) + sizeof(designations) + sizeof(occupancies); bytes_read += sizeof(DFHack::mapblock40d);
} }
} }
} }

@ -144,8 +144,6 @@ void clrscr()
GRASS2, GRASS2,
GRASS_DEAD, GRASS_DEAD,
GRASS_DRY, GRASS_DRY,
#include <DFProcess.h>
#include <DFProcess.h>
DRIFTWOOD, DRIFTWOOD,
HFS, HFS,
MAGMA, MAGMA,
@ -272,9 +270,12 @@ main(int argc, char *argv[])
int x_max,y_max,z_max; int x_max,y_max,z_max;
uint32_t x_max_a,y_max_a,z_max_a; uint32_t x_max_a,y_max_a,z_max_a;
/*
uint16_t tiletypes[16][16]; uint16_t tiletypes[16][16];
DFHack::t_designation designations[16][16]; DFHack::t_designation designations[16][16];
uint8_t regionoffsets[16]; uint8_t regionoffsets[16];
*/
mapblock40d Block;
map <int16_t, uint32_t> materials; map <int16_t, uint32_t> materials;
materials.clear(); materials.clear();
vector<DFHack::t_matgloss> stonetypes; vector<DFHack::t_matgloss> stonetypes;
@ -300,7 +301,6 @@ main(int argc, char *argv[])
error = "Can't find a map to look at."; error = "Can't find a map to look at.";
pDF = 0; pDF = 0;
finish(0); finish(0);
#include <DFMemInfo.h>
} }
DF.getSize(x_max_a,y_max_a,z_max_a); DF.getSize(x_max_a,y_max_a,z_max_a);
@ -401,30 +401,34 @@ main(int argc, char *argv[])
if(DF.isValidBlock(cursorX+i,cursorY+j,cursorZ)) if(DF.isValidBlock(cursorX+i,cursorY+j,cursorZ))
{ {
// read data // read data
DF.ReadBlock40d(cursorX+i,cursorY+j,cursorZ, &Block);
/*
DF.ReadTileTypes(cursorX+i,cursorY+j,cursorZ, (uint16_t *) tiletypes); DF.ReadTileTypes(cursorX+i,cursorY+j,cursorZ, (uint16_t *) tiletypes);
DF.ReadDesignations(cursorX+i,cursorY+j,cursorZ, (uint32_t *) designations); DF.ReadDesignations(cursorX+i,cursorY+j,cursorZ, (uint32_t *) designations);
*/
for(int x = 0; x < 16; x++) for(int x = 0; x < 16; x++)
{ {
for(int y = 0; y < 16; y++) for(int y = 0; y < 16; y++)
{ {
if(dig) if(dig)
{ {
if(tileTypeTable[tiletypes[x][y]].c == WALL && tileTypeTable[tiletypes[x][y]].m == VEIN TileClass tc = tileTypeTable[Block.tiletypes[x][y]].c;
|| tileTypeTable[tiletypes[x][y]].c == TREE_OK || tileTypeTable[tiletypes[x][y]].c == TREE_DEAD) TileMaterial tm = tileTypeTable[Block.tiletypes[x][y]].m;
if( tc == WALL && tm == VEIN || tc == TREE_OK || tc == TREE_DEAD)
{ {
designations[x][y].bits.dig = designation_default; Block.designaton[x][y].bits.dig = designation_default;
} }
} }
int color = COLOR_BLACK; int color = COLOR_BLACK;
color = pickColor(tiletypes[x][y]); color = pickColor(Block.tiletypes[x][y]);
if(designations[x][y].bits.hidden) if(Block.designaton[x][y].bits.hidden)
{ {
puttile(x+(i+1)*16,y+(j+1)*16,tiletypes[x][y], color); puttile(x+(i+1)*16,y+(j+1)*16,Block.tiletypes[x][y], color);
} }
else else
{ {
attron(A_STANDOUT); attron(A_STANDOUT);
puttile(x+(i+1)*16,y+(j+1)*16,tiletypes[x][y], color); puttile(x+(i+1)*16,y+(j+1)*16,Block.tiletypes[x][y], color);
attroff(A_STANDOUT); attroff(A_STANDOUT);
} }
} }
@ -439,7 +443,7 @@ main(int argc, char *argv[])
filenum++; filenum++;
} }
if(dig) if(dig)
DF.WriteDesignations(cursorX+i,cursorY+j,cursorZ, (uint32_t *) designations); DF.WriteDesignations(cursorX+i,cursorY+j,cursorZ, (uint32_t *) Block.designaton);
DF.ReadDirtyBit(cursorX+i,cursorY+j,cursorZ,dirtybit); DF.ReadDirtyBit(cursorX+i,cursorY+j,cursorZ,dirtybit);
if(digbit) if(digbit)
{ {

@ -23,6 +23,9 @@ distribution.
*/ */
#include "DFCommonInternal.h" #include "DFCommonInternal.h"
#include "../shmserver/shms.h"
#include "../shmserver/mod-core.h"
#include "../shmserver/mod-maps.h"
using namespace DFHack; using namespace DFHack;
/* /*
@ -106,6 +109,7 @@ public:
ProcessEnumerator* pm; ProcessEnumerator* pm;
Process* p; Process* p;
char * shm_start;
memory_info* offset_descriptor; memory_info* offset_descriptor;
vector<uint16_t> v_geology[eBiomeCount]; vector<uint16_t> v_geology[eBiomeCount];
string xml; string xml;
@ -121,6 +125,8 @@ public:
bool hotkeyInited; bool hotkeyInited;
bool settlementsInited; bool settlementsInited;
bool nameTablesInited; bool nameTablesInited;
uint32_t maps_module;
uint32_t tree_offset; uint32_t tree_offset;
DfVector *p_cre; DfVector *p_cre;
@ -149,6 +155,8 @@ API::API (const string path_to_xml)
d->notesInited = false; d->notesInited = false;
d->hotkeyInited = false; d->hotkeyInited = false;
d->pm = NULL; d->pm = NULL;
d->shm_start = 0;
d->maps_module = 0;
} }
API::~API() API::~API()
@ -156,6 +164,11 @@ API::~API()
delete d; delete d;
} }
#define SHMCMD ((shm_cmd *)d->shm_start)->pingpong
#define SHMHDR ((shm_core_hdr *)d->shm_start)
#define SHMMAPSHDR ((Maps::shm_maps_hdr *)d->shm_start)
#define SHMDATA(type) ((type *)(d->shm_start + SHM_HEADER))
/*-----------------------------------* /*-----------------------------------*
* Init the mapblock pointer array * * Init the mapblock pointer array *
*-----------------------------------*/ *-----------------------------------*/
@ -181,19 +194,43 @@ bool API::InitMap()
d->offset_descriptor->resolveClassnameToVPtr("block_square_event_frozen_liquid", d->vein_ice_vptr); d->offset_descriptor->resolveClassnameToVPtr("block_square_event_frozen_liquid", d->vein_ice_vptr);
d->vein_mineral_vptr = 0; d->vein_mineral_vptr = 0;
d->offset_descriptor->resolveClassnameToVPtr("block_square_event_mineral",d->vein_mineral_vptr); d->offset_descriptor->resolveClassnameToVPtr("block_square_event_mineral",d->vein_mineral_vptr);
/*
* --> SHM initialization (if possible) <--
*/
g_pProcess->getModuleIndex("Maps",1,d->maps_module);
if(d->maps_module)
{
// supply the module with offsets so it can work with them
Maps::maps_offsets *off = SHMDATA(Maps::maps_offsets);
off->biome_stuffs = d->biome_stuffs;
off->designation_offset = d->designation_offset;
off->map_offset = map_offset;
off->occupancy_offset = d->occupancy_offset;
off->tile_type_offset = d->tile_type_offset;
off->vein_ice_vptr = d->vein_ice_vptr; // FIXME: not necessarily true, the shm server side needs a class lookup >_<
off->vein_mineral_vptr = d->vein_mineral_vptr; // FIXME: not necessarily true, the shm server side needs a class lookup >_<
off->veinvector = d->veinvector;
off->x_count_offset = x_count_offset;
off->y_count_offset = y_count_offset;
off->z_count_offset = z_count_offset;
full_barrier
const uint32_t cmd = Maps::MAP_INIT + d->maps_module << 16;
SHMCMD = cmd;
g_pProcess->waitWhile(cmd);
//cerr << "Map acceleration enabled!" << endl;
}
// get the map pointer // get the map pointer
uint32_t x_array_loc = g_pProcess->readDWord (map_offset); uint32_t x_array_loc = g_pProcess->readDWord (map_offset);
//FIXME: very inadequate
if (!x_array_loc) if (!x_array_loc)
{ {
throw Error::NoMapLoaded(); throw Error::NoMapLoaded();
// bad stuffz happend
//return false;
} }
uint32_t mx, my, mz;
// get the size // get the size
uint32_t mx, my, mz;
mx = d->x_block_count = g_pProcess->readDWord (x_count_offset); mx = d->x_block_count = g_pProcess->readDWord (x_count_offset);
my = d->y_block_count = g_pProcess->readDWord (y_count_offset); my = d->y_block_count = g_pProcess->readDWord (y_count_offset);
mz = d->z_block_count = g_pProcess->readDWord (z_count_offset); mz = d->z_block_count = g_pProcess->readDWord (z_count_offset);
@ -253,6 +290,41 @@ uint32_t API::getBlockPtr (uint32_t x, uint32_t y, uint32_t z)
return d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; return d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
} }
bool API::ReadBlock40d(uint32_t x, uint32_t y, uint32_t z, mapblock40d * buffer)
{
if(d->shm_start && d->maps_module) // ACCELERATE!
{
SHMMAPSHDR->x = x;
SHMMAPSHDR->y = y;
SHMMAPSHDR->z = z;
const uint32_t cmd = Maps::MAP_READ_BLOCK_BY_COORDS + (d->maps_module << 16);
full_barrier
SHMCMD = cmd;
if(!g_pProcess->waitWhile(cmd))
{
return false;
}
memcpy(buffer,SHMDATA(mapblock40d),sizeof(mapblock40d));
return true;
}
else // plain old block read
{
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
g_pProcess->read (addr + d->tile_type_offset, sizeof (buffer->tiletypes), (uint8_t *) buffer->tiletypes);
g_pProcess->read (addr + d->occupancy_offset, sizeof (buffer->occupancy), (uint8_t *) buffer->occupancy);
g_pProcess->read (addr + d->designation_offset, sizeof (buffer->designaton), (uint8_t *) buffer->designaton);
g_pProcess->read (addr + d->biome_stuffs, sizeof (buffer->biome_indices), (uint8_t *) buffer->biome_indices);
uint32_t addr_of_struct = g_pProcess->readDWord(addr);
buffer->dirty_dword = g_pProcess->readDWord(addr_of_struct);
return true;
}
return false;
}
}
// 256 * sizeof(uint16_t) // 256 * sizeof(uint16_t)
bool API::ReadTileTypes (uint32_t x, uint32_t y, uint32_t z, uint16_t *buffer) bool API::ReadTileTypes (uint32_t x, uint32_t y, uint32_t z, uint16_t *buffer)
{ {
@ -713,7 +785,7 @@ bool API::ReadGeology (vector < vector <uint16_t> >& assign)
} }
assign.clear(); assign.clear();
assign.reserve (eBiomeCount); assign.reserve (eBiomeCount);
// TODO: clean this up // // TODO: clean this up
for (int i = 0; i < eBiomeCount;i++) for (int i = 0; i < eBiomeCount;i++)
{ {
assign.push_back (d->v_geology[i]); assign.push_back (d->v_geology[i]);
@ -1341,6 +1413,7 @@ bool API::Attach()
//cerr << "couldn't attach to process" << endl; //cerr << "couldn't attach to process" << endl;
//return false; // couldn't attach to process, no go //return false; // couldn't attach to process, no go
} }
d->shm_start = d->p->getSHMStart();
d->offset_descriptor = d->p->getDescriptor(); d->offset_descriptor = d->p->getDescriptor();
// process is attached, everything went just fine... hopefully // process is attached, everything went just fine... hopefully
return true; return true;
@ -1359,6 +1432,7 @@ bool API::Detach()
} }
d->pm = NULL; d->pm = NULL;
d->p = NULL; d->p = NULL;
d->shm_start = 0;
d->offset_descriptor = NULL; d->offset_descriptor = NULL;
return true; return true;
} }

@ -135,6 +135,8 @@ namespace DFHack
*/ */
uint32_t getBlockPtr (uint32_t blockx, uint32_t blocky, uint32_t blockz); uint32_t getBlockPtr (uint32_t blockx, uint32_t blocky, uint32_t blockz);
bool ReadBlock40d(uint32_t blockx, uint32_t blocky, uint32_t blockz, mapblock40d * buffer);
bool ReadTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint16_t *buffer); // 256 * sizeof(uint16_t) bool ReadTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint16_t *buffer); // 256 * sizeof(uint16_t)
bool WriteTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint16_t *buffer); // 256 * sizeof(uint16_t) bool WriteTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint16_t *buffer); // 256 * sizeof(uint16_t)

@ -28,7 +28,7 @@ distribution.
#include <sys/ipc.h> #include <sys/ipc.h>
#include <time.h> #include <time.h>
#include "../shmserver/shms.h" #include "../shmserver/shms.h"
#include "../shmserver/shms-core.h" #include "../shmserver/mod-core.h"
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
#include <sched.h> #include <sched.h>
@ -59,6 +59,7 @@ class Process::Private
pid_t my_pid; pid_t my_pid;
char *my_shm; char *my_shm;
int my_shmid; int my_shmid;
Process* q;
bool attached; bool attached;
bool suspended; bool suspended;
@ -66,10 +67,10 @@ class Process::Private
bool useYield; bool useYield;
bool validate(char* exe_file, uint32_t pid, std::vector< memory_info* >& known_versions); bool validate(char* exe_file, uint32_t pid, std::vector< memory_info* >& known_versions);
bool waitWhile (CORE_COMMAND state);
bool DF_TestBridgeVersion(bool & ret); bool DF_TestBridgeVersion(bool & ret);
bool DF_GetPID(pid_t & ret); bool DF_GetPID(pid_t & ret);
void DF_SyncAffinity(void); void DF_SyncAffinity(void);
bool waitWhile (uint32_t state);
}; };
// some helpful macros to keep the code bloat in check // some helpful macros to keep the code bloat in check
@ -83,7 +84,7 @@ class Process::Private
Yeah. with no way to synchronize things (locks are slow, the OS doesn't give us enough control over scheduling) Yeah. with no way to synchronize things (locks are slow, the OS doesn't give us enough control over scheduling)
we end up with this silly thing we end up with this silly thing
*/ */
bool Process::Private::waitWhile (CORE_COMMAND state) bool Process::Private::waitWhile (uint32_t state)
{ {
uint32_t cnt = 0; uint32_t cnt = 0;
struct shmid_ds descriptor; struct shmid_ds descriptor;
@ -121,6 +122,48 @@ bool Process::Private::waitWhile (CORE_COMMAND state)
return true; return true;
} }
/*
Yeah. with no way to synchronize things (locks are slow, the OS doesn't give us enough control over scheduling)
we end up with this silly thing
*/
bool Process::waitWhile (uint32_t state)
{
uint32_t cnt = 0;
struct shmid_ds descriptor;
while (D_SHMCMD == state)
{
if(cnt == 10000)// check if the other process is still there
{
shmctl(d->my_shmid, IPC_STAT, &descriptor);
if(descriptor.shm_nattch == 1)// DF crashed?
{
D_SHMCMD = CORE_RUNNING;
d->attached = d->suspended = false;
return false;
}
else
{
cnt = 0;
}
}
if(d->useYield)
{
SCHED_YIELD
}
cnt++;
}
if(D_SHMCMD == CORE_SV_ERROR)
{
D_SHMCMD = CORE_RUNNING;
d->attached = d->suspended = false;
cerr << "shm server error!" << endl;
assert (false);
return false;
}
return true;
}
bool Process::Private::DF_TestBridgeVersion(bool & ret) bool Process::Private::DF_TestBridgeVersion(bool & ret)
{ {
SHMCMD = CORE_GET_VERSION; SHMCMD = CORE_GET_VERSION;
@ -363,7 +406,7 @@ bool Process::suspend()
return true; return true;
} }
D_SHMCMD = CORE_SUSPEND; D_SHMCMD = CORE_SUSPEND;
if(!d->waitWhile(CORE_SUSPEND)) if(!waitWhile(CORE_SUSPEND))
{ {
return false; return false;
} }
@ -472,7 +515,7 @@ void Process::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
D_SHMHDR->length = size; D_SHMHDR->length = size;
gcc_barrier gcc_barrier
D_SHMCMD = CORE_DFPP_READ; D_SHMCMD = CORE_DFPP_READ;
d->waitWhile(CORE_DFPP_READ); waitWhile(CORE_DFPP_READ);
memcpy (target_buffer, d->my_shm + SHM_HEADER,size); memcpy (target_buffer, d->my_shm + SHM_HEADER,size);
} }
// a big read, we pull data over the shm in iterations // a big read, we pull data over the shm in iterations
@ -487,7 +530,7 @@ void Process::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
D_SHMHDR->length = to_read; D_SHMHDR->length = to_read;
gcc_barrier gcc_barrier
D_SHMCMD = CORE_DFPP_READ; D_SHMCMD = CORE_DFPP_READ;
d->waitWhile(CORE_DFPP_READ); waitWhile(CORE_DFPP_READ);
memcpy (target_buffer, d->my_shm + SHM_HEADER,size); memcpy (target_buffer, d->my_shm + SHM_HEADER,size);
// decrease size by bytes read // decrease size by bytes read
size -= to_read; size -= to_read;
@ -505,7 +548,7 @@ uint8_t Process::readByte (const uint32_t offset)
D_SHMHDR->address = offset; D_SHMHDR->address = offset;
gcc_barrier gcc_barrier
D_SHMCMD = CORE_READ_BYTE; D_SHMCMD = CORE_READ_BYTE;
d->waitWhile(CORE_READ_BYTE); waitWhile(CORE_READ_BYTE);
return D_SHMHDR->value; return D_SHMHDR->value;
} }
@ -514,7 +557,7 @@ void Process::readByte (const uint32_t offset, uint8_t &val )
D_SHMHDR->address = offset; D_SHMHDR->address = offset;
gcc_barrier gcc_barrier
D_SHMCMD = CORE_READ_BYTE; D_SHMCMD = CORE_READ_BYTE;
d->waitWhile(CORE_READ_BYTE); waitWhile(CORE_READ_BYTE);
val = D_SHMHDR->value; val = D_SHMHDR->value;
} }
@ -523,7 +566,7 @@ uint16_t Process::readWord (const uint32_t offset)
D_SHMHDR->address = offset; D_SHMHDR->address = offset;
gcc_barrier gcc_barrier
D_SHMCMD = CORE_READ_WORD; D_SHMCMD = CORE_READ_WORD;
d->waitWhile(CORE_READ_WORD); waitWhile(CORE_READ_WORD);
return D_SHMHDR->value; return D_SHMHDR->value;
} }
@ -532,7 +575,7 @@ void Process::readWord (const uint32_t offset, uint16_t &val)
D_SHMHDR->address = offset; D_SHMHDR->address = offset;
gcc_barrier gcc_barrier
D_SHMCMD = CORE_READ_WORD; D_SHMCMD = CORE_READ_WORD;
d->waitWhile(CORE_READ_WORD); waitWhile(CORE_READ_WORD);
val = D_SHMHDR->value; val = D_SHMHDR->value;
} }
@ -541,7 +584,7 @@ uint32_t Process::readDWord (const uint32_t offset)
D_SHMHDR->address = offset; D_SHMHDR->address = offset;
gcc_barrier gcc_barrier
D_SHMCMD = CORE_READ_DWORD; D_SHMCMD = CORE_READ_DWORD;
d->waitWhile(CORE_READ_DWORD); waitWhile(CORE_READ_DWORD);
return D_SHMHDR->value; return D_SHMHDR->value;
} }
void Process::readDWord (const uint32_t offset, uint32_t &val) void Process::readDWord (const uint32_t offset, uint32_t &val)
@ -549,7 +592,7 @@ void Process::readDWord (const uint32_t offset, uint32_t &val)
D_SHMHDR->address = offset; D_SHMHDR->address = offset;
gcc_barrier gcc_barrier
D_SHMCMD = CORE_READ_DWORD; D_SHMCMD = CORE_READ_DWORD;
d->waitWhile(CORE_READ_DWORD); waitWhile(CORE_READ_DWORD);
val = D_SHMHDR->value; val = D_SHMHDR->value;
} }
@ -563,7 +606,7 @@ void Process::writeDWord (uint32_t offset, uint32_t data)
D_SHMHDR->value = data; D_SHMHDR->value = data;
gcc_barrier gcc_barrier
D_SHMCMD = CORE_WRITE_DWORD; D_SHMCMD = CORE_WRITE_DWORD;
d->waitWhile(CORE_WRITE_DWORD); waitWhile(CORE_WRITE_DWORD);
} }
// using these is expensive. // using these is expensive.
@ -573,7 +616,7 @@ void Process::writeWord (uint32_t offset, uint16_t data)
D_SHMHDR->value = data; D_SHMHDR->value = data;
gcc_barrier gcc_barrier
D_SHMCMD = CORE_WRITE_WORD; D_SHMCMD = CORE_WRITE_WORD;
d->waitWhile(CORE_WRITE_WORD); waitWhile(CORE_WRITE_WORD);
} }
void Process::writeByte (uint32_t offset, uint8_t data) void Process::writeByte (uint32_t offset, uint8_t data)
@ -582,7 +625,7 @@ void Process::writeByte (uint32_t offset, uint8_t data)
D_SHMHDR->value = data; D_SHMHDR->value = data;
gcc_barrier gcc_barrier
D_SHMCMD = CORE_WRITE_BYTE; D_SHMCMD = CORE_WRITE_BYTE;
d->waitWhile(CORE_WRITE_BYTE); waitWhile(CORE_WRITE_BYTE);
} }
void Process::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer) void Process::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer)
@ -595,7 +638,7 @@ void Process::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer
memcpy(d->my_shm+SHM_HEADER,source_buffer, size); memcpy(d->my_shm+SHM_HEADER,source_buffer, size);
gcc_barrier gcc_barrier
D_SHMCMD = CORE_WRITE; D_SHMCMD = CORE_WRITE;
d->waitWhile(CORE_WRITE); waitWhile(CORE_WRITE);
} }
// a big write, we push this over the shm in iterations // a big write, we push this over the shm in iterations
else else
@ -610,7 +653,7 @@ void Process::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer
memcpy(d->my_shm+SHM_HEADER,source_buffer, to_write); memcpy(d->my_shm+SHM_HEADER,source_buffer, to_write);
gcc_barrier gcc_barrier
D_SHMCMD = CORE_WRITE; D_SHMCMD = CORE_WRITE;
d->waitWhile(CORE_WRITE); waitWhile(CORE_WRITE);
// decrease size by bytes written // decrease size by bytes written
size -= to_write; size -= to_write;
// move the cursors // move the cursors
@ -661,7 +704,7 @@ const std::string Process::readSTLString(uint32_t offset)
D_SHMHDR->address = offset; D_SHMHDR->address = offset;
full_barrier full_barrier
D_SHMCMD = CORE_READ_STL_STRING; D_SHMCMD = CORE_READ_STL_STRING;
d->waitWhile(CORE_READ_STL_STRING); waitWhile(CORE_READ_STL_STRING);
//int length = ((shm_retval *)d->my_shm)->value; //int length = ((shm_retval *)d->my_shm)->value;
return(string( (char *)d->my_shm+SHM_HEADER)); return(string( (char *)d->my_shm+SHM_HEADER));
} }
@ -671,7 +714,7 @@ size_t Process::readSTLString (uint32_t offset, char * buffer, size_t bufcapacit
D_SHMHDR->address = offset; D_SHMHDR->address = offset;
full_barrier full_barrier
D_SHMCMD = CORE_READ_STL_STRING; D_SHMCMD = CORE_READ_STL_STRING;
d->waitWhile(CORE_READ_STL_STRING); waitWhile(CORE_READ_STL_STRING);
size_t length = D_SHMHDR->value; size_t length = D_SHMHDR->value;
size_t fit = min(bufcapacity - 1, length); size_t fit = min(bufcapacity - 1, length);
strncpy(buffer,(char *)d->my_shm+SHM_HEADER,fit); strncpy(buffer,(char *)d->my_shm+SHM_HEADER,fit);
@ -685,7 +728,7 @@ void Process::writeSTLString(const uint32_t address, const std::string writeStri
strncpy(d->my_shm+SHM_HEADER,writeString.c_str(),writeString.length()+1); // length + 1 for the null terminator strncpy(d->my_shm+SHM_HEADER,writeString.c_str(),writeString.length()+1); // length + 1 for the null terminator
full_barrier full_barrier
D_SHMCMD = CORE_WRITE_STL_STRING; D_SHMCMD = CORE_WRITE_STL_STRING;
d->waitWhile(CORE_WRITE_STL_STRING); waitWhile(CORE_WRITE_STL_STRING);
} }
string Process::readClassName (uint32_t vptr) string Process::readClassName (uint32_t vptr)
@ -696,4 +739,23 @@ string Process::readClassName (uint32_t vptr)
size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers
size_t end = raw.length(); size_t end = raw.length();
return raw.substr(start,end-start - 2); // trim the 'st' from the end return raw.substr(start,end-start - 2); // trim the 'st' from the end
}
// get module index by name and version. bool 1 = error
bool Process::getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT)
{
modulelookup * payload = (modulelookup *) (d->my_shm + SHM_HEADER);
payload->version = version;
strcpy(payload->name,name);
full_barrier
D_SHMCMD = CORE_ACQUIRE_MODULE;
waitWhile(CORE_ACQUIRE_MODULE);
if(D_SHMHDR->error) return false;
OUTPUT = D_SHMHDR->value;
return true;
}
char * Process::getSHMStart (void)
{
return d->my_shm;
} }

@ -23,7 +23,7 @@ distribution.
*/ */
#include "DFCommonInternal.h" #include "DFCommonInternal.h"
#include "../shmserver/shms.h" #include "../shmserver/shms.h"
#include "../shmserver/shms-core.h" #include "../shmserver/mod-core.h"
using namespace DFHack; using namespace DFHack;
// a full memory barrier! better be safe than sorry. // a full memory barrier! better be safe than sorry.
@ -56,7 +56,7 @@ class Process::Private
bool identified; bool identified;
bool useYield; bool useYield;
bool waitWhile (CORE_COMMAND state); bool waitWhile (uint32_t state);
bool isValidSV(); bool isValidSV();
bool DF_TestBridgeVersion(bool & ret); bool DF_TestBridgeVersion(bool & ret);
bool DF_GetPID(uint32_t & ret); bool DF_GetPID(uint32_t & ret);
@ -98,10 +98,15 @@ bool Process::Private::isValidSV()
} }
} }
bool Process::Private::waitWhile (CORE_COMMAND state) bool Process::waitWhile (uint32_t state)
{
return d->waitWhile(state);
}
bool Process::Private::waitWhile (uint32_t state)
{ {
uint32_t cnt = 0; uint32_t cnt = 0;
while (((shm_cmd *)my_shm)->pingpong == state) while (SHMCMD == state)
{ {
// yield the CPU, only on single-core CPUs // yield the CPU, only on single-core CPUs
if(useYield) if(useYield)
@ -112,7 +117,7 @@ bool Process::Private::waitWhile (CORE_COMMAND state)
{ {
if(!isValidSV())// DF not there anymore? if(!isValidSV())// DF not there anymore?
{ {
((shm_cmd *)my_shm)->pingpong = CORE_RUNNING; SHMCMD = CORE_RUNNING;
attached = suspended = false; attached = suspended = false;
ReleaseMutex(DFCLMutex); ReleaseMutex(DFCLMutex);
return false; return false;
@ -124,9 +129,9 @@ bool Process::Private::waitWhile (CORE_COMMAND state)
} }
cnt++; cnt++;
} }
if(((shm_cmd *)my_shm)->pingpong == CORE_SV_ERROR) if(SHMCMD == CORE_SV_ERROR)
{ {
((shm_cmd *)my_shm)->pingpong = CORE_RUNNING; SHMCMD = CORE_RUNNING;
attached = suspended = false; attached = suspended = false;
cerr << "shm server error!" << endl; cerr << "shm server error!" << endl;
return false; return false;
@ -136,33 +141,28 @@ bool Process::Private::waitWhile (CORE_COMMAND state)
bool Process::Private::DF_TestBridgeVersion(bool & ret) bool Process::Private::DF_TestBridgeVersion(bool & ret)
{ {
((shm_cmd *)my_shm)->pingpong = CORE_GET_VERSION; SHMCMD = CORE_GET_VERSION;
full_barrier full_barrier
if(!waitWhile(CORE_GET_VERSION)) if(!waitWhile(CORE_GET_VERSION))
return false; return false;
full_barrier full_barrier
((shm_cmd *)my_shm)->pingpong = CORE_SUSPENDED; SHMCMD = CORE_SUSPENDED;
ret =( ((shm_val *)my_shm)->value == CORE_VERSION ); ret =( SHMHDR->value == CORE_VERSION );
return true; return true;
} }
bool Process::Private::DF_GetPID(uint32_t & ret) bool Process::Private::DF_GetPID(uint32_t & ret)
{ {
((shm_cmd *)my_shm)->pingpong = CORE_GET_PID; SHMCMD = CORE_GET_PID;
full_barrier full_barrier
if(!waitWhile(CORE_GET_PID)) if(!waitWhile(CORE_GET_PID))
return false; return false;
full_barrier full_barrier
((shm_cmd *)my_shm)->pingpong = CORE_SUSPENDED; SHMCMD = CORE_SUSPENDED;
ret = ((shm_val *)my_shm)->value; ret = SHMHDR->value;
return true; return true;
} }
void Process::Private::DF_SyncAffinity(void)
{
}
uint32_t OS_getAffinity() uint32_t OS_getAffinity()
{ {
HANDLE hProcess = GetCurrentProcess(); HANDLE hProcess = GetCurrentProcess();
@ -223,7 +223,7 @@ Process::Process(vector <memory_info *> & known_versions)
if(!bridgeOK) if(!bridgeOK)
{ {
fprintf(stderr,"SHM bridge version mismatch\n"); fprintf(stderr,"SHM bridge version mismatch\n");
((shm_cmd *)d->my_shm)->pingpong = CORE_RUNNING; D_SHMCMD = CORE_RUNNING;
UnmapViewOfFile(d->my_shm); UnmapViewOfFile(d->my_shm);
ReleaseMutex(d->DFCLMutex); ReleaseMutex(d->DFCLMutex);
CloseHandle(d->DFSVMutex); CloseHandle(d->DFSVMutex);
@ -300,7 +300,7 @@ Process::Process(vector <memory_info *> & known_versions)
} }
else else
{ {
((shm_cmd *)d->my_shm)->pingpong = CORE_RUNNING; D_SHMCMD = CORE_RUNNING;
UnmapViewOfFile(d->my_shm); UnmapViewOfFile(d->my_shm);
d->my_shm = 0; d->my_shm = 0;
ReleaseMutex(d->DFCLMutex); ReleaseMutex(d->DFCLMutex);
@ -417,7 +417,7 @@ bool Process::suspend()
cerr << "couldn't suspend, already suspended" << endl; cerr << "couldn't suspend, already suspended" << endl;
return true; return true;
} }
((shm_cmd *)d->my_shm)->pingpong = CORE_SUSPEND; D_SHMCMD = CORE_SUSPEND;
if(!d->waitWhile(CORE_SUSPEND)) if(!d->waitWhile(CORE_SUSPEND))
{ {
cerr << "couldn't suspend, DF not responding to commands" << endl; cerr << "couldn't suspend, DF not responding to commands" << endl;
@ -437,14 +437,14 @@ bool Process::asyncSuspend()
{ {
return true; return true;
} }
if(((shm_cmd *)d->my_shm)->pingpong == CORE_SUSPENDED) if(D_SHMCMD == CORE_SUSPENDED)
{ {
d->suspended = true; d->suspended = true;
return true; return true;
} }
else else
{ {
((shm_cmd *)d->my_shm)->pingpong = CORE_SUSPEND; D_SHMCMD = CORE_SUSPEND;
return false; return false;
} }
} }
@ -466,7 +466,7 @@ bool Process::resume()
cerr << "couldn't resume because of not being suspended" << endl; cerr << "couldn't resume because of not being suspended" << endl;
return true; return true;
} }
((shm_cmd *)d->my_shm)->pingpong = CORE_RUNNING; D_SHMCMD = CORE_RUNNING;
d->suspended = false; d->suspended = false;
return true; return true;
} }
@ -541,10 +541,10 @@ void Process::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
// normal read under 1MB // normal read under 1MB
if(size <= SHM_BODY) if(size <= SHM_BODY)
{ {
((shm_addrlen *)d->my_shm)->address = src_address; D_SHMHDR->address = src_address;
((shm_addrlen *)d->my_shm)->length = size; D_SHMHDR->length = size;
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_DFPP_READ; D_SHMCMD = CORE_DFPP_READ;
d->waitWhile(CORE_DFPP_READ); d->waitWhile(CORE_DFPP_READ);
memcpy (target_buffer, d->my_shm + SHM_HEADER,size); memcpy (target_buffer, d->my_shm + SHM_HEADER,size);
} }
@ -556,10 +556,10 @@ void Process::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
while (size) while (size)
{ {
// read to_read bytes from src_cursor // read to_read bytes from src_cursor
((shm_addrlen *)d->my_shm)->address = src_address; D_SHMHDR->address = src_address;
((shm_addrlen *)d->my_shm)->length = to_read; D_SHMHDR->length = to_read;
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_DFPP_READ; D_SHMCMD = CORE_DFPP_READ;
d->waitWhile(CORE_DFPP_READ); d->waitWhile(CORE_DFPP_READ);
memcpy (target_buffer, d->my_shm + SHM_HEADER,size); memcpy (target_buffer, d->my_shm + SHM_HEADER,size);
// decrease size by bytes read // decrease size by bytes read
@ -575,55 +575,55 @@ void Process::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
uint8_t Process::readByte (const uint32_t offset) uint8_t Process::readByte (const uint32_t offset)
{ {
((shm_addr *)d->my_shm)->address = offset; D_SHMHDR->address = offset;
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_BYTE; D_SHMCMD = CORE_READ_BYTE;
d->waitWhile(CORE_READ_BYTE); d->waitWhile(CORE_READ_BYTE);
return ((shm_val *)d->my_shm)->value; return D_SHMHDR->value;
} }
void Process::readByte (const uint32_t offset, uint8_t &val ) void Process::readByte (const uint32_t offset, uint8_t &val )
{ {
((shm_addr *)d->my_shm)->address = offset; D_SHMHDR->address = offset;
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_BYTE; D_SHMCMD = CORE_READ_BYTE;
d->waitWhile(CORE_READ_BYTE); d->waitWhile(CORE_READ_BYTE);
val = ((shm_val *)d->my_shm)->value; val = D_SHMHDR->value;
} }
uint16_t Process::readWord (const uint32_t offset) uint16_t Process::readWord (const uint32_t offset)
{ {
((shm_addr *)d->my_shm)->address = offset; D_SHMHDR->address = offset;
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_WORD; D_SHMCMD = CORE_READ_WORD;
d->waitWhile(CORE_READ_WORD); d->waitWhile(CORE_READ_WORD);
return ((shm_val *)d->my_shm)->value; return D_SHMHDR->value;
} }
void Process::readWord (const uint32_t offset, uint16_t &val) void Process::readWord (const uint32_t offset, uint16_t &val)
{ {
((shm_addr *)d->my_shm)->address = offset; D_SHMHDR->address = offset;
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_WORD; D_SHMCMD = CORE_READ_WORD;
d->waitWhile(CORE_READ_WORD); d->waitWhile(CORE_READ_WORD);
val = ((shm_val *)d->my_shm)->value; val = D_SHMHDR->value;
} }
uint32_t Process::readDWord (const uint32_t offset) uint32_t Process::readDWord (const uint32_t offset)
{ {
((shm_addr *)d->my_shm)->address = offset; D_SHMHDR->address = offset;
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_DWORD; D_SHMCMD = CORE_READ_DWORD;
d->waitWhile(CORE_READ_DWORD); d->waitWhile(CORE_READ_DWORD);
return ((shm_val *)d->my_shm)->value; return D_SHMHDR->value;
} }
void Process::readDWord (const uint32_t offset, uint32_t &val) void Process::readDWord (const uint32_t offset, uint32_t &val)
{ {
((shm_addr *)d->my_shm)->address = offset; D_SHMHDR->address = offset;
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_DWORD; D_SHMCMD = CORE_READ_DWORD;
d->waitWhile(CORE_READ_DWORD); d->waitWhile(CORE_READ_DWORD);
val = ((shm_val *)d->my_shm)->value; val = D_SHMHDR->value;
} }
/* /*
@ -632,29 +632,29 @@ void Process::readDWord (const uint32_t offset, uint32_t &val)
void Process::writeDWord (uint32_t offset, uint32_t data) void Process::writeDWord (uint32_t offset, uint32_t data)
{ {
((shm_addrval *)d->my_shm)->address = offset; D_SHMHDR->address = offset;
((shm_addrval *)d->my_shm)->value = data; D_SHMHDR->value = data;
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE_DWORD; D_SHMCMD = CORE_WRITE_DWORD;
d->waitWhile(CORE_WRITE_DWORD); d->waitWhile(CORE_WRITE_DWORD);
} }
// using these is expensive. // using these is expensive.
void Process::writeWord (uint32_t offset, uint16_t data) void Process::writeWord (uint32_t offset, uint16_t data)
{ {
((shm_addrval *)d->my_shm)->address = offset; D_SHMHDR->address = offset;
((shm_addrval *)d->my_shm)->value = data; D_SHMHDR->value = data;
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE_WORD; D_SHMCMD = CORE_WRITE_WORD;
d->waitWhile(CORE_WRITE_WORD); d->waitWhile(CORE_WRITE_WORD);
} }
void Process::writeByte (uint32_t offset, uint8_t data) void Process::writeByte (uint32_t offset, uint8_t data)
{ {
((shm_addrval *)d->my_shm)->address = offset; D_SHMHDR->address = offset;
((shm_addrval *)d->my_shm)->value = data; D_SHMHDR->value = data;
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE_BYTE; D_SHMCMD = CORE_WRITE_BYTE;
d->waitWhile(CORE_WRITE_BYTE); d->waitWhile(CORE_WRITE_BYTE);
} }
@ -663,11 +663,11 @@ void Process::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer
// normal write under 1MB // normal write under 1MB
if(size <= SHM_BODY) if(size <= SHM_BODY)
{ {
((shm_addrlen *)d->my_shm)->address = dst_address; D_SHMHDR->address = dst_address;
((shm_addrlen *)d->my_shm)->length = size; D_SHMHDR->length = size;
memcpy(d->my_shm+SHM_HEADER,source_buffer, size); memcpy(d->my_shm+SHM_HEADER,source_buffer, size);
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE; D_SHMCMD = CORE_WRITE;
d->waitWhile(CORE_WRITE); d->waitWhile(CORE_WRITE);
} }
// a big write, we push this over the shm in iterations // a big write, we push this over the shm in iterations
@ -678,11 +678,11 @@ void Process::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer
while (size) while (size)
{ {
// write to_write bytes to dst_cursor // write to_write bytes to dst_cursor
((shm_addrlen *)d->my_shm)->address = dst_address; D_SHMHDR->address = dst_address;
((shm_addrlen *)d->my_shm)->length = to_write; D_SHMHDR->length = to_write;
memcpy(d->my_shm+SHM_HEADER,source_buffer, to_write); memcpy(d->my_shm+SHM_HEADER,source_buffer, to_write);
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE; D_SHMCMD = CORE_WRITE;
d->waitWhile(CORE_WRITE); d->waitWhile(CORE_WRITE);
// decrease size by bytes written // decrease size by bytes written
size -= to_write; size -= to_write;
@ -734,11 +734,11 @@ DfVector Process::readVector (uint32_t offset, uint32_t item_size)
const std::string Process::readSTLString(uint32_t offset) const std::string Process::readSTLString(uint32_t offset)
{ {
//offset -= 4; //msvc std::string pointers are 8 bytes ahead of their data, not 4 //offset -= 4; //msvc std::string pointers are 8 bytes ahead of their data, not 4
((shm_addr *)d->my_shm)->address = offset; D_SHMHDR->address = offset;
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_STL_STRING; D_SHMCMD = CORE_READ_STL_STRING;
d->waitWhile(CORE_READ_STL_STRING); d->waitWhile(CORE_READ_STL_STRING);
int length = ((shm_val *)d->my_shm)->value; int length = D_SHMHDR->value;
// char temp_c[256]; // char temp_c[256];
// strncpy(temp_c, d->my_shm+SHM_HEADER,length+1); // length + 1 for the null terminator // strncpy(temp_c, d->my_shm+SHM_HEADER,length+1); // length + 1 for the null terminator
return(string(d->my_shm+SHM_HEADER)); return(string(d->my_shm+SHM_HEADER));
@ -747,11 +747,11 @@ const std::string Process::readSTLString(uint32_t offset)
size_t Process::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity) size_t Process::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{ {
//offset -= 4; //msvc std::string pointers are 8 bytes ahead of their data, not 4 //offset -= 4; //msvc std::string pointers are 8 bytes ahead of their data, not 4
((shm_addr *)d->my_shm)->address = offset; D_SHMHDR->address = offset;
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_STL_STRING; D_SHMCMD = CORE_READ_STL_STRING;
d->waitWhile(CORE_READ_STL_STRING); d->waitWhile(CORE_READ_STL_STRING);
size_t length = ((shm_val *)d->my_shm)->value; size_t length = D_SHMHDR->value;
size_t real = min(length, bufcapacity - 1); size_t real = min(length, bufcapacity - 1);
strncpy(buffer, d->my_shm+SHM_HEADER,real); // length + 1 for the null terminator strncpy(buffer, d->my_shm+SHM_HEADER,real); // length + 1 for the null terminator
buffer[real] = 0; buffer[real] = 0;
@ -760,10 +760,10 @@ size_t Process::readSTLString (uint32_t offset, char * buffer, size_t bufcapacit
void Process::writeSTLString(const uint32_t address, const std::string writeString) void Process::writeSTLString(const uint32_t address, const std::string writeString)
{ {
((shm_addr *)d->my_shm)->address = address/*-4*/; D_SHMHDR->address = address/*-4*/;
strncpy(d->my_shm+SHM_HEADER,writeString.c_str(),writeString.length()+1); // length + 1 for the null terminator strncpy(d->my_shm+SHM_HEADER,writeString.c_str(),writeString.length()+1); // length + 1 for the null terminator
full_barrier full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE_STL_STRING; D_SHMCMD = CORE_WRITE_STL_STRING;
d->waitWhile(CORE_WRITE_STL_STRING); d->waitWhile(CORE_WRITE_STL_STRING);
} }
@ -774,4 +774,23 @@ string Process::readClassName (uint32_t vptr)
string raw = readCString(typeinfo + 0xC); // skips the .?AV string raw = readCString(typeinfo + 0xC); // skips the .?AV
raw.resize(raw.length() - 4);// trim st@@ from end raw.resize(raw.length() - 4);// trim st@@ from end
return raw; return raw;
}
// get module index by name and version. bool 1 = error
bool Process::getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT)
{
modulelookup * payload = (modulelookup *) (d->my_shm + SHM_HEADER);
payload->version = version;
strcpy(payload->name,name);
full_barrier
D_SHMCMD = CORE_ACQUIRE_MODULE;
d->waitWhile(CORE_ACQUIRE_MODULE);
if(D_SHMHDR->error) return false;
OUTPUT = D_SHMHDR->value;
return true;
}
char * Process::getSHMStart (void)
{
return d->my_shm;
} }

@ -121,6 +121,12 @@ namespace DFHack
DFWindow * getWindow(); DFWindow * getWindow();
// get the DF Process ID // get the DF Process ID
int getPID(); int getPID();
// get module index by name and version. bool 1 = error
bool getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT);
// get the SHM start if available
char * getSHMStart (void);
// wait for a SHM state. returns 0 without the SHM
bool waitWhile (uint32_t state);
}; };
} }
#endif #endif

@ -764,6 +764,15 @@ union t_occupancy
naked_occupancy_grouped unibits; naked_occupancy_grouped unibits;
}; };
typedef struct
{
int16_t tiletypes [16][16];
DFHack::t_designation designaton [16][16];
DFHack::t_occupancy occupancy [16][16];
uint8_t biome_indices [7];
uint32_t dirty_dword; // bit 1 set means that the block is to be included in job checks
} mapblock40d;
struct t_viewscreen struct t_viewscreen
{ {
int32_t type; int32_t type;

@ -2,10 +2,13 @@
SET(PROJECT_HDRS SET(PROJECT_HDRS
shms.h shms.h
mod-core.h
mod-maps.h
) )
SET(PROJECT_SRCS SET(PROJECT_SRCS
shms-core.cpp mod-core.cpp
mod-maps.cpp
) )
SET(PROJECT_HDRS_LINUX SET(PROJECT_HDRS_LINUX

@ -32,8 +32,12 @@ distribution.
#include <string.h> #include <string.h>
#include <string> #include <string>
#include <vector> #include <vector>
#define SHM_INTERNAL // for things only visible to the SHM
#include "shms.h" #include "shms.h"
#include "shms-core.h" #include "mod-core.h"
#include "mod-maps.h"
std::vector <DFPP_module> module_registry; std::vector <DFPP_module> module_registry;
@ -46,57 +50,57 @@ bool useYield = 0;
#define SHMHDR ((shm_core_hdr *)shm) #define SHMHDR ((shm_core_hdr *)shm)
#define SHMCMD ((shm_cmd *)shm)->pingpong #define SHMCMD ((shm_cmd *)shm)->pingpong
void GetCoreVersion (void) void GetCoreVersion (void * data)
{ {
SHMHDR->value = module_registry[0].version; SHMHDR->value = module_registry[0].version;
} }
void GetPID (void) void GetPID (void * data)
{ {
SHMHDR->value = OS_getPID(); SHMHDR->value = OS_getPID();
} }
void ReadRaw (void) void ReadRaw (void * data)
{ {
memcpy(shm + SHM_HEADER, (void *) SHMHDR->address,SHMHDR->length); memcpy(shm + SHM_HEADER, (void *) SHMHDR->address,SHMHDR->length);
} }
void ReadDWord (void) void ReadDWord (void * data)
{ {
SHMHDR->value = *((uint32_t*) SHMHDR->address); SHMHDR->value = *((uint32_t*) SHMHDR->address);
} }
void ReadWord (void) void ReadWord (void * data)
{ {
SHMHDR->value = *((uint16_t*) SHMHDR->address); SHMHDR->value = *((uint16_t*) SHMHDR->address);
} }
void ReadByte (void) void ReadByte (void * data)
{ {
SHMHDR->value = *((uint8_t*) SHMHDR->address); SHMHDR->value = *((uint8_t*) SHMHDR->address);
} }
void WriteRaw (void) void WriteRaw (void * data)
{ {
memcpy((void *)SHMHDR->address, shm + SHM_HEADER,SHMHDR->length); memcpy((void *)SHMHDR->address, shm + SHM_HEADER,SHMHDR->length);
} }
void WriteDWord (void) void WriteDWord (void * data)
{ {
(*(uint32_t*)SHMHDR->address) = SHMHDR->value; (*(uint32_t*)SHMHDR->address) = SHMHDR->value;
} }
void WriteWord (void) void WriteWord (void * data)
{ {
(*(uint16_t*)SHMHDR->address) = SHMHDR->value; (*(uint16_t*)SHMHDR->address) = SHMHDR->value;
} }
void WriteByte (void) void WriteByte (void * data)
{ {
(*(uint8_t*)SHMHDR->address) = SHMHDR->value; (*(uint8_t*)SHMHDR->address) = SHMHDR->value;
} }
void ReadSTLString (void) void ReadSTLString (void * data)
{ {
std::string * myStringPtr = (std::string *) SHMHDR->address; std::string * myStringPtr = (std::string *) SHMHDR->address;
unsigned int l = myStringPtr->length(); unsigned int l = myStringPtr->length();
@ -105,7 +109,7 @@ void ReadSTLString (void)
strncpy(shm+SHM_HEADER,myStringPtr->c_str(),l+1); strncpy(shm+SHM_HEADER,myStringPtr->c_str(),l+1);
} }
void WriteSTLString (void) void WriteSTLString (void * data)
{ {
std::string * myStringPtr = (std::string *) SHMHDR->address; std::string * myStringPtr = (std::string *) SHMHDR->address;
// here we DO expect a 0 terminator // here we DO expect a 0 terminator
@ -122,7 +126,7 @@ int bitcount(uint32_t n)
} }
// get local and remote affinity, set up yield if required (single core available) // get local and remote affinity, set up yield if required (single core available)
void SyncYield (void) void SyncYield (void * data)
{ {
uint32_t local = OS_getAffinity(); uint32_t local = OS_getAffinity();
uint32_t remote = SHMHDR->value; uint32_t remote = SHMHDR->value;
@ -137,7 +141,33 @@ void SyncYield (void)
} }
} }
void InitCore(void) void FindModule (void * data)
{
bool found = false;
modulelookup * payload = (modulelookup *) (shm + SHM_HEADER);
std::string test = payload->name;
uint32_t version = payload->version;
for(unsigned int i = 0; i < module_registry.size();i++)
{
if(module_registry[i].name == test && module_registry[i].version == version)
{
// gotcha
SHMHDR->value = i;
found = true;
break;
}
}
if(found)
{
SHMHDR->error = false;
}
else
{
SHMHDR->error = true;
}
}
DFPP_module InitCore(void)
{ {
DFPP_module core; DFPP_module core;
core.name = "Core"; core.name = "Core";
@ -181,16 +211,31 @@ void InitCore(void)
core.set_command(CORE_RET_STRING, CLIENT_WAIT, "Return string"); core.set_command(CORE_RET_STRING, CLIENT_WAIT, "Return string");
core.set_command(CORE_WRITE_STL_STRING, FUNCTION, "Write STL string", WriteSTLString, CORE_SUSPENDED); core.set_command(CORE_WRITE_STL_STRING, FUNCTION, "Write STL string", WriteSTLString, CORE_SUSPENDED);
core.set_command(CORE_SYNC_YIELD, FUNCTION, "Synchronize affinity/yield", SyncYield, CORE_SYNC_YIELD_RET); core.set_command(CORE_SYNC_YIELD, FUNCTION, "Synchronize affinity/yield", SyncYield, CORE_SYNC_YIELD_RET);
module_registry.push_back(core); core.set_command(CORE_SYNC_YIELD_RET, CLIENT_WAIT, "Synchronize affinity/yield return");
core.set_command(CORE_ACQUIRE_MODULE, FUNCTION, "Module lookup", FindModule, CORE_RET_MODULE);
core.set_command(CORE_RET_MODULE, CLIENT_WAIT, "Return module index or error");
return core;
} }
void InitModules (void) void InitModules (void)
{ {
// create the core module // create the core module
InitCore(); module_registry.push_back(InitCore());
module_registry.push_back(InitMaps());
// TODO: dynamic module init // TODO: dynamic module init
} }
void KillModules (void)
{
for(unsigned int i = 0; i < module_registry.size();i++)
{
if(module_registry[i].modulestate)
free(module_registry[i].modulestate);
}
module_registry.clear();
}
void SHM_Act (void) void SHM_Act (void)
{ {
if(errorstate) if(errorstate)
@ -215,10 +260,12 @@ void SHM_Act (void)
} }
DFPP_module & mod = module_registry[((shm_cmd *)shm)->parts.module]; DFPP_module & mod = module_registry[((shm_cmd *)shm)->parts.module];
DFPP_command & cmd = mod.commands[((shm_cmd *)shm)->parts.command]; DFPP_command & cmd = mod.commands[((shm_cmd *)shm)->parts.command];
//fprintf(stderr, "Client invoked %s\n", cmd.name.c_str() ); //fprintf(stderr, "Client invoked %d:%d = ",((shm_cmd *)shm)->parts.module,((shm_cmd *)shm)->parts.command);
//fprintf(stderr, "%s\n",cmd.name.c_str());
if(cmd._function) if(cmd._function)
{ {
cmd._function(); cmd._function(mod.modulestate);
} }
if(cmd.nextState != -1) if(cmd.nextState != -1)
{ {

@ -3,7 +3,7 @@
#include <integers.h> #include <integers.h>
#include "shms.h" #include "shms.h"
#include "shms-core.h" #include "mod-core.h"
#include "mod-maps.h" #include "mod-maps.h"
#include <DFTypes.h> #include <DFTypes.h>
using namespace DFHack; using namespace DFHack;
@ -69,7 +69,7 @@ void ReadBlockByCoords (void * data)
*/ */
mblock * *** mapArray = *(mblock * ****)offsets.map_offset; mblock * *** mapArray = *(mblock * ****)offsets.map_offset;
mblock * block = mapArray[SHMHDR->x][SHMHDR->y][SHMHDR->z]; mblock * block = mapArray[SHMHDR->x][SHMHDR->y][SHMHDR->z];
fprintf(stderr, "Readblock: %d %d %d 0x%x\n", SHMHDR->x,SHMHDR->y,SHMHDR->z, block); //fprintf(stderr, "Readblock: %d %d %d 0x%x\n", SHMHDR->x,SHMHDR->y,SHMHDR->z, block);
if(block) if(block)
{ {
memcpy(&(SHMBLOCK->tiletypes), block + offsets.tile_type_offset, sizeof(SHMBLOCK->tiletypes)); memcpy(&(SHMBLOCK->tiletypes), block + offsets.tile_type_offset, sizeof(SHMBLOCK->tiletypes));
@ -85,7 +85,7 @@ void ReadBlockByCoords (void * data)
} }
} }
DFPP_module InitMaps(std::vector <DFPP_module>* module_registry) DFPP_module InitMaps( void )
{ {
DFPP_module maps; DFPP_module maps;
maps.name = "Maps"; maps.name = "Maps";
@ -103,11 +103,9 @@ DFPP_module InitMaps(std::vector <DFPP_module>* module_registry)
// will it fit into 1MB? We shouldn't assume this is the case // will it fit into 1MB? We shouldn't assume this is the case
maps.set_command(MAP_READ_BLOCKTREE, FUNCTION,"Get the tree of block pointers as a single structure", NullCommand, CORE_SUSPENDED); maps.set_command(MAP_READ_BLOCKTREE, FUNCTION,"Get the tree of block pointers as a single structure", NullCommand, CORE_SUSPENDED);
// really doesn't fit into 1MB, there should be a streaming variant to better utilize context switches // really doesn't fit into 1MB, there should be a streaming variant to better utilize context switches
maps.set_command(MAP_READ_BLOCKS_3D, FUNCTION, "Read a range of blocks between two sets of coords", NullCommand, CORE_SUSPENDED); maps.set_command(MAP_READ_BLOCKS_3D, FUNCTION, "Read a range of blocks between two sets of coords", NullCommand, CORE_SUSPENDED);
module_registry->push_back(maps); return maps;
} }

@ -37,7 +37,7 @@ distribution.
#include <vector> #include <vector>
#include <string> #include <string>
#include "shms.h" #include "shms.h"
#include "shms-core.h" #include "mod-core.h"
#include <sched.h> #include <sched.h>
#define DFhackCExport extern "C" __attribute__ ((visibility("default"))) #define DFhackCExport extern "C" __attribute__ ((visibility("default")))
@ -125,6 +125,7 @@ void SHM_Destroy ( void )
{ {
if(inited && !errorstate) if(inited && !errorstate)
{ {
KillModules();
shmid_ds descriptor; shmid_ds descriptor;
shmctl(shmid, IPC_STAT, &descriptor); shmctl(shmid, IPC_STAT, &descriptor);
shmdt(shm); shmdt(shm);

@ -37,6 +37,7 @@ distribution.
#include <vector> #include <vector>
#include <string> #include <string>
#include "shms.h" #include "shms.h"
#include "mod-core.h"
#include <cstdio> #include <cstdio>
int errorstate = 0; int errorstate = 0;
char *shm = 0; char *shm = 0;
@ -150,6 +151,7 @@ void SHM_Destroy ( void )
{ {
if(errorstate) if(errorstate)
return; return;
KillModules();
ReleaseMutex(DFSVMutex); ReleaseMutex(DFSVMutex);
CloseHandle(DFSVMutex); CloseHandle(DFSVMutex);
CloseHandle(DFCLMutex); CloseHandle(DFCLMutex);
@ -160,6 +162,17 @@ uint32_t OS_getPID()
return GetCurrentProcessId(); return GetCurrentProcessId();
} }
// TODO: move to some utils file
uint32_t OS_getAffinity()
{
HANDLE hProcess = GetCurrentProcess();
DWORD dwProcessAffinityMask, dwSystemAffinityMask;
GetProcessAffinityMask( hProcess, &dwProcessAffinityMask, &dwSystemAffinityMask );
return dwProcessAffinityMask;
}
// is the other side still there? // is the other side still there?
bool isValidSHM() bool isValidSHM()
{ {

@ -38,7 +38,7 @@ enum DFPP_CmdType
struct DFPP_command struct DFPP_command
{ {
void (*_function)(void); void (*_function)(void *);
DFPP_CmdType type:32; // force the enum to 32 bits for compatibility reasons DFPP_CmdType type:32; // force the enum to 32 bits for compatibility reasons
std::string name; std::string name;
uint32_t nextState; uint32_t nextState;
@ -46,7 +46,21 @@ struct DFPP_command
struct DFPP_module struct DFPP_module
{ {
inline void set_command(const unsigned int index, const DFPP_CmdType type, const char * name, void (*_function)(void) = 0,uint32_t nextState = -1) DFPP_module()
{
name = "Uninitialized module";
version = 0;
modulestate = 0;
}
// ALERT: the structures share state
DFPP_module(const DFPP_module & orig)
{
commands = orig.commands;
name = orig.name;
modulestate = orig.modulestate;
version = orig.version;
}
inline void set_command(const unsigned int index, const DFPP_CmdType type, const char * name, void (*_function)(void *) = 0,uint32_t nextState = -1)
{ {
commands[index].type = type; commands[index].type = type;
commands[index].name = name; commands[index].name = name;
@ -81,8 +95,10 @@ typedef union
void SHM_Act (void); void SHM_Act (void);
void InitModules (void); void InitModules (void);
void KillModules (void);
bool isValidSHM(); bool isValidSHM();
uint32_t OS_getPID(); uint32_t OS_getPID();
DFPP_module InitMaps(void);
uint32_t OS_getAffinity(); // limited to 32 processors. Silly, eh? uint32_t OS_getAffinity(); // limited to 32 processors. Silly, eh?
#endif #endif