diff --git a/data/Memory.xml b/data/Memory.xml
index fd0072623..3b50deb28 100644
--- a/data/Memory.xml
+++ b/data/Memory.xml
@@ -1721,6 +1721,7 @@ map_data_1b60_offset 0x1B9c
f0459165a426a9f2dd8d957e9fa7f01d
0x4C4C32E7
+ 0x18313D0
.-"""-.
' \
diff --git a/library/modules/Position.cpp b/library/modules/Position.cpp
index ab3fccba3..5443370bc 100644
--- a/library/modules/Position.cpp
+++ b/library/modules/Position.cpp
@@ -177,7 +177,8 @@ bool Position::getScreenTiles (int32_t width, int32_t height, t_screen screen[])
if(!d->StartedScreen) return false;
uint32_t screen_addr;
- d->owner->read (d->screen_tiles_ptr_offset, sizeof(uint32_t), (uint8_t *) screen_addr);
+ d->owner->readDWord(d->screen_tiles_ptr_offset,(uint32_t &) screen_addr);
+ //d->owner->read (d->screen_tiles_ptr_offset, sizeof(uint32_t), (uint8_t *) screen_addr);
uint8_t* tiles = new uint8_t[width*height*4/* + 80 + width*height*4*/];
@@ -187,12 +188,12 @@ bool Position::getScreenTiles (int32_t width, int32_t height, t_screen screen[])
{
for(int32_t ix=0; ix
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DFHACK_WANT_MISCUTILS
+#define DFHACK_WANT_TILETYPES
+#include
+#include "dfhack/modules/WindowIO.h"
+
+using namespace DFHack;
+//bool waitTillCursorState(DFHack::Context *DF, bool On);
+//bool waitTillCursorPositionState(DFHack::Context *DF, int32_t x,int32_t y, int32_t z);
+
+//change this if you are having problems getting correct results, lower if you would like to go faster
+//const int WAIT_AMT = 25;
+
+void sort(uint32_t &a,uint32_t &b)
+{
+ if(a > b){
+ uint32_t c = b;
+ b = a;
+ a = c;
+ }
+}
+void sort(int32_t &a,int32_t &b)
+{
+ if(a > b){
+ int16_t c = b;
+ b = a;
+ a = c;
+ }
+}
+void printVecOfVec(ostream &out, vector > >vec,char sep){
+ for(int k=0;k buildCommands;
+ buildCommands["building_stockpilest"]="";
+ buildCommands["building_zonest"]="";
+ buildCommands["building_construction_blueprintst"]="";
+ buildCommands["building_wagonst"]="";
+ buildCommands["building_armor_standst"]="a";
+ buildCommands["building_bedst"]="b";
+ buildCommands["building_seatst"]="c";
+ buildCommands["building_burial_receptaclest"]="n";
+ buildCommands["building_doorst"]="d";
+ buildCommands["building_floodgatest"]="x";
+ buildCommands["building_floor_hatchst"]="H";
+ buildCommands["building_wall_gratest"]="W";
+ buildCommands["building_floor_gratest"]="G";
+ buildCommands["building_vertical_barsst"]="B";
+ buildCommands["building_floor_barsst"]="alt-b";
+ buildCommands["building_cabinetst"]="f";
+ buildCommands["building_containerst"]="h";
+ buildCommands["building_shopst"]="";
+ buildCommands["building_workshopst"]="";
+ buildCommands["building_alchemists_laboratoryst"]="wa";
+ buildCommands["building_carpenters_workshopst"]="wc";
+ buildCommands["building_farmers_workshopst"]="ww";
+ buildCommands["building_masons_workshopst"]="wm";
+ buildCommands["building_craftdwarfs_workshopst"]="wr";
+ buildCommands["building_jewelers_workshopst"]="wj";
+ buildCommands["building_metalsmiths_workshopst"]="wf";
+ buildCommands["building_magma_forgest"]="";
+ buildCommands["building_bowyers_workshopst"]="wb";
+ buildCommands["building_mechanics_workshopst"]="wt";
+ buildCommands["building_siege_workshopst"]="ws";
+ buildCommands["building_butchers_shopst"]="wU";
+ buildCommands["building_leather_worksst"]="we";
+ buildCommands["building_tanners_shopst"]="wn";
+ buildCommands["building_clothiers_shopst"]="wk";
+ buildCommands["building_fisheryst"]="wh";
+ buildCommands["building_stillst"]="wl";
+ buildCommands["building_loomst"]="wo";
+ buildCommands["building_quernst"]="wq";
+ buildCommands["building_kennelsst"]="k";
+ buildCommands["building_kitchenst"]="wz";
+ buildCommands["building_asheryst"]="wy";
+ buildCommands["building_dyers_shopst"]="wd";
+ buildCommands["building_millstonest"]="wM";
+ buildCommands["building_farm_plotst"]="p";
+ buildCommands["building_weapon_rackst"]="r";
+ buildCommands["building_statuest"]="s";
+ buildCommands["building_tablest"]="t";
+ buildCommands["building_paved_roadst"]="o";
+ buildCommands["building_bridgest"]="g";
+ buildCommands["building_wellst"]="l";
+ buildCommands["building_siege enginest"]="i";
+ buildCommands["building_catapultst"]="ic";
+ buildCommands["building_ballistast"]="ib";
+ buildCommands["building_furnacest"]="";
+ buildCommands["building_wood_furnacest"]="ew";
+ buildCommands["building_smelterst"]="es";
+ buildCommands["building_glass_furnacest"]="ek";
+ buildCommands["building_kilnst"]="ek";
+ buildCommands["building_magma_smelterst"]="es";
+ buildCommands["building_magma_glass_furnacest"]="ek";
+ buildCommands["building_magma_kilnst"]="ek";
+ buildCommands["building_glass_windowst"]="y";
+ buildCommands["building_gem_windowst"]="Y";
+ buildCommands["building_tradedepotst"]="D";
+ buildCommands["building_mechanismst"]="";
+ buildCommands["building_leverst"]="Tl";
+ buildCommands["building_pressure_platest"]="Tp";
+ buildCommands["building_cage_trapst"]="Tc";
+ buildCommands["building_stonefall_trapst"]="Ts";
+ buildCommands["building_weapon_trapst"]="Tw";
+ buildCommands["building_spikest"]="";
+ buildCommands["building_animal_trapst"]="m";
+ buildCommands["building_screw_pumpst"]="Ms";
+ buildCommands["building_water_wheelst"]="Mw";
+ buildCommands["building_windmillst"]="Mm";
+ buildCommands["building_gear_assemblyst"]="Mg";
+ buildCommands["building_horizontal_axlest"]="Mh";
+ buildCommands["building_vertical_axlest"]="Mv";
+ buildCommands["building_supportst"]="S";
+ buildCommands["building_cagest"]="j";
+ buildCommands["building_archery_targetst"]="A";
+ buildCommands["building_restraintst"]="v";
+
+ DFHack::ContextManager DFMgr("Memory.xml");
+ DFHack::Context *DF = DFMgr.getSingleContext();
+
+ try
+ {
+ DF->Attach();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ #ifndef LINUX_BUILD
+ cin.ignore();
+ #endif
+ return 1;
+ }
+
+ DFHack::Position *Pos = DF->getPosition();
+ DFHack::memory_info* mem = DF->getMemoryInfo();
+ DFHack::Process * p = DF->getProcess();
+ uint32_t designations = mem->getOffset("map_data_designation");
+ uint32_t block_feature1 = mem->getOffset("map_data_feature_local");
+ uint32_t block_feature2 = mem->getOffset("map_data_feature_global");
+ uint32_t region_x_offset = mem->getAddress("region_x");
+ uint32_t region_y_offset = mem->getAddress("region_y");
+ uint32_t region_z_offset = mem->getAddress("region_z");
+ uint32_t feature1_start_ptr = mem->getAddress("local_feature_start_ptr");
+ int32_t regionX, regionY, regionZ;
+
+ // read position of the region inside DF world
+ p->readDWord (region_x_offset, (uint32_t &)regionX);
+ p->readDWord (region_y_offset, (uint32_t &)regionY);
+ p->readDWord (region_z_offset, (uint32_t &)regionZ);
+ while(1){
+ int32_t cx1,cy1,cz1;
+ cx1 = -30000;
+ while(cx1 == -30000){
+ DF->ForceResume();
+ cout << "Set cursor at first position, then press any key";
+ cin.ignore();
+ DF->Suspend();
+ Pos->getCursorCoords(cx1,cy1,cz1);
+ }
+
+ uint32_t tx1,ty1,tz1;
+ tx1 = cx1/16;
+ ty1 = cy1/16;
+ tz1 = cz1;
+
+ int32_t cx2,cy2,cz2;
+ cx2 = -30000;
+ while(cx2 == -30000){
+ DF->Resume();
+ cout << "Set cursor at second position, then press any key";
+ cin.ignore();
+ DF->Suspend();
+ Pos->getCursorCoords(cx2,cy2,cz2);
+ }
+ uint32_t tx2,ty2,tz2;
+ tx2 = cx2/16;
+ ty2 = cy2/16;
+ tz2 = cz2;
+ sort(tx1,tx2);
+ sort(ty1,ty2);
+ sort(tz1,tz2);
+ sort(cx1,cx2);
+ sort(cy1,cy2);
+ sort(cz1,cz2);
+
+ vector > >dig(cz2-cz1+1,vector >(cy2-cy1+1,vector(cx2-cx1+1)));
+ vector > >build(cz2-cz1+1,vector >(cy2-cy1+1,vector(cx2-cx1+1)));
+ mapblock40d block;
+ DFHack::Maps *Maps = DF->getMaps();
+ Maps->Start();
+ for(uint32_t y = ty1;y<=ty2;y++)
+ {
+ for(uint32_t x = tx1;x<=tx2;x++)
+ {
+ for(uint32_t z = tz1;z<=tz2;z++)
+ {
+ if(Maps->isValidBlock(x,y,z))
+ {
+ if(Maps->ReadBlock40d(x,y,z,&block))
+ {
+ int ystart,yend,xstart,xend;
+ ystart=xstart=0;
+ yend=xend=15;
+ if(y == ty2)
+ {
+ yend = cy2 % 16;
+ }
+ if(y == ty1)
+ {
+ ystart = cy1 % 16;
+ }
+ if(x == tx2)
+ {
+ xend = cx2 % 16;
+ }
+ if(x == tx1)
+ {
+ xstart = cx1 % 16;
+ }
+ int zidx = z-tz1;
+ for(int yy = ystart; yy <= yend;yy++)
+ {
+ int yidx = yy+(16*(y-ty1)-(cy1%16));
+ for(int xx = xstart; xx <= xend;xx++)
+ {
+ int xidx = xx+(16*(x-tx1)-(cx1%16));
+ if(DFHack::isOpenTerrain(block.tiletypes[xx][yy]) || DFHack::isFloorTerrain(block.tiletypes[xx][yy])) {dig[zidx][yidx][xidx] = "d";}
+ else if(DFHack::STAIR_DOWN == DFHack::tileTypeTable[block.tiletypes[xx][yy]].c){ dig [zidx][yidx][xidx] = "j"; build [zidx][yidx][xidx] = "Cd";}
+ else if(DFHack::STAIR_UP == DFHack::tileTypeTable[block.tiletypes[xx][yy]].c){ dig [zidx][yidx][xidx] = "u"; build [zidx][yidx][xidx] = "Cu";}
+ else if(DFHack::STAIR_UPDOWN == DFHack::tileTypeTable[block.tiletypes[xx][yy]].c){ dig [zidx][yidx][xidx] = "i"; build [zidx][yidx][xidx] = "Cx";}
+ else if(DFHack::isRampTerrain(block.tiletypes[xx][yy])){dig [zidx][yidx][xidx] = "r";build [zidx][yidx][xidx] = "Cr";}
+ else if(DFHack::isWallTerrain(block.tiletypes[xx][yy])){build [zidx][yidx][xidx] = "Cw";}
+ }
+ yidx++;
+ }
+ }
+ }
+ }
+ }
+ }
+ DFHack::Buildings * Bld = DF->getBuildings();
+ std::map custom_workshop_types;
+ uint32_t numBuildings;
+ if(Bld->Start(numBuildings))
+ {
+ Bld->ReadCustomWorkshopTypes(custom_workshop_types);
+ for(uint32_t i = 0; i < numBuildings; i++)
+ {
+ DFHack::t_building temp;
+ Bld->Read(i, temp);
+ if(temp.type != 0xFFFFFFFF) // check if type isn't invalid
+ {
+ std::string typestr;
+ mem->resolveClassIDToClassname(temp.type, typestr);
+ if(temp.z == cz1 && cx1 <= temp.x1 && cx2 >= temp.x2 && cy1 <= temp.y1 && cy2 >= temp.y2)
+ {
+ string currStr = build[temp.z-cz1][temp.y1-cy1][temp.x1-cx1];
+ stringstream stream;
+ string newStr = buildCommands[typestr];
+ if(temp.x1 != temp.x2)
+ {
+ stream << "(" << temp.x2-temp.x1+1 << "x" << temp.y2-temp.y1+1 << ")";
+ newStr += stream.str();
+ }
+ build[temp.z-cz1][temp.y1-cy1][temp.x1-cx1] = newStr + currStr;
+ }
+ }
+ }
+ }
+// for testing purposes
+ //ofstream outfile("test.txt");
+// printVecOfVec(outfile, dig,'\t');
+// outfile << endl;
+// printVecOfVec(outfile, build,'\t');
+// outfile << endl;
+// outfile.close();
+
+ int32_t cx3,cy3,cz3,cx4,cy4,cz4;
+ uint32_t tx3,ty3,tz3,tx4,ty4,tz4;
+ char result;
+ while(1){
+ cx3 = -30000;
+ while(cx3 == -30000){
+ DF->Resume();
+ cout << "Set cursor at new position, then press any key:";
+ result = cin.get();
+ DF->Suspend();
+ Pos->getCursorCoords(cx3,cy3,cz3);
+ }
+ if(result == 'q'){
+ break;
+ }
+ cx4 = cx3+cx2-cx1;
+ cy4 = cy3+cy2-cy1;
+ cz4 = cz3+cz2-cz1;
+ tx3=cx3/16;
+ ty3=cy3/16;
+ tz3=cz3;
+ tx4=cx4/16;
+ ty4=cy4/16;
+ tz4=cz4;
+ DFHack::WindowIO * Win = DF->getWindowIO();
+ designations40d designationBlock;
+ for(uint32_t y = ty3;y<=ty4;y++)
+ {
+ for(uint32_t x = tx3;x<=tx4;x++)
+ {
+ for(uint32_t z = tz3;z<=tz4;z++)
+ {
+ Maps->Start();
+ Maps->ReadBlock40d(x,y,z,&block);
+ Maps->ReadDesignations(x,y,z,&designationBlock);
+ int ystart,yend,xstart,xend;
+ ystart=xstart=0;
+ yend=xend=15;
+ if(y == ty4){
+ yend = cy4 % 16;
+ }
+ if(y == ty3){
+ ystart = cy3 % 16;
+ }
+ if(x == tx4){
+ xend = cx4 % 16;
+ }
+ if(x == tx3){
+ xstart = cx3 % 16;
+ }
+ int zidx = z-tz3;
+ for(int yy = ystart; yy <= yend;yy++){
+ int yidx = yy+(16*(y-ty3)-(cy3%16));
+ for(int xx = xstart; xx <= xend;xx++){
+ int xidx = xx+(16*(x-tx3)-(cx3%16));
+ if(dig[zidx][yidx][xidx] != ""){
+ char test = dig[zidx][yidx][xidx].c_str()[0];
+ switch (test){
+ case 'd':
+ designationBlock[xx][yy].bits.dig = DFHack::designation_default;
+ break;
+ case 'i':
+ designationBlock[xx][yy].bits.dig = DFHack::designation_ud_stair;
+ break;
+ case 'u':
+ designationBlock[xx][yy].bits.dig = DFHack::designation_u_stair;
+ break;
+ case 'j':
+ designationBlock[xx][yy].bits.dig = DFHack::designation_d_stair;
+ break;
+ case 'r':
+ designationBlock[xx][yy].bits.dig = DFHack::designation_ramp;
+ break;
+ }
+
+ }
+ }
+ yidx++;
+ }
+ Maps->Start();
+ Maps->WriteDesignations(x,y,z,&designationBlock);
+ }
+ }
+ }
+ }
+ }
+ DF->Detach();
+ #ifndef LINUX_BUILD
+ std::cout << "Done. Press any key to continue" << std::endl;
+ cin.ignore();
+ #endif
+ return 0;
+}
+/*
+bool waitTillCursorState(DFHack::Context *DF, bool On)
+{
+ DFHack::WindowIO * w = DF->getWindowIO();
+ DFHack::Position * p = DF->getPosition();
+ int32_t x,y,z;
+ int tryCount = 0;
+ DF->Suspend();
+ bool cursorResult = p->getCursorCoords(x,y,z);
+ while(tryCount < 50 && On && !cursorResult || !On && cursorResult)
+ {
+ DF->Resume();
+ w->TypeSpecial(DFHack::WAIT,1,WAIT_AMT);
+ tryCount++;
+ DF->Suspend();
+ cursorResult = p->getCursorCoords(x,y,z);
+ }
+ if(tryCount >= 50)
+ {
+ cerr << "Something went wrong, cursor at x: " << x << " y: " << y << " z: " << z << endl;
+ return false;
+ }
+ DF->Resume();
+ return true;
+}
+bool waitTillCursorPositionState(DFHack::Context *DF, int32_t x,int32_t y, int32_t z)
+{
+ DFHack::WindowIO * w = DF->getWindowIO();
+ DFHack::Position * p = DF->getPosition();
+ int32_t x2,y2,z2;
+ int tryCount = 0;
+ DF->Suspend();
+ bool cursorResult = p->getCursorCoords(x2,y2,z2);
+ while(tryCount < 50 && (x != x2 || y != y2 || z != z2))
+ {
+ DF->Resume();
+ w->TypeSpecial(DFHack::WAIT,1,WAIT_AMT);
+ tryCount++;
+ DF->Suspend();
+ cursorResult = p->getCursorCoords(x2,y2,z2);
+ }
+ if(tryCount >= 50)
+ {
+ cerr << "Something went wrong, cursor at x: " << x2 << " y: " << y2 << " z: " << z2 << endl;
+ return false;
+ }
+ DF->Resume();
+ return true;
+}*/
\ No newline at end of file