Project1
标题: RGSS的C/asm扩展 [打印本页]
作者: SixRC 时间: 2017-12-2 03:06
标题: RGSS的C/asm扩展
本帖最后由 SixRC 于 2017-12-2 14:46 编辑
本来晚饭时候突然想到上次那个字体加载问题的一个解 就是新写一个dll 然后这个dll先加载一下字体 再去调用RGSS
然后突然又想到 @guoxiaomi 的 RGSS的C/C++扩展
老实说 那个时候我没怎么看懂 基于种种奇怪的原因
但今天我好好的学习理解了 这门有趣的技艺
有一些感想收获 就发个帖子吧..不过我不知道取什么标题好..就照抄了 然后因为比起这两个我更不懂 c++ ..大概 就这样
最开始的时候没懂 感觉部分原因是没看 ruby 的源码吧
代码里好多宏定义都不太明白不想看 然后今天下了 ruby 1.8.1 的源码 参考下进展比较顺利
ruby 是拿 C 写的
而拓展的基本思路就是用 ruby 源码里的一些基本函数比方 rb_define_module(name) 去以 C 的方式定义 ruby 里的模块啊类啊方法啊等等 然后再在 ruby 里用
而这些基本函数封装在 RGSSxxx dll 里面 需要逆向获取地址
就目前看来 我感觉 dll 的部分源码应该是直接复制了 ruby 的源码 因为那些编译好的函数地址的顺序和 ruby 源码里的定义顺序一样
不过我总共也没跟几个地址 只是凭感觉 ..
然后接着说拓展 按拓展的时间顺序分 应该有两种
一种是在 RGSS 载入后再加载自己写的dll 可以用来进行功能拓展
另一种是在 RGSS 载入前魔改或者替换基本函数或 dll 定义的函数等等
比方 修改 rb_define_module(name) 函数
传入参数是 name 是字符串 你把它改成先对 name 进行处理 比方 a->b b->c ... z->a 再跳回正常的模块定义
然后 脚本编辑器里写的明明是 module ABC
调用的时候却是 BCD
关于这个 用 C 定义和用 ruby 定义似乎处理方式不同..
当然 在 RGSS 载入前也可以进行一些加载字体改分辨率等的事项而不再需要重载RGSS
嗯 确实是很有趣的新思想新方式啊!暂时不知道说啥了
最后是自己写的很简陋的随机数函数 新想法暂未付诸实践
static char ra[]={0x0F,0xC7,0xF8, // rdseed eax
0xD1,0xE0, // shl eax,1
0x83,0xC8,0x01, // or eax,1
0xC3}; // ret
static int (*rarand)() = (int(*)())ra;
static void (*rb_define_global_function)(char*,int(*)(),int);
int init(void* hmodule){
rb_define_global_function = (void (*)(char*,int(*)(),int))(hmodule+0x20BB0);
rb_define_global_function("rarand",rarand,0);
return 0;
}
static char ra[]={0x0F,0xC7,0xF8, // rdseed eax
0xD1,0xE0, // shl eax,1
0x83,0xC8,0x01, // or eax,1
0xC3}; // ret
static int (*rarand)() = (int(*)())ra;
static void (*rb_define_global_function)(char*,int(*)(),int);
int init(void* hmodule){
rb_define_global_function = (void (*)(char*,int(*)(),int))(hmodule+0x20BB0);
rb_define_global_function("rarand",rarand,0);
return 0;
}
拓展范例.zip
(630.88 KB, 下载次数: 95)
作者: fux2 时间: 2017-12-2 09:00
的确是已经有搭好的RGSSRuntime,不过ruby函数的地址都是用的RGSS301.dll里面的233,
项目并没有公开,我就不乱发了。
作者: guoxiaomi 时间: 2017-12-2 20:58
虽然@了我,但是我只能表示心理上的支持(ง •̀_•́)ง
顺便说一下要是能像后面的版本里一样,自然的扩展分辨率就好了……
作者: SixRC 时间: 2017-12-3 17:56
本帖最后由 SixRC 于 2017-12-3 19:19 编辑
拓展分辨率 这样?
/* 增加 Graphics.resize_screen(width,height) 方法
自动居中放置 支持渐变 不受 640*480 限制 */
#include <windows.h>
/* rb_define_module_function、Bitmap_initialize 等地址逆向得到
RGSSData 是一处 RGSS 存放一些数据的地方
其下存有用来渐变的位图、窗口句柄等等数据 */
static void (*rb_define_module_function)(int,char*,int (*)(),int);
// 新建 bitmap 去替换原渐变位图
static int (*Bitmap_initialize)(int,int*,int*);
// 两个类地址及桌面尺寸
static int Graphics,Bitmap,desktoprect[4];
static void** RGSSData;
static int *FreezeSection,*FreezeSection2;
// 窗口句柄
static void* hwnd;
static RECT* DesktopRect = (RECT*)desktoprect;
// resize_screen 会传入 类地址 + 其他指定的参数
static int resize(int graphics,int width,int height){
// 位图对象的储存方式 [flag 、类地址 、mark 、free 函数 、数据地址] 参考 ruby 源码
// 数据有三个元素 第三个是位图结构地址
// 位图结构有 0x58 大 22个元素
// FreezeSection指向的是位图结构 全复制过去就好 或复制指针 这里复制了所有的元素
// initialize 方法为可变参数 为 [argc,argv,obj]
int temp[3],size[]={width,height},new_bitmap[]={0x22,Bitmap,0,0,(int)temp};
Bitmap_initialize(2,size,new_bitmap);
// 删除旧位图 位图结构 + 2C 为位图句柄
DeleteObject((void*)FreezeSection[11]);
int *newsection = (int*)temp[2];
for(int i=0;i<22;i++){FreezeSection[i]=newsection[i];}
// 还需要修改另一块指定的渐变尺寸
FreezeSection2[4] = width;
FreezeSection2[5] = height;
FreezeSection2[50] = width;
FreezeSection2[51] = height;
// 渐变处理完毕 然后改窗口尺寸
// 因为有边框大小 调整一下 并根据桌面大小放置
// 但边框是定长的还是随不同电脑不同?是否需要获取边框尺寸?这里我懒
// ruby num 转 int
width = width >> 1;
height = height >> 1;
int x = (DesktopRect->right - width - 6)/2;
int y = (DesktopRect->bottom - height - 29)/2;
MoveWindow(hwnd,x,y,width+6,height+29,1);
// 4 为 nil
return 4;
}
// 初始化 传入dll名 设置变量 增加函数
void Init_Graphics_Resize(char* dll){
void *hmodule = GetModuleHandle(dll);
Graphics = ((int*)(hmodule+0x12DAF4))[0];
Bitmap = ((int*)(hmodule+0x12DADC))[0];
rb_define_module_function = hmodule+0x20B80;
Bitmap_initialize = hmodule+0x50F0;
RGSSData = ((void***)(hmodule+0x12B6C4))[0];
hwnd = ((void**)RGSSData)[2];
FreezeSection = ((int**)(RGSSData+0x144/4))[0];
FreezeSection2 = ((int**)(RGSSData+0x148/4))[0];
SystemParametersInfo(48,0,DesktopRect,0);
// 设置两个参数 但是实际传入的时候多一个 类地址
rb_define_module_function(Graphics,"resize_screen",resize,2);
return;
}
/* 增加 Graphics.resize_screen(width,height) 方法
自动居中放置 支持渐变 不受 640*480 限制 */
#include <windows.h>
/* rb_define_module_function、Bitmap_initialize 等地址逆向得到
RGSSData 是一处 RGSS 存放一些数据的地方
其下存有用来渐变的位图、窗口句柄等等数据 */
static void (*rb_define_module_function)(int,char*,int (*)(),int);
// 新建 bitmap 去替换原渐变位图
static int (*Bitmap_initialize)(int,int*,int*);
// 两个类地址及桌面尺寸
static int Graphics,Bitmap,desktoprect[4];
static void** RGSSData;
static int *FreezeSection,*FreezeSection2;
// 窗口句柄
static void* hwnd;
static RECT* DesktopRect = (RECT*)desktoprect;
// resize_screen 会传入 类地址 + 其他指定的参数
static int resize(int graphics,int width,int height){
// 位图对象的储存方式 [flag 、类地址 、mark 、free 函数 、数据地址] 参考 ruby 源码
// 数据有三个元素 第三个是位图结构地址
// 位图结构有 0x58 大 22个元素
// FreezeSection指向的是位图结构 全复制过去就好 或复制指针 这里复制了所有的元素
// initialize 方法为可变参数 为 [argc,argv,obj]
int temp[3],size[]={width,height},new_bitmap[]={0x22,Bitmap,0,0,(int)temp};
Bitmap_initialize(2,size,new_bitmap);
// 删除旧位图 位图结构 + 2C 为位图句柄
DeleteObject((void*)FreezeSection[11]);
int *newsection = (int*)temp[2];
for(int i=0;i<22;i++){FreezeSection[i]=newsection[i];}
// 还需要修改另一块指定的渐变尺寸
FreezeSection2[4] = width;
FreezeSection2[5] = height;
FreezeSection2[50] = width;
FreezeSection2[51] = height;
// 渐变处理完毕 然后改窗口尺寸
// 因为有边框大小 调整一下 并根据桌面大小放置
// 但边框是定长的还是随不同电脑不同?是否需要获取边框尺寸?这里我懒
// ruby num 转 int
width = width >> 1;
height = height >> 1;
int x = (DesktopRect->right - width - 6)/2;
int y = (DesktopRect->bottom - height - 29)/2;
MoveWindow(hwnd,x,y,width+6,height+29,1);
// 4 为 nil
return 4;
}
// 初始化 传入dll名 设置变量 增加函数
void Init_Graphics_Resize(char* dll){
void *hmodule = GetModuleHandle(dll);
Graphics = ((int*)(hmodule+0x12DAF4))[0];
Bitmap = ((int*)(hmodule+0x12DADC))[0];
rb_define_module_function = hmodule+0x20B80;
Bitmap_initialize = hmodule+0x50F0;
RGSSData = ((void***)(hmodule+0x12B6C4))[0];
hwnd = ((void**)RGSSData)[2];
FreezeSection = ((int**)(RGSSData+0x144/4))[0];
FreezeSection2 = ((int**)(RGSSData+0x148/4))[0];
SystemParametersInfo(48,0,DesktopRect,0);
// 设置两个参数 但是实际传入的时候多一个 类地址
rb_define_module_function(Graphics,"resize_screen",resize,2);
return;
}
调用
Win32API.new('resize','Init_Graphics_Resize','p','v').call("RGSS103J")
Graphics.resize_screen(1280,720)
Win32API.new('resize','Init_Graphics_Resize','p','v').call("RGSS103J")
Graphics.resize_screen(1280,720)
Resize.zip
(210.14 KB, 下载次数: 92)
突然想到传入 dll 名没什么意义..因为版本间不通用......
欢迎光临 Project1 (https://rpg.blue/) |
Powered by Discuz! X3.1 |