diff --git a/examples/expbench.cpp b/examples/expbench.cpp index c2b7621d9..272e46021 100644 --- a/examples/expbench.cpp +++ b/examples/expbench.cpp @@ -47,9 +47,7 @@ int main (int numargs, char** args) uint32_t x_max,y_max,z_max; uint32_t num_blocks = 0; uint64_t bytes_read = 0; - uint16_t tiletypes[16][16]; - DFHack::t_designation designations[16][16]; - DFHack::t_occupancy occupancies[16][16]; + DFHack::mapblock40d Block; DFHack::API DF("Memory.xml"); if(!DF.Attach()) @@ -76,11 +74,9 @@ int main (int numargs, char** args) { if(DF.isValidBlock(x,y,z)) { - DF.ReadTileTypes(x,y,z, (uint16_t *) tiletypes); - DF.ReadDesignations(x,y,z, (uint32_t *) designations); - DF.ReadOccupancy(x,y,z, (uint32_t *) occupancies); + DF.ReadBlock40d(x, y, z, &Block); num_blocks ++; - bytes_read += sizeof(tiletypes) + sizeof(designations) + sizeof(occupancies); + bytes_read += sizeof(DFHack::mapblock40d); } } } diff --git a/examples/veinlook.cpp b/examples/veinlook.cpp index e26aa2950..5d1e7bbda 100644 --- a/examples/veinlook.cpp +++ b/examples/veinlook.cpp @@ -144,8 +144,6 @@ void clrscr() GRASS2, GRASS_DEAD, GRASS_DRY, -#include -#include DRIFTWOOD, HFS, MAGMA, @@ -272,9 +270,12 @@ main(int argc, char *argv[]) int x_max,y_max,z_max; uint32_t x_max_a,y_max_a,z_max_a; + /* uint16_t tiletypes[16][16]; DFHack::t_designation designations[16][16]; uint8_t regionoffsets[16]; + */ + mapblock40d Block; map materials; materials.clear(); vector stonetypes; @@ -300,7 +301,6 @@ main(int argc, char *argv[]) error = "Can't find a map to look at."; pDF = 0; finish(0); -#include } 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)) { // read data + DF.ReadBlock40d(cursorX+i,cursorY+j,cursorZ, &Block); + /* DF.ReadTileTypes(cursorX+i,cursorY+j,cursorZ, (uint16_t *) tiletypes); DF.ReadDesignations(cursorX+i,cursorY+j,cursorZ, (uint32_t *) designations); + */ for(int x = 0; x < 16; x++) { for(int y = 0; y < 16; y++) { if(dig) { - if(tileTypeTable[tiletypes[x][y]].c == WALL && tileTypeTable[tiletypes[x][y]].m == VEIN - || tileTypeTable[tiletypes[x][y]].c == TREE_OK || tileTypeTable[tiletypes[x][y]].c == TREE_DEAD) + TileClass tc = tileTypeTable[Block.tiletypes[x][y]].c; + 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; - color = pickColor(tiletypes[x][y]); - if(designations[x][y].bits.hidden) + color = pickColor(Block.tiletypes[x][y]); + 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 { 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); } } @@ -439,7 +443,7 @@ main(int argc, char *argv[]) filenum++; } 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); if(digbit) { diff --git a/library/DFHackAPI.cpp b/library/DFHackAPI.cpp index 9c732fe26..0dc311609 100644 --- a/library/DFHackAPI.cpp +++ b/library/DFHackAPI.cpp @@ -23,6 +23,9 @@ distribution. */ #include "DFCommonInternal.h" +#include "../shmserver/shms.h" +#include "../shmserver/mod-core.h" +#include "../shmserver/mod-maps.h" using namespace DFHack; /* @@ -106,6 +109,7 @@ public: ProcessEnumerator* pm; Process* p; + char * shm_start; memory_info* offset_descriptor; vector v_geology[eBiomeCount]; string xml; @@ -121,6 +125,8 @@ public: bool hotkeyInited; bool settlementsInited; bool nameTablesInited; + + uint32_t maps_module; uint32_t tree_offset; DfVector *p_cre; @@ -149,6 +155,8 @@ API::API (const string path_to_xml) d->notesInited = false; d->hotkeyInited = false; d->pm = NULL; + d->shm_start = 0; + d->maps_module = 0; } API::~API() @@ -156,6 +164,11 @@ API::~API() 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 * *-----------------------------------*/ @@ -181,19 +194,43 @@ bool API::InitMap() d->offset_descriptor->resolveClassnameToVPtr("block_square_event_frozen_liquid", d->vein_ice_vptr); d->vein_mineral_vptr = 0; 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 uint32_t x_array_loc = g_pProcess->readDWord (map_offset); - //FIXME: very inadequate if (!x_array_loc) { throw Error::NoMapLoaded(); - // bad stuffz happend - //return false; } - uint32_t mx, my, mz; - + // get the size + uint32_t mx, my, mz; mx = d->x_block_count = g_pProcess->readDWord (x_count_offset); my = d->y_block_count = g_pProcess->readDWord (y_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]; } +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) bool API::ReadTileTypes (uint32_t x, uint32_t y, uint32_t z, uint16_t *buffer) { @@ -713,7 +785,7 @@ bool API::ReadGeology (vector < vector >& assign) } assign.clear(); assign.reserve (eBiomeCount); - // TODO: clean this up +// // TODO: clean this up for (int i = 0; i < eBiomeCount;i++) { assign.push_back (d->v_geology[i]); @@ -1341,6 +1413,7 @@ bool API::Attach() //cerr << "couldn't attach to process" << endl; //return false; // couldn't attach to process, no go } + d->shm_start = d->p->getSHMStart(); d->offset_descriptor = d->p->getDescriptor(); // process is attached, everything went just fine... hopefully return true; @@ -1359,6 +1432,7 @@ bool API::Detach() } d->pm = NULL; d->p = NULL; + d->shm_start = 0; d->offset_descriptor = NULL; return true; } diff --git a/library/DFHackAPI.h b/library/DFHackAPI.h index 77d75f9da..cc140807f 100644 --- a/library/DFHackAPI.h +++ b/library/DFHackAPI.h @@ -135,6 +135,8 @@ namespace DFHack */ 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 WriteTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint16_t *buffer); // 256 * sizeof(uint16_t) diff --git a/library/DFProcess-linux-SHM.cpp b/library/DFProcess-linux-SHM.cpp index 15c6a0c9e..84772de5d 100644 --- a/library/DFProcess-linux-SHM.cpp +++ b/library/DFProcess-linux-SHM.cpp @@ -28,7 +28,7 @@ distribution. #include #include #include "../shmserver/shms.h" -#include "../shmserver/shms-core.h" +#include "../shmserver/mod-core.h" #include #include #include @@ -59,6 +59,7 @@ class Process::Private pid_t my_pid; char *my_shm; int my_shmid; + Process* q; bool attached; bool suspended; @@ -66,10 +67,10 @@ class Process::Private bool useYield; 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_GetPID(pid_t & ret); void DF_SyncAffinity(void); + bool waitWhile (uint32_t state); }; // 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) 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; struct shmid_ds descriptor; @@ -121,6 +122,48 @@ bool Process::Private::waitWhile (CORE_COMMAND state) 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) { SHMCMD = CORE_GET_VERSION; @@ -363,7 +406,7 @@ bool Process::suspend() return true; } D_SHMCMD = CORE_SUSPEND; - if(!d->waitWhile(CORE_SUSPEND)) + if(!waitWhile(CORE_SUSPEND)) { return false; } @@ -472,7 +515,7 @@ void Process::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer) D_SHMHDR->length = size; gcc_barrier D_SHMCMD = CORE_DFPP_READ; - d->waitWhile(CORE_DFPP_READ); + waitWhile(CORE_DFPP_READ); memcpy (target_buffer, d->my_shm + SHM_HEADER,size); } // 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; gcc_barrier D_SHMCMD = CORE_DFPP_READ; - d->waitWhile(CORE_DFPP_READ); + waitWhile(CORE_DFPP_READ); memcpy (target_buffer, d->my_shm + SHM_HEADER,size); // decrease size by bytes read size -= to_read; @@ -505,7 +548,7 @@ uint8_t Process::readByte (const uint32_t offset) D_SHMHDR->address = offset; gcc_barrier D_SHMCMD = CORE_READ_BYTE; - d->waitWhile(CORE_READ_BYTE); + waitWhile(CORE_READ_BYTE); return D_SHMHDR->value; } @@ -514,7 +557,7 @@ void Process::readByte (const uint32_t offset, uint8_t &val ) D_SHMHDR->address = offset; gcc_barrier D_SHMCMD = CORE_READ_BYTE; - d->waitWhile(CORE_READ_BYTE); + waitWhile(CORE_READ_BYTE); val = D_SHMHDR->value; } @@ -523,7 +566,7 @@ uint16_t Process::readWord (const uint32_t offset) D_SHMHDR->address = offset; gcc_barrier D_SHMCMD = CORE_READ_WORD; - d->waitWhile(CORE_READ_WORD); + waitWhile(CORE_READ_WORD); return D_SHMHDR->value; } @@ -532,7 +575,7 @@ void Process::readWord (const uint32_t offset, uint16_t &val) D_SHMHDR->address = offset; gcc_barrier D_SHMCMD = CORE_READ_WORD; - d->waitWhile(CORE_READ_WORD); + waitWhile(CORE_READ_WORD); val = D_SHMHDR->value; } @@ -541,7 +584,7 @@ uint32_t Process::readDWord (const uint32_t offset) D_SHMHDR->address = offset; gcc_barrier D_SHMCMD = CORE_READ_DWORD; - d->waitWhile(CORE_READ_DWORD); + waitWhile(CORE_READ_DWORD); return D_SHMHDR->value; } 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; gcc_barrier D_SHMCMD = CORE_READ_DWORD; - d->waitWhile(CORE_READ_DWORD); + waitWhile(CORE_READ_DWORD); val = D_SHMHDR->value; } @@ -563,7 +606,7 @@ void Process::writeDWord (uint32_t offset, uint32_t data) D_SHMHDR->value = data; gcc_barrier D_SHMCMD = CORE_WRITE_DWORD; - d->waitWhile(CORE_WRITE_DWORD); + waitWhile(CORE_WRITE_DWORD); } // using these is expensive. @@ -573,7 +616,7 @@ void Process::writeWord (uint32_t offset, uint16_t data) D_SHMHDR->value = data; gcc_barrier D_SHMCMD = CORE_WRITE_WORD; - d->waitWhile(CORE_WRITE_WORD); + waitWhile(CORE_WRITE_WORD); } 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; gcc_barrier 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) @@ -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); gcc_barrier D_SHMCMD = CORE_WRITE; - d->waitWhile(CORE_WRITE); + waitWhile(CORE_WRITE); } // a big write, we push this over the shm in iterations 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); gcc_barrier D_SHMCMD = CORE_WRITE; - d->waitWhile(CORE_WRITE); + waitWhile(CORE_WRITE); // decrease size by bytes written size -= to_write; // move the cursors @@ -661,7 +704,7 @@ const std::string Process::readSTLString(uint32_t offset) D_SHMHDR->address = offset; full_barrier 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; 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; full_barrier 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 fit = min(bufcapacity - 1, length); 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 full_barrier D_SHMCMD = CORE_WRITE_STL_STRING; - d->waitWhile(CORE_WRITE_STL_STRING); + waitWhile(CORE_WRITE_STL_STRING); } 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 end = raw.length(); 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; } \ No newline at end of file diff --git a/library/DFProcess-windows-SHM.cpp b/library/DFProcess-windows-SHM.cpp index abf06fdb2..62c2cc50d 100644 --- a/library/DFProcess-windows-SHM.cpp +++ b/library/DFProcess-windows-SHM.cpp @@ -23,7 +23,7 @@ distribution. */ #include "DFCommonInternal.h" #include "../shmserver/shms.h" -#include "../shmserver/shms-core.h" +#include "../shmserver/mod-core.h" using namespace DFHack; // a full memory barrier! better be safe than sorry. @@ -56,7 +56,7 @@ class Process::Private bool identified; bool useYield; - bool waitWhile (CORE_COMMAND state); + bool waitWhile (uint32_t state); bool isValidSV(); bool DF_TestBridgeVersion(bool & 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; - while (((shm_cmd *)my_shm)->pingpong == state) + while (SHMCMD == state) { // yield the CPU, only on single-core CPUs if(useYield) @@ -112,7 +117,7 @@ bool Process::Private::waitWhile (CORE_COMMAND state) { if(!isValidSV())// DF not there anymore? { - ((shm_cmd *)my_shm)->pingpong = CORE_RUNNING; + SHMCMD = CORE_RUNNING; attached = suspended = false; ReleaseMutex(DFCLMutex); return false; @@ -124,9 +129,9 @@ bool Process::Private::waitWhile (CORE_COMMAND state) } 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; cerr << "shm server error!" << endl; return false; @@ -136,33 +141,28 @@ bool Process::Private::waitWhile (CORE_COMMAND state) bool Process::Private::DF_TestBridgeVersion(bool & ret) { - ((shm_cmd *)my_shm)->pingpong = CORE_GET_VERSION; + SHMCMD = CORE_GET_VERSION; full_barrier if(!waitWhile(CORE_GET_VERSION)) return false; full_barrier - ((shm_cmd *)my_shm)->pingpong = CORE_SUSPENDED; - ret =( ((shm_val *)my_shm)->value == CORE_VERSION ); + SHMCMD = CORE_SUSPENDED; + ret =( SHMHDR->value == CORE_VERSION ); return true; } bool Process::Private::DF_GetPID(uint32_t & ret) { - ((shm_cmd *)my_shm)->pingpong = CORE_GET_PID; + SHMCMD = CORE_GET_PID; full_barrier if(!waitWhile(CORE_GET_PID)) return false; full_barrier - ((shm_cmd *)my_shm)->pingpong = CORE_SUSPENDED; - ret = ((shm_val *)my_shm)->value; + SHMCMD = CORE_SUSPENDED; + ret = SHMHDR->value; return true; } -void Process::Private::DF_SyncAffinity(void) -{ - -} - uint32_t OS_getAffinity() { HANDLE hProcess = GetCurrentProcess(); @@ -223,7 +223,7 @@ Process::Process(vector & known_versions) if(!bridgeOK) { fprintf(stderr,"SHM bridge version mismatch\n"); - ((shm_cmd *)d->my_shm)->pingpong = CORE_RUNNING; + D_SHMCMD = CORE_RUNNING; UnmapViewOfFile(d->my_shm); ReleaseMutex(d->DFCLMutex); CloseHandle(d->DFSVMutex); @@ -300,7 +300,7 @@ Process::Process(vector & known_versions) } else { - ((shm_cmd *)d->my_shm)->pingpong = CORE_RUNNING; + D_SHMCMD = CORE_RUNNING; UnmapViewOfFile(d->my_shm); d->my_shm = 0; ReleaseMutex(d->DFCLMutex); @@ -417,7 +417,7 @@ bool Process::suspend() cerr << "couldn't suspend, already suspended" << endl; return true; } - ((shm_cmd *)d->my_shm)->pingpong = CORE_SUSPEND; + D_SHMCMD = CORE_SUSPEND; if(!d->waitWhile(CORE_SUSPEND)) { cerr << "couldn't suspend, DF not responding to commands" << endl; @@ -437,14 +437,14 @@ bool Process::asyncSuspend() { return true; } - if(((shm_cmd *)d->my_shm)->pingpong == CORE_SUSPENDED) + if(D_SHMCMD == CORE_SUSPENDED) { d->suspended = true; return true; } else { - ((shm_cmd *)d->my_shm)->pingpong = CORE_SUSPEND; + D_SHMCMD = CORE_SUSPEND; return false; } } @@ -466,7 +466,7 @@ bool Process::resume() cerr << "couldn't resume because of not being suspended" << endl; return true; } - ((shm_cmd *)d->my_shm)->pingpong = CORE_RUNNING; + D_SHMCMD = CORE_RUNNING; d->suspended = false; return true; } @@ -541,10 +541,10 @@ void Process::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer) // normal read under 1MB if(size <= SHM_BODY) { - ((shm_addrlen *)d->my_shm)->address = src_address; - ((shm_addrlen *)d->my_shm)->length = size; + D_SHMHDR->address = src_address; + D_SHMHDR->length = size; full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_DFPP_READ; + D_SHMCMD = CORE_DFPP_READ; d->waitWhile(CORE_DFPP_READ); 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) { // read to_read bytes from src_cursor - ((shm_addrlen *)d->my_shm)->address = src_address; - ((shm_addrlen *)d->my_shm)->length = to_read; + D_SHMHDR->address = src_address; + D_SHMHDR->length = to_read; full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_DFPP_READ; + D_SHMCMD = CORE_DFPP_READ; d->waitWhile(CORE_DFPP_READ); memcpy (target_buffer, d->my_shm + SHM_HEADER,size); // 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) { - ((shm_addr *)d->my_shm)->address = offset; + D_SHMHDR->address = offset; full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_READ_BYTE; + D_SHMCMD = 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 ) { - ((shm_addr *)d->my_shm)->address = offset; + D_SHMHDR->address = offset; full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_READ_BYTE; + D_SHMCMD = 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) { - ((shm_addr *)d->my_shm)->address = offset; + D_SHMHDR->address = offset; full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_READ_WORD; + D_SHMCMD = 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) { - ((shm_addr *)d->my_shm)->address = offset; + D_SHMHDR->address = offset; full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_READ_WORD; + D_SHMCMD = 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) { - ((shm_addr *)d->my_shm)->address = offset; + D_SHMHDR->address = offset; full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_READ_DWORD; + D_SHMCMD = 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) { - ((shm_addr *)d->my_shm)->address = offset; + D_SHMHDR->address = offset; full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_READ_DWORD; + D_SHMCMD = 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) { - ((shm_addrval *)d->my_shm)->address = offset; - ((shm_addrval *)d->my_shm)->value = data; + D_SHMHDR->address = offset; + D_SHMHDR->value = data; full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE_DWORD; + D_SHMCMD = CORE_WRITE_DWORD; d->waitWhile(CORE_WRITE_DWORD); } // using these is expensive. void Process::writeWord (uint32_t offset, uint16_t data) { - ((shm_addrval *)d->my_shm)->address = offset; - ((shm_addrval *)d->my_shm)->value = data; + D_SHMHDR->address = offset; + D_SHMHDR->value = data; full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE_WORD; + D_SHMCMD = CORE_WRITE_WORD; d->waitWhile(CORE_WRITE_WORD); } void Process::writeByte (uint32_t offset, uint8_t data) { - ((shm_addrval *)d->my_shm)->address = offset; - ((shm_addrval *)d->my_shm)->value = data; + D_SHMHDR->address = offset; + D_SHMHDR->value = data; full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE_BYTE; + D_SHMCMD = 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 if(size <= SHM_BODY) { - ((shm_addrlen *)d->my_shm)->address = dst_address; - ((shm_addrlen *)d->my_shm)->length = size; + D_SHMHDR->address = dst_address; + D_SHMHDR->length = size; memcpy(d->my_shm+SHM_HEADER,source_buffer, size); full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE; + D_SHMCMD = CORE_WRITE; d->waitWhile(CORE_WRITE); } // 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) { // write to_write bytes to dst_cursor - ((shm_addrlen *)d->my_shm)->address = dst_address; - ((shm_addrlen *)d->my_shm)->length = to_write; + D_SHMHDR->address = dst_address; + D_SHMHDR->length = to_write; memcpy(d->my_shm+SHM_HEADER,source_buffer, to_write); full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE; + D_SHMCMD = CORE_WRITE; d->waitWhile(CORE_WRITE); // decrease size by bytes written 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) { //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 - ((shm_cmd *)d->my_shm)->pingpong = CORE_READ_STL_STRING; + D_SHMCMD = 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]; // strncpy(temp_c, d->my_shm+SHM_HEADER,length+1); // length + 1 for the null terminator 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) { //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 - ((shm_cmd *)d->my_shm)->pingpong = CORE_READ_STL_STRING; + D_SHMCMD = 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); strncpy(buffer, d->my_shm+SHM_HEADER,real); // length + 1 for the null terminator 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) { - ((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 full_barrier - ((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE_STL_STRING; + D_SHMCMD = 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 raw.resize(raw.length() - 4);// trim st@@ from end 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; } \ No newline at end of file diff --git a/library/DFProcess.h b/library/DFProcess.h index 28525daec..8ad71e04e 100644 --- a/library/DFProcess.h +++ b/library/DFProcess.h @@ -121,6 +121,12 @@ namespace DFHack DFWindow * getWindow(); // get the DF Process ID 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 diff --git a/library/DFTypes.h b/library/DFTypes.h index 9959526d5..db47c23fc 100644 --- a/library/DFTypes.h +++ b/library/DFTypes.h @@ -764,6 +764,15 @@ union t_occupancy 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 { int32_t type; diff --git a/shmserver/CMakeLists.txt b/shmserver/CMakeLists.txt index 108b30e8c..75c007678 100644 --- a/shmserver/CMakeLists.txt +++ b/shmserver/CMakeLists.txt @@ -2,10 +2,13 @@ SET(PROJECT_HDRS shms.h +mod-core.h +mod-maps.h ) SET(PROJECT_SRCS -shms-core.cpp +mod-core.cpp +mod-maps.cpp ) SET(PROJECT_HDRS_LINUX diff --git a/shmserver/shms-core.cpp b/shmserver/mod-core.cpp similarity index 76% rename from shmserver/shms-core.cpp rename to shmserver/mod-core.cpp index 3a20a2439..093aefec5 100644 --- a/shmserver/shms-core.cpp +++ b/shmserver/mod-core.cpp @@ -32,8 +32,12 @@ distribution. #include #include #include + +#define SHM_INTERNAL // for things only visible to the SHM + #include "shms.h" -#include "shms-core.h" +#include "mod-core.h" +#include "mod-maps.h" std::vector module_registry; @@ -46,57 +50,57 @@ bool useYield = 0; #define SHMHDR ((shm_core_hdr *)shm) #define SHMCMD ((shm_cmd *)shm)->pingpong -void GetCoreVersion (void) +void GetCoreVersion (void * data) { SHMHDR->value = module_registry[0].version; } -void GetPID (void) +void GetPID (void * data) { SHMHDR->value = OS_getPID(); } -void ReadRaw (void) +void ReadRaw (void * data) { memcpy(shm + SHM_HEADER, (void *) SHMHDR->address,SHMHDR->length); } -void ReadDWord (void) +void ReadDWord (void * data) { SHMHDR->value = *((uint32_t*) SHMHDR->address); } -void ReadWord (void) +void ReadWord (void * data) { SHMHDR->value = *((uint16_t*) SHMHDR->address); } -void ReadByte (void) +void ReadByte (void * data) { SHMHDR->value = *((uint8_t*) SHMHDR->address); } -void WriteRaw (void) +void WriteRaw (void * data) { memcpy((void *)SHMHDR->address, shm + SHM_HEADER,SHMHDR->length); } -void WriteDWord (void) +void WriteDWord (void * data) { (*(uint32_t*)SHMHDR->address) = SHMHDR->value; } -void WriteWord (void) +void WriteWord (void * data) { (*(uint16_t*)SHMHDR->address) = SHMHDR->value; } -void WriteByte (void) +void WriteByte (void * data) { (*(uint8_t*)SHMHDR->address) = SHMHDR->value; } -void ReadSTLString (void) +void ReadSTLString (void * data) { std::string * myStringPtr = (std::string *) SHMHDR->address; unsigned int l = myStringPtr->length(); @@ -105,7 +109,7 @@ void ReadSTLString (void) strncpy(shm+SHM_HEADER,myStringPtr->c_str(),l+1); } -void WriteSTLString (void) +void WriteSTLString (void * data) { std::string * myStringPtr = (std::string *) SHMHDR->address; // 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) -void SyncYield (void) +void SyncYield (void * data) { uint32_t local = OS_getAffinity(); 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; core.name = "Core"; @@ -181,16 +211,31 @@ void InitCore(void) 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_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) { // create the core module - InitCore(); + module_registry.push_back(InitCore()); + module_registry.push_back(InitMaps()); // 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) { if(errorstate) @@ -215,10 +260,12 @@ void SHM_Act (void) } DFPP_module & mod = module_registry[((shm_cmd *)shm)->parts.module]; 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) { - cmd._function(); + cmd._function(mod.modulestate); } if(cmd.nextState != -1) { diff --git a/shmserver/shms-core.h b/shmserver/mod-core.h similarity index 100% rename from shmserver/shms-core.h rename to shmserver/mod-core.h diff --git a/shmserver/mod-maps.cpp b/shmserver/mod-maps.cpp index 54700101a..a67d040db 100644 --- a/shmserver/mod-maps.cpp +++ b/shmserver/mod-maps.cpp @@ -3,7 +3,7 @@ #include #include "shms.h" -#include "shms-core.h" +#include "mod-core.h" #include "mod-maps.h" #include using namespace DFHack; @@ -69,7 +69,7 @@ void ReadBlockByCoords (void * data) */ mblock * *** mapArray = *(mblock * ****)offsets.map_offset; 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) { memcpy(&(SHMBLOCK->tiletypes), block + offsets.tile_type_offset, sizeof(SHMBLOCK->tiletypes)); @@ -85,7 +85,7 @@ void ReadBlockByCoords (void * data) } } -DFPP_module InitMaps(std::vector * module_registry) +DFPP_module InitMaps( void ) { DFPP_module maps; maps.name = "Maps"; @@ -103,11 +103,9 @@ DFPP_module InitMaps(std::vector * module_registry) // 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); - - - + // 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); - module_registry->push_back(maps); + return maps; } \ No newline at end of file diff --git a/shmserver/shms-linux.cpp b/shmserver/shms-linux.cpp index 9fa02595d..63812b673 100644 --- a/shmserver/shms-linux.cpp +++ b/shmserver/shms-linux.cpp @@ -37,7 +37,7 @@ distribution. #include #include #include "shms.h" -#include "shms-core.h" +#include "mod-core.h" #include #define DFhackCExport extern "C" __attribute__ ((visibility("default"))) @@ -125,6 +125,7 @@ void SHM_Destroy ( void ) { if(inited && !errorstate) { + KillModules(); shmid_ds descriptor; shmctl(shmid, IPC_STAT, &descriptor); shmdt(shm); diff --git a/shmserver/shms-windows.cpp b/shmserver/shms-windows.cpp index 19c22548b..25b90b4ab 100644 --- a/shmserver/shms-windows.cpp +++ b/shmserver/shms-windows.cpp @@ -37,6 +37,7 @@ distribution. #include #include #include "shms.h" +#include "mod-core.h" #include int errorstate = 0; char *shm = 0; @@ -150,6 +151,7 @@ void SHM_Destroy ( void ) { if(errorstate) return; + KillModules(); ReleaseMutex(DFSVMutex); CloseHandle(DFSVMutex); CloseHandle(DFCLMutex); @@ -160,6 +162,17 @@ uint32_t OS_getPID() 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? bool isValidSHM() { diff --git a/shmserver/shms.h b/shmserver/shms.h index 5eb0db961..174614c8e 100644 --- a/shmserver/shms.h +++ b/shmserver/shms.h @@ -38,7 +38,7 @@ enum DFPP_CmdType struct DFPP_command { - void (*_function)(void); + void (*_function)(void *); DFPP_CmdType type:32; // force the enum to 32 bits for compatibility reasons std::string name; uint32_t nextState; @@ -46,7 +46,21 @@ struct DFPP_command 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].name = name; @@ -81,8 +95,10 @@ typedef union void SHM_Act (void); void InitModules (void); +void KillModules (void); bool isValidSHM(); uint32_t OS_getPID(); +DFPP_module InitMaps(void); uint32_t OS_getAffinity(); // limited to 32 processors. Silly, eh? #endif