Project1
标题: Ruby 版本置换 1.0 (->2.5.1) [打印本页]
作者: SixRC 时间: 2018-9-15 16:42
标题: Ruby 版本置换 1.0 (->2.5.1)
本帖最后由 SixRC 于 2018-9-15 16:45 编辑
切换了之前的思路 这次说是版本置换也贴切 说是双版本也贴切
原理大概是这样的:
用了 RubyInstaller 编译好的 dll 自己再写了个 dll 用来启动等等
在代码页 init 里面初始化 修改了部分机器码使得此后的代码页交由新版本的 ruby 解释器执行
至于如何在新版本的解释器里执行原 RGSS 功能 我的做法大体上是利用 eval
新解释器里我写了三个方法 一个是 p 类同原功能 因为新版本对字符串编码的不同 若 p 一个包含中文的非字符串对象将无法显示中文 此外 一些函数不同了 游戏中部分显示文章的功能需要改写 这个我没附上 因为比较简单 可自己根据需求写
一个是 rgss_eval(str) 用旧版本的解释器 eval str 会有返回值 若是常量如 nil true false 和不大的数字 以及字符串 可以正常返回 其余的返回不可靠
这是因为新旧版本储存对象的方式和解释器环境不同 对象不可共用 除非是一些常量 数字 字符串能返回是因为我作了一个判断 然后作了转换
一个是 rgss_save_str(var_name, str) 将 str 储存到旧解释器的变量 var_name 中 如 rgss_save_str("$hello", "hello");rgss_eval("p $hello")
利用这三个方法 我将 RGSS 作了包装以用于新的解释器 如
module Audio
module_function
def bgm_play(filename, volume = 100, pitch = 100)
rgss_eval("Audio.bgm_play(\"#{filename}\",#{volume},#{pitch})")
end
end
module Audio
module_function
def bgm_play(filename, volume = 100, pitch = 100)
rgss_eval("Audio.bgm_play(\"#{filename}\",#{volume},#{pitch})")
end
end
类的包装借助了全局变量 $bitmap 等等 每个新解释器下的原 RGSS 对象都有一个 n 属性 是对应全局变量的编号以便于操作
所有的 RGSS 功能已经被包装 不需要了解细节也可以如常使用 细节在下面范例的脚本中 那个范例是一个模板 假如要使用可以从那个开始 或者把文件夹下的 dll 啊 lib 库 和需要的脚本拷贝过去 需要什么库自己 require
我也有写 ReadMe.txt 其余的细节看那个吧 大致写的差不多
看一些转换和包装的脚本大概就能理解运作的过程了 操作内存的脚本需要改造 如保存 png 的 理由很明显 不想改造就把脚本放在 init 脚本页前的旧解释器环境下 然后用 rgss_eval 调用
这次应当并无隐疾 除了因为版本不同而造成的不同 这些请自己调整
下为范例
ruby版本置换1.0 8cbg
大致如此 有bug请提 欢迎建议
作者: 星之璇 时间: 2020-2-1 00:04
谢谢!这么好的文章居然没一点回复?!
作者: 星之璇 时间: 2020-2-1 05:42
嗯……突然发现原来这个是XP的工程啊…………我都没XP呢……
看了你的readme,发现如果用新的解释器就没办法实例化一个旧RGSS的类……以及发现原来1.9和2.5~2.6差别这么大!Marshal都无法通用了。
因为原rgss的操作全部写成了rgss_eval之类的,那调用rgss本身的数据结构(不是脚本里写的game_XXX)以及Bitmap,Sprite啊都得靠全局变量来完成?
看不到你的脚本不能只能瞎猜了。
弱弱的问一句,你说自己写的dll 是哪个?
我只认识ruby的解释器dll msvcrt-rubyXXX.dll 以及一系列lib。
难道是nr.dll?
还有个问题,能不能反过来考虑,比如rmva的ruby 1.9没有yaml,我能否依然用rgss的ruby解释器但是调用新版本ruby里的libyaml.dll来实现yaml?
作者: SixRC 时间: 2020-2-1 13:23
1.没有XP不是我的错吧 不应该下一个吗 两分钟的事情啊 遇事不决难道就靠猜吗..有功夫向我求证不如下个XP自己鼓捣啊 我虽然平时只用XP 但是VAVX我都有下载的 有需要可以很快开始研究 (当然MV没有 那完全不是一系列东西了)
2.旧RGSS的类迁移到新Ruby里就行了 我的范例中所有旧脚本都迁移到新解释器里了 不然也可以旧解释器里用 类同内建模块的处理
3.Marshal还是一样的 只是加密的不一样了 因为对加密的是加载到旧解释器中的 而新旧解释器的对象是不共享的 所以才需要先转换成字符串再迁移过去
4."所有原有的 RGSS 我已经相似地转换到了新的解释器下 并不需要了解所有细节 像之前一样使用也是可以的"
所有内建模块我已经封装好了 只有当使用时有特别需求才需要引用那些全局变量
5.嗯 是 nr.dll
# 写成全局变量防止 dll 被释放
$nr = Win32API.new('nr','NR_init','v','v')
$nr.call
# 写成全局变量防止 dll 被释放
$nr = Win32API.new('nr','NR_init','v','v')
$nr.call
这里做了初始化 调用了NR_init这个东西 它做了一些事 比方使之后的代码页交由新解释器执行 等等
6.新旧解释器 不共享对象
所以对于没有side effect或是可以容忍的函数是可以互相调用的 比方我对RGSS的处理方式
所以假如你想调用的新ruby的功能不涉及复杂对象 只涉及基础类型 那很简单就能达到
假如你指旧解释器加载新版本ruby的dll 很明确的说 那是不可能的
①首先 RGSS是闭源的 而模块dll需要内部函数才能运作
这里逆向是可以拿到内部函数地址的
②新旧ruby的内部函数和规范不一样 即使所有内部函数是明的 也不能互相调用dll
极端一点 有些项目 哪怕换个编译器互相调用都会爆炸 就是因为内部规范不一致
③当然 提取RGSS内部函数地址 然后传给对应的1.9版本的ruby的模块dll 那可以吗 那是可以的 我也做过 加载so以win32ole为例
④对于这个 我还是建议自己用C/C++写个dll 然后RGSS调用 过程不是更清晰吗 有什么需求写什么功能 不一定要限死用ruby内置功能
以上
欢迎光临 Project1 (https://rpg.blue/) |
Powered by Discuz! X3.1 |