[FC][SRAM扩容教程(Mapper 4为例)]
[FC][SRAM扩容教程(Mapper 4为例)]
时间:2017.4.28
作者:FlameCyclone
工具:FCEUX 2.2.3,Hxd 1.7.7.0,6502_Simulator
ROM:双截龙2(J).nes
适用:没有使用SRAM的ROM
首先用Hxd打开ROM:
然后扩容:
先看看任天堂产品系统文件对NES文件的说明:
NES文件格式
.NES文件为模拟用来储存NES卡带的映像。下面是一个.NES文件的结构。
偏移 |
字节数 |
内容 |
0-3 |
4 |
字符串“NES^Z”用来识别.NES文件 |
4 |
1 |
16kB ROM的数目 |
5 |
1 |
8kB VROM的数目 |
6 |
1 |
D0:1=垂直镜像,0=水平镜像 |
D1:1=有电池记忆,SRAM地址$6000-$7FFF |
||
D2:1=在$7000-$71FF有一个512字节的trainer |
||
D3:1=4屏幕VRAM布局 |
||
D4-D7:ROM Mapper的低4位 |
||
7 |
1 |
D0-D3:保留,必须是0(准备作为副Mapper号^_^) |
D4-D7:ROM Mapper的高4位 |
||
8-F |
8 |
保留,必须是0 |
16- |
16KxM |
ROM段升序排列,如果存在trainer,它的512字节摆在ROM段之前 |
-EOF |
8KxN |
VROM段, 升序排列 |
然后知道这个ROM有0x08个PROM和0x10个VROM
接下来扩展PROM位0x10个:
先把第0x04字节改为0x10,0x06字节的D1位置1(设置有SRAM):
由于mapper4的ROM在模拟器载入时会把最后16KB载入到整个64KB内存的C000-FFFF,因此需要在最后的16KB PROM(0x4000)前添加8x16KB PROM(0x20000大小),然后跳转到最后一个PROM的头部:偏移计算:
最后一个PROM的头部 = (总PROM数 - 1) x 0x4000 + 文件头0x10字节。
于是可以得到双截龙2的是:
(8-1)x 0x4000 + 0x10 = 0x$1C010。
然后跳转到$1C010:
然后插入0x20000字节的0xFF:
然后保存:
用FCEUX打开正常运行:
查看文件信息:
接下来切页:
先打开十六进制编辑器:
中断地址 |
中断 |
优先权 |
$FFFA |
NMI |
中 |
$FFFC |
RESET |
高 |
$FFFE |
IRQ/BRK |
低 |
把滑块拉到最后,看看RESET重启中断:
RESET中断是ROM载入模拟器后最先开始运行的地方,只运行一次。
由此可知双截龙2的RESET中断$FF65。
接下来添加$FF65的执行断点:
打开调试器:
添加$FF65的执行断点:
单击确定:
然后重启ROM:
调试器此时弹出来:
然后打开Hxd,写一段mapper 4的切换bank的程序:
先看看mapper 4的说明文档:
Mapper 4
$8000: 模式号
位D0-D2:
0:选择2KB的VROM存储体映射到PPU的$0000
1:选择2KB的VROM存储体映射到PPU的$0800
2:选择1KB的VROM存储体映射到PPU的$1000
3:选择1KB的VROM存储体映射到PPU的$1400
4:选择1KB的VROM存储体映射到PPU的$1800
5:选择1KB的VROM存储体映射到PPU的$1C00
6:选择8KB的ROM存储体映射到$8000
7:选择8KB的ROM存储体映射到$A000
位D6:
0:允许擦写$8000和$A000
1:允许擦写$A000和$C000
位D7:
0:模式号D0-D2使用普通地址
1:模式号D0-D2地址异或$1000
$8001: 模式页面号
写入一个数(00-07),切换存储体到对应地址
$A000: 镜像选择
0:垂直镜像
1:水平镜像
$A001: SaveRAM 切换
0:禁用$6000-$7FFF
1:启用$6000-$7FFF
$C000: IRQ计数器
IRQ计数器的值存储在此处
$C001: IRQ暂存器
IRQ暂存器的值存储在此处
$E000: IRQ控制计数器0
向这里写入任何数来关闭IRQ,并从暂存器中拷贝数据开始计数,进入IRQ
$E001: IRQ控制计数器1
向这里写入任何数,允许IRQ(退出IRQ,允许下一个IRQ进来)
那么就写段切页到$8000-$9FFF,然后跳转到$8000的切bank程序:
48 A9 06 8D 00 80 A9 0E 8D 01 80 20 00 80 68
PHA 累加器A入栈
LDA #$06 设置切bank地址为$8000-$9FFF
STA $8000
LDA #$0E 将第0x0E号bank切到$8000-$9FFF
STA $8001
JSR $8000 跳转到子程序$8000
PLA 累加器A出栈
为何切换的bank号是0x0E呢?
因为在扩容ROM后,文件PROM结构为:
原来的0x07个16KB PROM + 自己的0x08个 16KB PROM + 原来的最后0x01个16KB PROM
Mapper 4切bank一次是切8KB,那么文件结构就是:
原来的0x0E个8KB PROM (00-0D) + 自己的0x10个8KB PROM (0E-1D) + 原来的最后0x01个8KB PROM (1E-1F)
因此选择扩容的第一个空白bank就是0x0E号bank。
然后去调试器找RESET中断中可以放下切页程序的地方:
首先长度要小于等于自己写的切页程序。
可以看到$FF7C可以使用(一般找程序中已经禁用中断后的地方,也就是找使用了SEI指令后的地方)
然后跳转到$FF7C:
复制下可以被替换用于写切页的程序:
先选中,再复制:
在Hxd中新建一个文件,把复制的数据粘贴上去:
然后回到十六进制模拟器:
转到$FF7C对应的ROM地址:
然后复制Hxd的切页程序,粘贴到这里:
没有覆盖的用EA覆盖:
打开调试器可以看到变化:
然后添加$FF7C执行断点:
单击运行:
然后程序在$FF7C这里停下来了。
然后单击单步进入慢慢跟踪,直到跳转到$8000:
然后打开6502_Simulator:
再打开我写的数据搬移程序:
然后修改对应的数据:
程序开始地址:修改比如$8100就修改为 .ORG $8100
复制到什么地方就修改Addr_To,比如复制到$7000: .BYTE $00,$70
从哪里开始复制就修改Addr_Begin,比如从$8200开始复制: .BYTE $00,$82
想到哪里结束复制就修改Addr_End,比如复制的数据源地址到$91FF: .BYTE $FF,$91
也可以直接修改为 .BYTE $FF,$FF(复制目的地址到7FFF时会结束复制的)。
如果复制的数据最终超过7FFF,那么程序会结束复制,7FFF后面是程序块,不能乱搞。
中断地址可以不管,因为在RESET中中断已经禁用了,程序不会被中断。
后面的不用管。
设置完数据后单击编译:
然后保存编译文件:
选择二进制方式保存:
用Hxd打开保存的二进制文件:
跳转到设置的程序开始$8100:
回到FCEUX,转到NES内存的$8100对应的ROM地址:
然后把Hxd里编译的数据搬移程序复制后粘贴到ROM里:
然后转到NES内存的$8000对应的ROM地址:
写上如下程序:
A9 80 8D 01 A0 20 00 81
LDA #$80
STA $A001 可写方式开启SRAM
JSR $8100 跳转到子程序$8100
然后把Hxd里被覆盖的程序复制过来粘贴在后面:
末尾补上一个0x60:
RTS 子程序返回
然后单击运行,ROM音乐响起,正常运行:
然后转到NES地址$7000:
可以看到,$7000-7FFF都被复制了一片数据。
测试没有问题,然后保存文件:
以上就是Mapper 4 的复制数据到SRAM($6000-$7FFF)教程的全部讲解。
后期修改ROM时遇到没有空间写程序时可以使用此方法进行扩容,将自己的其他程序放在 复制开始地址 至 复制结束地址 之间,这样ROM载入模拟器后会执行一次数据复制程序,把自己的程序复制到$6000-7FFF之间,后面的修改只需要跳转到$6000-$7FFF之间自己写的程序那儿就可以了。
[FC][SRAM扩容教程(Mapper 4为例)]相关推荐
- FC按键修改教程之一键开关
FC按键修改教程之一键开关 一.需要具备的知识:懂6502汇编,不需要精通,至少会使用比较指令,传送指令,逻辑运算,跳转指令等. 二.需要用到的工具: FCEUX 2.2.1.2807汉化绿色版(非常 ...
- android手机的扩容教程,解决手机系统空间不足
android手机的扩容教程,解决手机系统空间不足问题 --通过将手机中的应用搬到SD卡中实现手机扩容 在智能手机中,android手机从市场占有率来看占有绝对优势,然而随着使用时间的增加,许多用户也 ...
- [FC][移动速度修改教程]
[FC][移动速度修改教程] 时间: 2016.06.11 作者:FlameCyclone 工具:FCEUX,实验ROM一个; 1.打开rom(魂斗罗为例): 2.找到任务移动坐标: 找到坐标为033 ...
- MapServer Tutorial——MapServer7.2.1教程学习——第一节用例实践:Example1.5 Adding a raster layer...
MapServer Tutorial--MapServer7.2.1教程学习--第一节用例实践:Example1.5 Adding a raster layer 一.前言 MapServer不仅支持 ...
- Java 结构体之 JavaStruct 使用教程二 JavaStruct 用例分析
使用环境 前一篇在介绍 JavaStruct 类时指定了使用库使用环境为 Java 5 及以上,也即开发我们使用的 JDK 版本为1.5及以上就可以了.以下讲解的用例可以直接将 code 直接粘贴到 ...
- python菜鸟教程100例-对菜鸟教程的Python一百例的个别改进
开篇语 好吧,其实是我小妹子Python公选课结课,所以我来帮忙做个大作业(简单到哭的大作业好吗?)!她的大作业就是老师把菜鸟教程的Python一百例扒下来做成文档,然后让学生自己找三个验证下!我们当 ...
- OPENWRT网络打印机TCP/IP共享设置教程 以703N为例
OPENWRT网络打印机TCP/IP共享设置教程以703N为例 前言 最近一台带USB2.0接口的惠普P1106激光打印机使我比较头疼,由于打印机放在家中楼上,没空调,夏天太热,每次抱着电脑上楼打印都 ...
- Python教程: while循环20例
Python教程: while循环20例 介绍 循环是计算机编程中最常用的结构之一.在Python中,有两种类型的循环:while循环和for循环.在本文中,我们将专注于while循环并提供20个实用 ...
- 《软件安装与使用教程》— Windows操作系统快速安装MATLAB最新最全教程(保姆级教程以MATLAB2019A为例)
<MATLAB教程>- Windows操作系统快速安装MATLAB(保姆级教程以MATLAB2019A为例) 目录 <MATLAB教程>- Windows操作系统快速安装MAT ...
最新文章
- 多行文本框拖动问题解决
- Centos下GCC引用mysql头文件和库文件
- python精要(79)-模块与包组织(2)-相对导入
- ivona tts语音合成引擎_高端玩家!树莓派 + Node.js 实现语音机器人
- 线程之间的通信(thread signal)
- 关于@PathVariable与@RequestParam
- [Linux: 编程]如何调试GCC段错误-转
- [air for ios] 三小时开发一个iOS飞行射击游戏
- EJB开发第一个无状态会话bean、开发EJB客户端
- Springboot结合ESAPI——配置XSS防御过滤
- c语言听课记录,听课笔记:初识C语言2
- Ubuntu解决RTNETLINK answers: File exists
- 欧姆龙CP1H 原点搜索和原点返回功能
- android edittext 输入手机号码格式变化
- 以太网采集欧姆龙PLC DM数据并存入ACCESS 使用C#编写上位机程序
- 《JavaScript实现页面图片滚动播放》
- java 打印菱形和空心菱形
- python 证书-python+证书
- python如何爬取糗事百科
- 控制电路中的紧急停止按钮,该用常开点NO还是常闭点NC?
热门文章
- demonstration记忆_托福阅读素材:婴幼儿期记忆缺失(社会科学篇)
- python迭代器和可迭代对象_python tips:迭代器与可迭代对象
- turtle中circle的用法_Python的turtle库的画图学习-附:五角星和太极图
- Linux内核之 内核同步
- 基于AD7792的pH在线监测传感器采集电路设计
- Python3学习(三十):python连接mysql数据库及相关操作
- 5G与物联网技术趋势分析
- 芯科(Silabs) Matter 全栈解决方案,附录高质量Matter培训资
- RAR文件格式(计算机数据恢复)
- 开心公寓房屋出租管理系统的设计与实现(系统源码+技术文档+论文)