使用c++模拟红白机——概论篇(一)

news/2024/12/2 16:01:38/

  任天堂的红白机系列的游戏应该是大家的童年了,红白机,又称FC,随着计算机技术的不断发展,现在市场上基本已经淘汰了红白机系列的硬件设备了。我偶尔的一个突发奇想,想要在体验一下红白机游戏的乐趣,于是乎我想到了用c++来实现一个模拟器的环境。

  众所周知,红白机是一个比较简单的计算机系统,它由CPU,PPU,ROM,外设,卡带,显示器等组成。CPU当然是用来处理命令信息的,FC的CPU是6502,PPU相对来说可能对大家来说比较新奇一点 ,它的全称是图像控制器,可以把它当成是计算机中的显卡,它的显存是2KB,外设自然是大家手中的那个手柄,而卡带和显示器相信大家都明白它们的含义,就不在赘述。

  上面已经大体上介绍了FC的大致组成,下面就正式进入模拟器的主体部分——CPU的模拟。

  FC的CPU型号是6502,在模拟之前我们自然首先要清楚它的性能。大家肯定都学习过计算机组成原理,明白我们的的这个CPU是一个很典型的冯诺依曼结构,并且肯定也知道CPU中有地址总线,数据总线和各种寄存器,我们的6502CPU地址线是16位,数据线是8位(其寻址范围是多少?),它的寄存器也比较少,只有6个,分别是A,X,Y,P,SP,PC。这里只有PC(程序计数器)比较特殊,是16位的,而其他的寄存器都是8位的。SP是堆栈指针。一般堆栈空间分配在0x01FF~0x0100,堆栈的低8位是SP高8位是0x01。 6502的堆栈是向下增长的。P寄存器就是PSW处理器的状态位。A、X和Y是数据寄存器。那我们知道了这些基础知识之后应该要怎样去模拟6502CPU的工作环境呢?

       首先,FC要加载模拟器的日志文件,如下:

    std::ofstream logFile ("simplenes.log"), cpuTraceFile;sn::TeeStream logTee (logFile, std::cout);if (logFile.is_open() && logFile.good())sn::Log::get().setLogStream(logTee);elsesn::Log::get().setLogStream(std::cout);sn::Log::get().setLevel(sn::Info);

日志文件加载完毕之后,就轮到了我们的CPU开始工作了

        else if (std::strcmp(argv[i], "--log-cpu") == 0){sn::Log::get().setLevel(sn::CpuTrace);cpuTraceFile.open("sn.cpudump");sn::Log::get().setCpuTraceStream(cpuTraceFile);LOG(sn::Info) << "CPU logging set." << std::endl;}

接着,就到了显示画面这一环节,这其中包括画面宽度,高度,缩放等的设置,

        else if (std::strcmp(argv[i], "-s") == 0 || std::strcmp(argv[i], "--scale") == 0){float scale;std::stringstream ss;if (i + 1 < argc && ss << argv[i + 1] && ss >> scale)emulator.setVideoScale(scale);elseLOG(sn::Error) << "Setting scale from argument failed" << std::endl;++i;}else if (std::strcmp(argv[i], "-w") == 0 || std::strcmp(argv[i], "--width") == 0){int width;std::stringstream ss;if (i + 1 < argc && ss << argv[i + 1] && ss >> width)emulator.setVideoWidth(width);elseLOG(sn::Error) << "Setting width from argument failed" << std::endl;++i;}else if (std::strcmp(argv[i], "-H") == 0 || std::strcmp(argv[i], "--height") == 0){int height;std::stringstream ss;if (i + 1 < argc && ss << argv[i + 1] && ss >> height)emulator.setVideoHeight(height);elseLOG(sn::Error) << "Setting height from argument failed" << std::endl;++i;}

最后,则是要加载我们即将要开始玩的游戏的路径并设置玩家1和玩家2的键盘操作,运行该游戏。然后我们就可以开心的享受欢乐的游戏时光了。

    sn::parseControllerConf("keybindings.conf", p1, p2);emulator.setKeys(p1, p2);emulator.run(path);

 


http://www.ppmy.cn/news/165218.html

相关文章

使用C++实现FC红白机模拟器 Cartridge 与 Mapper(实现篇)

(继上篇&#xff1a;原理篇&#xff0c;下&#xff1a;实现篇) 2. Cartridge 与 Mapper的实现 首先我们在QT中创建两个类&#xff0c;Cartridge 与 Mapper类&#xff1a; Cartridge 类负责加载和解析ROM&#xff0c;因为CPU和PPU的内存映射都有指向卡带的部分&#xff08;如…

【游戏开发实战】重温红白机经典FC游戏,顺便教你快速搭建2D游戏关卡(Tilemap | 场景 | 地图)

文章目录 一、前言&#xff1a;童年的回忆二、本文Unity制作的效果三、情怀来了&#xff0c;想玩FC游戏1、下载FC模拟器&#xff0c;推荐nestopia2、启动nestopia3、下载FC卡带包&#xff1a;76合1&#xff08;76in1&#xff09;4、载入卡带&#xff08;.nes&#xff09;5、设置…

nes 红白机模拟器 第1篇

对比了很多种&#xff0c;开源的 NES 模拟器 VirtuaNES , nestopia , FakeNES , FCEUX , InfoNES , LiteNES 最后决定使用 LiteNES 进行移值&#xff0c;它是由 mynes 移值而来。LiteNES 对 mynes 代码进行整理兼容了 C99 标准&#xff0c;编译时无警告。 https://github.com/N…

使用C++实现FC红白机模拟器 Cartridge 与 Mapper(原理篇)

1. 认识nes文件 我们既然是模拟&#xff0c;就不可能使用实体的卡带硬件。那我们如何获取游戏文件呢&#xff1f;好在已经有人为我们准备好了&#xff08;心怀感恩&#xff09;。 .nes文件是NES&#xff08;FC&#xff09;的rom文件&#xff0c;关于它的来龙去脉这里就不做详细…

童年经典,任天堂switch红白机游戏

相信很多90后的小伙伴应该玩过任天堂的游戏&#xff0c;比如魂斗罗&#xff0c;影子传说等&#xff0c;如图&#xff1a; 今天小编就给大家带来了这么一个红白机的JavaScript版本&#xff0c;我们可以直接在浏览器中玩&#xff0c;当然你也可以在模拟器中玩&#xff0c;这里…

大数据教程【05.01】--Python 数据分析简介

更多信息请关注WX搜索GZH&#xff1a;XiaoBaiGPT Python数据分析简介 本教程将介绍如何使用Python进行大数据分析。Python是一种功能强大且易于使用的编程语言&#xff0c;具备丰富的数据分析库和工具。在本教程中&#xff0c;我们将涵盖以下主题&#xff1a; 数据分析准备工作…

2023年上半年系统规划与管理师上午真题及答案解析

1.香农用概率来定量描述信息的公式如下&#xff0c;其中H(x)表示X的( )&#xff0c;Pi是( )出现第i种状态的( )。 A.信息熵 事件 概率 B.总熵 单位 概率 C.信息熵 单位 概率 D.总熵 单位 度量 2.信息传输模型中&#xff0c;( )负责信息的向外传播&#xff0c;( )负责…

代码随想录算法训练营15期 Day 10 | 理论基础、232.用栈实现队列、225. 用队列实现栈

理论基础 队列是先进先出&#xff0c;栈是先进后出。 四个问题&#xff1a; C中stack 是容器么&#xff1f;我们使用的stack是属于哪个版本的STL&#xff1f;我们使用的STL中stack是如何实现的&#xff1f;stack 提供迭代器来遍历stack空间么&#xff1f; 栈和队列是STL&am…