live2d吧 关注:37,158贴子:46,697
  • 14回复贴,共1

【开坑记录】live2d krkr插件

只看楼主收藏回复

前段时间逆向了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,感觉可以直接封装移植转接过来。正在想怎么写比较好。


1楼2015-01-18 01:28回复
    18/01/2015:
    看了半天krkr的图层实现,大概知道怎么做了。
    在tTJSNI_BaseLayer类的实现中可以制定该层加载图片或者修改该层的绘图设备,应该可以设计一个初始化函数 让用户在krkr脚本中传入指定存放立绘的layer,在dll中重写该层的绘图让l2d接管或者 干脆dx渲染压成一层图片传进去(=_=这么做大概帧率会很有压力)。
    于是继续研究


    3楼2015-01-18 11:44
    回复
      前排【这算哪门子前排】支持一下 之前我也研究过 然后就没然后了。。。


      IP属地:辽宁4楼2015-01-19 08:30
      回复
        19/1/2015:
        今天继续看了下,有点没有头绪,于是又翻回老本行去了
        根据emoteAcademic的krkr sdk中的emoteplayer.ks 猜测,他的实现方法是传入 前景 和 背景 layer,然后 在插件player.dll中合成(中间插入绘制)。
        不过此方法应该没啥意义,academic版本中的player无法确定是否使用到d3d。 如果只是实现幻灯片(每次渲染一张bmp插入krkr),那我已经试过了,帧率感人。
        根据非academic版本中的逆向结果 可以知道 neko中是使用d3d的, 具体看了下 krkr z(git上有开源),实现了dx9的底层,另通过逆向手段获得了几个dx layer的tjs。 可以借鉴他的插入方法,使用krkr z的实现并入l2d.
        还没看完,不清楚是 dx层单独拿出来绘制 然后krkr整合呢,还是 插件获取图层后 和立绘合并 一起绘制到窗口。
        以下提取的几个tjs,这个礼拜暂时没时间继续研究了,如果有发现也可以告诉我。
        http://www.mediafire.com/download/5cafacjzs2am028/system.7z


        5楼2015-01-20 00:02
        收起回复
          那些galgame里面是使用emote吗?什么或守install之类的


          来自Android客户端7楼2015-02-11 20:48
          回复
            不明觉厉
                --如果有人说出人人平等这种话,除非他是神,否则在这个世界上他谁也不爱!


            IP属地:安徽来自Android客户端12楼2015-04-14 17:36
            回复
              总感觉…看不懂…
              谢谢楼主的研究!!【精品贴不算坟啊


              13楼2015-11-24 00:04
              回复
                可惜作者没有继续


                IP属地:黑龙江来自Android客户端14楼2017-09-14 10:35
                回复


                  IP属地:黑龙江来自Android客户端15楼2018-12-26 11:02
                  回复
                    不明真相的萌新路过


                    IP属地:广东来自Android客户端16楼2019-01-31 00:51
                    回复