前段时间逆向了emote引擎(广泛使用于krkr,可惜是坑爹收费的)。 然后就一直在想到了同类的live2d引擎,可惜的是live2d没有krkr版本。于是准备尝试写一个,应该会用的galgame会变多吧,毕竟比起收费的坑爹玩意,l2d是360度视角且小型作品免费发布授权的。
于是开坑记录下开发过程.
17/01/2015:
初步研究清楚了krkr的插件机制,如下
调用过程: 用户脚本->tjs->dll
如下tjs代码
@loadplugin module=dirlist.dll
@iscript
var list = getDirList("c:/");
dm(list.count);
for(var i=0; i<list.count; i++)
{
dm(list[i]);
dm("\n");
}
@endscript
加载了dirlist插件,调用了其中的getDirList函数,那么这个插件dll是怎么实现的呢?
#include "tp_stub.h"
#pragma comment(linker, "/EXPORT:V2Link=_V2Link@4")
#pragma comment(linker, "/EXPORT:V2Unlink=_V2Unlink@0")
dll编写中首先包含此头文件,可从krkr的svn中获得。需要实现V2Link V2Unlink两个函数,用于注册和反注册。
注册函数
EXPORT(HRESULT) V2Link(iTVPFunctionExporter *exporter)
{
TVPInitImportStub(exporter); // 必须初始化步骤,其实就是把krkr的全局变量记录下
iTJSDispatch2 * global = TVPGetScriptDispatch();// TVPGetScriptDispatch会根据之前记录的exporter变量创建
GetDirListFunction = new tGetDirListFunction();
/*
GetDirListFunction是指向你自己实现的tTJSDispatch子类对象的指针
class tGetDirListFunction : public tTJSDispatch {...}申明,后面解释
tGetDirListFunction *GetDirListFunction;
*/
tTJSVariant val = tTJSVariant(GetDirListFunction); // 申明函数存储对象
GetDirListFunction->Release(); // 释放原来的对象,因val已经存储过了
global->PropSet( // 注册对象到krkr全局,这里开始你自制的函数已经被记录了
TJS_MEMBERENSURE, // 创建如果对象不存在
TJS_W("getDirList"), // 对象名字,你在tjs中调用用到的就是这个
NULL, // 函数hash值,其实无所谓永远留空就像
&val, // 你的函数地址
global // 注册的上下文环境,一般global就行
);
global->Release(); //释放global
val.Clear(); //释放val
return S_OK; //注册函数成功
}
反注册函数(就不解释了,和注册过程差不多
EXPORT(HRESULT) V2Unlink()
{
iTJSDispatch2 * global = TVPGetScriptDispatch();
if (global)
{
global->DeleteMember(
0,
TJS_W("getDirList"),
NULL,
global
);
}
if (global) global->Release();
TVPUninitImportStub(); // 必要卸载过程
return S_OK;
}
下面 最关键的一部,函数本体的实现
class tGetDirListFunction : public tTJSDispatch
{
tjs_error TJS_INTF_METHOD FuncCall(
tjs_uint32 flag, const tjs_char * membername, tjs_uint32 *hint,
tTJSVariant *result,
tjs_int numparams, tTJSVariant **param, iTJSDispatch2 *objthis)
{
// 你的代码
}
}
变量的用处都可以从名字看出来,具体传递的内容并无详细文档记载,但是通过svn的代码比对基本能知道怎么用了。
稍微看了下l2d的dx版本sdk,感觉可以直接封装移植转接过来。正在想怎么写比较好。
于是开坑记录下开发过程.
17/01/2015:
初步研究清楚了krkr的插件机制,如下
调用过程: 用户脚本->tjs->dll
如下tjs代码
@loadplugin module=dirlist.dll
@iscript
var list = getDirList("c:/");
dm(list.count);
for(var i=0; i<list.count; i++)
{
dm(list[i]);
dm("\n");
}
@endscript
加载了dirlist插件,调用了其中的getDirList函数,那么这个插件dll是怎么实现的呢?
#include "tp_stub.h"
#pragma comment(linker, "/EXPORT:V2Link=_V2Link@4")
#pragma comment(linker, "/EXPORT:V2Unlink=_V2Unlink@0")
dll编写中首先包含此头文件,可从krkr的svn中获得。需要实现V2Link V2Unlink两个函数,用于注册和反注册。
注册函数
EXPORT(HRESULT) V2Link(iTVPFunctionExporter *exporter)
{
TVPInitImportStub(exporter); // 必须初始化步骤,其实就是把krkr的全局变量记录下
iTJSDispatch2 * global = TVPGetScriptDispatch();// TVPGetScriptDispatch会根据之前记录的exporter变量创建
GetDirListFunction = new tGetDirListFunction();
/*
GetDirListFunction是指向你自己实现的tTJSDispatch子类对象的指针
class tGetDirListFunction : public tTJSDispatch {...}申明,后面解释
tGetDirListFunction *GetDirListFunction;
*/
tTJSVariant val = tTJSVariant(GetDirListFunction); // 申明函数存储对象
GetDirListFunction->Release(); // 释放原来的对象,因val已经存储过了
global->PropSet( // 注册对象到krkr全局,这里开始你自制的函数已经被记录了
TJS_MEMBERENSURE, // 创建如果对象不存在
TJS_W("getDirList"), // 对象名字,你在tjs中调用用到的就是这个
NULL, // 函数hash值,其实无所谓永远留空就像
&val, // 你的函数地址
global // 注册的上下文环境,一般global就行
);
global->Release(); //释放global
val.Clear(); //释放val
return S_OK; //注册函数成功
}
反注册函数(就不解释了,和注册过程差不多
EXPORT(HRESULT) V2Unlink()
{
iTJSDispatch2 * global = TVPGetScriptDispatch();
if (global)
{
global->DeleteMember(
0,
TJS_W("getDirList"),
NULL,
global
);
}
if (global) global->Release();
TVPUninitImportStub(); // 必要卸载过程
return S_OK;
}
下面 最关键的一部,函数本体的实现
class tGetDirListFunction : public tTJSDispatch
{
tjs_error TJS_INTF_METHOD FuncCall(
tjs_uint32 flag, const tjs_char * membername, tjs_uint32 *hint,
tTJSVariant *result,
tjs_int numparams, tTJSVariant **param, iTJSDispatch2 *objthis)
{
// 你的代码
}
}
变量的用处都可以从名字看出来,具体传递的内容并无详细文档记载,但是通过svn的代码比对基本能知道怎么用了。
稍微看了下l2d的dx版本sdk,感觉可以直接封装移植转接过来。正在想怎么写比较好。