十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

如何看懂 Sonic CD 脚本引擎:RSDKv3 字节码虚拟机与操作码执行完整解析

如何看懂 Sonic CD 脚本引擎:RSDKv3 字节码虚拟机与操作码执行完整解析 如何看懂 Sonic CD 脚本引擎RSDKv3 字节码虚拟机与操作码执行完整解析【免费下载链接】Sonic-CD-11-DecompilationA Full Decompilation of Sonic CD (2011) Retro Engine (v3)项目地址: https://gitcode.com/gh_mirrors/so/Sonic-CD-11-DecompilationSonic CD 脚本引擎的完整反编译项目Sonic-CD-11-Decompilation还原了《索尼克CD》(2011) 及其背后的 Retro Engine v3简称 RSDKv3。其中最精巧的部分是这套字节码虚拟机游戏的所有行为——角色移动、敌人AI、画面绘制——都不是 C 硬编码而是一段段.bin字节码文件由 RSDKv3/Script.cpp 中的解释器逐条取出操作码并执行。本文带你快速读懂这台虚拟机的内存布局、字节码加载与指令执行全流程。 一台虚拟机需要哪些硬件RSDKv3 的虚拟机全部由几块固定大小的内存构成定义在 RSDKv3/Script.hpp 中内存区大小作用scriptCode0x40000 个 int字节码本体指令序列jumpTable0x4000 个 int跳转表存放 if/switch 的目标地址jumpTableStack0x400 个 int跳转栈保存未完成的跳转上下文functionStack0x400 个 int函数调用栈运行时寄存器则集中在ScriptEngine结构体里RSDKv3/Script.hppoperands[10]当前指令最多 10 个操作数tempValue[8]8 个临时变量TempValue0~7arrayPosition[3]数组遍历位置对应loop指令checkResult比较类指令的结果标志 字节码从哪里来LoadBytecode 加载流程每个关卡的脚本都以.bin文件存放在Data/Scripts/ByteCode/目录下例如GS000.bin、GlobalCode.bin。加载函数LoadBytecodeRSDKv3/Script.cpp做了三件事按关卡类型拼出路径根据 stageListID演示/普通/奖励/特殊关卡把GSxxx.bin填入路径读取 4 字节总长度然后逐块读入scriptCode缓冲区解码简易压缩格式每块第一个字节的最高位是标志位——0x80以上表示后续是 32 位字4 字节/条否则是 1 字节常量RSDKv3/Script.cpp。同一套逻辑再执行一次把跳转数据读入jumpTable。这种字/字节双密度的编码让常量多的脚本体积大幅缩小是 16 位时代遗留的实用技巧。 操作码表指令的字典虚拟机是典型的操作码操作数结构。所有指令集中登记在functions[]静态表里RSDKv3/Script.cpp每条只有两样信息指令名和操作数个数。操作码操作数说明End0结束当前脚本Add/Sub/Mul/Div2算术运算结果写入临时变量CheckEqual/CheckGreater2比较结果存入checkResultIfEqual等 If 系列3条件跳转写入跳转表loop/break/switch0~2循环与分支控制Sin/Cos256/Interpolate2~4三角函数与插值用于动画与 3D 特效DrawSprite/DrawSpriteXY1~3精灵绘制LoadPalette/RotatePalette3~5调色板操作LoadStage0切换关卡表的位置即操作码编号——第 0 号指令是End第 2 号是Add以此类推执行时直接用下标查表。⚙️ 执行循环ProcessScript 如何一步步跑核心函数ProcessScriptRSDKv3/Script.cpp是一个while(running)大循环每一轮完成取指 → 读操作数 → 执行第一步取指从scriptCode[scriptCodePtr]取出操作码编号再查functions[opcode].opcodeSize得到这条指令需要几个操作数然后循环opcodeSize次把操作数解析进scriptEng.operands[i]。第二步操作数解析这是虚拟机的精华所在RSDKv3/Script.cpp。字节码里不写变量名而是写变量类型编码执行器据此现场取值数组解析先读一个数组模式VARARR_NONE当前对象、VARARR_ARRAY绝对下标、VARARR_ENTNOPLUS1相对下标等算出实体编号arrayVal变量解析再读变量编码比如VAR_OBJECTXPOS就取objectEntityList[arrayVal].XPosVAR_GLOBAL取globalVariables[arrayVal]。也就是说把 3 号敌人的 X 坐标加到 TempValue0 上这种逻辑在字节码里就是几个编码字由这个双重 switch 实时展开。第三步执行取出全部操作数后按操作码执行具体逻辑——算术直接算、绘制调用绘图模块、IfEqual则把目标地址压入jumpTableStack并可能跳转scriptCodePtr。函数调用与返回由functionStack支撑。️ 变量系统TempValue 与 Object.XPos编译器阶段玩家写的是可读文本变量如Object.XPos、Player.State、Global.100完整别名表见 RSDKv3/Script.cpp。每个对象拥有 4 个独立脚本入口RSDKv3/Script.hppSUB_MAIN每帧主逻辑实体 AI 所在SUB_PLAYERINTERACTION玩家触碰交互SUB_DRAW绘制回调SUB_SETUP初始化ObjectScript结构体为每个对象保存这四个入口的字节码起点关卡开始时由引擎分别启动这就是每个游戏对象都是脚本驱动的实现方式。️ 动手阅读源码的路线想深入这套 Sonic CD 脚本引擎建议按此顺序阅读内存与结构定义 → RSDKv3/Script.hpp不足 100 行10 分钟读完字节码加载 →LoadBytecode位于 RSDKv3/Script.cpp#L1888操作码表 →functions[]位于 RSDKv3/Script.cpp#L300执行循环 →ProcessScript位于 RSDKv3/Script.cpp#L2200另外项目开启了RETRO_USE_COMPILER意味着内置了文本脚本编译器ParseScriptFile、ConvertIfWhileStatement等函数RSDKv3/Script.hpp会把类似 C 的文本脚本在加载期转成字节码——这也是 Mod 开发者能写自定义脚本的原因。配套的 ModAPI 模块RSDKv3/ModAPI.cpp则让 Mod 可以注入脚本调用引擎能力。结语RSDKv3 脚本引擎用不到 5000 行 C 就实现了一台完整的字节码虚拟机压缩字节码 跳转表 双重栈 变量编码解析正是这套设计让《索尼克CD》里每个敌人、每段过场都成为可被 Mod 修改的脚本资产。读懂ProcessScript这一个函数你就掌握了整个游戏的行为引擎。【免费下载链接】Sonic-CD-11-DecompilationA Full Decompilation of Sonic CD (2011) Retro Engine (v3)项目地址: https://gitcode.com/gh_mirrors/so/Sonic-CD-11-Decompilation创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表