krkr引擎研究记录

Author Avatar
子虚乌有 2月 24, 2021

写在前面

  1. 本文档部分内容来源于百度贴吧和B站up主Dir-A的教程视频(目前所有相关视频均已删除),在此表示感谢

  2. 本文档中的软件工具和代码绝大部分来源于Github,在此向各位开发者表示感谢

入门

识别

  1. 最普遍的方式,查看文件属性

  2. 当安装完一个游戏之后,最简单的判断就是里面是否出现大量.xp3扩展名的文件如果只有一个data.xp3也算。

  3. 如果文件夹下没有.xp3文件,而是有其他的文件例如data.dat,此时可以通过查看这个文件的前3字节,xp3文件的前3字节是58 50 33,即unicode下的XP3字符

    实例:syugaten/data.xp3

    Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F   
    00000000   58 50 33 0D 0A 20 0A 1A  8B 67 01 17 00 00 00 00   XP3     媑      
    00000010   00 00 00 01 00 00 00 80  00 00 00 00 00 00 00 0000000020   C3 65 9F 1F 00 00 00 00  89 50 4E 47 0A 1A 0A 00?    PNG    
    00000030   ......
  4. xp3数据包其实可以打包进exe里,此时exe本身就可以看作xp3,而kirikiroid2能运行exe,其实指的是exe内嵌了xp3数据包,然后运行里面的脚本。遇到这种情况,右键exe属性,在详细信息里面可以看到TVP(KIRIKIRI) 2 core字样的话,那就可以确定了。

  5. 游戏入口的脚本默认在data.xp3包里,如果不存在这个包,那说明要么data包其实和exe捆绑了,要么就是exe被修改过,令其从其它包开始运行。

  6. 其它的情况就算有也是极少数,而且往往已经深度改造过了。

插件与解密

  1. 游戏文件夹中存在一些dll,这些一般可以认为是插件,可以对照后面的KR2官方标准插件集来判断游戏是否使用了自定义插件。最后还附有Kirikiroid2已经实现了的插件集,可以对照判断Kirikiroid2对该游戏的支持程度。此外,并不是存在某个dll就说明游戏就一定会使用它,有时候开发者仅仅只是无脑复制了所有的插件到游戏目录中而已。

  2. tpm扩展名的文件是在KR2运行时自动加载的插件,如果出现它,说明这个游戏极可能有经过加密,特别是这个tpm的名字与游戏名相同,或者叫dec、decode之类的。此外,如果文件名和官方插件列表中的插件一致的话,那也可能是作者懒得在脚本中加载插件,于是弄成tpm自动加载了。

  3. 官方插件中必带的有wuvorbiskrmovie,前者提供ogg音频解码,后者提供视频回放支持。这两者的功能在Kirikiroid2中已经实现。

  4. dll插件其实可以打包进xp3包中,有时候看不到任何dll,不能说明这个游戏就没用插件。但至少可以说明它应该是没有加密的。如果需要测试它到底是否有加密的话,可以下载一个官方的krkr.exe,放到游戏目录中看能否运行即可。

  5. 结合之前xp3包可以打包进exe的情况,只有一个exe的游戏也可能用到了插件。而要判断它是否加密,同样用官方的krkr.exe,将游戏的exe拖到krkr.exe上,看能否运行即可。

附录

KIRIKIROID2支持的插件
wuvorbis krmovie extrans csvParser fstat
getSample layerExBTOA layerExRaster saveStruct scriptsEx
shrinkCopy layerExImage(1.0.1起支持)
KR2官方插件集
addFont adjustMonitor base64 basetest binaryStream
clipboardEx csvParser dirlist drawdevice drawdeviceD3D
drawdeviceIrrlicht drawdeviceOgre encode exceptiontest expat
extrans fftgraph flashPlayer fpslimit fstat
gameswf getSample htmlhelp httprequest httpserv
imagesaver javascript json KAGParserEx layerEx
layerExAgg layerExAreaAverage layerExAVI layerExBTOA layerExCairo
layerExDraw layerExGdiPlus layerExImage layerExLongExposure layerExMovie
layerExPerspective layerExRaster layerExSave lineParser magickpp
memfile messenger minizip mkpj msgreceiver
nativeclasstest ncbind parserskelton process qrcode
registory saveStruct scriptsEx shellExecute shrinkCopy
sigcheck sqlite3 sqlite3_xp3_vfs squirrel stdio
systemEx tftSave varfile videoEncoder win32dialog
win32ole windowEx windowExProgress wmrdump wsh
wumsadp wutcwf wuvorbis xmlhttprequest xpressive

实例

syugaten
|   data.xp3 // 主要的数据包
|   data.xp3.sig // *.sig文件是用来验证数据完整和防止篡改的,下同
|   evimage.xp3 // cg数据包
|   evimage.xp3.sig
|   fgimage.xp3 // 立绘数据包
|   fgimage.xp3.sig
|   syugaten.exe // 主程序
|   syugaten.exe.sig
|   video.xp3 // 视频数据包
|   video.xp3.sig
|   voice.xp3 // 语音数据包
|   voice.xp3.sig
|
|   // 可能还会出现的有
|   // patch*.xp3 补丁数据包
|   // scenario.xp3 剧本数据包
|   // bgimage.xp3 背景图数据包
|   // *.cf 这个文件指定了存档目录
|
\---plugin // 插件文件夹
        AlphaMovie.dll
        AlphaMovie.dll.sig
        extNagano.dll
        extNagano.dll.sig
        extrans.dll
        extrans.dll.sig
        getSample.dll
        getSample.dll.sig
        k2compat.dll
        k2compat.dll.sig
        kagexopt.dll
        kagexopt.dll.sig
        KAGParserEx.dll
        KAGParserEx.dll.sig
        krmovie.dll
        krmovie.dll.sig
        kztouch.dll
        kztouch.dll.sig
        layerExDraw.dll
        layerExDraw.dll.sig
        lzfs.dll
        lzfs.dll.sig
        menu.dll
        menu.dll.sig
        multiimage.dll
        multiimage.dll.sig
        PackinOne.dll
        PackinOne.dll.sig
        pkutil.dll
        pkutil.dll.sig
        psbfile.dll
        psbfile.dll.sig
        psd.dll
        psd.dll.sig
        textrender.dll
        textrender.dll.sig
        win32dialog.dll
        win32dialog.dll.sig
        win32ole.dll
        win32ole.dll.sig
        windowEx.dll
        windowEx.dll.sig
        wuopus.dll
        wuopus.dll.sig
        wuvorbis.dll
        wuvorbis.dll.sig

资源加密

  1. 如果文件夹中含有.tpm文件,尤其是文件名和游戏名相同的情况下(不论位置,例如,插件可以存在于plugin/目录下或者游戏根目录下),那么就要注意资源文件可能是被加密存储的

  2. 对于这种情况要对资源进行解密才能提取出来,如果要进行资源重新打包,也要按照原来的加密方式进行打包,如果要以未加密方式打包就要移除加密插件并且解密所有的xp3文件

  3. .tpm文件不一定就是加密插件

  4. 数据包内的脚本和文本文件可能会被二次加密,可以用下文提到的KrkrTextDecryption进行解密

  5. 直接将解密出来的脚本文件打包不会影响游戏的正常运行

解包 / 打包

常用的解包工具有:

运行流程

  1. 加载插件,加载.tpm文件进行解密

  2. 加载data.xp3/startup.tjs,这个脚本的唯一用途一般是调用data.xp3/system/Initialize.tjs进行游戏初始化

  3. 运行游戏

资源文件的加载优先级

  1. 一般来说,如果同时存在xp3文件,xp3文件同名文件夹,patch*.xp3,那么文件夹和patch的优先级要比原数据包优先级高

    • 特别地,如果游戏不允许资源不打包运行,则不会使用data/文件夹的内容替换资源文件,详细查看此处
  2. patch后数字越大优先级越高

    例如,如果同时存在data.xp3data/文件夹,patch.xp3patch2.xp3,那么patch2.xp3的同名资源会覆盖掉patch.xp3data/data.xp3中的同名资源

  3. 并不是所有的游戏都允许不打包资源文件运行,修改方法请查看此处

编码转换

如果要在中文系统上运行日文原版游戏,那么需要把里面的脚本文件进行编码转换,避免崩溃和乱码问题

  • 常见的需要转换编码的文件类型

    .tjs.ks.scn.csv.txt.ini.func.asd.sinfo.stand等一切文本类型的文件

  • 编码转换

    原始文件通常是Shift-JIS编码,需要转换为UTF-16 LE并且保留BOM头

  • 对于.scn文件,需要把.scn二次解包提取出剧本文件后转换编码,再打包回.scn

字体制作

参考链接:原文章 | 网页备份

让游戏正常显示中文以及绕过文件验证

参考链接:原文章 | 网页备份

附注

修改窗口标题

游戏窗口标题通常在Override.tjs(位置应该是data.xp3/system/Override.tjs)中的System.title,或者全局搜索标题

xp3资源文件校验

xp3文件校验在scripts/release.tjs中,或搜索data.xp3

立绘缺失问题

  1. 对于csv编码转换后立绘无法正常显示,可以在Override.tjs(位置应该是data.xp3/sysscn/Override.tjs中第一行Plugins.link("csvParser.dll");下添加以下代码

    with(global.CSVParser) {
       .origParseStorage = .parseStorage;
       .parseStorage = function (filename, utf8) {this.parse([].load(filename).join('\n'));}; //for utf-16 CSV
       .initStorage = function (filename) {this.StorageBuffer = [].load(filename); this.StorageBuffer.reverse();};
       .getNextLine = function () {
          if (this.StorageBuffer!==void) {
          var retData=this.StorageBuffer.pop();
          if (retData!==void) return retData.split('\t');
          }
       };
    };
  2. 对于因为资源包中路径是日文导致的立绘无法加载甚至游戏崩溃的情况,可以将Initialize.tjs中,将类似于

    Storages.addAutoPath("xxx") // 括号内为中文的路径

    复制到Config.tjs的头部,重新打包运行即可

不封包运行

让游戏允许在data/文件夹资源文件未打包的情况下运行

十六进制编辑游戏主程序,搜索forcedataxp3,将括号内1所对应的字节改为0

实例:syugaten.exe


修改前

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F
002F09A0   ......
002F09B0   2D 2D 20 54 56 50 53 79  73 74 65 6D 53 65 63 75   -- TVPSystemSecu
002F09C0   72 69 74 79 4F 70 74 69  6F 6E 73 20 64 69 73 61   rityOptions disa
002F09D0   62 6C 65 6D 73 67 6D 61  70 28 31 29 3A 66 6F 72   blemsgmap(1):for
002F09E0   63 65 64 61 74 61 78 70  33 28 31 29 3A 61 63 63   cedataxp3(1):acc
002F09F0   65 70 74 66 69 6C 65 6E  61 6D 65 61 72 67 75 6D   eptfilenameargum
002F0A00   ......


修改后

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F
002F09A0   ......
002F09B0   2D 2D 20 54 56 50 53 79  73 74 65 6D 53 65 63 75   -- TVPSystemSecu
002F09C0   72 69 74 79 4F 70 74 69  6F 6E 73 20 64 69 73 61   rityOptions disa
002F09D0   62 6C 65 6D 73 67 6D 61  70 28 31 29 3A 66 6F 72   blemsgmap(1):for
002F09E0   63 65 64 61 74 61 78 70  33 28 30 29 3A 61 63 63   cedataxp3(0):acc
002F09F0   65 70 74 66 69 6C 65 6E  61 6D 65 61 72 67 75 6D   eptfilenameargum
002F0A00   ......


可以看到,修改前后的区别就在002F09E0 + A位置上的31变成了30,使程序中的forcedataxp3参数由1变成了0从而实现了不打包资源也运行

其实建议顺带将disablemsgmap的参数也一并改成0,以防止奇奇怪怪的问题

修改存档路径

在游戏根目录下找到.cf文件,打开后将datapath内容删除或直接删除这一项配置即可

这一项配置的内容是用十六进制编码的,用来表示路径的字符串

如果这个文件不存在/这一项为空/根本不存在这个字段时,存档则放在/savedata/下(默认路径)

所以理论上可以删除这个文件,使之把存档放在游戏目录下,但是如果游戏原本就存在这个文件的情况下,不建议删除这个文件

修改默认资源读取路径(仅krkr2)

  1. 其实这个方法理论上来说对于krkrz引擎也是适用的,只不过修改的字符串是unicode(一个字符两字节)编码的(krkr2是ascii码,一个字符一字节),需要把新文件名转换成unicode编码再修改,但是我没有修改成功,不知道为什么

    krkrz下的例子

    Offset      0  1  2  3  4  5  6  7   8  9 10 11 12 13 14 15
    03081904   5C 00 00 00 2D 00 73 00  65 00 6C 00 00 00 00 00   \   - s e l     
    03081920   63 00 6F 00 6E 00 74 00  65 00 6E 00 74 00 2D 00   c o n t e n t - 
    03081936   64 00 61 00 74 00 61 00  00 00 00 00 5C 00 00 00   d a t a     \   
    03081952   64 00 61 00 74 00 61 00  2E 00 78 00 70 00 33 00   d a t a . x p 3 
    03081968   00 00 00 00 64 00 61 00  74 00 61 00 2E 00 65 00       d a t a . e 
    03081984   78 00 65 00 00 00 00 00  64 00 61 00 74 00 61 00   x e     d a t a 
  2. 默认读取的文件夹是data,使用十六进制编辑器搜索exe中的content-data,并将data修改为想要的名称即可

  3. 默认读取data.xp3,搜索并修改data.xp3即可

    实例:lol2.exe

    Offset      0  1  2  3  4  5  6  7   8  9 10 11 12 13 14 15   
    03104160   5C 00 2D 00 73 00 65 00  6C 00 00 00 63 6F 6E 74   \ - s e l   cont
    03104176   65 6E 74 2D 64 61 74 61  00 64 61 74 61 2E 78 70   ent-data data.xp
    03104192   33 00 64 61 74 61 2E 65  78 65 00 41 62 6F 72 74   3 data.exe Abort
    03104208   65 64 00 6B 72 64 65 76  75 69 2E 64 6C 6C 00 74   ed krdevui.dll t

    修改前

    修改后

引用其他封包下的资源文件

实现

如果要制作汉化补丁的话,把整个data解包->汉化文本->打包发布显然是不太现实的,因为一般来说,data.xp3的大小在1G以上,而我们需要汉化的部分只有文本和脚本、可能还会有少量的图片

这时我们可能会想到:能不能通过修改游戏默认加载资源文件的方式,让其默认加载我们制作的补丁文件,然后在补丁中引用原始data.xp3的资源文件达到复用资源的目的,减少补丁大小

打开一个已经制作好补丁的游戏看一下里面的实现

重点在于

Storages.addAutoPath(System.exePath+"data.xp3>");
Storages.addAutoPath(System.exePath+"data.xp3>bgimage/");
Storages.addAutoPath(System.exePath+"data.xp3>bgm/");
Storages.addAutoPath(System.exePath+"data.xp3>fgimage/");
Storages.addAutoPath(System.exePath+"data.xp3>image/");
Storages.addAutoPath(System.exePath+"data.xp3>others/");
Storages.addAutoPath(System.exePath+"data.xp3>rule/");
Storages.addAutoPath(System.exePath+"data.xp3>scenario/");
Storages.addAutoPath(System.exePath+"data.xp3>sound/");
Storages.addAutoPath(System.exePath+"data.xp3>system/");

这一段代码引用了原始的data.xp3下面的资源文件夹,达到了复用的目的

注意

  1. 所引用的资源不会包括子文件夹,如果要引用子文件夹中的资源需要单独列出

    比如文件夹的结构为

    data.xp3
    |   ....
    \---bgimage
    |     |  a.png
    |     |  ....
    |     \--- a
    |           aa.png
    |           ab.png
    |           ....
    \---fgimage
    |     ....
    ....

    要引用bgimage下所有资源和bgimage/a文件夹下所有的文件时,要写成

    Storages.addAutoPath(System.exePath+"data.xp3>bgimage/");
    Storages.addAutoPath(System.exePath+"data.xp3>bgimage/a/");
  2. 所有文件夹的名字要以\结尾

  3. 如果有某些图片资源要单独修改,直接把修改后的图片放在补丁文件夹根目录下打包即可

作者:子虚乌有
版权声明:本网站所有文章除特别声明外,均采用CC BY-NC-ND 4.0许可协议,转载请注明出处
注意:本网站所有文章内容仅供参考,如果您需解决具体问题(尤其法律、医学等领域),建议您详细咨询相关领域专业人士。

本文链接:http://peanutmelonseedbigalmond.pages.dev/2021/02/24/krkr%E5%BC%95%E6%93%8E%E7%A0%94%E7%A9%B6%E8%AE%B0%E5%BD%95/