当前位置:网站首页>FC 游戏机的工作原理是怎样的?
FC 游戏机的工作原理是怎样的?
2020-11-09 00:28:00 【shzwork】
(NES PPU)
做一个简单计算:
分辨率256x240 = 61440,即画面上有这么多个像素点。(忽略NTSC系统损失的16行,PAL系统上是256x240)
我们如果只显示黑白,即每个像素非黑即白,那么单像素一个bit就可以了,这么大的分辨率下,一共需要1 * 61440 / 8 / 1024 = 7.5KB,要是直接这么干黑白点都装不下主机显存,当时好点的电脑勉强差不多。
假设我们用现在非常普通的256色,即8个二进制位,一个字节存储,整个画面61440 / 1024 = 60KB,这在FC时代是任何普通机器都不能直接做到的。
为了显示彩色,当时的不同机器有各种技术手段,可以说八仙过海各显神通。FC用的第一种手段叫做Color Cell,具体来说:
- 将整个图像分割成许多8x8的小cell (或者叫tile)
- 每个cell内至多有4种颜色
这样,每个像素只用2bit来存储色彩,然后对一共 32x30 = 960 个cell再分配色彩编码,指示有哪几种颜色。
举个栗子,我们熟悉的恶魔城 (Castlevania, 1986) 开场:(图片来自[dustmop.io blog])
图中最小的格子(所有明暗线分割出的)即一个cell或tile,四个tile组成一个block(仅亮线分割出的)。图中一共用了10种颜色。你绝对找不出用了超过4种颜色的cell。
再看一个我顶我顶:
编码后的cell表将存储在显存所谓name table区域中,刚才的恶魔城开场的区域编码成形如下图所示:
FC第二个高明的地方在于领先时代的滚屏技术,由于PPU内部有两个(镜像后是四个)name table来存储cell表信息,我们可以一直预先存储着超过显示部分的内容,在玩家或者程序触发滚屏操作后,通过向两个寄存器PPUSCROLL和PPUCTRL写相关信息,即可移动游戏镜头。
在FC之前的主机,滚屏操作几乎都要覆写整块屏幕,代价高昂。FC的出现同时使得动作、射击型游戏得到极大发展。
最后一个部分是游戏中运动的Sprite,存储于显卡的特定内置存储区域,通常单个大小为8x8或8x16,我们看到的主角们大都是多个Sprite拼到一起的,比如Mario实际上是4个Sprite拼出来的,只是在程序中保证不会散架。
Sprite的显示是覆盖背景的,无论背景如何设置,在PPU进行Sprite探测后都会将对应位设置成Sprite的色彩。
最后,btw,基本上所有的FC/NES开发资料都能在NES dev和其附属wiki上找到,只是没有相关专业知识可能比较难啃。
国人的《任天堂游戏编程探秘》一书总的来说还是比较详细的,然而很多关键之处却语焉不详,且花了很多篇幅教怎么写代码。对于外行来说还好,对于专业人士就基本无用了。更重要的是,这本书几乎没有讲任何Rationale的东西,对于真正的学习是灾难性的。
http://nesdev.com/NESDoc.pdf
这个文档里基本把原理都写出来了。核心是CPU(Central Processing Unit)和PPU(Picture Processing Unit),PPU的设计很精妙。
Github上有各种版本的NES模拟器源码,通过这些代码你可以更清晰的理解NES的运行过程:
- go + OpenGL视频 + PortAudio音频 :fogleman/nes · GitHub
- javascript + dynamicaudio音频:bfirsh/jsnes · GitHub
- Rust : pcwalton/sprocketnes · GitHub
- C++ :Cephas1982/NES · GitHub (这个还没做完)
FC使用理光开发的图像控制器(PPU),有 2KB 的视频内存,调色盘可显示 48 色及 5 个灰阶。一个画面可显示 64 个角色(sprites) ,角色格式为 8x8 或 8x16 个像素,一条扫描线最多显示 8 个角色,虽然可以超过此限制,但是会造成角色闪烁。背景仅能显示一个卷轴,画面分辨率为 256x240 ,但因为 NTSC 系统的限制,不能显示顶部及底部的 8 条扫描线,所以分辨率剩下 256x224。
从体系结构上来说,FC有一个伪声音处理器(pseudo-Audiom Processing Unit,pAPU),在实际硬件中,这个处理器是集成在2A03 NMOS处理器中的[2]。pAPU内置了2个几乎一样(nearly-identical)的矩形波通道,1个三角波通道,1个噪声通道和1个音频采样回放通道(DCM,增量调制方式)[2]。其中3个模拟声道用于演奏乐音,1个杂音声道表现特殊声效(爆炸声,枪炮声等),音频采样回放通道则可以用来表现连续的背景音。
FC主机上有一个复位开关、1个电源开关、1个游戏卡插槽、2个带有十字方向键的2键手柄(游戏控制器),主手柄上有“选择”和“开始”按钮。主机背面有电源接口、RF射频输出接口、视频图像输出接口、音频输出接口。前面还有一个扩展端口,用于连接光线枪、附加连发手柄等外部设备。
FC游戏通常以只读内存形式存放于可插在主机插槽上的游戏卡中,容量有LA系列24K,LB系列40K,LC系列48K,LD系列64K,LE系列80K,LF系列128K,LG系列160K,LH系列256K,特卡系列和多合一卡带等。还有一些带有电池用来保存游戏进度。
1986年2月21日,任天堂还推出了一款FC磁碟机,可以在FC主机上通过转换器使用专用的软驱来读写游戏,软盘容量为112KB。
版权声明
本文为[shzwork]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/4000302/blog/4708432
边栏推荐
- 表连接
- 实现图片的复制
- Database design: paradigms and anti paradigms
- Save code
- Introduction to nmon
- App crashed inexplicably. At first, it thought it was the case of the name in the header. Finally, it was found that it was the fault of the container!
- 如何让脚本同时兼容Python2和Python3?
- 写时复制集合 —— CopyOnWriteArrayList
- VIM 入门手册, (VS Code)
- android开发中提示:requires permission android.permission write_settings解决方法
猜你喜欢
AQS 都看完了,Condition 原理可不能少!
Leetcode-15: sum of three numbers
Fiddler can't grab requests from browsers like Google_ Solution
Salesforce connect & external object
C / C + + Programming Notes: pointer! Understand pointer from memory, let you understand pointer completely
分库分表的几种常见玩法及如何解决跨库查询等问题
App crashed inexplicably. At first, it thought it was the case of the name in the header. Finally, it was found that it was the fault of the container!
On buffer overflow
Leetcode-11: container with the most water
数据库设计:范式与反范式
随机推荐
The vowels in the inverted string of leetcode
梁老师小课堂|谈谈模板方法模式
Factory Pattern模式(简单工厂、工厂方法、抽象工厂模式)
基于链表的有界阻塞队列 —— LinkedBlockingQueue
Using annotation + interceptor to implement asynchronous execution
信息安全课程设计第一周任务(7条指令的分析)
Five design patterns frequently used in development
华为HCIA笔记
国内三大云数据库测试对比
一堆代码忘了缩进?快捷方式教你无忧无虑!
STC转STM32第一次开发
架构中台图
构造函数和原型
通过canvas获取视频第一帧封面图
Introduction skills of big data software learning
How to make scripts compatible with both Python 2 and python 3?
leetcode之反转字符串中的元音字母
Dynamic ReLU:微软推出提点神器,可能是最好的ReLU改进 | ECCV 2020
Concurrent linked queue: a non blocking unbounded thread safe queue
Test comparison of three domestic cloud databases