diff --git a/Memory.xml b/Memory.xml
index 1639ff148..f3dff230b 100644
--- a/Memory.xml
+++ b/Memory.xml
@@ -803,8 +803,8 @@
+
-
@@ -1127,8 +1127,6 @@
-
-
@@ -1307,7 +1305,6 @@
constructions 0xffffffff
creatures 0x0166eccc
current_cursor_creature 0x00ae82cc
- current_menu_state 0x017f6f38
cursor_xyz 0x0166ecd4
effects_vector 0x017f6da0
hotkey_start 0x01476ecc
@@ -1323,7 +1320,6 @@
settlement_current 0xffffffff
settlements 0x016af4a4
translation_vector 0x016b0010
- view_screen 0xffffffff
window_dims 0x017f5abc
window_x 0x00e32798
window_y 0x00e60838
@@ -3019,6 +3015,8 @@
WORLD: 0x93f77a0
+
+
Maybe, possibly.
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 3a5b4a4b7..eb6136312 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -20,6 +20,7 @@ SET(PROJECT_HDRS
include/DFHack.h
include/dfhack/Error.h
include/dfhack/Export.h
+include/dfhack/Virtual.h
include/dfhack/MiscUtils.h
include/dfhack/Module.h
include/dfhack/Pragma.h
@@ -53,6 +54,7 @@ PluginManager.cpp
VersionInfo.cpp
VersionInfoFactory.cpp
TileTypes.cpp
+Virtual.cpp
depends/md5/md5.cpp
depends/md5/md5wrapper.cpp
diff --git a/library/Core.cpp b/library/Core.cpp
index b67c207c2..761122939 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -38,14 +38,14 @@ using namespace std;
#include "dfhack/Process.h"
#include "dfhack/Core.h"
#include "dfhack/Console.h"
+#include "dfhack/Module.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/PluginManager.h"
#include "ModuleFactory.h"
-
#include "dfhack/modules/Gui.h"
-#include "dfhack/modules/Vegetation.h"
-#include "dfhack/modules/Maps.h"
-#include "dfhack/modules/World.h"
+
+#include "dfhack/SDL_fakes/events.h"
+
#include
#include
using namespace DFHack;
@@ -63,11 +63,41 @@ struct IODATA
PluginManager * plug_mgr;
};
+// A thread function... for handling hotkeys. This is needed because
+// all the plugin commands are expected to be run from foreign threads.
+// Running them from one of the main DF threads will result in deadlock!
+int fHKthread(void * iodata)
+{
+ Core * core = ((IODATA*) iodata)->core;
+ PluginManager * plug_mgr = ((IODATA*) iodata)->plug_mgr;
+ if(plug_mgr == 0 || core == 0)
+ {
+ cerr << "Hotkey thread has croaked." << endl;
+ return 0;
+ }
+ while(1)
+ {
+ std::string stuff = core->getHotkeyCmd(); // waits on mutex!
+ if(!stuff.empty())
+ {
+ vector crap;
+ plug_mgr->InvokeCommand(stuff, crap);
+ }
+ }
+}
+
+// A thread function... for the interactive console.
+static bool flip0 = false;
int fIOthread(void * iodata)
{
+ if(!flip0)
+ {
+ std::cerr << "Console from Thread " << SDL_ThreadID() << std::endl;
+ flip0 = true;
+ }
Core * core = ((IODATA*) iodata)->core;
PluginManager * plug_mgr = ((IODATA*) iodata)->plug_mgr;
- if(plug_mgr == 0)
+ if(plug_mgr == 0 || core == 0)
{
dfout << "Something horrible happened to the plugin manager in Core's constructor..." << std::endl;
return 0;
@@ -140,8 +170,34 @@ int fIOthread(void * iodata)
Core::Core()
{
// init the console. This must be always the first step!
- con = new Console();
+ con = 0;
plug_mgr = 0;
+ vif = 0;
+ p = 0;
+ errorstate = false;
+ vinfo = 0;
+ started = false;
+ memset(&(s_mods), 0, sizeof(s_mods));
+
+ // create mutex for syncing with interactive tasks
+ AccessMutex = 0;
+ // set up hotkey capture
+ memset(hotkey_states,0,sizeof(hotkey_states));
+ hotkey_set = false;
+ HotkeyMutex = 0;
+ HotkeyCond = 0;
+};
+
+static bool flip1 = 0;
+bool Core::Init()
+{
+ // init the console. This must be always the first step!
+ con = new Console();
+ if(!flip1)
+ {
+ std::cerr << "Construct from Thread " << SDL_ThreadID() << std::endl;
+ flip1 = true;
+ }
// find out what we are...
vif = new DFHack::VersionInfoFactory("Memory.xml");
p = new DFHack::Process(vif);
@@ -151,36 +207,71 @@ Core::Core()
errorstate = true;
delete p;
p = NULL;
- return;
+ return false;
}
vinfo = p->getDescriptor();
- // init module storage
- allModules.clear();
- memset(&(s_mods), 0, sizeof(s_mods));
-
// create mutex for syncing with interactive tasks
AccessMutex = SDL_CreateMutex();
if(!AccessMutex)
{
dfout << "Mutex creation failed." << std::endl;
errorstate = true;
- return;
+ return false;
}
- // all OK
- errorstate = false;
// lock mutex
SDL_mutexP(AccessMutex);
+
+ // create plugin manager
plug_mgr = new PluginManager(this);
+ if(!plug_mgr)
+ {
+ dfout << "Failed to create the Plugin Manager." << std::endl;
+ errorstate = true;
+ return false;
+ }
// look for all plugins,
// create IO thread
IODATA *temp = new IODATA;
temp->core = this;
temp->plug_mgr = plug_mgr;
- DFThread * IO = SDL_CreateThread(fIOthread, (void *) temp);
- delete temp;
- // and let DF do its thing.
-};
+ SDL::Thread * IO = SDL_CreateThread(fIOthread, (void *) temp);
+ // set up hotkey capture
+ HotkeyMutex = SDL_CreateMutex();
+ HotkeyCond = SDL_CreateCond();
+ SDL::Thread * HK = SDL_CreateThread(fHKthread, (void *) temp);
+ started = true;
+ return true;
+}
+/// sets the current hotkey command
+bool Core::setHotkeyCmd( std::string cmd )
+{
+ // access command
+ SDL_mutexP(HotkeyMutex);
+ {
+ hotkey_set = true;
+ hotkey_cmd = cmd;
+ SDL_CondSignal(HotkeyCond);
+ }
+ SDL_mutexV(HotkeyMutex);
+ return true;
+}
+/// removes the hotkey command and gives it to the caller thread
+std::string Core::getHotkeyCmd( void )
+{
+ string returner;
+ SDL_mutexP(HotkeyMutex);
+ while ( ! hotkey_set )
+ {
+ SDL_CondWait(HotkeyCond, HotkeyMutex);
+ }
+ hotkey_set = false;
+ returner = hotkey_cmd;
+ hotkey_cmd.clear();
+ SDL_mutexV(HotkeyMutex);
+ return returner;
+}
+
void Core::Suspend()
{
@@ -198,10 +289,18 @@ void Core::Resume()
SDL_mutexV(AccessMutex);
}
+// should always be from simulation thread!
+static bool flip2 = false;
int Core::Update()
{
+ if(!started) Init();
if(errorstate)
return -1;
+ if(!flip2)
+ {
+ std::cerr << "Update from Thread " << SDL_ThreadID() << std::endl;
+ flip2 = true;
+ }
// notify all the plugins that a game tick is finished
plug_mgr->OnUpdate();
SDL_mutexV(AccessMutex);
@@ -228,20 +327,58 @@ int Core::Shutdown ( void )
memset(&(s_mods), 0, sizeof(s_mods));
dfout << std::endl;
// kill the console object
- delete con;
+ if(con)
+ delete con;
con = 0;
return -1;
}
-void Core::SDL_Event(FakeSDL::Event* event)
+static bool flip3 = 0;
+int Core::SDL_Event(SDL::Event* ev, int orig_return)
{
- if(!event)
- return;
- if(event->type == FakeSDL::ET_KEYDOWN)
+ // do NOT process events before we are ready.
+ if(!started) return orig_return;
+ if(!flip3)
+ {
+ std::cerr << "Event from Thread " << SDL_ThreadID() << std::endl;
+ flip3 = true;
+ }
+ if(!ev)
+ return orig_return;
+ if(ev && ev->type == SDL::ET_KEYDOWN || ev->type == SDL::ET_KEYUP)
{
- FakeSDL::KeyboardEvent * kev = (FakeSDL::KeyboardEvent *) event;
- cerr << "Key " << kev->ksym.sym << std::endl;
+ SDL::KeyboardEvent * ke = (SDL::KeyboardEvent *)ev;
+ bool shift = ke->ksym.mod & SDL::KMOD_SHIFT;
+ // consuming F1 .. F8
+ int idx = ke->ksym.sym - SDL::K_F1;
+ if(idx < 0 || idx > 7)
+ return orig_return;
+ idx += 8*shift;
+ // now we have the real index...
+ if(ke->state == SDL::BTN_PRESSED && !hotkey_states[idx])
+ {
+ hotkey_states[idx] = 1;
+ Gui * g = getGui();
+ if(g->hotkeys && g->interface && g->menu_state)
+ {
+ t_viewscreen * ws = g->GetCurrentScreen();
+ if(ws->getClassName() == "viewscreen_dwarfmodest" && *g->menu_state == 0x23)
+ return orig_return;
+ else
+ {
+ std::cerr << "Hotkey " << idx << " triggered. Thread " << SDL_ThreadID() << std::endl;
+ t_hotkey & hotkey = (*g->hotkeys)[idx];
+ setHotkeyCmd(hotkey.name);
+ }
+ }
+ }
+ else if(ke->state == SDL::BTN_RELEASED)
+ {
+ hotkey_states[idx] = 0;
+ }
}
+ return orig_return;
+ // do stuff with the events...
}
/*******************************************************************************
diff --git a/library/FakeSDL-linux.cpp b/library/FakeSDL-linux.cpp
index cef9557c3..484970dc0 100644
--- a/library/FakeSDL-linux.cpp
+++ b/library/FakeSDL-linux.cpp
@@ -85,7 +85,7 @@ DFhackCExport int SDL_NumJoysticks(void)
//static void (*_SDL_GL_SwapBuffers)(void) = 0;
static void (*_SDL_Quit)(void) = 0;
static int (*_SDL_Init)(uint32_t flags) = 0;
-static DFThread * (*_SDL_CreateThread)(int (*fn)(void *), void *data) = 0;
+static SDL::Thread * (*_SDL_CreateThread)(int (*fn)(void *), void *data) = 0;
//static int (*_SDL_Flip)(void * some_ptr) = 0;
/*
// hook - called every tick in OpenGL mode of DF
@@ -119,26 +119,26 @@ DFhackCExport int SDL_Flip(void * some_ptr)
}
*/
-static DFMutex * (*_SDL_CreateMutex)(void) = 0;
-DFhackCExport DFMutex * SDL_CreateMutex(void)
+static SDL::Mutex * (*_SDL_CreateMutex)(void) = 0;
+DFhackCExport SDL::Mutex * SDL_CreateMutex(void)
{
return _SDL_CreateMutex();
}
-static int (*_SDL_mutexP)(DFMutex * mutex) = 0;
-DFhackCExport int SDL_mutexP(DFMutex * mutex)
+static int (*_SDL_mutexP)(SDL::Mutex * mutex) = 0;
+DFhackCExport int SDL_mutexP(SDL::Mutex * mutex)
{
return _SDL_mutexP(mutex);
}
-static int (*_SDL_mutexV)(DFMutex * mutex) = 0;
-DFhackCExport int SDL_mutexV(DFMutex * mutex)
+static int (*_SDL_mutexV)(SDL::Mutex * mutex) = 0;
+DFhackCExport int SDL_mutexV(SDL::Mutex * mutex)
{
return _SDL_mutexV(mutex);
}
-static void (*_SDL_DestroyMutex)(DFMutex * mutex) = 0;
-DFhackCExport void SDL_DestroyMutex(DFMutex * mutex)
+static void (*_SDL_DestroyMutex)(SDL::Mutex * mutex) = 0;
+DFhackCExport void SDL_DestroyMutex(SDL::Mutex * mutex)
{
_SDL_DestroyMutex(mutex);
}
@@ -155,41 +155,77 @@ DFhackCExport void SDL_Quit(void)
}
// called by DF to check input events
-static int (*_SDL_PollEvent)(FakeSDL::Event* event) = 0;
-DFhackCExport int SDL_PollEvent(FakeSDL::Event* event)
+static int (*_SDL_PollEvent)(SDL::Event* event) = 0;
+DFhackCExport int SDL_PollEvent(SDL::Event* event)
{
- int ret = _SDL_PollEvent(event);
+ int orig_return = _SDL_PollEvent(event);
// only send events to Core after we get first SDL_NumJoysticks call
// DF event loop is possibly polling for SDL events before things get inited properly
// SDL handles it. We don't, because we use some other parts of SDL too.
if(inited && event != 0)
{
DFHack::Core & c = DFHack::Core::getInstance();
- c.SDL_Event(event);
+ return c.SDL_Event(event, orig_return);
}
- return ret;
+ return orig_return;
+}
+
+static uint32_t (*_SDL_ThreadID)(void) = 0;
+DFhackCExport uint32_t SDL_ThreadID()
+{
+ return _SDL_ThreadID();
}
+static SDL::Cond * (*_SDL_CreateCond)(void) = 0;
+DFhackCExport SDL::Cond *SDL_CreateCond(void)
+{
+ return _SDL_CreateCond();
+}
+static void (*_SDL_DestroyCond)(SDL::Cond *) = 0;
+DFhackCExport void SDL_DestroyCond(SDL::Cond *cond)
+{
+ _SDL_DestroyCond(cond);
+}
+static int (*_SDL_CondSignal)(SDL::Cond *) = 0;
+DFhackCExport int SDL_CondSignal(SDL::Cond *cond)
+{
+ return _SDL_CondSignal(cond);
+}
+static int (*_SDL_CondWait)(SDL::Cond *, SDL::Mutex *) = 0;
+DFhackCExport int SDL_CondWait(SDL::Cond *cond, SDL::Mutex * mut)
+{
+ return _SDL_CondWait(cond, mut);
+}
// hook - called at program start, initialize some stuffs we'll use later
DFhackCExport int SDL_Init(uint32_t flags)
{
freopen("stdout.log", "w", stdout);
freopen("stderr.log", "w", stderr);
+ // horrible casts not supported by the C or C++ standards. Only POSIX. Damn you, POSIX.
// find real functions
//_SDL_GL_SwapBuffers = (void (*)( void )) dlsym(RTLD_NEXT, "SDL_GL_SwapBuffers");
_SDL_Init = (int (*)( uint32_t )) dlsym(RTLD_NEXT, "SDL_Init");
//_SDL_Flip = (int (*)( void * )) dlsym(RTLD_NEXT, "SDL_Flip");
_SDL_Quit = (void (*)( void )) dlsym(RTLD_NEXT, "SDL_Quit");
- _SDL_CreateThread = (DFThread* (*)(int (*fn)(void *), void *data))dlsym(RTLD_NEXT, "SDL_CreateThread");
- _SDL_CreateMutex = (DFMutex*(*)())dlsym(RTLD_NEXT,"SDL_CreateMutex");
- _SDL_DestroyMutex = (void (*)(DFMutex*))dlsym(RTLD_NEXT,"SDL_DestroyMutex");
- _SDL_mutexP = (int (*)(DFMutex*))dlsym(RTLD_NEXT,"SDL_mutexP");
- _SDL_mutexV = (int (*)(DFMutex*))dlsym(RTLD_NEXT,"SDL_mutexV");
- _SDL_PollEvent = (int (*)(FakeSDL::Event*))dlsym(RTLD_NEXT,"SDL_PollEvent");
+ _SDL_CreateThread = (SDL::Thread* (*)(int (*fn)(void *), void *data))dlsym(RTLD_NEXT, "SDL_CreateThread");
+ _SDL_CreateMutex = (SDL::Mutex*(*)())dlsym(RTLD_NEXT,"SDL_CreateMutex");
+ _SDL_DestroyMutex = (void (*)(SDL::Mutex*))dlsym(RTLD_NEXT,"SDL_DestroyMutex");
+ _SDL_mutexP = (int (*)(SDL::Mutex*))dlsym(RTLD_NEXT,"SDL_mutexP");
+ _SDL_mutexV = (int (*)(SDL::Mutex*))dlsym(RTLD_NEXT,"SDL_mutexV");
+ _SDL_PollEvent = (int (*)(SDL::Event*))dlsym(RTLD_NEXT,"SDL_PollEvent");
+ _SDL_ThreadID = (uint32_t (*)())dlsym(RTLD_NEXT,"SDL_ThreadID");
+
+ _SDL_CreateCond = (SDL::Cond * (*)())dlsym(RTLD_NEXT,"SDL_CreateCond");
+ _SDL_DestroyCond = (void(*)(SDL::Cond *))dlsym(RTLD_NEXT,"SDL_DestroyCond");
+ _SDL_CondSignal = (int (*)(SDL::Cond *))dlsym(RTLD_NEXT,"SDL_CondSignal");
+ _SDL_CondWait = (int (*)(SDL::Cond *, SDL::Mutex *))dlsym(RTLD_NEXT,"SDL_CondWait");
// check if we got them
- if(_SDL_Init && _SDL_Quit && _SDL_CreateThread && _SDL_CreateMutex && _SDL_DestroyMutex && _SDL_mutexP && _SDL_mutexV)
+ if(_SDL_Init && _SDL_Quit && _SDL_CreateThread
+ && _SDL_CreateMutex && _SDL_DestroyMutex && _SDL_mutexP
+ && _SDL_mutexV && _SDL_PollEvent && _SDL_ThreadID
+ && _SDL_CondSignal && _SDL_CondWait && _SDL_CreateCond && _SDL_DestroyCond)
{
fprintf(stderr,"dfhack: hooking successful\n");
}
diff --git a/library/PluginManager.cpp b/library/PluginManager.cpp
index 85d48a564..be57ca1bd 100644
--- a/library/PluginManager.cpp
+++ b/library/PluginManager.cpp
@@ -170,7 +170,7 @@ PluginManager::~PluginManager()
all_plugins.clear();
}
-Plugin *PluginManager::getPluginByName (const std::string & name)
+const Plugin *PluginManager::getPluginByName (const std::string & name)
{
for(int i = 0; i < all_plugins.size(); i++)
{
diff --git a/library/include/dfhack/Core.h b/library/include/dfhack/Core.h
index cdc192193..7cab16960 100644
--- a/library/include/dfhack/Core.h
+++ b/library/include/dfhack/Core.h
@@ -53,6 +53,9 @@ namespace DFHack
class Console;
class PluginManager;
class Core;
+ class Hotkey;
+ // anon type, pretty much
+ struct DFLibrary;
DFLibrary * OpenPlugin (const char * filename);
void * LookupPlugin (DFLibrary * plugin ,const char * function);
@@ -65,7 +68,7 @@ namespace DFHack
{
friend int ::SDL_NumJoysticks(void);
friend void ::SDL_Quit(void);
- friend int ::SDL_PollEvent(FakeSDL::Event *);
+ friend int ::SDL_PollEvent(SDL::Event *);
public:
/// Get the single Core instance or make one.
static Core& getInstance()
@@ -103,20 +106,25 @@ namespace DFHack
Buildings * getBuildings();
/// get the constructions module
Constructions * getConstructions();
+ /// sets the current hotkey command
+ bool setHotkeyCmd( std::string cmd );
+ /// removes the hotkey command and gives it to the caller thread
+ std::string getHotkeyCmd( void );
DFHack::Process * p;
DFHack::VersionInfo * vinfo;
DFHack::Console * con;
private:
Core();
+ bool Init();
int Update (void);
int Shutdown (void);
- void SDL_Event(FakeSDL::Event* event);
+ int SDL_Event(SDL::Event* event, int orig_return);
Core(Core const&); // Don't Implement
void operator=(Core const&); // Don't implement
bool errorstate;
// mutex for access to DF
- DFMutex * AccessMutex;
+ SDL::Mutex * AccessMutex;
// FIXME: shouldn't be kept around like this
DFHack::VersionInfoFactory * vif;
// Module storage
@@ -136,5 +144,13 @@ namespace DFHack
} s_mods;
std::vector allModules;
DFHack::PluginManager * plug_mgr;
+ // hotkey-related stuff
+ int hotkey_states[16];
+ std::string hotkey_cmd;
+ bool hotkey_set;
+ SDL::Mutex * HotkeyMutex;
+ SDL::Cond * HotkeyCond;
+ // Very important!
+ bool started;
};
}
\ No newline at end of file
diff --git a/library/include/dfhack/FakeSDL.h b/library/include/dfhack/FakeSDL.h
index 5ca3662d4..029ee4484 100644
--- a/library/include/dfhack/FakeSDL.h
+++ b/library/include/dfhack/FakeSDL.h
@@ -32,29 +32,37 @@ distribution.
#include "dfhack/Export.h"
#include
#include
-#include "dfhack/SDL_fakes/events.h"
-#include "dfhack/SDL_fakes/keyboard.h"
-#include "dfhack/SDL_fakes/keysym.h"
// function and variable pointer... we don't try to understand what SDL does here
typedef void * fPtr;
typedef void * vPtr;
-struct DFMutex;
-struct DFThread;
-struct DFLibrary;
+namespace SDL
+{
+ union Event;
+ struct Thread;
+ struct Mutex;
+ struct Cond;
+}
-// mutex and thread functions. We can call these.
-DFhackCExport DFMutex * SDL_CreateMutex(void);
-DFhackCExport int SDL_mutexP(DFMutex *);
-DFhackCExport int SDL_mutexV(DFMutex *);
-DFhackCExport void SDL_DestroyMutex(DFMutex *);
-DFhackCExport DFThread *SDL_CreateThread(int (*fn)(void *), void *data);
+// mutex stuff
+DFhackCExport SDL::Mutex * SDL_CreateMutex(void);
+DFhackCExport int SDL_mutexP(SDL::Mutex *);
+DFhackCExport int SDL_mutexV(SDL::Mutex *);
+DFhackCExport void SDL_DestroyMutex(SDL::Mutex *);
+// thread stuff
+DFhackCExport SDL::Thread *SDL_CreateThread(int (*fn)(void *), void *data);
+DFhackCExport uint32_t SDL_ThreadID();
+// condition variables
+DFhackCExport SDL::Cond *SDL_CreateCond(void);
+DFhackCExport void SDL_DestroyCond(SDL::Cond *cond);
+DFhackCExport int SDL_CondSignal(SDL::Cond *cond);
+DFhackCExport int SDL_CondWait(SDL::Cond *cond, SDL::Mutex * mut);
// these functions are here because they call into DFHack::Core and therefore need to
// be declared as friend functions/known
DFhackCExport int SDL_NumJoysticks(void);
DFhackCExport void SDL_Quit(void);
-DFhackCExport int SDL_PollEvent(FakeSDL::Event* event);
+DFhackCExport int SDL_PollEvent(SDL::Event* event);
/*
// not yet.
DFhackCExport int SDL_Init(uint32_t flags);
diff --git a/library/include/dfhack/PluginManager.h b/library/include/dfhack/PluginManager.h
index 398c62e2f..13ce3484a 100644
--- a/library/include/dfhack/PluginManager.h
+++ b/library/include/dfhack/PluginManager.h
@@ -92,13 +92,15 @@ namespace DFHack
};
class DFHACK_EXPORT PluginManager
{
- public:
+ // PRIVATE METHODS
+ friend class Core;
PluginManager(Core * core);
~PluginManager();
- Plugin *getPluginByName (const std::string & name);
- command_result InvokeCommand( std::string & command, std::vector & parameters);
void OnUpdate( void );
- //FIXME: how do we deal with errors inside DF? Unhandled exceptions are deadly.
+ // PUBLIC METHODS
+ public:
+ const Plugin *getPluginByName (const std::string & name);
+ command_result InvokeCommand( std::string & command, std::vector & parameters );
const Plugin* operator[] (std::size_t index)
{
if(index >= all_plugins.size())
@@ -109,6 +111,7 @@ namespace DFHack
{
return all_plugins.size();
}
+ // DATA
private:
std::map commands;
std::vector all_plugins;
diff --git a/library/include/dfhack/SDL_fakes/events.h b/library/include/dfhack/SDL_fakes/events.h
index 33a337ed2..b8b8b1eb6 100644
--- a/library/include/dfhack/SDL_fakes/events.h
+++ b/library/include/dfhack/SDL_fakes/events.h
@@ -20,10 +20,13 @@
slouken@libsdl.org
*/
+// Fake - only structs. Shamelessly pilfered from the SDL library.
+// Needed for processing its event types without polluting our namespaces with C garbage
+
#pragma once
#include "keyboard.h"
-namespace FakeSDL
+namespace SDL
{
enum ButtonState
{
diff --git a/library/include/dfhack/SDL_fakes/keyboard.h b/library/include/dfhack/SDL_fakes/keyboard.h
index 42cb93763..a49cf2517 100644
--- a/library/include/dfhack/SDL_fakes/keyboard.h
+++ b/library/include/dfhack/SDL_fakes/keyboard.h
@@ -27,7 +27,7 @@
#include "keysym.h"
#include
-namespace FakeSDL
+namespace SDL
{
/** Keysym structure
*
diff --git a/library/include/dfhack/SDL_fakes/keysym.h b/library/include/dfhack/SDL_fakes/keysym.h
index 013a462c6..4f01cfa9c 100644
--- a/library/include/dfhack/SDL_fakes/keysym.h
+++ b/library/include/dfhack/SDL_fakes/keysym.h
@@ -20,9 +20,12 @@
slouken@libsdl.org
*/
+// Fake - only structs. Shamelessly pilfered from the SDL library.
+// Needed for processing its event types without polluting our namespaces with C garbage
+
#pragma once
-namespace FakeSDL
+namespace SDL
{
/** What we really want is a mapping of every raw key on the keyboard.
* To support international keyboards, we use the range 0xA1 - 0xFF
diff --git a/library/include/dfhack/Virtual.h b/library/include/dfhack/Virtual.h
new file mode 100644
index 000000000..11d8bc78d
--- /dev/null
+++ b/library/include/dfhack/Virtual.h
@@ -0,0 +1,35 @@
+/*
+https://github.com/peterix/dfhack
+Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
+
+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.
+*/
+
+#pragma once
+#include
+namespace DFHack
+{
+ /// very generic representation of a virtual class... just the pointer to the vtable.
+ struct t_virtual
+ {
+ void * vptr;
+ std::string getClassName();
+ };
+}
\ No newline at end of file
diff --git a/library/include/dfhack/modules/Gui.h b/library/include/dfhack/modules/Gui.h
index 71263eef7..e11e046c0 100644
--- a/library/include/dfhack/modules/Gui.h
+++ b/library/include/dfhack/modules/Gui.h
@@ -28,6 +28,8 @@ distribution.
#include "dfhack/Export.h"
#include "dfhack/Module.h"
+#include "dfhack/Virtual.h"
+#include
/**
* \defgroup grp_gui query DF's GUI state
@@ -40,13 +42,27 @@ namespace DFHack
/**
* \ingroup grp_gui
*/
- struct t_viewscreen
+ struct t_viewscreen : public t_virtual
{
- int32_t type;
- //There is more info in these objects, but I don't know what it is yet
+ t_viewscreen * child;
+ t_viewscreen * parent;
+ char unk1; // varies
+ char unk2; // state?
};
+ /**
+ * \ingroup grp_gui
+ */
+ struct t_interface
+ {
+ int fps;
+ t_viewscreen view;
+ unsigned int flags; // ?
+ // more crud this way ...
+ };
+
#define NUM_HOTKEYS 16
/**
+ * The hotkey structure
* \ingroup grp_gui
*/
struct t_hotkey
@@ -57,8 +73,10 @@ namespace DFHack
int32_t y;
int32_t z;
};
- typedef t_hotkey hotkey_array[16];
+ typedef t_hotkey hotkey_array[NUM_HOTKEYS];
+
/**
+ * One tile of the screen. Possibly outdated.
* \ingroup grp_gui
*/
struct t_screen
@@ -70,6 +88,7 @@ namespace DFHack
uint8_t gtile;
uint8_t grayscale;
};
+
/**
* The Gui module
* \ingroup grp_modules
@@ -91,6 +110,16 @@ namespace DFHack
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);
+ /*
+ * Gui screens
+ */
+ /// handle to the interface object
+ t_interface * interface;
+ /// Get the current top-level view-screen
+ t_viewscreen * GetCurrentScreen();
+ /// The DF menu state (designation menu ect)
+ uint32_t * menu_state;
+
/*
* Hotkeys (DF's zoom locations)
*/
@@ -105,11 +134,6 @@ namespace DFHack
* Screen tiles
*/
bool getScreenTiles(int32_t width, int32_t height, t_screen screen[]);
-
- /// 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();
private:
struct Private;
diff --git a/library/include/dfhack/modules/Maps.h b/library/include/dfhack/modules/Maps.h
index ba4c44ad3..e88795e47 100644
--- a/library/include/dfhack/modules/Maps.h
+++ b/library/include/dfhack/modules/Maps.h
@@ -34,6 +34,7 @@ distribution.
#include "dfhack/Module.h"
#include "dfhack/modules/Vegetation.h"
#include
+#include "dfhack/Virtual.h"
/**
* \defgroup grp_maps Maps module and its types
@@ -145,10 +146,6 @@ namespace DFHack
uint32_t origin;
};
- struct t_virtual
- {
- void * vptr;
- };
/**
* mineral vein object - bitmap with a material type
* \ingroup grp_maps
diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp
index 6992b9978..1a29e5d43 100644
--- a/library/modules/Gui.cpp
+++ b/library/modules/Gui.cpp
@@ -48,14 +48,9 @@ struct Gui::Private
{
Private()
{
- Started = ViewScreeInited = MenuStateInited = false;
+ Started = false;
StartedScreen = false;
}
- bool ViewScreeInited;
- uint32_t view_screen_offset;
-
- bool MenuStateInited;
- uint32_t current_menu_state_offset;
bool Started;
uint32_t window_x_offset;
@@ -77,6 +72,8 @@ Gui::Gui()
d->owner = c.p;
VersionInfo * mem = c.vinfo;
OffsetGroup * OG_Gui = mem->getGroup("GUI");
+
+ // Setting up hotkeys
try
{
hotkeys = (hotkey_array *) OG_Gui->getAddress("hotkeys");
@@ -85,18 +82,27 @@ Gui::Gui()
{
hotkeys = 0;
};
+
+ // Setting up menu state
try
{
- d->current_menu_state_offset = OG_Gui->getAddress("current_menu_state");
- d->MenuStateInited = true;
+ menu_state = (uint32_t *) OG_Gui->getAddress("current_menu_state");
}
- catch(exception &){};
+ catch(Error::All &)
+ {
+ menu_state = 0;
+ };
+
+ // Setting up the view screen stuff
try
{
- d->view_screen_offset = OG_Gui->getAddress ("view_screen");
- d->ViewScreeInited = true;
+ interface = (t_interface *) OG_Gui->getAddress ("interface");
}
- catch(exception &){};
+ catch(exception &)
+ {
+ interface = 0;
+ };
+
OffsetGroup * OG_Position;
try
{
@@ -132,30 +138,19 @@ bool Gui::Finish()
return true;
}
-uint32_t Gui::ReadMenuState()
-{
- if(d->MenuStateInited)
- return(d->owner->readDWord(d->current_menu_state_offset));
- return false;
-}
-
-// FIXME: variable ‘screenAddr’ set but not used [-Wunused-but-set-variable]
-bool Gui::ReadViewScreen (t_viewscreen &screen)
+t_viewscreen * Gui::GetCurrentScreen()
{
- if (!d->ViewScreeInited) return false;
- Process * p = d->owner;
-
- uint32_t last = p->readDWord (d->view_screen_offset);
- uint32_t screenAddr = p->readDWord (last);
- uint32_t nextScreenPtr = p->readDWord (last + 4);
- while (nextScreenPtr != 0)
+ if(!interface)
+ return 0;
+ t_viewscreen * ws = &interface->view;
+ while(ws)
{
- last = nextScreenPtr;
- screenAddr = p->readDWord (nextScreenPtr);
- nextScreenPtr = p->readDWord (nextScreenPtr + 4);
+ if(ws->child)
+ ws = ws->child;
+ else
+ return ws;
}
- Core & c = Core::getInstance();
- return c.vinfo->resolveObjectToClassID (last, screen.type);
+ return 0;
}
bool Gui::getViewCoords (int32_t &x, int32_t &y, int32_t &z)
diff --git a/plugins/reveal.cpp b/plugins/reveal.cpp
index 1f1165ac6..d3f910712 100644
--- a/plugins/reveal.cpp
+++ b/plugins/reveal.cpp
@@ -97,7 +97,7 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
DFhackCExport command_result reveal(DFHack::Core * c, std::vector & params)
{
bool no_hell = false;
- if(params[0] == "safe")
+ if(params.size() && params[0] == "safe")
{
no_hell = true;
}
@@ -177,7 +177,7 @@ DFhackCExport command_result reveal(DFHack::Core * c, std::vector &
c->Resume();
dfout << "Map revealed." << std::endl;
if(!no_hell)
- dfout << "Unpausing can unleash the forces of hell, so it has been temporarily disabled!" << std::endl;
+ dfout << "Unpausing can unleash the forces of hell, so it has been temporarily disabled." << std::endl;
dfout << "Run 'unreveal' to revert to previous state." << std::endl;
return CR_OK;
}