Skip to content

Commit 01ba2a3

Browse files
committed
Tweak the interpose API, and fix a couple of bugs.
1 parent 236ffd5 commit 01ba2a3

3 files changed

Lines changed: 26 additions & 9 deletions

File tree

library/VTableInterpose.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ VMethodInterposeLinkBase::VMethodInterposeLinkBase(virtual_identity *host, int v
161161
: host(host), vmethod_idx(vmethod_idx), interpose_method(interpose_method), chain_mptr(chain_mptr),
162162
saved_chain(NULL), next(NULL), prev(NULL)
163163
{
164+
assert(vmethod_idx >= 0 && interpose_method != NULL);
164165
}
165166

166167
VMethodInterposeLinkBase::~VMethodInterposeLinkBase()
@@ -198,6 +199,7 @@ bool VMethodInterposeLinkBase::apply()
198199
return false;
199200

200201
set_chain(old_ptr);
202+
host->interpose_list.push_back(this);
201203

202204
// Link into the chain if any
203205
if (old_link)

library/include/VTableInterpose.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,18 @@ namespace DFHack
8181
return addr_to_method_pointer<P>(identity.get_vmethod_ptr(idx));
8282
}
8383

84-
/* VMethod interpose API
84+
/* VMethod interpose API.
85+
86+
This API allows replacing an entry in the original vtable
87+
with code defined by DFHack, while retaining ability to
88+
call the original code. The API can be safely used from
89+
plugins, and multiple hooks for the same vmethod are
90+
automatically chained in undefined order.
8591
8692
Usage:
8793
88-
struct my_hack : public someclass {
89-
typedef someclass interpose_base;
94+
struct my_hack : df::someclass {
95+
typedef df::someclass interpose_base;
9096
9197
DEFINE_VMETHOD_INTERPOSE(void, foo, (int arg)) {
9298
...
@@ -98,7 +104,12 @@ namespace DFHack
98104
IMPLEMENT_VMETHOD_INTERPOSE(my_hack, foo);
99105
100106
void init() {
101-
my_hack::interpose_foo.apply()
107+
if (!INTERPOSE_HOOK(my_hack, foo).apply())
108+
error();
109+
}
110+
111+
void shutdown() {
112+
INTERPOSE_HOOK(my_hack, foo).remove();
102113
}
103114
*/
104115

@@ -112,6 +123,7 @@ namespace DFHack
112123
class::interpose_##name(&class::interpose_base::name, &class::interpose_fn_##name);
113124

114125
#define INTERPOSE_NEXT(name) (this->*interpose_##name.chain)
126+
#define INTERPOSE_HOOK(class, name) (class::interpose_##name)
115127

116128
class DFHACK_EXPORT VMethodInterposeLinkBase {
117129
/*

plugins/devel/vshook.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@ struct title_hook : df::viewscreen_titlest {
3333
uint8_t *buf = gps->screen;
3434
int32_t *stp = gps->screentexpos;
3535

36-
for (const char *p = "DFHack " DFHACK_VERSION; *p; p++) {
37-
*buf++ = *p; *buf++ = 7; *buf++ = 0; *buf++ = 1;
38-
*stp++ = 0;
36+
for (const char *p = "DFHack " DFHACK_VERSION;
37+
*p && buf < gps->screen_limit;
38+
p++, buf += gps->dimy*4, stp += gps->dimy)
39+
{
40+
buf[0] = *p; buf[1] = 7; buf[2] = 0; buf[3] = 1;
41+
*stp = 0;
3942
}
4043
}
4144
}
@@ -47,7 +50,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
4750
{
4851
if (gps)
4952
{
50-
if (!title_hook::interpose_render.apply())
53+
if (!INTERPOSE_HOOK(title_hook, render).apply())
5154
out.printerr("Could not interpose viewscreen_titlest::render\n");
5255
}
5356

@@ -56,6 +59,6 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
5659

5760
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
5861
{
59-
title_hook::interpose_render.remove();
62+
INTERPOSE_HOOK(title_hook, render).remove();
6063
return CR_OK;
6164
}

0 commit comments

Comments
 (0)