diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ba3c5e4b..7c7a474ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,8 +34,9 @@ include_directories (${CMAKE_SOURCE_DIR}/dfhack/depends/argstream/) add_subdirectory (dfhack) add_subdirectory (dfhack/shm) -add_subdirectory (dfhack/depends/md5) -add_subdirectory (dfhack/depends/tinyxml) +#FIXME: add exports for MSVC +#add_subdirectory (dfhack/depends/md5) +#add_subdirectory (dfhack/depends/tinyxml) #add_subdirectory (dfhack/depends/argstream) add_subdirectory (tools) add_subdirectory (examples) diff --git a/dfhack/APIPrivate.cpp b/dfhack/APIPrivate.cpp new file mode 100644 index 000000000..a45be66ec --- /dev/null +++ b/dfhack/APIPrivate.cpp @@ -0,0 +1,35 @@ +#include "DFCommonInternal.h" +#include +#include +#include +#include +using namespace DFHack; + +#include "private/APIPrivate.h" + +APIPrivate::APIPrivate() +{ +} + +bool APIPrivate::InitReadNames() +{ + try + { + name_firstname_offset = offset_descriptor->getOffset("name_firstname"); + name_nickname_offset = offset_descriptor->getOffset("name_nickname"); + name_words_offset = offset_descriptor->getOffset("name_words"); + } + catch(Error::MissingMemoryDefinition) + { + return false; + } + return true; +} + + +void APIPrivate::readName(t_name & name, uint32_t address) +{ + g_pProcess->readSTLString(address + name_firstname_offset , name.first_name, 128); + g_pProcess->readSTLString(address + name_nickname_offset , name.nickname, 128); + g_pProcess->read(address + name_words_offset ,48, (uint8_t *) name.words); +} \ No newline at end of file diff --git a/dfhack/CMakeLists.txt b/dfhack/CMakeLists.txt index 06e1c41b1..ca851a01e 100644 --- a/dfhack/CMakeLists.txt +++ b/dfhack/CMakeLists.txt @@ -20,15 +20,30 @@ SET(PROJECT_SRCS DFMemInfo.cpp DFMemInfoManager.cpp DFHackAPI.cpp +APIPrivate.cpp DFTileTypes.cpp DFVector.cpp + +depends/md5/md5.cpp +depends/md5/md5wrapper.cpp + +depends/tinyxml/tinystr.cpp +depends/tinyxml/tinyxml.cpp +depends/tinyxml/tinyxmlerror.cpp +depends/tinyxml/tinyxmlparser.cpp + +modules/Creatures.cpp +modules/Gui.cpp +modules/Maps.cpp +modules/Materials.cpp +modules/Position.cpp ) SET(PROJECT_HDRS_LINUX ) SET(PROJECT_HDRS_WINDOWS -stdint_win.h +include/stdint_win.h ) SET(PROJECT_SRCS_LINUX @@ -75,9 +90,9 @@ IF(UNIX) SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -pedantic") SET(CMAKE_CXX_FLAGS "-fvisibility=hidden") - SET(PROJECT_LIBS ${X11_LIBRARY} rt dfhack-md5 tixml-static) + SET(PROJECT_LIBS ${X11_LIBRARY} rt ) #dfhack-md5 dfhack-tixml ELSE(UNIX) - SET(PROJECT_LIBS psapi dfhack-md5 tixml-static) + SET(PROJECT_LIBS psapi) ENDIF(UNIX) ADD_LIBRARY(dfhack SHARED ${PROJECT_SRCS}) diff --git a/dfhack/DFHackAPI.cpp b/dfhack/DFHackAPI.cpp index 2d649c638..bcdee6efc 100644 --- a/dfhack/DFHackAPI.cpp +++ b/dfhack/DFHackAPI.cpp @@ -29,153 +29,16 @@ distribution. #include using namespace DFHack; -/* -FIXME: memset to 0? -*/ -class API::Private -{ -public: - Private() - : block (NULL) - , pm (NULL), p (NULL), offset_descriptor (NULL) - , p_cons (NULL), p_bld (NULL), p_veg (NULL) - {} - - void readName(t_name & name, uint32_t address); - // get the name offsets - bool InitReadNames(); - - uint32_t * block; - uint32_t x_block_count, y_block_count, z_block_count; - uint32_t regionX, regionY, regionZ; - uint32_t worldSizeX, worldSizeY; - - uint32_t tile_type_offset; - uint32_t designation_offset; - uint32_t occupancy_offset; - uint32_t block_flags_offset; - uint32_t biome_stuffs; - uint32_t veinvector; - uint32_t veinsize; - uint32_t vein_mineral_vptr; - uint32_t vein_ice_vptr; - - uint32_t maps_module; - - uint32_t window_x_offset; - uint32_t window_y_offset; - uint32_t window_z_offset; - uint32_t cursor_xyz_offset; - uint32_t window_dims_offset; - uint32_t current_cursor_creature_offset; - uint32_t pause_state_offset; - uint32_t view_screen_offset; - uint32_t current_menu_state_offset; - - uint32_t name_firstname_offset; - uint32_t name_nickname_offset; - uint32_t name_words_offset; - - Creatures::creature_offsets creatures; - uint32_t creature_module; - - - uint32_t item_material_offset; - - uint32_t note_foreground_offset; - uint32_t note_background_offset; - uint32_t note_name_offset; - uint32_t note_xyz_offset; - uint32_t hotkey_start; - uint32_t hotkey_mode_offset; - uint32_t hotkey_xyz_offset; - uint32_t hotkey_size; - - uint32_t settlement_name_offset; - uint32_t settlement_world_xy_offset; - uint32_t settlement_local_xy_offset; - - uint32_t dwarf_lang_table_offset; - - ProcessEnumerator* pm; - Process* p; - char * shm_start; - memory_info* offset_descriptor; - vector v_geology[eBiomeCount]; - string xml; - - bool constructionsInited; - bool buildingsInited; - bool effectsInited; - bool vegetationInited; - bool creaturesInited; - bool cursorWindowInited; - bool viewSizeInited; - bool itemsInited; - bool notesInited; - bool namesInited; - bool hotkeyInited; - bool settlementsInited; - bool nameTablesInited; - - uint32_t tree_offset; - DfVector *p_cre; - DfVector *p_cons; - DfVector *p_bld; - DfVector *p_effect; - DfVector *p_veg; - DfVector *p_itm; - DfVector *p_notes; - DfVector *p_settlements; - DfVector *p_current_settlement; -}; - -bool API::Private::InitReadNames() -{ - try - { - name_firstname_offset = offset_descriptor->getOffset("name_firstname"); - name_nickname_offset = offset_descriptor->getOffset("name_nickname"); - name_words_offset = offset_descriptor->getOffset("name_words"); - } - catch(Error::MissingMemoryDefinition) - { - return false; - } - return true; -} - - -void API::Private::readName(t_name & name, uint32_t address) -{ - g_pProcess->readSTLString(address + name_firstname_offset , name.first_name, 128); - g_pProcess->readSTLString(address + name_nickname_offset , name.nickname, 128); - g_pProcess->read(address + name_words_offset ,48, (uint8_t *) name.words); -} +#include "private/APIPrivate.h" API::API (const string path_to_xml) - : d (new Private()) + : d (new APIPrivate()) { d->xml = QUOT (MEMXML_DATA_PATH); d->xml += "/"; d->xml += path_to_xml; - d->constructionsInited = false; - d->creaturesInited = false; - d->buildingsInited = false; - d->effectsInited = false; - d->vegetationInited = false; - d->cursorWindowInited = false; - d->viewSizeInited = false; - d->itemsInited = false; - d->notesInited = false; - d->hotkeyInited = false; - d->namesInited = false; - d->nameTablesInited = false; d->pm = NULL; d->shm_start = 0; - - d->maps_module = 0; - d->creature_module = 0; } API::~API() @@ -185,641 +48,110 @@ API::~API() delete d; } -#define SHMCMD(num) ((shm_cmd *)d->shm_start)[num]->pingpong -#define SHMHDR ((shm_core_hdr *)d->shm_start) -#define SHMMAPSHDR ((Maps::shm_maps_hdr *)d->shm_start) -#define SHMCREATURESHDR ((Creatures::shm_creature_hdr *)d->shm_start) -#define SHMDATA(type) ((type *)(d->shm_start + SHM_HEADER)) - -/*-----------------------------------* - * Init the mapblock pointer array * - *-----------------------------------*/ -bool API::InitMap() +bool API::Attach() { - 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"); - - // get the offsets once here - d->tile_type_offset = d->offset_descriptor->getOffset ("type"); - d->designation_offset = d->offset_descriptor->getOffset ("designation"); - d->occupancy_offset = d->offset_descriptor->getOffset ("occupancy"); - d->biome_stuffs = d->offset_descriptor->getOffset ("biome_stuffs"); - - d->veinvector = d->offset_descriptor->getOffset ("v_vein"); - d->veinsize = d->offset_descriptor->getHexValue ("v_vein_size"); - - // these can fail and will be found when looking at the actual veins later - // basically a cache - d->vein_ice_vptr = 0; - 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",3,d->maps_module); - - if(d->maps_module) + // detach all processes, destroy manager + if (d->pm == 0) { - // 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); - g_pProcess->SetAndWait(cmd); - //cerr << "Map acceleration enabled!" << endl; + d->pm = new ProcessEnumerator (d->xml); // FIXME: handle bad XML better } - - // get the map pointer - uint32_t x_array_loc = g_pProcess->readDWord (map_offset); - if (!x_array_loc) + else { - return false; - // FIXME: only throw this due to programmer error, in the other map functions - //throw Error::NoMapLoaded(); + d->pm->purge(); } - - // 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); - - // test for wrong map dimensions - if (mx == 0 || mx > 48 || my == 0 || my > 48 || mz == 0) + + // find a process (ProcessManager can find multiple when used properly) + if (!d->pm->findProcessess()) { - throw Error::BadMapDimensions(mx, my); + throw Error::NoProcess(); + //cerr << "couldn't find a suitable process" << endl; //return false; } - - // alloc array for pointers to all blocks - d->block = new uint32_t[mx*my*mz]; - uint32_t *temp_x = new uint32_t[mx]; - uint32_t *temp_y = new uint32_t[my]; - uint32_t *temp_z = new uint32_t[mz]; - - g_pProcess->read (x_array_loc, mx * sizeof (uint32_t), (uint8_t *) temp_x); - for (uint32_t x = 0; x < mx; x++) + d->p = (*d->pm) [0]; + if (!d->p->attach()) { - g_pProcess->read (temp_x[x], my * sizeof (uint32_t), (uint8_t *) temp_y); - // y -> map column - for (uint32_t y = 0; y < my; y++) - { - g_pProcess->read (temp_y[y], - mz * sizeof (uint32_t), - (uint8_t *) (d->block + x*my*mz + y*mz)); - } + throw Error::CantAttach(); + //cerr << "couldn't attach to process" << endl; + //return false; // couldn't attach to process, no go } - delete [] temp_x; - delete [] temp_y; - delete [] temp_z; + d->shm_start = d->p->getSHMStart(); + d->offset_descriptor = d->p->getDescriptor(); + // process is attached, everything went just fine... hopefully return true; } -bool API::DestroyMap() -{ - if (d->block != NULL) - { - delete [] d->block; - d->block = NULL; - } - return true; -} -bool API::isValidBlock (uint32_t x, uint32_t y, uint32_t z) +bool API::Detach() { - if ( x >= d->x_block_count || y >= d->y_block_count || z >= d->z_block_count) + if(!d->p) return false; - return d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z] != 0; -} - -uint32_t API::getBlockPtr (uint32_t x, uint32_t y, uint32_t z) -{ - if ( x >= d->x_block_count || y >= d->y_block_count || z >= d->z_block_count) - return 0; - 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; - volatile uint32_t cmd = Maps::MAP_READ_BLOCK_BY_COORDS + (d->maps_module << 16); - if(!g_pProcess->SetAndWait(cmd)) - return false; - memcpy(buffer,SHMDATA(mapblock40d),sizeof(mapblock40d)); - return true; - } - else // plain old block read + if (!d->p->detach()) { - 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->designation), (uint8_t *) buffer->designation); - g_pProcess->read (addr + d->biome_stuffs, sizeof (buffer->biome_indices), (uint8_t *) buffer->biome_indices); - buffer->origin = addr; - uint32_t addr_of_struct = g_pProcess->readDWord(addr); - buffer->blockflags.whole = 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, tiletypes40d *buffer) -{ - 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 (tiletypes40d), (uint8_t *) buffer); - return true; - } - return false; -} - -bool API::ReadDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool &dirtybit) -{ - uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; - if(addr) - { - uint32_t addr_of_struct = g_pProcess->readDWord(addr); - dirtybit = g_pProcess->readDWord(addr_of_struct) & 1; - return true; - } - return false; -} - -bool API::WriteDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool dirtybit) -{ - uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; - if (addr) - { - uint32_t addr_of_struct = g_pProcess->readDWord(addr); - uint32_t dirtydword = g_pProcess->readDWord(addr_of_struct); - dirtydword &= 0xFFFFFFFE; - dirtydword |= (uint32_t) dirtybit; - g_pProcess->writeDWord (addr_of_struct, dirtydword); - return true; - } - return false; -} - -/// read/write the block flags -bool API::ReadBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags &blockflags) -{ - uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; - if(addr) - { - uint32_t addr_of_struct = g_pProcess->readDWord(addr); - blockflags.whole = g_pProcess->readDWord(addr_of_struct); - return true; - } - return false; -} -bool API::WriteBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags blockflags) -{ - uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; - if (addr) - { - uint32_t addr_of_struct = g_pProcess->readDWord(addr); - g_pProcess->writeDWord (addr_of_struct, blockflags.whole); - return true; - } - return false; -} - -bool API::ReadDesignations (uint32_t x, uint32_t y, uint32_t z, designations40d *buffer) -{ - 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->designation_offset, sizeof (designations40d), (uint8_t *) buffer); - return true; - } - return false; -} - - -// 256 * sizeof(uint32_t) -bool API::ReadOccupancy (uint32_t x, uint32_t y, uint32_t z, occupancies40d *buffer) -{ - 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->occupancy_offset, sizeof (occupancies40d), (uint8_t *) buffer); - return true; - } - return false; -} - - -// 256 * sizeof(uint16_t) -bool API::WriteTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buffer) -{ - uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; - if (addr) + if (d->pm != NULL) { - g_pProcess->write (addr + d->tile_type_offset, sizeof (tiletypes40d), (uint8_t *) buffer); - return true; + delete d->pm; } - return false; -} - -bool API::getCurrentCursorCreature(uint32_t & creature_index) -{ - if(!d->cursorWindowInited) return false; - creature_index = g_pProcess->readDWord(d->current_cursor_creature_offset); + d->pm = NULL; + d->p = NULL; + d->shm_start = 0; + d->offset_descriptor = NULL; return true; } -// 256 * sizeof(uint32_t) -bool API::WriteDesignations (uint32_t x, uint32_t y, uint32_t z, designations40d *buffer) -{ - uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; - if (addr) - { - g_pProcess->write (addr + d->designation_offset, sizeof (designations40d), (uint8_t *) buffer); - return true; - } - return false; -} -// 256 * sizeof(uint32_t) -bool API::WriteOccupancy (uint32_t x, uint32_t y, uint32_t z, occupancies40d *buffer) +bool API::isAttached() { - uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; - if (addr) - { - g_pProcess->write (addr + d->occupancy_offset, sizeof (occupancies40d), (uint8_t *) buffer); - return true; - } - return false; + return d->p != NULL; } -// FIXME: this is bad. determine the real size! -//16 of them? IDK... there's probably just 7. Reading more doesn't cause errors as it's an array nested inside a block -// 16 * sizeof(uint8_t) -bool API::ReadRegionOffsets (uint32_t x, uint32_t y, uint32_t z, biome_indices40d *buffer) +bool API::Suspend() { - 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->biome_stuffs, sizeof (biome_indices40d), (uint8_t *) buffer); - return true; - } - return false; + return d->p->suspend(); } - -// veins of a block, expects empty vein vectors -bool API::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector & veins, vector & ices) +bool API::AsyncSuspend() { - uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; - veins.clear(); - ices.clear(); - if (addr && d->veinvector && d->veinsize) - { - // veins are stored as a vector of pointers to veins - /*pointer is 4 bytes! we work with a 32bit program here, no matter what architecture we compile khazad for*/ - DfVector p_veins (d->p, addr + d->veinvector, 4); - uint32_t size = p_veins.getSize(); - veins.reserve (size); - - // read all veins - for (uint32_t i = 0; i < size;i++) - { - t_vein v; - t_frozenliquidvein fv; - - // read the vein pointer from the vector - uint32_t temp = * (uint32_t *) p_veins[i]; - uint32_t type = g_pProcess->readDWord(temp); -try_again: - if(type == d->vein_mineral_vptr) - { - // read the vein data (dereference pointer) - g_pProcess->read (temp, sizeof(t_vein), (uint8_t *) &v); - v.address_of = temp; - // store it in the vector - veins.push_back (v); - } - else if(type == d->vein_ice_vptr) - { - // read the ice vein data (dereference pointer) - g_pProcess->read (temp, sizeof(t_frozenliquidvein), (uint8_t *) &fv); - // store it in the vector - ices.push_back (fv); - } - else if(g_pProcess->readClassName(type) == "block_square_event_frozen_liquid") - { - d->vein_ice_vptr = type; - goto try_again; - } - else if(g_pProcess->readClassName(type) == "block_square_event_mineral") - { - d->vein_mineral_vptr = type; - goto try_again; - } - } - return true; - } - return false; + return d->p->asyncSuspend(); } - -// getter for map size -void API::getSize (uint32_t& x, uint32_t& y, uint32_t& z) +bool API::Resume() { - x = d->x_block_count; - y = d->y_block_count; - z = d->z_block_count; + return d->p->resume(); } - -bool API::ReadWoodMatgloss (vector & woods) +bool API::ForceResume() { - - int matgloss_address = d->offset_descriptor->getAddress ("matgloss"); - int matgloss_wood_name_offset = d->offset_descriptor->getOffset("matgloss_wood_name"); - // TODO: find flag for autumnal coloring? - DfVector p_matgloss(d->p, matgloss_address, 4); - - woods.clear(); - - t_matgloss mat; - // TODO: use brown? - mat.fore = 7; - mat.back = 0; - mat.bright = 0; - uint32_t size = p_matgloss.getSize(); - for (uint32_t i = 0; i < size ;i++) - { - // read the matgloss pointer from the vector into temp - uint32_t temp = * (uint32_t *) p_matgloss[i]; - // read the string pointed at by - /* - fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address - */ - d->p->readSTLString (temp, mat.id, 128); - d->p->readSTLString (temp+matgloss_wood_name_offset, mat.name, 128); - woods.push_back (mat); - } - return true; + return d->p->forceresume(); } - -bool API::ReadStoneMatgloss (vector & stones) +bool API::isSuspended() { - memory_info * minfo = d->offset_descriptor; - int matgloss_address = minfo->getAddress ("matgloss"); - int matgloss_offset = minfo->getHexValue ("matgloss_skip"); - int matgloss_colors = minfo->getOffset ("matgloss_stone_color"); - int matgloss_stone_name_offset = minfo->getOffset("matgloss_stone_name"); - - DfVector p_matgloss (d->p, matgloss_address + matgloss_offset, 4); - - uint32_t size = p_matgloss.getSize(); - stones.resize (0); - stones.reserve (size); - for (uint32_t i = 0; i < size;i++) - { - // read the matgloss pointer from the vector into temp - uint32_t temp = * (uint32_t *) p_matgloss[i]; - // read the string pointed at by - t_matgloss mat; - //fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address - d->p->readSTLString (temp, mat.id, 128); - d->p->readSTLString (temp+matgloss_stone_name_offset, mat.name, 128); - mat.fore = (uint8_t) g_pProcess->readWord (temp + matgloss_colors); - mat.back = (uint8_t) g_pProcess->readWord (temp + matgloss_colors + 2); - mat.bright = (uint8_t) g_pProcess->readWord (temp + matgloss_colors + 4); - stones.push_back (mat); - } - return true; + return d->p->isSuspended(); } - -bool API::ReadMetalMatgloss (vector & metals) +void API::ReadRaw (const uint32_t offset, const uint32_t size, uint8_t *target) { - memory_info * minfo = d->offset_descriptor; - int matgloss_address = minfo->getAddress ("matgloss"); - int matgloss_offset = minfo->getHexValue ("matgloss_skip"); - int matgloss_colors = minfo->getOffset ("matgloss_metal_color"); - int matgloss_metal_name_offset = minfo->getOffset("matgloss_metal_name"); - DfVector p_matgloss(d->p, matgloss_address + matgloss_offset * 3, 4); - - metals.clear(); - - for (uint32_t i = 0; i < p_matgloss.getSize();i++) - { - // read the matgloss pointer from the vector into temp - uint32_t temp = * (uint32_t *) p_matgloss[i]; - // read the string pointed at by - t_matgloss mat; - //fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address - d->p->readSTLString (temp, mat.id, 128); - d->p->readSTLString (temp+matgloss_metal_name_offset, mat.name, 128); - mat.fore = (uint8_t) g_pProcess->readWord (temp + matgloss_colors); - mat.back = (uint8_t) g_pProcess->readWord (temp + matgloss_colors + 2); - mat.bright = (uint8_t) g_pProcess->readWord (temp + matgloss_colors + 4); - metals.push_back (mat); - } - return true; + g_pProcess->read (offset, size, target); } -bool API::ReadPlantMatgloss (vector & plants) +void API::WriteRaw (const uint32_t offset, const uint32_t size, uint8_t *source) { - memory_info * minfo = d->offset_descriptor; - int matgloss_address = minfo->getAddress ("matgloss"); - int matgloss_offset = minfo->getHexValue ("matgloss_skip"); - int matgloss_plant_name_offset = minfo->getOffset("matgloss_plant_name"); - DfVector p_matgloss(d->p, matgloss_address + matgloss_offset * 2, 4); - - plants.clear(); - - // TODO: use green? - t_matgloss mat; - mat.fore = 7; - mat.back = 0; - mat.bright = 0; - for (uint32_t i = 0; i < p_matgloss.getSize();i++) - { - // read the matgloss pointer from the vector into temp - uint32_t temp = * (uint32_t *) p_matgloss[i]; - // read the string pointed at by - //fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address - d->p->readSTLString (temp, mat.id, 128); - d->p->readSTLString (temp+matgloss_plant_name_offset, mat.name, 128); - plants.push_back (mat); - } - return true; + g_pProcess->write (offset, size, source); } -bool API::ReadPlantMatgloss (vector & plants) +memory_info *API::getMemoryInfo() { - memory_info * minfo = d->offset_descriptor; - int matgloss_address = minfo->getAddress ("matgloss"); - int matgloss_offset = minfo->getHexValue ("matgloss_skip"); - int matgloss_plant_name_offset = minfo->getOffset("matgloss_plant_name"); - int matgloss_plant_drink_offset = minfo->getOffset("matgloss_plant_drink"); - int matgloss_plant_food_offset = minfo->getOffset("matgloss_plant_food"); - int matgloss_plant_extract_offset = minfo->getOffset("matgloss_plant_extract"); - DfVector p_matgloss(d->p, matgloss_address + matgloss_offset * 2, 4); - - plants.clear(); - - // TODO: use green? - t_matglossPlant mat; - mat.fore = 7; - mat.back = 0; - mat.bright = 0; - for (uint32_t i = 0; i < p_matgloss.getSize();i++) - { - // read the matgloss pointer from the vector into temp - uint32_t temp = * (uint32_t *) p_matgloss[i]; - // read the string pointed at by - //fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address - d->p->readSTLString (temp, mat.id, 128); - d->p->readSTLString (temp+matgloss_plant_name_offset, mat.name, 128); - d->p->readSTLString (temp+matgloss_plant_drink_offset, mat.drink_name, 128); - d->p->readSTLString (temp+matgloss_plant_food_offset, mat.food_name, 128); - d->p->readSTLString (temp+matgloss_plant_extract_offset, mat.extract_name, 128); - - //d->p->readSTLString (temp - plants.push_back (mat); - } - return true; + return d->offset_descriptor; } - -bool API::ReadCreatureMatgloss (vector & creatures) +Process * API::getProcess() { - memory_info * minfo = d->offset_descriptor; - int matgloss_address = minfo->getAddress ("matgloss"); - int matgloss_offset = minfo->getHexValue ("matgloss_skip"); - int matgloss_creature_name_offset = minfo->getOffset("matgloss_creature_name"); - DfVector p_matgloss (d->p, matgloss_address + matgloss_offset * 6, 4); - - creatures.clear(); - - // TODO: use green? - t_matgloss mat; - mat.fore = 7; - mat.back = 0; - mat.bright = 0; - for (uint32_t i = 0; i < p_matgloss.getSize();i++) - { - // read the matgloss pointer from the vector into temp - uint32_t temp = * (uint32_t *) p_matgloss[i]; - // read the string pointed at by - //fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address - d->p->readSTLString (temp, mat.id, 128); - d->p->readSTLString (temp+matgloss_creature_name_offset, mat.name, 128); - creatures.push_back (mat); - } - return true; + return d->p; } - -//vector v_geology[eBiomeCount]; -bool API::ReadGeology (vector < vector >& assign) +DFWindow * API::getWindow() { - memory_info * minfo = d->offset_descriptor; - // get needed addresses and offsets. Now this is what I call crazy. - int region_x_offset = minfo->getAddress ("region_x"); - int region_y_offset = minfo->getAddress ("region_y"); - int region_z_offset = minfo->getAddress ("region_z"); - int world_offset = minfo->getAddress ("world"); - int world_regions_offset = minfo->getOffset ("w_regions_arr"); - int region_size = minfo->getHexValue ("region_size"); - int region_geo_index_offset = minfo->getOffset ("region_geo_index_off"); - int world_geoblocks_offset = minfo->getOffset ("w_geoblocks"); - int world_size_x = minfo->getOffset ("world_size_x"); - int world_size_y = minfo->getOffset ("world_size_y"); - int geolayer_geoblock_offset = minfo->getOffset ("geolayer_geoblock_offset"); - - uint32_t regionX, regionY, regionZ; - uint16_t worldSizeX, worldSizeY; - - // read position of the region inside DF world - g_pProcess->readDWord (region_x_offset, regionX); - g_pProcess->readDWord (region_y_offset, regionY); - g_pProcess->readDWord (region_z_offset, regionZ); - - // get world size - g_pProcess->readWord (world_offset + world_size_x, worldSizeX); - g_pProcess->readWord (world_offset + world_size_y, worldSizeY); - - // get pointer to first part of 2d array of regions - uint32_t regions = g_pProcess->readDWord (world_offset + world_regions_offset); - - // read the geoblock vector - DfVector geoblocks (d->p, world_offset + world_geoblocks_offset, 4); - - // iterate over 8 surrounding regions + local region - for (int i = eNorthWest; i < eBiomeCount; i++) - { - // check bounds, fix them if needed - int bioRX = regionX / 16 + (i % 3) - 1; - if (bioRX < 0) bioRX = 0; - if (bioRX >= worldSizeX) bioRX = worldSizeX - 1; - int bioRY = regionY / 16 + (i / 3) - 1; - if (bioRY < 0) bioRY = 0; - if (bioRY >= worldSizeY) bioRY = worldSizeY - 1; - - // get pointer to column of regions - uint32_t geoX; - g_pProcess->readDWord (regions + bioRX*4, geoX); - - // get index into geoblock vector - uint16_t geoindex; - g_pProcess->readWord (geoX + bioRY*region_size + region_geo_index_offset, geoindex); - - // get the geoblock from the geoblock vector using the geoindex - // read the matgloss pointer from the vector into temp - uint32_t geoblock_off = * (uint32_t *) geoblocks[geoindex]; - - // get the vector with pointer to layers - DfVector geolayers (d->p, geoblock_off + geolayer_geoblock_offset , 4); // let's hope - // make sure we don't load crap - assert (geolayers.getSize() > 0 && geolayers.getSize() <= 16); - - d->v_geology[i].reserve (geolayers.getSize()); - // finally, read the layer matgloss - for (uint32_t j = 0;j < geolayers.getSize();j++) - { - // read pointer to a layer - uint32_t geol_offset = * (uint32_t *) geolayers[j]; - // read word at pointer + 2, store in our geology vectors - d->v_geology[i].push_back (g_pProcess->readWord (geol_offset + 2)); - } - } - assign.clear(); - assign.reserve (eBiomeCount); -// // TODO: clean this up - for (int i = 0; i < eBiomeCount;i++) - { - assign.push_back (d->v_geology[i]); - } - return true; + return d->p->getWindow(); } - +/* // returns number of buildings, expects v_buildingtypes that will later map t_building.type to its name bool API::InitReadBuildings ( uint32_t& numbuildings ) { @@ -1034,86 +366,8 @@ void API::FinishReadVegetation() } d->vegetationInited = false; } - - -bool API::InitReadCreatures( uint32_t &numcreatures ) -{ - if(!d->InitReadNames()) return false; - try - { - memory_info * minfo = d->offset_descriptor; - Creatures::creature_offsets & off = d->creatures; - off.creature_vector = minfo->getAddress ("creatures"); - off.creature_pos_offset = minfo->getOffset ("creature_position"); - off.creature_type_offset = minfo->getOffset ("creature_race"); - off.creature_flags1_offset = minfo->getOffset ("creature_flags1"); - off.creature_flags2_offset = minfo->getOffset ("creature_flags2"); - off.creature_name_offset = minfo->getOffset ("creature_name"); - off.creature_custom_profession_offset = minfo->getOffset ("creature_custom_profession"); - off.creature_profession_offset = minfo->getOffset ("creature_profession"); - off.creature_sex_offset = minfo->getOffset ("creature_sex"); - off.creature_id_offset = minfo->getOffset ("creature_id"); - off.creature_squad_name_offset = minfo->getOffset ("creature_squad_name"); - off.creature_squad_leader_id_offset = minfo->getOffset ("creature_squad_leader_id"); - off.creature_money_offset = minfo->getOffset ("creature_money"); - off.creature_current_job_offset = minfo->getOffset ("creature_current_job"); - off.creature_current_job_id_offset = minfo->getOffset ("current_job_id"); - off.creature_strength_offset = minfo->getOffset ("creature_strength"); - off.creature_agility_offset = minfo->getOffset ("creature_agility"); - off.creature_toughness_offset = minfo->getOffset ("creature_toughness"); - off.creature_skills_offset = minfo->getOffset ("creature_skills"); - off.creature_labors_offset = minfo->getOffset ("creature_labors"); - off.creature_happiness_offset = minfo->getOffset ("creature_happiness"); - off.creature_traits_offset = minfo->getOffset ("creature_traits"); - off.creature_likes_offset = minfo->getOffset("creature_likes"); - off.creature_artifact_name_offset = minfo->getOffset("creature_artifact_name"); - off.creature_mood_offset = minfo->getOffset("creature_mood"); - - off.creature_pregnancy_offset = minfo->getOffset("creature_pregnancy"); - off.creature_blood_max_offset = minfo->getOffset("creature_blood_max"); - off.creature_blood_current_offset = minfo->getOffset("creature_blood_current"); - off.creature_bleed_offset = minfo->getOffset("creature_bleed"); - - // name offsets for the creature module - off.name_firstname_offset = minfo->getOffset("name_firstname"); - off.name_nickname_offset = minfo->getOffset("name_nickname"); - off.name_words_offset = minfo->getOffset("name_words"); - - // HACK: vector correction. No longer relevant. - off.vector_correct = 0; - - d->p_cre = new DfVector (d->p, off.creature_vector, 4); - d->creaturesInited = true; - numcreatures = d->p_cre->getSize(); - - /* - * --> SHM initialization (if possible) <-- - */ - g_pProcess->getModuleIndex("Creatures40d",1,d->creature_module); - - if(d->creature_module) - { - // supply the module with offsets so it can work with them - memcpy(SHMDATA(Creatures::creature_offsets),&d->creatures,sizeof(Creatures::creature_offsets)); - const uint32_t cmd = Creatures::CREATURE_INIT + (d->creature_module << 16); - g_pProcess->SetAndWait(cmd); - //cerr << "Creature acceleration enabled!" << endl; - } - /* - else - { - cerr << "Creature acceleration NOT enabled!" << endl; - } - */ - return true; - } - catch (Error::MissingMemoryDefinition&) - { - d->creaturesInited = false; - numcreatures = 0; - throw; - } -} +*/ +/* bool API::InitReadNotes( uint32_t &numnotes ) { try @@ -1328,104 +582,8 @@ bool API::getItemIndexesInBox(vector &indexes, } return true; } - -bool API::ReadCreature (const int32_t index, t_creature & furball) -{ - if(!d->creaturesInited) return false; - if(d->creature_module) - { - // supply the module with offsets so it can work with them - SHMCREATURESHDR->index = index; - const uint32_t cmd = Creatures::CREATURE_AT_INDEX + (d->creature_module << 16); - g_pProcess->SetAndWait(cmd); - memcpy(&furball,SHMDATA(t_creature),sizeof(t_creature)); - // cerr << "creature read from SHM!" << endl; - return true; - } - // read pointer from vector at position - uint32_t temp = * (uint32_t *) d->p_cre->at (index); - furball.origin = temp; - Creatures::creature_offsets &offs = d->creatures; - //read creature from memory - g_pProcess->read (temp + offs.creature_pos_offset, 3 * sizeof (uint16_t), (uint8_t *) & (furball.x)); // xyz really - g_pProcess->readDWord (temp + offs.creature_type_offset, furball.type); - g_pProcess->readDWord (temp + offs.creature_flags1_offset, furball.flags1.whole); - g_pProcess->readDWord (temp + offs.creature_flags2_offset, furball.flags2.whole); - // names - d->readName(furball.name,temp + offs.creature_name_offset); - d->readName(furball.squad_name, temp + offs.creature_squad_name_offset); - d->readName(furball.artifact_name, temp + offs.creature_artifact_name_offset); - // custom profession - fill_char_buf (furball.custom_profession, d->p->readSTLString (temp + offs.creature_custom_profession_offset)); - - // labors - g_pProcess->read (temp + offs.creature_labors_offset, NUM_CREATURE_LABORS, furball.labors); - // traits - g_pProcess->read (temp + offs.creature_traits_offset, sizeof (uint16_t) * NUM_CREATURE_TRAITS, (uint8_t *) &furball.traits); - // learned skills - DfVector skills (d->p, temp + offs.creature_skills_offset, 4 ); - furball.numSkills = skills.getSize(); - for (uint32_t i = 0; i < furball.numSkills;i++) - { - uint32_t temp2 = * (uint32_t *) skills[i]; - //skills.read(i, (uint8_t *) &temp2); - // a byte: this gives us 256 skills maximum. - furball.skills[i].id = g_pProcess->readByte (temp2); - furball.skills[i].rating = g_pProcess->readByte (temp2 + 4); - furball.skills[i].experience = g_pProcess->readWord (temp2 + 8); - } - // profession - furball.profession = g_pProcess->readByte (temp + offs.creature_profession_offset); - // current job HACK: the job object isn't cleanly represented here - uint32_t jobIdAddr = g_pProcess->readDWord (temp + offs.creature_current_job_offset); - - if (jobIdAddr) - { - furball.current_job.active = true; - furball.current_job.jobId = g_pProcess->readByte (jobIdAddr + offs.creature_current_job_id_offset); - } - else - { - furball.current_job.active = false; - } - - //likes - DfVector likes(d->p, temp + offs.creature_likes_offset, 4); - furball.numLikes = likes.getSize(); - for(uint32_t i = 0;iread(temp2,sizeof(t_like),(uint8_t *) &furball.likes[i]); - } - - furball.mood = (int16_t) g_pProcess->readWord (temp + offs.creature_mood_offset); - - - g_pProcess->readDWord (temp + offs.creature_happiness_offset, furball.happiness); - g_pProcess->readDWord (temp + offs.creature_id_offset, furball.id); - g_pProcess->readDWord (temp + offs.creature_agility_offset, furball.agility); - g_pProcess->readDWord (temp + offs.creature_strength_offset, furball.strength); - g_pProcess->readDWord (temp + offs.creature_toughness_offset, furball.toughness); - g_pProcess->readDWord (temp + offs.creature_money_offset, furball.money); - furball.squad_leader_id = (int32_t) g_pProcess->readDWord (temp + offs.creature_squad_leader_id_offset); - g_pProcess->readByte (temp + offs.creature_sex_offset, furball.sex); - - g_pProcess->readDWord(temp + offs.creature_pregnancy_offset, furball.pregnancy_timer); - furball.blood_max = (int32_t) g_pProcess->readDWord(temp + offs.creature_blood_max_offset); - furball.blood_current = (int32_t) g_pProcess->readDWord(temp + offs.creature_blood_current_offset); - g_pProcess->readDWord(temp + offs.creature_bleed_offset, furball.bleed_rate); - - - return true; -} - -bool API::WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]) -{ - if(!d->creaturesInited) return false; - uint32_t temp = * (uint32_t *) d->p_cre->at (index); - WriteRaw(temp + d->creatures.creature_labors_offset, NUM_CREATURE_LABORS, labors); -} - +*/ +/* bool API::InitReadNameTables(vector > & translations , vector > & foreign_languages) //(map< string, vector > & nameTable) { try @@ -1569,208 +727,9 @@ void API::FinishReadNotes() } d->notesInited = false; } - -bool API::Attach() -{ - // detach all processes, destroy manager - if (d->pm == 0) - { - d->pm = new ProcessEnumerator (d->xml); // FIXME: handle bad XML better - } - else - { - d->pm->purge(); - } - - // find a process (ProcessManager can find multiple when used properly) - if (!d->pm->findProcessess()) - { - throw Error::NoProcess(); - //cerr << "couldn't find a suitable process" << endl; - //return false; - } - d->p = (*d->pm) [0]; - if (!d->p->attach()) - { - throw Error::CantAttach(); - //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; -} - - -bool API::Detach() -{ - if(!d->p) - return false; - if (!d->p->detach()) - { - return false; - } - if (d->pm != NULL) - { - delete d->pm; - } - d->pm = NULL; - d->p = NULL; - d->shm_start = 0; - d->offset_descriptor = NULL; - return true; -} - -bool API::isAttached() -{ - return d->p != NULL; -} - -bool API::Suspend() -{ - return d->p->suspend(); -} -bool API::AsyncSuspend() -{ - return d->p->asyncSuspend(); -} - -bool API::Resume() -{ - return d->p->resume(); -} -bool API::ForceResume() -{ - return d->p->forceresume(); -} -bool API::isSuspended() -{ - return d->p->isSuspended(); -} - -void API::ReadRaw (const uint32_t offset, const uint32_t size, uint8_t *target) -{ - g_pProcess->read (offset, size, target); -} - -void API::WriteRaw (const uint32_t offset, const uint32_t size, uint8_t *source) -{ - g_pProcess->write (offset, size, source); -} - -bool API::InitViewAndCursor() -{ - try - { - d->window_x_offset = d->offset_descriptor->getAddress ("window_x"); - d->window_y_offset = d->offset_descriptor->getAddress ("window_y"); - d->window_z_offset = d->offset_descriptor->getAddress ("window_z"); - d->cursor_xyz_offset = d->offset_descriptor->getAddress ("cursor_xyz"); - d->current_cursor_creature_offset = d->offset_descriptor->getAddress ("current_cursor_creature"); - - d->current_menu_state_offset = d->offset_descriptor->getAddress("current_menu_state"); - d->pause_state_offset = d->offset_descriptor->getAddress ("pause_state"); - d->view_screen_offset = d->offset_descriptor->getAddress ("view_screen"); - - d->cursorWindowInited = true; - return true; - } - catch (Error::MissingMemoryDefinition&) - { - d->cursorWindowInited = false; - throw; - } -} - -bool API::InitViewSize() -{ - try - { - d->window_dims_offset = d->offset_descriptor->getAddress ("window_dims"); - - d->viewSizeInited = true; - return true; - } - catch (Error::MissingMemoryDefinition&) - { - d->viewSizeInited = false; - throw; - } -} - -bool API::getViewCoords (int32_t &x, int32_t &y, int32_t &z) -{ - if (!d->cursorWindowInited) return false; - g_pProcess->readDWord (d->window_x_offset, (uint32_t &) x); - g_pProcess->readDWord (d->window_y_offset, (uint32_t &) y); - g_pProcess->readDWord (d->window_z_offset, (uint32_t &) z); - return true; -} -//FIXME: confine writing of coords to map bounds? -bool API::setViewCoords (const int32_t x, const int32_t y, const int32_t z) -{ - if (!d->cursorWindowInited) return false; - g_pProcess->writeDWord (d->window_x_offset, (uint32_t) x); - g_pProcess->writeDWord (d->window_y_offset, (uint32_t) y); - g_pProcess->writeDWord (d->window_z_offset, (uint32_t) z); - return true; -} - -bool API::getCursorCoords (int32_t &x, int32_t &y, int32_t &z) -{ - if(!d->cursorWindowInited) return false; - int32_t coords[3]; - g_pProcess->read (d->cursor_xyz_offset, 3*sizeof (int32_t), (uint8_t *) coords); - x = coords[0]; - y = coords[1]; - z = coords[2]; - if (x == -30000) return false; - return true; -} -//FIXME: confine writing of coords to map bounds? -bool API::setCursorCoords (const int32_t x, const int32_t y, const int32_t z) -{ - if (!d->cursorWindowInited) return false; - int32_t coords[3] = {x, y, z}; - g_pProcess->write (d->cursor_xyz_offset, 3*sizeof (int32_t), (uint8_t *) coords); - return true; -} -bool API::getWindowSize (int32_t &width, int32_t &height) -{ - if(! d->viewSizeInited) return false; - - int32_t coords[2]; - g_pProcess->read (d->window_dims_offset, 2*sizeof (int32_t), (uint8_t *) coords); - width = coords[0]; - height = coords[1]; - return true; -} -/* -bool API::getClassIDMapping (vector & objecttypes) -{ - if(isAttached()) - { - d->offset_descriptor->getClassIDMapping(objecttypes); - return true; - } - return false; -} */ -memory_info *API::getMemoryInfo() -{ - return d->offset_descriptor; -} -Process * API::getProcess() -{ - return d->p; -} - -DFWindow * API::getWindow() -{ - return d->p->getWindow(); -} +/* bool API::InitReadItems(uint32_t & numitems) { try @@ -1831,39 +790,8 @@ void API::FinishReadItems() } d->itemsInited = false; } - -bool API::ReadPauseState() -{ - // replace with an exception - if(!d->cursorWindowInited) return false; - - uint32_t pauseState = g_pProcess->readDWord (d->pause_state_offset); - return pauseState & 1; -} - -uint32_t API::ReadMenuState() -{ - if(d->cursorWindowInited) - return(g_pProcess->readDWord(d->current_menu_state_offset)); - return false; -} - -bool API::ReadViewScreen (t_viewscreen &screen) -{ - if (!d->cursorWindowInited) return false; - - uint32_t last = g_pProcess->readDWord (d->view_screen_offset); - uint32_t screenAddr = g_pProcess->readDWord (last); - uint32_t nextScreenPtr = g_pProcess->readDWord (last + 4); - while (nextScreenPtr != 0) - { - last = nextScreenPtr; - screenAddr = g_pProcess->readDWord (nextScreenPtr); - nextScreenPtr = g_pProcess->readDWord (nextScreenPtr + 4); - } - return d->offset_descriptor->resolveObjectToClassID (last, screen.type); -} - +*/ +/* bool API::ReadItemTypes(vector< vector< t_itemType > > & itemTypes) { memory_info * minfo = d->offset_descriptor; @@ -1887,4 +815,5 @@ bool API::ReadItemTypes(vector< vector< t_itemType > > & itemTypes) itemTypes.push_back(typesForVec); } return true; -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/dfhack/DFProcess-windows-SHM.cpp b/dfhack/DFProcess-windows-SHM.cpp index 983b1f83e..33a1ceb7b 100644 --- a/dfhack/DFProcess-windows-SHM.cpp +++ b/dfhack/DFProcess-windows-SHM.cpp @@ -22,8 +22,8 @@ must not be misrepresented as being the original software. distribution. */ #include "DFCommonInternal.h" -#include "../shmserver/shms.h" -#include "../shmserver/mod-core.h" +#include "shms.h" +#include "mod-core.h" using namespace DFHack; // a full memory barrier! better be safe than sorry. diff --git a/dfhack/depends/md5/CMakeLists.txt b/dfhack/depends/md5/CMakeLists.txt index 842573605..fc4845bd4 100644 --- a/dfhack/depends/md5/CMakeLists.txt +++ b/dfhack/depends/md5/CMakeLists.txt @@ -1,18 +1 @@ -# main project file. use it from a build sub-folder, see COMPILE for details -PROJECT (dfhack-md5) -cmake_minimum_required(VERSION 2.6) - -# disable warning, autosearch -if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) -endif(COMMAND cmake_policy) - -if("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}") - message(SEND_ERROR "In-source builds are not allowed.") -endif("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}") - -IF(NOT DEFINED CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.") -ENDIF(NOT DEFINED CMAKE_BUILD_TYPE) - ADD_LIBRARY(dfhack-md5 SHARED md5.cpp md5wrapper.cpp) diff --git a/dfhack/depends/tinyxml/CMakeLists.txt b/dfhack/depends/tinyxml/CMakeLists.txt index 888527046..effdf8945 100644 --- a/dfhack/depends/tinyxml/CMakeLists.txt +++ b/dfhack/depends/tinyxml/CMakeLists.txt @@ -1,18 +1 @@ -# main project file. use it from a build sub-folder, see COMPILE for details -PROJECT (dfhack-tixml) -cmake_minimum_required(VERSION 2.6) - -# disable warning, autosearch -if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) -endif(COMMAND cmake_policy) - -if("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}") - message(SEND_ERROR "In-source builds are not allowed.") -endif("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}") - -IF(NOT DEFINED CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.") -ENDIF(NOT DEFINED CMAKE_BUILD_TYPE) - -ADD_LIBRARY(tixml-static SHARED tinystr.cpp tinyxml.cpp tinyxmlerror.cpp tinyxmlparser.cpp) \ No newline at end of file +ADD_LIBRARY(dfhack-tixml SHARED tinystr.cpp tinyxml.cpp tinyxmlerror.cpp tinyxmlparser.cpp) \ No newline at end of file diff --git a/dfhack/include/DFHackAPI.h b/dfhack/include/DFHackAPI.h index 7896cf9b4..70416fa2c 100644 --- a/dfhack/include/DFHackAPI.h +++ b/dfhack/include/DFHackAPI.h @@ -37,15 +37,16 @@ distribution. namespace DFHack { + class APIPrivate; class memory_info; class Process; class DFHACK_EXPORT API { - class Private; - Private * const d; + APIPrivate * const d; public: API(const std::string path_to_xml); ~API(); + /* * Basic control over DF's process state */ @@ -66,236 +67,114 @@ namespace DFHack /// forces resume on Windows. This can be a bad thing with multiple DF tools running! bool ForceResume(); - - /* - * Query the DF's GUI state - */ - ///true if paused, false if not - bool ReadPauseState(); - /// read the DF menu view state (stock screen, unit screen, other screens - bool ReadViewScreen(t_viewscreen &); - /// read the DF menu state (designation menu ect) - uint32_t ReadMenuState(); - - - /* - * Matgloss. next four methods look very similar. I could use two and move the processing one level up... - * I'll keep it like this, even with the code duplication as it will hopefully get more features and separate data types later. - * Yay for nebulous plans for a rock survey tool that tracks how much of which metal could be smelted from available resorces - */ - bool ReadStoneMatgloss(std::vector & output); - bool ReadWoodMatgloss (std::vector & output); - bool ReadMetalMatgloss(std::vector & output); - bool ReadPlantMatgloss(std::vector & output); - bool ReadPlantMatgloss (std::vector & plants); - bool ReadCreatureMatgloss(std::vector & output); - - // read region surroundings, get their vectors of geolayers so we can do translation (or just hand the translation table to the client) - // returns an array of 9 vectors of indices into stone matgloss - /** - Method for reading the geological surrounding of the currently loaded region. - assign is a reference to an array of nine vectors of unsigned words that are to be filled with the data - array is indexed by the BiomeOffset enum - - I omitted resolving the layer matgloss in this API, because it would - introduce overhead by calling some method for each tile. You have to do it - yourself. First get the stuff from ReadGeology and then for each block get - the RegionOffsets. For each tile get the real region from RegionOffsets and - cross-reference it with the geology stuff (region -- array of vectors, depth -- - vector). I'm thinking about turning that Geology stuff into a - two-dimensional array with static size. - - this is the algorithm for applying matgloss: - void DfMap::applyGeoMatgloss(Block * b) - { - // load layer matgloss - for(int x_b = 0; x_b < BLOCK_SIZE; x_b++) - { - for(int y_b = 0; y_b < BLOCK_SIZE; y_b++) - { - int geolayer = b->designation[x_b][y_b].bits.geolayer_index; - int biome = b->designation[x_b][y_b].bits.biome; - b->material[x_b][y_b].type = Mat_Stone; - b->material[x_b][y_b].index = v_geology[b->RegionOffsets[biome]][geolayer]; - } - } - } - */ - bool ReadGeology( std::vector < std::vector >& assign ); - - /* - * BLOCK DATA - */ - /// allocate and read pointers to map blocks - bool InitMap(); - /// destroy the mapblock cache - bool DestroyMap(); - /// get size of the map in tiles - void getSize(uint32_t& x, uint32_t& y, uint32_t& z); - - /** - * Return false/0 on failure, buffer allocated by client app, 256 items long - */ - bool isValidBlock(uint32_t blockx, uint32_t blocky, uint32_t blockz); - /** - * Get the address of a block or 0 if block is not valid - */ - uint32_t getBlockPtr (uint32_t blockx, uint32_t blocky, uint32_t blockz); - - /// read the whole map block at block coords (see DFTypes.h for the block structure) - bool ReadBlock40d(uint32_t blockx, uint32_t blocky, uint32_t blockz, mapblock40d * buffer); - - /// read/write block tile types - bool ReadTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, tiletypes40d *buffer); - bool WriteTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, tiletypes40d *buffer); - /// read/write block designations - bool ReadDesignations(uint32_t blockx, uint32_t blocky, uint32_t blockz, designations40d *buffer); - bool WriteDesignations (uint32_t blockx, uint32_t blocky, uint32_t blockz, designations40d *buffer); - - /// read/write block occupancies - bool ReadOccupancy(uint32_t blockx, uint32_t blocky, uint32_t blockz, occupancies40d *buffer); - bool WriteOccupancy(uint32_t blockx, uint32_t blocky, uint32_t blockz, occupancies40d *buffer); - - /// read/write the block dirty bit - this is used to mark a map block so that DF scans it for designated jobs like digging - bool ReadDirtyBit(uint32_t blockx, uint32_t blocky, uint32_t blockz, bool &dirtybit); - bool WriteDirtyBit(uint32_t blockx, uint32_t blocky, uint32_t blockz, bool dirtybit); - - /// read/write the block flags - bool ReadBlockFlags(uint32_t blockx, uint32_t blocky, uint32_t blockz, t_blockflags &blockflags); - bool WriteBlockFlags(uint32_t blockx, uint32_t blocky, uint32_t blockz, t_blockflags blockflags); + memory_info *getMemoryInfo(); + Process * getProcess(); + DFWindow * getWindow(); - /// read region offsets of a block - used for determining layer stone matgloss - bool ReadRegionOffsets(uint32_t blockx, uint32_t blocky, uint32_t blockz, biome_indices40d *buffer); + /// read/write size bytes of raw data at offset. DANGEROUS, CAN SEGFAULT DF! + void ReadRaw (const uint32_t offset, const uint32_t size, uint8_t *target); + void WriteRaw (const uint32_t offset, const uint32_t size, uint8_t *source); - /// read aggregated veins of a block - bool ReadVeins(uint32_t blockx, uint32_t blocky, uint32_t blockz, std::vector & veins, std::vector & ices); + #include "../modules/Position-proc.h" + #include "../modules/Gui-proc.h" + #include "../modules/Maps-proc.h" + #include "../modules/Materials-proc.h" + #include "../modules/Creatures-proc.h" /* * Constructions (costructed walls, floors, ramps, etc...) */ + /* /// start reading constructions. numconstructions is an output - total constructions present bool InitReadConstructions( uint32_t & numconstructions ); /// read a construiction at index bool ReadConstruction(const int32_t index, t_construction & construction); /// cleanup after reading constructions void FinishReadConstructions(); - +*/ /* * Buildings - also includes zones and stockpiles */ + /* bool InitReadBuildings ( uint32_t & numbuildings ); bool ReadBuilding(const int32_t index, t_building & building); void FinishReadBuildings(); - + */ /* * Effects like mist, dragonfire or dust */ + /* bool InitReadEffects ( uint32_t & numeffects ); bool ReadEffect(const uint32_t index, t_effect_df40d & effect); bool WriteEffect(const uint32_t index, const t_effect_df40d & effect); void FinishReadEffects(); - + */ /* * Trees and shrubs */ + /* bool InitReadVegetation( uint32_t & numplants ); bool ReadVegetation(const int32_t index, t_tree_desc & shrubbery); void FinishReadVegetation(); - - /* - * Creatures - */ - bool InitReadCreatures( uint32_t & numcreatures ); - /** - * Read creatures in a box, starting with index. Returns -1 if no more creatures - * found. Call repeatedly do get all creatures in a specified box (uses tile coords) - */ - int32_t ReadCreatureInBox(const int32_t index, t_creature & furball, - const uint16_t x1, const uint16_t y1,const uint16_t z1, - const uint16_t x2, const uint16_t y2,const uint16_t z2); - bool ReadCreature(const int32_t index, t_creature & furball); - void FinishReadCreatures(); - - /// read/write size bytes of raw data at offset. DANGEROUS, CAN SEGFAULT DF! - void ReadRaw (const uint32_t offset, const uint32_t size, uint8_t *target); - void WriteRaw (const uint32_t offset, const uint32_t size, uint8_t *source); - /// write labors of a creature (for Dwarf Therapist) - bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); - + */ + /* * Notes placed by the player */ - + /* /// start reading notes. numnotes is an output - total notes present bool InitReadNotes( uint32_t & numnotes ); /// read note from the note vector at index bool ReadNote(const int32_t index, t_note & note); /// free the note vector void FinishReadNotes(); - + */ /* * Settlements */ + /* bool InitReadSettlements( uint32_t & numsettlements ); bool ReadSettlement(const int32_t index, t_settlement & settlement); bool ReadCurrentSettlement(t_settlement & settlement); void FinishReadSettlements(); - + */ /* * Hotkeys (DF's zoom locations) */ + /* bool InitReadHotkeys( ); bool ReadHotkeys(t_hotkey hotkeys[]); - - /* - * Cursor, and view coords - */ - bool InitViewAndCursor(); - bool getViewCoords (int32_t &x, int32_t &y, int32_t &z); - bool setViewCoords (const int32_t x, const int32_t y, const int32_t z); - - bool getCursorCoords (int32_t &x, int32_t &y, int32_t &z); - bool setCursorCoords (const int32_t x, const int32_t y, const int32_t z); - - /// get the creature vector index of the creature currently under DF' cursor - bool getCurrentCursorCreature (uint32_t & creature_index); - - /* - * Window size in tiles - */ - bool InitViewSize(); - bool getWindowSize(int32_t & width, int32_t & height); - + */ /* * DF translation tables and name translation */ + /* bool InitReadNameTables (std::vector< std::vector > & translations , std::vector< std::vector > & foreign_languages); void FinishReadNameTables(); std::string TranslateName(const t_name & name,const std::vector< std::vector > & translations ,const std::vector< std::vector > & foreign_languages, bool inEnglish=true); - + */ /* * Item reading */ + /* bool InitReadItems(uint32_t & numitems); bool getItemIndexesInBox(std::vector &indexes, const uint16_t x1, const uint16_t y1, const uint16_t z1, const uint16_t x2, const uint16_t y2, const uint16_t z2); bool ReadItem(const uint32_t index, t_item & item); void FinishReadItems(); - + */ /* * Get the other API parts for raw access */ - memory_info *getMemoryInfo(); - Process * getProcess(); - DFWindow * getWindow(); + /* // FIXME: BAD! bool ReadAllMatgloss(vector< vector< string > > & all); */ - bool ReadItemTypes(std::vector< std::vector< t_itemType > > & itemTypes); + //bool ReadItemTypes(std::vector< std::vector< t_itemType > > & itemTypes); }; } // namespace DFHack #endif // SIMPLEAPI_H_INCLUDED diff --git a/dfhack/modules/Creatures.cpp b/dfhack/modules/Creatures.cpp new file mode 100644 index 000000000..b16c7b2ad --- /dev/null +++ b/dfhack/modules/Creatures.cpp @@ -0,0 +1,206 @@ +/* +www.sourceforge.net/projects/dfhack +Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf + +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. +*/ + +#include "DFCommonInternal.h" +#include "../private/APIPrivate.h" + +#define SHMCREATURESHDR ((Creatures::shm_creature_hdr *)d->shm_start) + +using namespace DFHack; +/* +bool API::InitReadCreatures( uint32_t &numcreatures ) +{ + if(!d->InitReadNames()) return false; + try + { + memory_info * minfo = d->offset_descriptor; + Creatures::creature_offsets & off = d->creatures; + off.creature_vector = minfo->getAddress ("creatures"); + off.creature_pos_offset = minfo->getOffset ("creature_position"); + off.creature_type_offset = minfo->getOffset ("creature_race"); + off.creature_flags1_offset = minfo->getOffset ("creature_flags1"); + off.creature_flags2_offset = minfo->getOffset ("creature_flags2"); + off.creature_name_offset = minfo->getOffset ("creature_name"); + off.creature_custom_profession_offset = minfo->getOffset ("creature_custom_profession"); + off.creature_profession_offset = minfo->getOffset ("creature_profession"); + off.creature_sex_offset = minfo->getOffset ("creature_sex"); + off.creature_id_offset = minfo->getOffset ("creature_id"); + off.creature_squad_name_offset = minfo->getOffset ("creature_squad_name"); + off.creature_squad_leader_id_offset = minfo->getOffset ("creature_squad_leader_id"); + off.creature_money_offset = minfo->getOffset ("creature_money"); + off.creature_current_job_offset = minfo->getOffset ("creature_current_job"); + off.creature_current_job_id_offset = minfo->getOffset ("current_job_id"); + off.creature_strength_offset = minfo->getOffset ("creature_strength"); + off.creature_agility_offset = minfo->getOffset ("creature_agility"); + off.creature_toughness_offset = minfo->getOffset ("creature_toughness"); + off.creature_skills_offset = minfo->getOffset ("creature_skills"); + off.creature_labors_offset = minfo->getOffset ("creature_labors"); + off.creature_happiness_offset = minfo->getOffset ("creature_happiness"); + off.creature_traits_offset = minfo->getOffset ("creature_traits"); + off.creature_likes_offset = minfo->getOffset("creature_likes"); + off.creature_artifact_name_offset = minfo->getOffset("creature_artifact_name"); + off.creature_mood_offset = minfo->getOffset("creature_mood"); + + off.creature_pregnancy_offset = minfo->getOffset("creature_pregnancy"); + off.creature_blood_max_offset = minfo->getOffset("creature_blood_max"); + off.creature_blood_current_offset = minfo->getOffset("creature_blood_current"); + off.creature_bleed_offset = minfo->getOffset("creature_bleed"); + + // name offsets for the creature module + off.name_firstname_offset = minfo->getOffset("name_firstname"); + off.name_nickname_offset = minfo->getOffset("name_nickname"); + off.name_words_offset = minfo->getOffset("name_words"); + + // HACK: vector correction. No longer relevant. + off.vector_correct = 0; + + d->p_cre = new DfVector (d->p, off.creature_vector, 4); + d->creaturesInited = true; + numcreatures = d->p_cre->getSize(); + + // --> SHM initialization (if possible) <-- + g_pProcess->getModuleIndex("Creatures40d",1,d->creature_module); + + if(d->creature_module) + { + // supply the module with offsets so it can work with them + memcpy(SHMDATA(Creatures::creature_offsets),&d->creatures,sizeof(Creatures::creature_offsets)); + const uint32_t cmd = Creatures::CREATURE_INIT + (d->creature_module << 16); + g_pProcess->SetAndWait(cmd); + } + return true; + } + catch (Error::MissingMemoryDefinition&) + { + d->creaturesInited = false; + numcreatures = 0; + throw; + } +} + +bool API::ReadCreature (const int32_t index, t_creature & furball) +{ + if(!d->creaturesInited) return false; + if(d->creature_module) + { + // supply the module with offsets so it can work with them + SHMCREATURESHDR->index = index; + const uint32_t cmd = Creatures::CREATURE_AT_INDEX + (d->creature_module << 16); + g_pProcess->SetAndWait(cmd); + memcpy(&furball,SHMDATA(t_creature),sizeof(t_creature)); + // cerr << "creature read from SHM!" << endl; + return true; + } + // read pointer from vector at position + uint32_t temp = * (uint32_t *) d->p_cre->at (index); + furball.origin = temp; + Creatures::creature_offsets &offs = d->creatures; + //read creature from memory + g_pProcess->read (temp + offs.creature_pos_offset, 3 * sizeof (uint16_t), (uint8_t *) & (furball.x)); // xyz really + g_pProcess->readDWord (temp + offs.creature_type_offset, furball.type); + g_pProcess->readDWord (temp + offs.creature_flags1_offset, furball.flags1.whole); + g_pProcess->readDWord (temp + offs.creature_flags2_offset, furball.flags2.whole); + // names + d->readName(furball.name,temp + offs.creature_name_offset); + d->readName(furball.squad_name, temp + offs.creature_squad_name_offset); + d->readName(furball.artifact_name, temp + offs.creature_artifact_name_offset); + // custom profession + fill_char_buf (furball.custom_profession, d->p->readSTLString (temp + offs.creature_custom_profession_offset)); + + // labors + g_pProcess->read (temp + offs.creature_labors_offset, NUM_CREATURE_LABORS, furball.labors); + // traits + g_pProcess->read (temp + offs.creature_traits_offset, sizeof (uint16_t) * NUM_CREATURE_TRAITS, (uint8_t *) &furball.traits); + // learned skills + DfVector skills (d->p, temp + offs.creature_skills_offset, 4 ); + furball.numSkills = skills.getSize(); + for (uint32_t i = 0; i < furball.numSkills;i++) + { + uint32_t temp2 = * (uint32_t *) skills[i]; + //skills.read(i, (uint8_t *) &temp2); + // a byte: this gives us 256 skills maximum. + furball.skills[i].id = g_pProcess->readByte (temp2); + furball.skills[i].rating = g_pProcess->readByte (temp2 + 4); + furball.skills[i].experience = g_pProcess->readWord (temp2 + 8); + } + // profession + furball.profession = g_pProcess->readByte (temp + offs.creature_profession_offset); + // current job HACK: the job object isn't cleanly represented here + uint32_t jobIdAddr = g_pProcess->readDWord (temp + offs.creature_current_job_offset); + + if (jobIdAddr) + { + furball.current_job.active = true; + furball.current_job.jobId = g_pProcess->readByte (jobIdAddr + offs.creature_current_job_id_offset); + } + else + { + furball.current_job.active = false; + } + + //likes + DfVector likes(d->p, temp + offs.creature_likes_offset, 4); + furball.numLikes = likes.getSize(); + for(uint32_t i = 0;iread(temp2,sizeof(t_like),(uint8_t *) &furball.likes[i]); + } + + furball.mood = (int16_t) g_pProcess->readWord (temp + offs.creature_mood_offset); + + + g_pProcess->readDWord (temp + offs.creature_happiness_offset, furball.happiness); + g_pProcess->readDWord (temp + offs.creature_id_offset, furball.id); + g_pProcess->readDWord (temp + offs.creature_agility_offset, furball.agility); + g_pProcess->readDWord (temp + offs.creature_strength_offset, furball.strength); + g_pProcess->readDWord (temp + offs.creature_toughness_offset, furball.toughness); + g_pProcess->readDWord (temp + offs.creature_money_offset, furball.money); + furball.squad_leader_id = (int32_t) g_pProcess->readDWord (temp + offs.creature_squad_leader_id_offset); + g_pProcess->readByte (temp + offs.creature_sex_offset, furball.sex); + + g_pProcess->readDWord(temp + offs.creature_pregnancy_offset, furball.pregnancy_timer); + furball.blood_max = (int32_t) g_pProcess->readDWord(temp + offs.creature_blood_max_offset); + furball.blood_current = (int32_t) g_pProcess->readDWord(temp + offs.creature_blood_current_offset); + g_pProcess->readDWord(temp + offs.creature_bleed_offset, furball.bleed_rate); + + + return true; +} + +bool API::WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]) +{ + if(!d->creaturesInited) return false; + uint32_t temp = * (uint32_t *) d->p_cre->at (index); + WriteRaw(temp + d->creatures.creature_labors_offset, NUM_CREATURE_LABORS, labors); +} + + +bool API::getCurrentCursorCreature(uint32_t & creature_index) +{ + if(!d->cursorWindowInited) return false; + creature_index = g_pProcess->readDWord(d->current_cursor_creature_offset); + return true; +} +*/ \ No newline at end of file diff --git a/dfhack/modules/Gui.cpp b/dfhack/modules/Gui.cpp new file mode 100644 index 000000000..d7b814e6e --- /dev/null +++ b/dfhack/modules/Gui.cpp @@ -0,0 +1,59 @@ +/* +www.sourceforge.net/projects/dfhack +Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf + +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. +*/ + +#include "DFCommonInternal.h" +#include "../private/APIPrivate.h" +using namespace DFHack; + +bool API::ReadPauseState() +{ + // replace with an exception + if(!d->cursorWindowInited) return false; + + uint32_t pauseState = g_pProcess->readDWord (d->pause_state_offset); + return pauseState & 1; +} + +uint32_t API::ReadMenuState() +{ + if(d->cursorWindowInited) + return(g_pProcess->readDWord(d->current_menu_state_offset)); + return false; +} + +bool API::ReadViewScreen (t_viewscreen &screen) +{ + if (!d->cursorWindowInited) return false; + + uint32_t last = g_pProcess->readDWord (d->view_screen_offset); + uint32_t screenAddr = g_pProcess->readDWord (last); + uint32_t nextScreenPtr = g_pProcess->readDWord (last + 4); + while (nextScreenPtr != 0) + { + last = nextScreenPtr; + screenAddr = g_pProcess->readDWord (nextScreenPtr); + nextScreenPtr = g_pProcess->readDWord (nextScreenPtr + 4); + } + return d->offset_descriptor->resolveObjectToClassID (last, screen.type); +} diff --git a/dfhack/modules/Maps.cpp b/dfhack/modules/Maps.cpp new file mode 100644 index 000000000..75008851e --- /dev/null +++ b/dfhack/modules/Maps.cpp @@ -0,0 +1,442 @@ +/* +www.sourceforge.net/projects/dfhack +Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf + +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. +*/ + +#include "DFCommonInternal.h" +#include "../private/APIPrivate.h" + +#define SHMMAPSHDR ((Maps::shm_maps_hdr *)d->shm_start) + +using namespace DFHack; + +/*-----------------------------------* + * Init the mapblock pointer array * + *-----------------------------------*/ +bool API::InitMap() +{ + uint32_t map_offset = d->offset_descriptor->getAddress ("map_data"); + uint32_t x_count_offset = d->offset_descriptor->getAddress ("x_count_block"); + uint32_t y_count_offset = d->offset_descriptor->getAddress ("y_count_block"); + uint32_t z_count_offset = d->offset_descriptor->getAddress ("z_count_block"); + + // get the offsets once here + d->tile_type_offset = d->offset_descriptor->getOffset ("type"); + d->designation_offset = d->offset_descriptor->getOffset ("designation"); + //d->occupancy_offset = d->offset_descriptor->getOffset ("occupancy"); + //d->biome_stuffs = d->offset_descriptor->getOffset ("biome_stuffs"); + + d->veinvector = d->offset_descriptor->getOffset ("v_vein"); + + // these can fail and will be found when looking at the actual veins later + // basically a cache + d->vein_ice_vptr = 0; + 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("Maps2010",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->designation_offset = d->designation_offset; + off->map_offset = map_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); + g_pProcess->SetAndWait(cmd); + //cerr << "Map acceleration enabled!" << endl; + } + + // get the map pointer + uint32_t x_array_loc = g_pProcess->readDWord (map_offset); + if (!x_array_loc) + { + return false; + // FIXME: only throw this due to programmer error, in the other map functions + //throw Error::NoMapLoaded(); + } + + // 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); + + // test for wrong map dimensions + if (mx == 0 || mx > 48 || my == 0 || my > 48 || mz == 0) + { + throw Error::BadMapDimensions(mx, my); + //return false; + } + + // alloc array for pointers to all blocks + d->block = new uint32_t[mx*my*mz]; + uint32_t *temp_x = new uint32_t[mx]; + uint32_t *temp_y = new uint32_t[my]; + uint32_t *temp_z = new uint32_t[mz]; + + g_pProcess->read (x_array_loc, mx * sizeof (uint32_t), (uint8_t *) temp_x); + for (uint32_t x = 0; x < mx; x++) + { + g_pProcess->read (temp_x[x], my * sizeof (uint32_t), (uint8_t *) temp_y); + // y -> map column + for (uint32_t y = 0; y < my; y++) + { + g_pProcess->read (temp_y[y], + mz * sizeof (uint32_t), + (uint8_t *) (d->block + x*my*mz + y*mz)); + } + } + delete [] temp_x; + delete [] temp_y; + delete [] temp_z; + return true; +} + +bool API::DestroyMap() +{ + if (d->block != NULL) + { + delete [] d->block; + d->block = NULL; + } + return true; +} + +bool API::isValidBlock (uint32_t x, uint32_t y, uint32_t z) +{ + if ( x >= d->x_block_count || y >= d->y_block_count || z >= d->z_block_count) + return false; + return d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z] != 0; +} + +uint32_t API::getBlockPtr (uint32_t x, uint32_t y, uint32_t z) +{ + if ( x >= d->x_block_count || y >= d->y_block_count || z >= d->z_block_count) + return 0; + 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; + volatile uint32_t cmd = Maps::MAP_READ_BLOCK_BY_COORDS + (d->maps_module << 16); + if(!g_pProcess->SetAndWait(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); + buffer->origin = addr; + uint32_t addr_of_struct = g_pProcess->readDWord(addr); + buffer->blockflags.whole = 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, tiletypes40d *buffer) +{ + 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 (tiletypes40d), (uint8_t *) buffer); + return true; + } + return false; +} + +bool API::ReadDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool &dirtybit) +{ + uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; + if(addr) + { + uint32_t addr_of_struct = g_pProcess->readDWord(addr); + dirtybit = g_pProcess->readDWord(addr_of_struct) & 1; + return true; + } + return false; +} + +bool API::WriteDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool dirtybit) +{ + uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; + if (addr) + { + uint32_t addr_of_struct = g_pProcess->readDWord(addr); + uint32_t dirtydword = g_pProcess->readDWord(addr_of_struct); + dirtydword &= 0xFFFFFFFE; + dirtydword |= (uint32_t) dirtybit; + g_pProcess->writeDWord (addr_of_struct, dirtydword); + return true; + } + return false; +} + +/// read/write the block flags +bool API::ReadBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags &blockflags) +{ + uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; + if(addr) + { + uint32_t addr_of_struct = g_pProcess->readDWord(addr); + blockflags.whole = g_pProcess->readDWord(addr_of_struct); + return true; + } + return false; +} +bool API::WriteBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags blockflags) +{ + uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; + if (addr) + { + uint32_t addr_of_struct = g_pProcess->readDWord(addr); + g_pProcess->writeDWord (addr_of_struct, blockflags.whole); + return true; + } + return false; +} + +bool API::ReadDesignations (uint32_t x, uint32_t y, uint32_t z, designations40d *buffer) +{ + 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->designation_offset, sizeof (designations40d), (uint8_t *) buffer); + return true; + } + return false; +} + +// 256 * sizeof(uint16_t) +bool API::WriteTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buffer) +{ + uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; + if (addr) + { + g_pProcess->write (addr + d->tile_type_offset, sizeof (tiletypes40d), (uint8_t *) buffer); + return true; + } + return false; +} + + +// 256 * sizeof(uint32_t) +bool API::WriteDesignations (uint32_t x, uint32_t y, uint32_t z, designations40d *buffer) +{ + uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; + if (addr) + { + g_pProcess->write (addr + d->designation_offset, sizeof (designations40d), (uint8_t *) buffer); + return true; + } + return false; +} + +// FIXME: this is bad. determine the real size! +//16 of them? IDK... there's probably just 7. Reading more doesn't cause errors as it's an array nested inside a block +// 16 * sizeof(uint8_t) +/* +bool API::ReadRegionOffsets (uint32_t x, uint32_t y, uint32_t z, biome_indices40d *buffer) +{ + 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->biome_stuffs, sizeof (biome_indices40d), (uint8_t *) buffer); + return true; + } + return false; +} +*/ + +// veins of a block, expects empty vein vectors +bool API::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector & veins, vector & ices) +{ + uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; + veins.clear(); + ices.clear(); + if (addr && d->veinvector) + { + // veins are stored as a vector of pointers to veins + /*pointer is 4 bytes! we work with a 32bit program here, no matter what architecture we compile khazad for*/ + DfVector p_veins (d->p, addr + d->veinvector, 4); + uint32_t size = p_veins.getSize(); + veins.reserve (size); + + // read all veins + for (uint32_t i = 0; i < size;i++) + { + t_vein v; + t_frozenliquidvein fv; + + // read the vein pointer from the vector + uint32_t temp = * (uint32_t *) p_veins[i]; + uint32_t type = g_pProcess->readDWord(temp); +try_again: + if(type == d->vein_mineral_vptr) + { + // read the vein data (dereference pointer) + g_pProcess->read (temp, sizeof(t_vein), (uint8_t *) &v); + v.address_of = temp; + // store it in the vector + veins.push_back (v); + } + else if(type == d->vein_ice_vptr) + { + // read the ice vein data (dereference pointer) + g_pProcess->read (temp, sizeof(t_frozenliquidvein), (uint8_t *) &fv); + // store it in the vector + ices.push_back (fv); + } + else if(g_pProcess->readClassName(type) == "block_square_event_frozen_liquid") + { + d->vein_ice_vptr = type; + goto try_again; + } + else if(g_pProcess->readClassName(type) == "block_square_event_mineral") + { + d->vein_mineral_vptr = type; + goto try_again; + } + } + return true; + } + return false; +} + + +// getter for map size +void API::getSize (uint32_t& x, uint32_t& y, uint32_t& z) +{ + x = d->x_block_count; + y = d->y_block_count; + z = d->z_block_count; +} + +/* +//vector v_geology[eBiomeCount]; +bool API::ReadGeology (vector < vector >& assign) +{ + memory_info * minfo = d->offset_descriptor; + // get needed addresses and offsets. Now this is what I call crazy. + int region_x_offset = minfo->getAddress ("region_x"); + int region_y_offset = minfo->getAddress ("region_y"); + int region_z_offset = minfo->getAddress ("region_z"); + int world_offset = minfo->getAddress ("world"); + int world_regions_offset = minfo->getOffset ("w_regions_arr"); + int region_size = minfo->getHexValue ("region_size"); + int region_geo_index_offset = minfo->getOffset ("region_geo_index_off"); + int world_geoblocks_offset = minfo->getOffset ("w_geoblocks"); + int world_size_x = minfo->getOffset ("world_size_x"); + int world_size_y = minfo->getOffset ("world_size_y"); + int geolayer_geoblock_offset = minfo->getOffset ("geolayer_geoblock_offset"); + + uint32_t regionX, regionY, regionZ; + uint16_t worldSizeX, worldSizeY; + + // read position of the region inside DF world + g_pProcess->readDWord (region_x_offset, regionX); + g_pProcess->readDWord (region_y_offset, regionY); + g_pProcess->readDWord (region_z_offset, regionZ); + + // get world size + g_pProcess->readWord (world_offset + world_size_x, worldSizeX); + g_pProcess->readWord (world_offset + world_size_y, worldSizeY); + + // get pointer to first part of 2d array of regions + uint32_t regions = g_pProcess->readDWord (world_offset + world_regions_offset); + + // read the geoblock vector + DfVector geoblocks (d->p, world_offset + world_geoblocks_offset, 4); + + // iterate over 8 surrounding regions + local region + for (int i = eNorthWest; i < eBiomeCount; i++) + { + // check bounds, fix them if needed + int bioRX = regionX / 16 + (i % 3) - 1; + if (bioRX < 0) bioRX = 0; + if (bioRX >= worldSizeX) bioRX = worldSizeX - 1; + int bioRY = regionY / 16 + (i / 3) - 1; + if (bioRY < 0) bioRY = 0; + if (bioRY >= worldSizeY) bioRY = worldSizeY - 1; + + // get pointer to column of regions + uint32_t geoX; + g_pProcess->readDWord (regions + bioRX*4, geoX); + + // get index into geoblock vector + uint16_t geoindex; + g_pProcess->readWord (geoX + bioRY*region_size + region_geo_index_offset, geoindex); + + // get the geoblock from the geoblock vector using the geoindex + // read the matgloss pointer from the vector into temp + uint32_t geoblock_off = * (uint32_t *) geoblocks[geoindex]; + + // get the vector with pointer to layers + DfVector geolayers (d->p, geoblock_off + geolayer_geoblock_offset , 4); // let's hope + // make sure we don't load crap + assert (geolayers.getSize() > 0 && geolayers.getSize() <= 16); + + d->v_geology[i].reserve (geolayers.getSize()); + // finally, read the layer matgloss + for (uint32_t j = 0;j < geolayers.getSize();j++) + { + // read pointer to a layer + uint32_t geol_offset = * (uint32_t *) geolayers[j]; + // read word at pointer + 2, store in our geology vectors + d->v_geology[i].push_back (g_pProcess->readWord (geol_offset + 2)); + } + } + assign.clear(); + assign.reserve (eBiomeCount); +// // TODO: clean this up + for (int i = 0; i < eBiomeCount;i++) + { + assign.push_back (d->v_geology[i]); + } + return true; +} +*/ \ No newline at end of file diff --git a/dfhack/modules/Materials.cpp b/dfhack/modules/Materials.cpp new file mode 100644 index 000000000..756a95bf8 --- /dev/null +++ b/dfhack/modules/Materials.cpp @@ -0,0 +1,188 @@ +/* +www.sourceforge.net/projects/dfhack +Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf + +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. +*/ + +#include "DFCommonInternal.h" +#include "../private/APIPrivate.h" +using namespace DFHack; + + + +bool API::ReadWoodMaterials (vector & woods) +{ +/* + int matgloss_address = d->offset_descriptor->getAddress ("matgloss"); + int matgloss_wood_name_offset = d->offset_descriptor->getOffset("matgloss_wood_name"); + // TODO: find flag for autumnal coloring? + DfVector p_matgloss(d->p, matgloss_address, 4); + + woods.clear(); + + t_matgloss mat; + // TODO: use brown? + mat.fore = 7; + mat.back = 0; + mat.bright = 0; + uint32_t size = p_matgloss.getSize(); + for (uint32_t i = 0; i < size ;i++) + { + // read the matgloss pointer from the vector into temp + uint32_t temp = * (uint32_t *) p_matgloss[i]; + // read the string pointed at by + d->p->readSTLString (temp, mat.id, 128); + d->p->readSTLString (temp+matgloss_wood_name_offset, mat.name, 128); + woods.push_back (mat); + } + */ + return true; +} + +bool API::ReadInorganicMaterials (vector & inorganic) +{ + memory_info * minfo = d->offset_descriptor; + int matgloss_address = minfo->getAddress ("mat_inorganics"); + //int matgloss_colors = minfo->getOffset ("material_color"); + //int matgloss_stone_name_offset = minfo->getOffset("matgloss_stone_name"); + + DfVector p_matgloss (d->p, matgloss_address, 4); + + uint32_t size = p_matgloss.getSize(); + inorganic.resize (0); + inorganic.reserve (size); + for (uint32_t i = 0; i < size;i++) + { + // read the matgloss pointer from the vector into temp + uint32_t temp = * (uint32_t *) p_matgloss[i]; + // read the string pointed at by + t_matgloss mat; + //fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address + d->p->readSTLString (temp, mat.id, 128); + /* + d->p->readSTLString (temp+matgloss_stone_name_offset, mat.name, 128); + mat.fore = (uint8_t) g_pProcess->readWord (temp + matgloss_colors); + mat.back = (uint8_t) g_pProcess->readWord (temp + matgloss_colors + 2); + mat.bright = (uint8_t) g_pProcess->readWord (temp + matgloss_colors + 4); + */ + inorganic.push_back (mat); + } + return true; + +} + +bool API::ReadPlantMaterials (vector & plants) +{ + /* + memory_info * minfo = d->offset_descriptor; + int matgloss_address = minfo->getAddress ("matgloss"); + int matgloss_offset = minfo->getHexValue ("matgloss_skip"); + int matgloss_plant_name_offset = minfo->getOffset("matgloss_plant_name"); + DfVector p_matgloss(d->p, matgloss_address + matgloss_offset * 2, 4); + + plants.clear(); + + // TODO: use green? + t_matgloss mat; + mat.fore = 7; + mat.back = 0; + mat.bright = 0; + for (uint32_t i = 0; i < p_matgloss.getSize();i++) + { + // read the matgloss pointer from the vector into temp + uint32_t temp = * (uint32_t *) p_matgloss[i]; + // read the string pointed at by + //fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address + d->p->readSTLString (temp, mat.id, 128); + d->p->readSTLString (temp+matgloss_plant_name_offset, mat.name, 128); + plants.push_back (mat); + } + */ + return true; +} + +bool API::ReadPlantMaterials (vector & plants) +{ + /* + memory_info * minfo = d->offset_descriptor; + int matgloss_address = minfo->getAddress ("matgloss"); + int matgloss_offset = minfo->getHexValue ("matgloss_skip"); + int matgloss_plant_name_offset = minfo->getOffset("matgloss_plant_name"); + int matgloss_plant_drink_offset = minfo->getOffset("matgloss_plant_drink"); + int matgloss_plant_food_offset = minfo->getOffset("matgloss_plant_food"); + int matgloss_plant_extract_offset = minfo->getOffset("matgloss_plant_extract"); + DfVector p_matgloss(d->p, matgloss_address + matgloss_offset * 2, 4); + + plants.clear(); + + // TODO: use green? + t_matglossPlant mat; + mat.fore = 7; + mat.back = 0; + mat.bright = 0; + for (uint32_t i = 0; i < p_matgloss.getSize();i++) + { + // read the matgloss pointer from the vector into temp + uint32_t temp = * (uint32_t *) p_matgloss[i]; + // read the string pointed at by + //fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address + d->p->readSTLString (temp, mat.id, 128); + d->p->readSTLString (temp+matgloss_plant_name_offset, mat.name, 128); + d->p->readSTLString (temp+matgloss_plant_drink_offset, mat.drink_name, 128); + d->p->readSTLString (temp+matgloss_plant_food_offset, mat.food_name, 128); + d->p->readSTLString (temp+matgloss_plant_extract_offset, mat.extract_name, 128); + + //d->p->readSTLString (temp + plants.push_back (mat); + } + */ + return true; +} + +bool API::ReadCreatureTypes (vector & creatures) +{ + /* + memory_info * minfo = d->offset_descriptor; + int matgloss_address = minfo->getAddress ("matgloss"); + int matgloss_offset = minfo->getHexValue ("matgloss_skip"); + int matgloss_creature_name_offset = minfo->getOffset("matgloss_creature_name"); + DfVector p_matgloss (d->p, matgloss_address + matgloss_offset * 6, 4); + + creatures.clear(); + + // TODO: use green? + t_matgloss mat; + mat.fore = 7; + mat.back = 0; + mat.bright = 0; + for (uint32_t i = 0; i < p_matgloss.getSize();i++) + { + // read the matgloss pointer from the vector into temp + uint32_t temp = * (uint32_t *) p_matgloss[i]; + // read the string pointed at by + //fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address + d->p->readSTLString (temp, mat.id, 128); + d->p->readSTLString (temp+matgloss_creature_name_offset, mat.name, 128); + creatures.push_back (mat); + } + */ + return true; +} diff --git a/dfhack/modules/Position.cpp b/dfhack/modules/Position.cpp new file mode 100644 index 000000000..679d1b10c --- /dev/null +++ b/dfhack/modules/Position.cpp @@ -0,0 +1,103 @@ +/* +www.sourceforge.net/projects/dfhack +Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf + +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. +*/ + +#include "DFCommonInternal.h" +#include "../private/APIPrivate.h" +using namespace DFHack; + +bool API::InitViewAndCursor() +{ + try + { + d->window_x_offset = d->offset_descriptor->getAddress ("window_x"); + d->window_y_offset = d->offset_descriptor->getAddress ("window_y"); + d->window_z_offset = d->offset_descriptor->getAddress ("window_z"); + d->cursor_xyz_offset = d->offset_descriptor->getAddress ("cursor_xyz"); + d->current_cursor_creature_offset = d->offset_descriptor->getAddress ("current_cursor_creature"); + d->window_dims_offset = d->offset_descriptor->getAddress ("window_dims"); + + d->current_menu_state_offset = d->offset_descriptor->getAddress("current_menu_state"); + d->pause_state_offset = d->offset_descriptor->getAddress ("pause_state"); + d->view_screen_offset = d->offset_descriptor->getAddress ("view_screen"); + + d->cursorWindowInited = true; + return true; + } + catch (Error::MissingMemoryDefinition&) + { + d->cursorWindowInited = false; + throw; + } +} + +bool API::getViewCoords (int32_t &x, int32_t &y, int32_t &z) +{ + if (!d->cursorWindowInited) return false; + g_pProcess->readDWord (d->window_x_offset, (uint32_t &) x); + g_pProcess->readDWord (d->window_y_offset, (uint32_t &) y); + g_pProcess->readDWord (d->window_z_offset, (uint32_t &) z); + return true; +} + +//FIXME: confine writing of coords to map bounds? +bool API::setViewCoords (const int32_t x, const int32_t y, const int32_t z) +{ + if (!d->cursorWindowInited) return false; + g_pProcess->writeDWord (d->window_x_offset, (uint32_t) x); + g_pProcess->writeDWord (d->window_y_offset, (uint32_t) y); + g_pProcess->writeDWord (d->window_z_offset, (uint32_t) z); + return true; +} + +bool API::getCursorCoords (int32_t &x, int32_t &y, int32_t &z) +{ + if(!d->cursorWindowInited) return false; + int32_t coords[3]; + g_pProcess->read (d->cursor_xyz_offset, 3*sizeof (int32_t), (uint8_t *) coords); + x = coords[0]; + y = coords[1]; + z = coords[2]; + if (x == -30000) return false; + return true; +} + +//FIXME: confine writing of coords to map bounds? +bool API::setCursorCoords (const int32_t x, const int32_t y, const int32_t z) +{ + if (!d->cursorWindowInited) return false; + int32_t coords[3] = {x, y, z}; + g_pProcess->write (d->cursor_xyz_offset, 3*sizeof (int32_t), (uint8_t *) coords); + return true; +} + +bool API::getWindowSize (int32_t &width, int32_t &height) +{ + if(! d->cursorWindowInited) return false; + + int32_t coords[2]; + g_pProcess->read (d->window_dims_offset, 2*sizeof (int32_t), (uint8_t *) coords); + width = coords[0]; + height = coords[1]; + return true; +} \ No newline at end of file diff --git a/dfhack/private/APIPrivate.h b/dfhack/private/APIPrivate.h new file mode 100644 index 000000000..6c3752a7f --- /dev/null +++ b/dfhack/private/APIPrivate.h @@ -0,0 +1,113 @@ +/* +www.sourceforge.net/projects/dfhack +Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf + +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. +*/ + +/* +* WARNING: Only include from API modules +*/ + +#ifndef APIPRIVATE_H_INCLUDED +#define APIPRIVATE_H_INCLUDED + +// we connect to those +#include +#include +#include +#include + +#define SHMCMD(num) ((shm_cmd *)d->shm_start)[num]->pingpong +#define SHMHDR ((shm_core_hdr *)d->shm_start) +#define SHMDATA(type) ((type *)(d->shm_start + SHM_HEADER)) + +namespace DFHack +{ + +class APIPrivate +{ +public: + APIPrivate(); + void readName(t_name & name, uint32_t address); + // get the name offsets + bool InitReadNames(); + + #include "../modules/Creatures-data.h" + #include "../modules/Maps-data.h" + #include "../modules/Position-data.h" + #include "../modules/Gui-data.h" + #include "../modules/Materials-data.h" + + uint32_t name_firstname_offset; + uint32_t name_nickname_offset; + uint32_t name_words_offset; + + ProcessEnumerator* pm; + Process* p; + char * shm_start; + memory_info* offset_descriptor; + string xml; + + /* + uint32_t item_material_offset; + + uint32_t note_foreground_offset; + uint32_t note_background_offset; + uint32_t note_name_offset; + uint32_t note_xyz_offset; + uint32_t hotkey_start; + uint32_t hotkey_mode_offset; + uint32_t hotkey_xyz_offset; + uint32_t hotkey_size; + + uint32_t settlement_name_offset; + uint32_t settlement_world_xy_offset; + uint32_t settlement_local_xy_offset; + + uint32_t dwarf_lang_table_offset; + + bool constructionsInited; + bool buildingsInited; + bool effectsInited; + bool vegetationInited; + + + bool itemsInited; + bool notesInited; + bool namesInited; + bool hotkeyInited; + bool settlementsInited; + bool nameTablesInited; + + uint32_t tree_offset; + + DfVector *p_cons; + DfVector *p_bld; + DfVector *p_effect; + DfVector *p_veg; + DfVector *p_itm; + DfVector *p_notes; + DfVector *p_settlements; + DfVector *p_current_settlement; + */ +}; +} +#endif \ No newline at end of file diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 2e3be5a4b..1181c83d6 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -9,17 +9,17 @@ ENDIF(UNIX) ADD_EXECUTABLE(dfattachtest attachtest.cpp) TARGET_LINK_LIBRARIES(dfattachtest dfhack) +# buildingsdump - dump buildings and their raw data filtered by type +#ADD_EXECUTABLE(dfbuildingsdump buildingsdump.cpp) +#TARGET_LINK_LIBRARIES(dfbuildingsdump dfhack) + # a benchmark program, reads the map 1000x ADD_EXECUTABLE(dfexpbench expbench.cpp) TARGET_LINK_LIBRARIES(dfexpbench dfhack) # creaturedump - basic creature dump - a test of the creature related exports -ADD_EXECUTABLE(dfcreaturedump creaturedump.cpp) -TARGET_LINK_LIBRARIES(dfcreaturedump dfhack) - -# buildingsdump - dump buildings and their raw data filtered by type -ADD_EXECUTABLE(dfbuildingsdump buildingsdump.cpp) -TARGET_LINK_LIBRARIES(dfbuildingsdump dfhack) +# ADD_EXECUTABLE(dfcreaturedump creaturedump.cpp) +# TARGET_LINK_LIBRARIES(dfcreaturedump dfhack) # materialtest - just list the first material of each type ADD_EXECUTABLE(dfmaterialtest materialtest.cpp) @@ -35,13 +35,13 @@ ADD_EXECUTABLE(dfsuspend suspendtest.cpp) TARGET_LINK_LIBRARIES(dfsuspend dfhack) # itemdump - dump the item under the cursor -ADD_EXECUTABLE(dfitemdump dfitemdump.cpp) -TARGET_LINK_LIBRARIES(dfitemdump dfhack) +# ADD_EXECUTABLE(dfitemdump dfitemdump.cpp) +# TARGET_LINK_LIBRARIES(dfitemdump dfhack) # hotkeynotedump - dumps the hotkeys and notes for the loaded map # Author: belal -ADD_EXECUTABLE(dfhotkeynotedump hotkeynotedump.cpp) -TARGET_LINK_LIBRARIES(dfhotkeynotedump dfhack) +# ADD_EXECUTABLE(dfhotkeynotedump hotkeynotedump.cpp) +# TARGET_LINK_LIBRARIES(dfhotkeynotedump dfhack) # findnameindexes # Author: belal @@ -50,8 +50,8 @@ TARGET_LINK_LIBRARIES(dfhotkeynotedump dfhack) # settlementdump - dumps the settlements on the loaded map # Author: belal -ADD_EXECUTABLE(dfsettlementdump settlementdump.cpp) -TARGET_LINK_LIBRARIES(dfsettlementdump dfhack) +# ADD_EXECUTABLE(dfsettlementdump settlementdump.cpp) +# TARGET_LINK_LIBRARIES(dfsettlementdump dfhack) # veccheck - read vector values at address ADD_EXECUTABLE(dfvecc veccheck.cpp) @@ -59,67 +59,67 @@ TARGET_LINK_LIBRARIES(dfvecc dfhack) # catsplosion - Makes every cat pregnant, and almost due... # Author: Zhentar -ADD_EXECUTABLE(dfcatsplosion catsplosion.cpp) -TARGET_LINK_LIBRARIES(dfcatsplosion dfhack) - -IF(UNIX) - SET(CURSES_NEED_WIDE "YES") - SET(CURSES_NEED_NCURSES "YES") - find_package(Curses) - - IF(CURSES_FOUND) - if(CURSES_HAVE_NCURSESW_NCURSES_H) - SET(NCURSES_H "ncursesw/ncurses.h") - elseif(CURSES_HAVE_NCURSESW_CURSES_H) - SET(NCURSES_H "ncursesw/curses.h") - elseif(CURSES_HAVE_NCURSESW_H) - SET(NCURSES_H "ncursesw.h") - elseif(CURSES_HAVE_CURSESW_H) - SET(NCURSES_H "cursesw.h") - endif(CURSES_HAVE_NCURSESW_NCURSES_H) - IF(NCURSES_H) - # OPTION( VARIABLE "Description" Initial state) - #OPTION( WITH_FOO "Enable FOO support" ON ) - #OPTION( WITH_BAR "Enable BAR component" OFF ) - #SET( BAZ 18 ) - CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/fake-curses.h.cmake ${CMAKE_CURRENT_SOURCE_DIR}/fake-curses.h ) - - # veinlook - look at the map... sort of - ADD_EXECUTABLE(dfveinlook veinlook.cpp) - INCLUDE_DIRECTORIES(${CURSES_INCLUDE_DIR}) - TARGET_LINK_LIBRARIES(dfveinlook dfhack ${CURSES_LIBRARIES}) - install(TARGETS - dfveinlook - RUNTIME DESTINATION bin - ) - ENDIF(NCURSES_H) - ELSE(CURSES_FOUND) - MESSAGE(STATUS "Wide-character ncurses library not found - vainlook can't be built") - ENDIF(CURSES_FOUND) -ENDIF(UNIX) +# ADD_EXECUTABLE(dfcatsplosion catsplosion.cpp) +# TARGET_LINK_LIBRARIES(dfcatsplosion dfhack) + +# IF(UNIX) +# SET(CURSES_NEED_WIDE "YES") +# SET(CURSES_NEED_NCURSES "YES") +# find_package(Curses) +# +# IF(CURSES_FOUND) +# if(CURSES_HAVE_NCURSESW_NCURSES_H) +# SET(NCURSES_H "ncursesw/ncurses.h") +# elseif(CURSES_HAVE_NCURSESW_CURSES_H) +# SET(NCURSES_H "ncursesw/curses.h") +# elseif(CURSES_HAVE_NCURSESW_H) +# SET(NCURSES_H "ncursesw.h") +# elseif(CURSES_HAVE_CURSESW_H) +# SET(NCURSES_H "cursesw.h") +# endif(CURSES_HAVE_NCURSESW_NCURSES_H) +# IF(NCURSES_H) +# # OPTION( VARIABLE "Description" Initial state) +# #OPTION( WITH_FOO "Enable FOO support" ON ) +# #OPTION( WITH_BAR "Enable BAR component" OFF ) +# #SET( BAZ 18 ) +# CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/fake-curses.h.cmake ${CMAKE_CURRENT_SOURCE_DIR}/fake-curses.h ) +# +# # veinlook - look at the map... sort of +# ADD_EXECUTABLE(dfveinlook veinlook.cpp) +# INCLUDE_DIRECTORIES(${CURSES_INCLUDE_DIR}) +# TARGET_LINK_LIBRARIES(dfveinlook dfhack ${CURSES_LIBRARIES}) +# install(TARGETS +# dfveinlook +# RUNTIME DESTINATION bin +# ) +# ENDIF(NCURSES_H) +# ELSE(CURSES_FOUND) +# MESSAGE(STATUS "Wide-character ncurses library not found - vainlook can't be built") +# ENDIF(CURSES_FOUND) +# ENDIF(UNIX) # renamer - change the custom names and professions of creatures, sends keys to # df directly # Author: belal -ADD_EXECUTABLE(dfrenamer renamer.cpp) -TARGET_LINK_LIBRARIES(dfrenamer dfhack) +#ADD_EXECUTABLE(dfrenamer renamer.cpp) +#TARGET_LINK_LIBRARIES(dfrenamer dfhack) IF(UNIX) install(TARGETS dfattachtest -dfexpbench -dfcreaturedump -dfbuildingsdump +#dfexpbench +#dfcreaturedump +#dfbuildingsdump dfmaterialtest dfposition dfsuspend -dfitemdump -dfhotkeynotedump +#dfitemdump +#dfhotkeynotedump #dffindnameindexes -dfsettlementdump -dfrenamer -#dfvecc -dfcatsplosion +#dfsettlementdump +#dfrenamer +dfvecc +#dfcatsplosion RUNTIME DESTINATION bin ) ENDIF(UNIX) \ No newline at end of file diff --git a/examples/materialtest.cpp b/examples/materialtest.cpp index 2337b3fc9..ba82b2f87 100644 --- a/examples/materialtest.cpp +++ b/examples/materialtest.cpp @@ -1,15 +1,51 @@ +// Just show some position data + #include #include #include #include +#include #include using namespace std; #include #include +#include +#include +#include -int main (void) +void DumpObjStr0Vector (const char * name, DFHack::Process *p, uint32_t addr) { + cout << "----==== " << name << " ====----" << endl; + DFHack::DfVector vect(p,addr,4); + for(int i = 0; i < vect.getSize();i++) + { + uint32_t addr = *(uint32_t *) vect[i]; + cout << p->readSTLString(addr) << endl; + } + cout << endl; +} + +void DumpDWordVector (const char * name, DFHack::Process *p, uint32_t addr) +{ + cout << "----==== " << name << " ====----" << endl; + DFHack::DfVector vect(p,addr,4); + for(int i = 0; i < vect.getSize();i++) + { + uint32_t number = *(uint32_t *) vect[i]; + cout << number << endl; + } + cout << endl; +} + +int main (int numargs, const char ** args) +{ + uint32_t addr; + if (numargs == 2) + { + istringstream input (args[1],istringstream::in); + input >> std::hex >> addr; + } DFHack::API DF("Memory.xml"); try { @@ -24,48 +60,40 @@ int main (void) return 1; } - if(!DF.InitMap()) - { - cerr << "No map loaded, it would be unsafe to enumerate materials" << endl; - #ifndef LINUX_BUILD - cin.ignore(); - #endif - return 1; - } - DF.DestroyMap(); + DFHack::Process* p = DF.getProcess(); + DFHack::memory_info* mem = DF.getMemoryInfo(); + //const vector * names = mem->getClassIDMapping(); - vector Woods; - DF.ReadWoodMatgloss(Woods); + DumpObjStr0Vector("Material templates",p, mem->getAddress("mat_templates")); - vector Plants; - DF.ReadPlantMatgloss(Plants); + DumpObjStr0Vector("Inorganics",p, mem->getAddress("mat_inorganics")); - vector Metals; - DF.ReadMetalMatgloss(Metals); + DumpObjStr0Vector("Organics - all",p, mem->getAddress("mat_organics_all")); - vector Stones; - DF.ReadStoneMatgloss(Stones); + DumpObjStr0Vector("Organics - plants",p, mem->getAddress("mat_organics_plants")); - vector CreatureTypes; - DF.ReadCreatureMatgloss(CreatureTypes); + DumpDWordVector("Maybe map between all organics and plants",p, mem->getAddress("mat_unk1_numbers")); + + DumpObjStr0Vector("Trees/wood",p, mem->getAddress("mat_organics_trees")); + + DumpDWordVector("Maybe map between all organics and trees",p, mem->getAddress("mat_unk2_numbers")); + + DumpObjStr0Vector("Body material templates",p, mem->getAddress("mat_body_material_templates")); + + DumpObjStr0Vector("Body detail plans",p, mem->getAddress("mat_body_detail_plans")); + + DumpObjStr0Vector("Bodies",p, mem->getAddress("mat_bodies")); + + DumpObjStr0Vector("Bodygloss",p, mem->getAddress("mat_bodygloss")); + + DumpObjStr0Vector("Creature variations",p, mem->getAddress("mat_creature_variations")); + + DumpObjStr0Vector("Creature types",p, mem->getAddress("mat_creature_types")); - cout << "Wood: " << Woods[0].id << endl; - cout << "Plant: " << Plants[0].id << endl; - cout << "Metal: " << Metals[0].id << endl; - cout << "Stone: " << Stones[0].id << endl; - cout << "Creature: " << CreatureTypes[0].id << endl; - cout << endl; - cout << "Dumping all stones!" << endl; - for(uint32_t i = 0; i < Stones.size();i++) - { - cout << Stones[i].id << "$" << endl;; - } - DF.Detach(); #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); #endif - return 0; } diff --git a/examples/position.cpp b/examples/position.cpp index 05bcc4b87..a2120bac7 100644 --- a/examples/position.cpp +++ b/examples/position.cpp @@ -29,27 +29,20 @@ int main (void) if (DF.InitViewAndCursor()) { int32_t x,y,z; + int32_t width,height; + if(DF.getViewCoords(x,y,z)) cout << "view coords: " << x << "/" << y << "/" << z << endl; if(DF.getCursorCoords(x,y,z)) cout << "cursor coords: " << x << "/" << y << "/" << z << endl; + if(DF.getWindowSize(width,height)) + cout << "window size : " << width << " " << height << endl; } else { cerr << "cursor and window parameters are unsupported on your version of DF" << endl; } - if(DF.InitViewSize()) - { - int32_t width,height; - if(DF.getWindowSize(width,height)) - cout << "window size : " << width << " " << height << endl; - } - else - { - cerr << "view size is unsupported on your version of DF" << endl; - } - if(!DF.Detach()) { cerr << "Can't detach from DF" << endl; diff --git a/output/Memory.xml b/output/Memory.xml index b38aaa0c1..f4c52240e 100644 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -3098,7 +3098,7 @@ Map stuff =========
0x016AD718
- 0x10 + 0x08 0x0092 0x029C