Merge branch 'shm-only'
commit
5c4ef73f4d
@ -0,0 +1,292 @@
|
|||||||
|
/*
|
||||||
|
www.sourceforge.net/projects/dfhack
|
||||||
|
Copyright (c) 2009 Petr Mrázek (peterix)
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the source for the DF <-> dfhack shm bridge's core module.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../library/integers.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#define SHM_INTERNAL // for things only visible to the SHM
|
||||||
|
|
||||||
|
#include "shms.h"
|
||||||
|
#include "mod-core.h"
|
||||||
|
#include "mod-maps.h"
|
||||||
|
|
||||||
|
std::vector <DFPP_module> module_registry;
|
||||||
|
|
||||||
|
// various crud
|
||||||
|
extern int errorstate;
|
||||||
|
extern char *shm;
|
||||||
|
extern int shmid;
|
||||||
|
bool useYield = 0;
|
||||||
|
|
||||||
|
#define SHMHDR ((shm_core_hdr *)shm)
|
||||||
|
#define SHMCMD ((shm_cmd *)shm)->pingpong
|
||||||
|
#define SHMDATA(type) ((type *)(shm + SHM_HEADER))
|
||||||
|
|
||||||
|
void ReadRaw (void * data)
|
||||||
|
{
|
||||||
|
memcpy(shm + SHM_HEADER, (void *) SHMHDR->address,SHMHDR->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadDWord (void * data)
|
||||||
|
{
|
||||||
|
SHMHDR->value = *((uint32_t*) SHMHDR->address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadWord (void * data)
|
||||||
|
{
|
||||||
|
SHMHDR->value = *((uint16_t*) SHMHDR->address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadByte (void * data)
|
||||||
|
{
|
||||||
|
SHMHDR->value = *((uint8_t*) SHMHDR->address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRaw (void * data)
|
||||||
|
{
|
||||||
|
memcpy((void *)SHMHDR->address, shm + SHM_HEADER,SHMHDR->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteDWord (void * data)
|
||||||
|
{
|
||||||
|
(*(uint32_t*)SHMHDR->address) = SHMHDR->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteWord (void * data)
|
||||||
|
{
|
||||||
|
(*(uint16_t*)SHMHDR->address) = SHMHDR->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteByte (void * data)
|
||||||
|
{
|
||||||
|
(*(uint8_t*)SHMHDR->address) = SHMHDR->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadSTLString (void * data)
|
||||||
|
{
|
||||||
|
std::string * myStringPtr = (std::string *) SHMHDR->address;
|
||||||
|
unsigned int l = myStringPtr->length();
|
||||||
|
SHMHDR->value = l;
|
||||||
|
// FIXME: there doesn't have to be a null terminator!
|
||||||
|
strncpy(shm+SHM_HEADER,myStringPtr->c_str(),l+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteSTLString (void * data)
|
||||||
|
{
|
||||||
|
std::string * myStringPtr = (std::string *) SHMHDR->address;
|
||||||
|
// here we DO expect a 0 terminator
|
||||||
|
myStringPtr->assign((const char *) (shm + SHM_HEADER));
|
||||||
|
}
|
||||||
|
|
||||||
|
// MIT HAKMEM bitcount
|
||||||
|
int bitcount(uint32_t n)
|
||||||
|
{
|
||||||
|
register uint32_t tmp;
|
||||||
|
|
||||||
|
tmp = n - ((n >> 1) & 033333333333) - ((n >> 2) & 011111111111);
|
||||||
|
return ((tmp + (tmp >> 3)) & 030707070707) % 63;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get local and remote affinity, set up yield if required (single core available)
|
||||||
|
void CoreAttach (void * data)
|
||||||
|
{
|
||||||
|
// sync affinity
|
||||||
|
uint32_t local = OS_getAffinity();
|
||||||
|
uint32_t remote = SHMDATA(coreattach)->cl_affinity;
|
||||||
|
uint32_t pool = local | remote;
|
||||||
|
SHMDATA(coreattach)->sv_useYield = useYield = (bitcount(pool) == 1);
|
||||||
|
// return our PID
|
||||||
|
SHMDATA(coreattach)->sv_PID = OS_getPID();
|
||||||
|
// return core version
|
||||||
|
SHMDATA(coreattach)->sv_version = module_registry[0].version;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SHMHDR->error = !found;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindCommand (void * data)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
commandlookup * payload = SHMDATA(commandlookup);
|
||||||
|
std::string modname = payload->module;
|
||||||
|
std::string cmdname = payload->name;
|
||||||
|
uint32_t version = payload->version;
|
||||||
|
for(unsigned int i = 0; i < module_registry.size();i++)
|
||||||
|
{
|
||||||
|
if(module_registry[i].name == modname && module_registry[i].version == version)
|
||||||
|
{
|
||||||
|
for(unsigned int j = 0 ; j < module_registry[i].commands.size();j++)
|
||||||
|
{
|
||||||
|
if(module_registry[i].commands[j].name == cmdname)
|
||||||
|
{
|
||||||
|
// gotcha
|
||||||
|
SHMHDR->value = j + (i << 16);
|
||||||
|
SHMHDR->error = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SHMHDR->error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFPP_module InitCore(void)
|
||||||
|
{
|
||||||
|
DFPP_module core;
|
||||||
|
core.name = "Core";
|
||||||
|
core.version = CORE_VERSION;
|
||||||
|
core.modulestate = 0; // this one is dumb and has no real state
|
||||||
|
|
||||||
|
core.reserve(NUM_CORE_CMDS);
|
||||||
|
// basic states
|
||||||
|
core.set_command(CORE_RUNNING, CANCELLATION, "Running");
|
||||||
|
core.set_command(CORE_SUSPEND, CLIENT_WAIT, "Suspend", 0 , CORE_SUSPENDED);
|
||||||
|
core.set_command(CORE_SUSPENDED, CLIENT_WAIT, "Suspended");
|
||||||
|
core.set_command(CORE_ERROR, CANCELLATION, "Error");
|
||||||
|
|
||||||
|
// utility commands
|
||||||
|
core.set_command(CORE_ATTACH, FUNCTION,"Core attach",CoreAttach, CORE_SUSPENDED);
|
||||||
|
core.set_command(CORE_ACQUIRE_MODULE, FUNCTION, "Module lookup", FindModule, CORE_SUSPENDED);
|
||||||
|
core.set_command(CORE_ACQUIRE_COMMAND, FUNCTION, "Command lookup", FindCommand, CORE_SUSPENDED);
|
||||||
|
|
||||||
|
// raw reads
|
||||||
|
core.set_command(CORE_DFPP_READ, FUNCTION,"Raw read",ReadRaw, CORE_SUSPENDED);
|
||||||
|
core.set_command(CORE_READ_DWORD, FUNCTION,"Read DWORD",ReadDWord, CORE_SUSPENDED);
|
||||||
|
core.set_command(CORE_READ_WORD, FUNCTION,"Read WORD",ReadWord, CORE_SUSPENDED);
|
||||||
|
core.set_command(CORE_READ_BYTE, FUNCTION,"Read BYTE",ReadByte, CORE_SUSPENDED);
|
||||||
|
|
||||||
|
// raw writes
|
||||||
|
core.set_command(CORE_WRITE, FUNCTION, "Raw write", WriteRaw, CORE_SUSPENDED);
|
||||||
|
core.set_command(CORE_WRITE_DWORD, FUNCTION, "Write DWORD", WriteDWord, CORE_SUSPENDED);
|
||||||
|
core.set_command(CORE_WRITE_WORD, FUNCTION, "Write WORD", WriteWord, CORE_SUSPENDED);
|
||||||
|
core.set_command(CORE_WRITE_BYTE, FUNCTION, "Write BYTE", WriteByte, CORE_SUSPENDED);
|
||||||
|
|
||||||
|
// stl string commands
|
||||||
|
core.set_command(CORE_READ_STL_STRING, FUNCTION, "Read STL string", ReadSTLString, CORE_SUSPENDED);
|
||||||
|
core.set_command(CORE_READ_C_STRING, CLIENT_WAIT, "RESERVED");
|
||||||
|
core.set_command(CORE_WRITE_STL_STRING, FUNCTION, "Write STL string", WriteSTLString, CORE_SUSPENDED);
|
||||||
|
return core;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitModules (void)
|
||||||
|
{
|
||||||
|
// create the core module
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t numwaits = 0;
|
||||||
|
check_again: // goto target!!!
|
||||||
|
if(numwaits == 10000)
|
||||||
|
{
|
||||||
|
// this tests if there's a process on the other side
|
||||||
|
if(isValidSHM())
|
||||||
|
{
|
||||||
|
numwaits = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
full_barrier
|
||||||
|
SHMCMD = CORE_RUNNING;
|
||||||
|
fprintf(stderr,"dfhack: Broke out of loop, other process disappeared.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is very important! copying two words separately from the command variable leads to inconsistency.
|
||||||
|
// Always copy the thing in one go.
|
||||||
|
// Also, this whole SHM thing probably only works on intel processors
|
||||||
|
|
||||||
|
volatile shm_cmd atomic = SHMHDR->cmd;
|
||||||
|
full_barrier
|
||||||
|
DFPP_module & mod = module_registry[atomic.parts.module];
|
||||||
|
DFPP_command & cmd = mod.commands[atomic.parts.command];
|
||||||
|
full_barrier
|
||||||
|
/*
|
||||||
|
fprintf(stderr, "Called %x\0", cmd._function);
|
||||||
|
fprintf(stderr, "Client invoked %d:%d = ",atomic.parts.module,atomic.parts.command);
|
||||||
|
fprintf(stderr, "%s\n",cmd.name.c_str());
|
||||||
|
*/
|
||||||
|
full_barrier
|
||||||
|
if(cmd._function)
|
||||||
|
{
|
||||||
|
cmd._function(mod.modulestate);
|
||||||
|
}
|
||||||
|
full_barrier
|
||||||
|
if(cmd.nextState != -1)
|
||||||
|
{
|
||||||
|
SHMCMD = cmd.nextState;
|
||||||
|
}
|
||||||
|
full_barrier
|
||||||
|
if(cmd.type != CANCELLATION)
|
||||||
|
{
|
||||||
|
if(useYield)
|
||||||
|
{
|
||||||
|
SCHED_YIELD
|
||||||
|
}
|
||||||
|
numwaits ++; // watchdog timeout
|
||||||
|
goto check_again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
www.sourceforge.net/projects/dfhack
|
||||||
|
Copyright (c) 2009 Petr Mrázek (peterix)
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHMS_CORE_H
|
||||||
|
#define SHMS_CORE_H
|
||||||
|
|
||||||
|
// increment on every core change
|
||||||
|
#define CORE_VERSION 7
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
shm_cmd cmd;
|
||||||
|
uint32_t address;
|
||||||
|
uint32_t value;
|
||||||
|
uint32_t length;
|
||||||
|
uint32_t error;
|
||||||
|
} shm_core_hdr;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t version;
|
||||||
|
char name[256];
|
||||||
|
} modulelookup;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t version;
|
||||||
|
char module[256];
|
||||||
|
char name[256];
|
||||||
|
} commandlookup;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t sv_version; // output
|
||||||
|
uint32_t cl_affinity; // input
|
||||||
|
uint32_t sv_PID; // output
|
||||||
|
uint32_t sv_useYield; // output
|
||||||
|
} coreattach;
|
||||||
|
|
||||||
|
enum CORE_COMMAND
|
||||||
|
{
|
||||||
|
// basic states
|
||||||
|
CORE_RUNNING = 0, // no command, normal server execution
|
||||||
|
CORE_SUSPEND, // client notifies server to wait for commands (server is stalled in busy wait)
|
||||||
|
CORE_SUSPENDED, // response to WAIT, server is stalled in busy wait
|
||||||
|
CORE_ERROR, // there was a server error
|
||||||
|
|
||||||
|
// utility commands
|
||||||
|
CORE_ATTACH, // compare affinity, get core version and process ID
|
||||||
|
CORE_ACQUIRE_MODULE, // get index of a loaded module by name and version
|
||||||
|
CORE_ACQUIRE_COMMAND, // get module::command callsign by module name, command name and module version
|
||||||
|
|
||||||
|
// raw reads
|
||||||
|
CORE_DFPP_READ, // cl -> sv, read some data
|
||||||
|
CORE_READ_DWORD, // cl -> sv, read a dword
|
||||||
|
CORE_READ_WORD, // cl -> sv, read a word
|
||||||
|
CORE_READ_BYTE, // cl -> sv, read a byte
|
||||||
|
|
||||||
|
// raw writes
|
||||||
|
CORE_WRITE,// client writes to server
|
||||||
|
CORE_WRITE_DWORD,// client writes a DWORD to server
|
||||||
|
CORE_WRITE_WORD,// client writes a WORD to server
|
||||||
|
CORE_WRITE_BYTE,// client writes a BYTE to server
|
||||||
|
|
||||||
|
// string functions
|
||||||
|
CORE_READ_STL_STRING,// client requests contents of STL string at address
|
||||||
|
CORE_READ_C_STRING,// client requests contents of a C string at address, max length (0 means zero terminated)
|
||||||
|
CORE_WRITE_STL_STRING,// client wants to set STL string at address to something
|
||||||
|
|
||||||
|
// total commands
|
||||||
|
NUM_CORE_CMDS
|
||||||
|
};
|
||||||
|
#endif
|
@ -0,0 +1,121 @@
|
|||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <integers.h>
|
||||||
|
|
||||||
|
#include "shms.h"
|
||||||
|
#include "mod-core.h"
|
||||||
|
#include "mod-maps.h"
|
||||||
|
#include <DFTypes.h>
|
||||||
|
using namespace DFHack;
|
||||||
|
using namespace DFHack::Maps;
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
extern char *shm;
|
||||||
|
|
||||||
|
//TODO: circular buffer streaming primitives required
|
||||||
|
//TODO: commands can fail without the proper offsets. Hot to handle that?
|
||||||
|
|
||||||
|
#define SHMHDR ((shm_maps_hdr *)shm)
|
||||||
|
#define SHMCMD ((shm_cmd *)shm)->pingpong
|
||||||
|
#define SHMDATA ((char *)(shm + SHM_HEADER))
|
||||||
|
|
||||||
|
void NullCommand (void* data)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
void InitOffsets (void* data)
|
||||||
|
{
|
||||||
|
maps_modulestate * state = (maps_modulestate *) data;
|
||||||
|
memcpy((void *) &(state->offsets), SHMDATA, sizeof(maps_offsets));
|
||||||
|
((maps_modulestate *) data)->inited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetMapSize (void *data)
|
||||||
|
{
|
||||||
|
maps_modulestate * state = (maps_modulestate *) data;
|
||||||
|
if(state->inited)
|
||||||
|
{
|
||||||
|
SHMHDR->x = *(uint32_t *) (state->offsets.x_count_offset);
|
||||||
|
SHMHDR->y = *(uint32_t *) (state->offsets.y_count_offset);
|
||||||
|
SHMHDR->z = *(uint32_t *) (state->offsets.z_count_offset);
|
||||||
|
SHMHDR->error = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHMHDR->error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mblock
|
||||||
|
{
|
||||||
|
uint32_t * ptr_to_dirty;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SHMBLOCK ((mapblock40d *)(shm + SHM_HEADER))
|
||||||
|
|
||||||
|
inline void ReadBlockByAddress (void * data)
|
||||||
|
{
|
||||||
|
maps_modulestate * state = (maps_modulestate *) data;
|
||||||
|
maps_offsets & offsets = state->offsets;
|
||||||
|
mblock * block = (mblock *) SHMHDR->address;
|
||||||
|
if(block)
|
||||||
|
{
|
||||||
|
memcpy(&(SHMBLOCK->tiletypes), ((char *) block) + offsets.tile_type_offset, sizeof(SHMBLOCK->tiletypes));
|
||||||
|
memcpy(&(SHMBLOCK->designaton), ((char *) block) + offsets.designation_offset, sizeof(SHMBLOCK->designaton));
|
||||||
|
memcpy(&(SHMBLOCK->occupancy), ((char *) block) + offsets.occupancy_offset, sizeof(SHMBLOCK->occupancy));
|
||||||
|
memcpy(&(SHMBLOCK->biome_indices), ((char *) block) + offsets.biome_stuffs, sizeof(SHMBLOCK->biome_indices));
|
||||||
|
SHMBLOCK->dirty_dword = *block->ptr_to_dirty;
|
||||||
|
|
||||||
|
SHMBLOCK->origin = (uint32_t)block;
|
||||||
|
SHMHDR->error = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHMHDR->error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadBlockByCoords (void * data)
|
||||||
|
{
|
||||||
|
maps_modulestate * state = (maps_modulestate *) data;
|
||||||
|
maps_offsets & offsets = state->offsets;
|
||||||
|
/* map_offset is a pointer to
|
||||||
|
a pointer to
|
||||||
|
an X block of pointers to
|
||||||
|
an Y blocks of pointers to
|
||||||
|
a Z blocks of pointers to
|
||||||
|
map blocks
|
||||||
|
only Z blocks can have NULL pointers? TODO: verify
|
||||||
|
*/
|
||||||
|
mblock * *** mapArray = *(mblock * ****)offsets.map_offset;
|
||||||
|
SHMHDR->address = (uint32_t) mapArray[SHMHDR->x][SHMHDR->y][SHMHDR->z];
|
||||||
|
ReadBlockByAddress(data); // I wonder... will this inline properly?
|
||||||
|
}
|
||||||
|
|
||||||
|
DFPP_module InitMaps( void )
|
||||||
|
{
|
||||||
|
DFPP_module maps;
|
||||||
|
maps.name = "Maps";
|
||||||
|
maps.version = MAPS_VERSION;
|
||||||
|
// freed by the core
|
||||||
|
maps.modulestate = malloc(sizeof(maps_modulestate)); // we store a flag
|
||||||
|
memset(maps.modulestate,0,sizeof(maps_modulestate));
|
||||||
|
|
||||||
|
maps.reserve(NUM_MAPS_CMDS);
|
||||||
|
|
||||||
|
// client sends a maps_offsets struct -> inited = true;
|
||||||
|
maps.set_command(MAP_INIT, FUNCTION, "Supply the module with offsets",InitOffsets,CORE_SUSPENDED);
|
||||||
|
maps.set_command(MAP_GET_SIZE, FUNCTION, "Get map size in 16x16x1 tile blocks", GetMapSize, CORE_SUSPENDED);
|
||||||
|
maps.set_command(MAP_READ_BLOCK_BY_COORDS, FUNCTION, "Read the whole block with specified coords", ReadBlockByCoords, CORE_SUSPENDED);
|
||||||
|
maps.set_command(MAP_READ_BLOCK_BY_ADDRESS, FUNCTION, "Read the whole block from an address", ReadBlockByAddress, CORE_SUSPENDED);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
return maps;
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
www.sourceforge.net/projects/dfhack
|
||||||
|
Copyright (c) 2009 Petr Mrázek (peterix)
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MOD_MAPS_H
|
||||||
|
#define MOD_MAPS_H
|
||||||
|
|
||||||
|
// increment on every change
|
||||||
|
#include <DFTypes.h>
|
||||||
|
|
||||||
|
namespace DFHack
|
||||||
|
{
|
||||||
|
namespace Maps
|
||||||
|
{
|
||||||
|
|
||||||
|
#define MAPS_VERSION 2
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t map_offset;// = d->offset_descriptor->getAddress ("map_data");
|
||||||
|
uint32_t x_count_offset;// = d->offset_descriptor->getAddress ("x_count");
|
||||||
|
uint32_t y_count_offset;// = d->offset_descriptor->getAddress ("y_count");
|
||||||
|
uint32_t z_count_offset;// = d->offset_descriptor->getAddress ("z_count");
|
||||||
|
uint32_t tile_type_offset;// = d->offset_descriptor->getOffset ("type");
|
||||||
|
uint32_t designation_offset;// = d->offset_descriptor->getOffset ("designation");
|
||||||
|
uint32_t occupancy_offset;// = d->offset_descriptor->getOffset ("occupancy");
|
||||||
|
uint32_t biome_stuffs;// = d->offset_descriptor->getOffset ("biome_stuffs");
|
||||||
|
uint32_t veinvector;// = d->offset_descriptor->getOffset ("v_vein");
|
||||||
|
uint32_t vein_mineral_vptr;
|
||||||
|
uint32_t vein_ice_vptr;
|
||||||
|
/*
|
||||||
|
GEOLOGY
|
||||||
|
uint32_t region_x_offset;// = minfo->getAddress ("region_x");
|
||||||
|
uint32_t region_y_offset;// = minfo->getAddress ("region_y");
|
||||||
|
uint32_t region_z_offset;// = minfo->getAddress ("region_z");
|
||||||
|
uint32_t world_offset;// = minfo->getAddress ("world");
|
||||||
|
uint32_t world_regions_offset;// = minfo->getOffset ("w_regions_arr");
|
||||||
|
uint32_t region_size;// = minfo->getHexValue ("region_size");
|
||||||
|
uint32_t region_geo_index_offset;// = minfo->getOffset ("region_geo_index_off");
|
||||||
|
uint32_t world_geoblocks_offset;// = minfo->getOffset ("w_geoblocks");
|
||||||
|
uint32_t world_size_x;// = minfo->getOffset ("world_size_x");
|
||||||
|
uint32_t world_size_y;// = minfo->getOffset ("world_size_y");
|
||||||
|
uint32_t geolayer_geoblock_offset;// = minfo->getOffset ("geolayer_geoblock_offset");
|
||||||
|
*/
|
||||||
|
} maps_offsets;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
bool inited;
|
||||||
|
maps_offsets offsets;
|
||||||
|
} maps_modulestate;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
shm_cmd cmd;
|
||||||
|
uint32_t x;
|
||||||
|
uint32_t y;
|
||||||
|
uint32_t z;
|
||||||
|
uint32_t x2;
|
||||||
|
uint32_t y2;
|
||||||
|
uint32_t z2;
|
||||||
|
uint32_t address;
|
||||||
|
uint32_t error;
|
||||||
|
} shm_maps_hdr;
|
||||||
|
|
||||||
|
enum MAPS_COMMAND
|
||||||
|
{
|
||||||
|
MAP_INIT = 0, // initialization
|
||||||
|
MAP_PROBE, // check if the map is still there
|
||||||
|
MAP_GET_SIZE, // get the map size in 16x16x1 blocks
|
||||||
|
MAP_READ_BLOCKTREE, // read the structure of pointers to blocks
|
||||||
|
MAP_READ_BLOCK_BY_COORDS, // read block by cords
|
||||||
|
MAP_READ_BLOCK_BY_ADDRESS, // read block by address
|
||||||
|
MAP_WRITE_BLOCK,
|
||||||
|
MAP_READ_BLOCKS_3D, // read blocks between two coords (volumetric)
|
||||||
|
MAP_READ_ALL_BLOCKS, // read the entire map
|
||||||
|
MAP_REVEAL, // reveal the whole map
|
||||||
|
NUM_MAPS_CMDS,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,187 +0,0 @@
|
|||||||
/*
|
|
||||||
www.sourceforge.net/projects/dfhack
|
|
||||||
Copyright (c) 2009 Petr Mrázek (peterix)
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the source for the DF <-> dfhack shm bridge, server protocol part
|
|
||||||
*/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "../library/integers.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <string>
|
|
||||||
//#include <unistd.h>
|
|
||||||
#include "shms.h"
|
|
||||||
// various crud
|
|
||||||
extern int errorstate;
|
|
||||||
extern char *shm;
|
|
||||||
extern int shmid;
|
|
||||||
|
|
||||||
void SHM_Act (void)
|
|
||||||
{
|
|
||||||
if(errorstate)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint32_t numwaits = 0;
|
|
||||||
uint32_t length;
|
|
||||||
uint32_t address;
|
|
||||||
std::string * myStringPtr;
|
|
||||||
check_again: // goto target!!!
|
|
||||||
SCHED_YIELD // yield the CPU, valid only on single-core CPUs
|
|
||||||
if(numwaits == 10000)
|
|
||||||
{
|
|
||||||
// this tests if there's a process on the other side
|
|
||||||
if(isValidSHM())
|
|
||||||
{
|
|
||||||
numwaits = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
full_barrier
|
|
||||||
((shm_cmd *)shm)->pingpong = DFPP_RUNNING;
|
|
||||||
fprintf(stderr,"dfhack: Broke out of loop, other process disappeared.\n");
|
|
||||||
//MessageBox(0,"Broke out of loop, other process disappeared.","FUN", MB_OK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (((shm_cmd *)shm)->pingpong)
|
|
||||||
{
|
|
||||||
case DFPP_RET_VERSION:
|
|
||||||
case DFPP_RET_DATA:
|
|
||||||
case DFPP_RET_DWORD:
|
|
||||||
case DFPP_RET_WORD:
|
|
||||||
case DFPP_RET_BYTE:
|
|
||||||
case DFPP_RET_STRING:
|
|
||||||
case DFPP_SUSPENDED:
|
|
||||||
case DFPP_RET_PID:
|
|
||||||
case DFPP_SV_ERROR:
|
|
||||||
numwaits++;
|
|
||||||
goto check_again;
|
|
||||||
case DFPP_SUSPEND:
|
|
||||||
full_barrier
|
|
||||||
((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED;
|
|
||||||
goto check_again;
|
|
||||||
/*
|
|
||||||
case DFPP_BOUNCE:
|
|
||||||
length = ((shm_bounce *)shm)->length;
|
|
||||||
memcpy(BigFat,shm + SHM_HEADER,length);
|
|
||||||
memcpy(shm + SHM_HEADER,BigFat,length);
|
|
||||||
((shm_cmd *)shm)->pingpong = DFPP_RET_DATA;
|
|
||||||
goto check_again;
|
|
||||||
*/
|
|
||||||
case DFPP_PID:
|
|
||||||
((shm_retval *)shm)->value = getPID();
|
|
||||||
full_barrier
|
|
||||||
((shm_retval *)shm)->pingpong = DFPP_RET_PID;
|
|
||||||
goto check_again;
|
|
||||||
|
|
||||||
case DFPP_VERSION:
|
|
||||||
((shm_retval *)shm)->value = PINGPONG_VERSION;
|
|
||||||
full_barrier
|
|
||||||
((shm_retval *)shm)->pingpong = DFPP_RET_VERSION;
|
|
||||||
goto check_again;
|
|
||||||
|
|
||||||
case DFPP_READ:
|
|
||||||
length = ((shm_read *)shm)->length;
|
|
||||||
address = ((shm_read *)shm)->address;
|
|
||||||
memcpy(shm + SHM_HEADER, (void *) address,length);
|
|
||||||
full_barrier
|
|
||||||
((shm_cmd *)shm)->pingpong = DFPP_RET_DATA;
|
|
||||||
goto check_again;
|
|
||||||
|
|
||||||
case DFPP_READ_DWORD:
|
|
||||||
address = ((shm_read_small *)shm)->address;
|
|
||||||
((shm_retval *)shm)->value = *((uint32_t*) address);
|
|
||||||
full_barrier
|
|
||||||
((shm_retval *)shm)->pingpong = DFPP_RET_DWORD;
|
|
||||||
goto check_again;
|
|
||||||
|
|
||||||
case DFPP_READ_WORD:
|
|
||||||
address = ((shm_read_small *)shm)->address;
|
|
||||||
((shm_retval *)shm)->value = *((uint16_t*) address);
|
|
||||||
full_barrier
|
|
||||||
((shm_retval *)shm)->pingpong = DFPP_RET_WORD;
|
|
||||||
goto check_again;
|
|
||||||
|
|
||||||
case DFPP_READ_BYTE:
|
|
||||||
address = ((shm_read_small *)shm)->address;
|
|
||||||
((shm_retval *)shm)->value = *((uint8_t*) address);
|
|
||||||
full_barrier
|
|
||||||
((shm_retval *)shm)->pingpong = DFPP_RET_BYTE;
|
|
||||||
goto check_again;
|
|
||||||
|
|
||||||
case DFPP_WRITE:
|
|
||||||
address = ((shm_write *)shm)->address;
|
|
||||||
length = ((shm_write *)shm)->length;
|
|
||||||
memcpy((void *)address, shm + SHM_HEADER,length);
|
|
||||||
full_barrier
|
|
||||||
((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED;
|
|
||||||
goto check_again;
|
|
||||||
|
|
||||||
case DFPP_WRITE_DWORD:
|
|
||||||
(*(uint32_t*)((shm_write_small *)shm)->address) = ((shm_write_small *)shm)->value;
|
|
||||||
full_barrier
|
|
||||||
((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED;
|
|
||||||
goto check_again;
|
|
||||||
|
|
||||||
case DFPP_WRITE_WORD:
|
|
||||||
(*(uint16_t*)((shm_write_small *)shm)->address) = ((shm_write_small *)shm)->value;
|
|
||||||
full_barrier
|
|
||||||
((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED;
|
|
||||||
goto check_again;
|
|
||||||
|
|
||||||
case DFPP_WRITE_BYTE:
|
|
||||||
(*(uint8_t*)((shm_write_small *)shm)->address) = ((shm_write_small *)shm)->value;
|
|
||||||
full_barrier
|
|
||||||
((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED;
|
|
||||||
goto check_again;
|
|
||||||
|
|
||||||
case DFPP_CL_ERROR:
|
|
||||||
case DFPP_RUNNING:
|
|
||||||
//fprintf(stderr, "no. of waits: %d\n", numwaits);
|
|
||||||
//MessageBox(0,"Broke out of loop properly","FUN", MB_OK);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DFPP_READ_STL_STRING:
|
|
||||||
myStringPtr = (std::string *) ((shm_read_small *)shm)->address;
|
|
||||||
((shm_retval *)shm)->value = myStringPtr->length();
|
|
||||||
strncpy(shm+SHM_HEADER,myStringPtr->c_str(),myStringPtr->length()+1);// length + 1 for the null terminator
|
|
||||||
full_barrier
|
|
||||||
((shm_retval *)shm)->pingpong = DFPP_RET_STRING;
|
|
||||||
goto check_again;
|
|
||||||
|
|
||||||
case DFPP_WRITE_STL_STRING:
|
|
||||||
myStringPtr = (std::string *) ((shm_write *)shm)->address;
|
|
||||||
myStringPtr->assign((const char *) (shm + SHM_HEADER));
|
|
||||||
full_barrier
|
|
||||||
((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED;
|
|
||||||
goto check_again;
|
|
||||||
|
|
||||||
|
|
||||||
default:
|
|
||||||
((shm_retval *)shm)->value = DFEE_INVALID_COMMAND;
|
|
||||||
full_barrier
|
|
||||||
((shm_retval *)shm)->pingpong = DFPP_SV_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue