diff --git a/library/VTableInterpose.cpp b/library/VTableInterpose.cpp index 447070624..f612ba8bd 100644 --- a/library/VTableInterpose.cpp +++ b/library/VTableInterpose.cpp @@ -161,6 +161,7 @@ VMethodInterposeLinkBase::VMethodInterposeLinkBase(virtual_identity *host, int v : host(host), vmethod_idx(vmethod_idx), interpose_method(interpose_method), chain_mptr(chain_mptr), saved_chain(NULL), next(NULL), prev(NULL) { + assert(vmethod_idx >= 0 && interpose_method != NULL); } VMethodInterposeLinkBase::~VMethodInterposeLinkBase() @@ -198,6 +199,7 @@ bool VMethodInterposeLinkBase::apply() return false; set_chain(old_ptr); + host->interpose_list.push_back(this); // Link into the chain if any if (old_link) diff --git a/library/include/VTableInterpose.h b/library/include/VTableInterpose.h index 59a5c2831..5eaeaed85 100644 --- a/library/include/VTableInterpose.h +++ b/library/include/VTableInterpose.h @@ -81,12 +81,18 @@ namespace DFHack return addr_to_method_pointer

(identity.get_vmethod_ptr(idx)); } - /* VMethod interpose API + /* VMethod interpose API. + + This API allows replacing an entry in the original vtable + with code defined by DFHack, while retaining ability to + call the original code. The API can be safely used from + plugins, and multiple hooks for the same vmethod are + automatically chained in undefined order. Usage: - struct my_hack : public someclass { - typedef someclass interpose_base; + struct my_hack : df::someclass { + typedef df::someclass interpose_base; DEFINE_VMETHOD_INTERPOSE(void, foo, (int arg)) { ... @@ -98,7 +104,12 @@ namespace DFHack IMPLEMENT_VMETHOD_INTERPOSE(my_hack, foo); void init() { - my_hack::interpose_foo.apply() + if (!INTERPOSE_HOOK(my_hack, foo).apply()) + error(); + } + + void shutdown() { + INTERPOSE_HOOK(my_hack, foo).remove(); } */ @@ -112,6 +123,7 @@ namespace DFHack class::interpose_##name(&class::interpose_base::name, &class::interpose_fn_##name); #define INTERPOSE_NEXT(name) (this->*interpose_##name.chain) +#define INTERPOSE_HOOK(class, name) (class::interpose_##name) class DFHACK_EXPORT VMethodInterposeLinkBase { /* diff --git a/plugins/devel/vshook.cpp b/plugins/devel/vshook.cpp index 28f983624..319ff0e99 100644 --- a/plugins/devel/vshook.cpp +++ b/plugins/devel/vshook.cpp @@ -33,9 +33,12 @@ struct title_hook : df::viewscreen_titlest { uint8_t *buf = gps->screen; int32_t *stp = gps->screentexpos; - for (const char *p = "DFHack " DFHACK_VERSION; *p; p++) { - *buf++ = *p; *buf++ = 7; *buf++ = 0; *buf++ = 1; - *stp++ = 0; + for (const char *p = "DFHack " DFHACK_VERSION; + *p && buf < gps->screen_limit; + p++, buf += gps->dimy*4, stp += gps->dimy) + { + buf[0] = *p; buf[1] = 7; buf[2] = 0; buf[3] = 1; + *stp = 0; } } } @@ -47,7 +50,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector