【SMB源码解析系列】——001.JumpEngine函数
在SMB的源码中大概有不到20处看起来很奇怪的指令,它的格式是通过jsr指令调用一个名为JumpEngine的函数,其后并不是跟随某些后续的逻辑指令,而是通过.dw定义了一系列16位地址。

我们可以看到在jsr指令之前,还会将某个值写入A寄存器。
JumpEngine函数本身代码并不长:

让我们来看看这段函数到底做了什么:
1.将A寄存器的值乘以2,然后写入Y寄存器;
2.从栈中取出2字节数据,分别写入$04、$05,然后将Y寄存器的值+1;
3.通过"后索引间接寻址"方式,将($04),y中的数据写入到$06中,又将($04),y+1处的数据写入$07中;
4.通过"间接寻址"方式,跳转至($0006)处执行代码。
原本我们如果在966行处调用了jsr指令(此时会先将指令所在地址$8234+2=$8236推入栈中),按正常流程应该在跳转至JumpEngine之后某处调用一次rts指令(把栈中的$8236取出并+1得到$8237),然后程序会跳转至$8237处继续执行。
但在第二步,我们将栈中的信息手动取出($8236),存入了$04、$05,并将Y寄存器+1,如果OperMode_Task的值是0的话,此时$04、$05中保存的值是$8236,Y寄存器的值为0*2+1=1,lda ($04),y就相当于是把$8236+1=$8237处的数据取出来写入$06,接着又将($04),y+1也就是$8238处的值取出来,写入$07。
这时我们就发现,968行通过.dw定义的16位地址InitializeGame已经被写入$06、$07中了。
最后通过唯一的一个间接寻址指令jmp ($0006)我们就跳转到了InitializeGame继续执行代码。
程序中的其他地方,可能会修改OperMode_Task的值为1,这样第二步Y寄存器的值最终为1*2+1=3,第三步就是把$8239,$8240处的值(ScreenRoutines)取出来了。目前看来这种方式最长可以通过.dw定义100多个函数地址~
SMB中就是依靠JumpEngine函数,让程序按照某个顺序逐一执行,序列化的完成了整个游戏逻辑的控制。不过我觉得这更像是在射击CPU硬件逻辑时就设计好的一个"语法糖",因为这个函数的思路和指令的实现逻辑结合的实在是太完美无缺了,当然这只是我的个人臆想罢了。
【SMB源码解析系列】——001.JumpEngine函数的更多相关文章
- 【SMB源码解析系列】——003.SMB游戏基本框架
前面有了解到RESET中断相关代码,结尾处通过一句jmp进入了无限循环,之后CPU将会在每一帧PUU进入VBlank状态时,接收NMI中断信号, 跳转至NMI代码处继续执行,直到遇见RTI指令时又返回 ...
- 【SMB源码解析系列】——004.AreaParserTaskControl行列绘制控制程序
前提知识: 任天堂游戏系统的画面分辨率是256*240像素,基本的显示单位是tile,包含8x8=64个像素 根据电视机的制式不同,NTSC制式只显示256*224,也就是32x28个tile,画面的 ...
- 【SMB源码解析系列】——002.RESET中断
跟随代码结尾处的中断向量,我们可以看到RESET中断所在地址为Start标签处. 这部分代码比较简单,从字面便可基本理解. 1.(682~683)状态寄存器设置,sei指令用于禁用IRQ中断,SMB中 ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
- 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新
上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...
- 【安卓网络请求开源框架Volley源码解析系列】定制自己的Request请求及Volley框架源码剖析
通过前面的学习我们已经掌握了Volley的基本用法,没看过的建议大家先去阅读我的博文[安卓网络请求开源框架Volley源码解析系列]初识Volley及其基本用法.如StringRequest用来请求一 ...
- 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新
本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...
- Cwinux源码解析系列
Cwinux源码解析系列
- TiKV 源码解析系列文章(三)Prometheus(上)
本文为 TiKV 源码解析系列的第三篇,继续为大家介绍 TiKV 依赖的周边库 rust-prometheus,本篇主要介绍基础知识以及最基本的几个指标的内部工作机制,下篇会介绍一些高级功能的实现原理 ...
随机推荐
- 《并发编程的艺术》阅读笔记之Sychronized
概述 在JDK1.6中,锁一共四种状态,级别由低到高依次是:无锁状态.偏向锁状态.轻量级锁状态和重量级锁状态.锁可以升级但不能降级,这是为了提高获得锁和释放锁的效率.只有重量级锁涉及到操作系统线程切换 ...
- redis:key命令(二)
设置一个key:set name hello 获取一个key的值:get name 查看所有的key:keys * 查看key是否存在:exists name 移动key到指定库:move name ...
- MAC地址欺骗(原理及实验)
MAC地址欺骗 MAC地址欺骗(或MAC地址盗用)通常用于突破基于MAC地址的局域网访问控制,例如在交换机上限定只转发源MAC地址修改为某个存在于访问列表中的MAC地址即可突破该访问限制,而且这种修改 ...
- Linux系统硬件时间12小时制和24小时制表示设置
目前的服务器status是下面这样的 服务器系统 centos7 Linux系统时间 Fri Mar 20 15:26:27 CST 2020 Linux系统硬件时间 Fri 20 ...
- Openstack object list 一次最多有一万个 object
When you request a list of containers or objects, Object Storage returns a maximum of 10,000 names f ...
- java 8中 predicate chain的使用
目录 简介 基本使用 使用多个Filter 使用复合Predicate 组合Predicate Predicate的集合操作 总结 java 8中 predicate chain的使用 简介 Pred ...
- CUBA:如何准备上线
"在我电脑上是好的呢!"现在看来,这句话更像是调侃开发人员的一个段子,但是"开发环境与生产环境"之间的矛盾依然存在.作为开发者,你需要记住,你写 ...
- 【EditPlus】参数设置
1. 设置javac,java快捷键 工具-参数设置-工具-用户工具 组和工具项-组名,更改组名为“java” 添加工具 javac 菜单文字:javac 命令:安装java的javac.exe的绝对 ...
- mac OS 配置Apache服务器
Mac自带了Apache环境 查看Apache版本 sudo apachectl -v 在终端输入:sudo apachectl start 在浏览器输入"http://localhost& ...
- 数学--博弈论--巴什博奕(Bash Game)
终于也轮到我做游戏了,他们做了好几个月的游戏了. 巴什博弈: 两个人做游戏,取石子,一个人最多可以可以取M个,至少取1个,最后取完的赢. 显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先 ...