wasm nes-模拟器 内存修改 简易八门神器/CE

576 阅读2分钟

前因

吃饭排队的时候和小伙伴聊到以前用的游戏修改器, 在讨论实现方式的时候想到同样的思路在wasm中也可行, 之前做nes进度保存时稍微了解过wasm的内存, 经过测试此思路可行

效果

在游戏运行中修改了命数, 这个修改是有效的, 不仅仅只是UI显示上的效果, 通过控制台 setLife 函数修改生命

实现思路

wasm 的 nes模拟器

这里用的rust版本, github.com/bokuweb/rus…

操作wasm内存

wasm内存对js完全透明, 可以直接操作

const b = new Uint8Array(wasm.memory.buffer);
b[1332212] = n;

找目标数据地址

玩游戏的过程中, 在目标数据变化时把整个内存下载下来, 由于js和wasm是同步的所以不担心拷贝过程中其他线程修改数据

下载后的文件用于分析, 比如 1.mem, 2.mem, 3.mem 分别表示命是1,2,3的内存

对内存数据逐字节遍历, 把所有符合要求的地址都加到set里, 然后对三个set求交集, 得到最终地址, 理想情况下只会有一个地址, 也可能会有多个, 更多时候没有交集, 此时需要转换思路用其他办法找数据

  • 一般命都是两位数, 刚好一个字节255能放下, 如果不加其他信息一个uin8就是命的值, 但那个时候内存都很珍贵, 所以可以用第一个字节表示玩家AB, 这时就需要用int8, 甚至可能8个字节里面只有6个有效位, 其他两位有特殊含义的就稍微麻烦点
  • 考虑到内存最终都是01, 所以可以将内存全部转成01数组, 然后在这个01数组中找对应数据的01串出现的位置, 将这个位置作为指针, 这种会比较慢但效果会好点, 因为一个字节里如果是混合信息的话这种方式也能找得到

胡言乱语

  • wasm和js内存共享个人觉得还是很方便且高效的, 之前有试过将这个nes模拟器用tauri实现, 但是没找到tauri如何和js共享内存, 每次通信都要传一个大的buffer, 导致卡的不能玩, wasm就很方便, 传一个指针就行, js直接在内存里面捞数据非常快
  • 其实之前先尝试的是马里奥, 马里奥第一关有加命蘑菇, 想着数据能多一点, 但是试了好多方法都没成功, 最后抱着试一试的想法换成冒险岛, 结果一下就成功了, 这块涉猎不深, 要是小伙伴有思路的话也欢迎交流哈~
  • 话说有啥办法让wasm只能在特定的网站上生效吗?