祭祀秀忒 发表于 2012-3-22 20:53:01

Sannybuilder---SCM.&CLEO[原理解析篇]

转自sannybuilder吧
-------------------------
打开MAIN.SCM会发现开头有一大块空白的位置,这里就是存放全局变量的地方。前两个双字包含一个跳转,通常都会空着,不作为全局变量使用。所有的全局变量的大小都是一个双字(4个字节)。一个全局变量$10在编译后的scm文件中会表示为40(4乘以10)或者十六进制的0x28,这样使用这个变量时只要把0x28加上0x821280,就得到了变量的地址0x8212A8。默认的或者说原版的MAIN.SCM文件整个头部,包括前两个双字,共0x8620字节,即34336字节,所以全局变量最多能使用到$8583。

Sanny Builder其中一项功能,能将这些全局变量的数字用一些好记的名称来代替。比如用$PLAYER_CHAR来表示$2,用$PLAYER_ACTOR来表示$3等。这项功能的开启或关闭可以在选项中设置,默认是开启的。数字和名称的对应关系保存在对应游戏的CustomVariables.ini中(比如罪恶都市的在SannyBuilder目录\data\vc\CustomVariables.ini中),可以向其中添加新的对应关系。另外,如果在选项中设置了Add extra info to SCM(向文件添加额外的信息),那么这些对应关系会添加到scm文件的末尾(同样也会添加到CLEO中)。

任务线程会在执行opcode start_mission时被载入内存,位置紧接着MAIN.SCM载入的位置,也就是0x858368处。这块区域的大小为35000字节。同时只能有一个任务线程被载入。游戏会在载入SCM文件时记录每个任务在文件中的位置,最多能记录120个,所以最多能有120个任务。
其他线程执行的代码都在0x821280部分中。使用004F或者00D7创建新线程,会从非活跃的线程列队中取出一个线程,进行初始化,并将它放入活跃的线程列队中。游戏本身的线程列队天朝有80个线程,所以同时最多可以有80个线程。这些线程会在载入SCM时初始化(事实上我认为这里的初始化是多余的)。使用004F可以向新线程传递参数,事实上004F会将它带的所有参数复制到新线程的局部变量中。

CLEO线程和普通的线程稍有不同,CLEO线程的代码会载入到堆上分配的空间中。安装了CLEO以后,在载入SCM时会搜索CLEO\下的所有*.cs文件,并载入到游戏中。CLEO的线程结构比普通的线程结构要多出几个变量,其中偏移0x98的变量存放了CLEO代码在内存中的位置。
每一个线程都有18个局部变量,这些变量保存在线程各自的结构中。其中前16个是普通的变量,后两个是计时器(timer)。计时器会不断的增加,可以认为它的值每毫秒都会加1。

每个线程有一个变量,记录当前执行的代码的在SCM中的位置,暂且将它称为ip。将ip的值加上0x821280就得到当前执行的代码在内存中的位置。无论是主线程还是任务线程甚至CLEO线程都是这样。
每个线程结构中有一个大小为6个双字的栈(stack)和一个栈指针,每次使用0050: gosub会将当前的ip存入栈(由上到下),并将栈指针增加。而 0051:ret 的行为则相反。教程至此结束= =
我估计现在搞scm的人很少吧,毕竟和cleo还是有不同的,而且不像cleo那样具备灵活性

为主的祥助 发表于 2012-3-22 22:25:27

支持下下

离殇 发表于 2012-3-24 15:06:18

支持
页: [1]
查看完整版本: Sannybuilder---SCM.&CLEO[原理解析篇]