实现 NES 中的一些笔记:nametable 的 mirror 计算

实现 NES 中的一些笔记:nametable 的 mirror 计算

💡 原文中文,约4200字,阅读约需10分钟。
📝

内容提要

本文介绍了NES红白机中nametable的镜像计算,包括渲染过程、分辨率、Pattern Table和Attribute Table的作用,以及四个nametable的布局和镜像计算方式。作者还提供了两种计算方式的代码和性能测试结果,并总结了古早系统中为了性能而采用的各种技巧。

🔎

延伸解读

镜像计算的实际意义

NES 的 PPU 只有 2KB VRAM,却要管理四个 nametable(理论 4KB),因此必须通过镜像将部分 nametable 映射到同一物理内存。垂直镜像让 C 映射到 A、D 映射到 B;水平镜像让 B 映射到 A、D 映射到 C。这种复用背景的方式节省了宝贵的内存,但也要求开发者在写地址时清楚当前镜像模式,否则背景显示会出错。

两种实现方式的取舍

文章对比了哈希表查表和纯算术两种镜像地址计算。哈希表方法直观,但需要额外存储映射表,且每次计算涉及多次寻址,在 70 年代硬件上开销较大。新方法利用取模和位运算直接推导地址,无需额外空间。不过作者也提醒,在 Python 中位运算不一定更快,最终用 C 测试才验证了性能提升,说明优化效果与语言和平台密切相关。

性能测试的启示

作者在 C 语言下对两种方法各运行一亿次,新方法耗时约 251868 微秒,旧方法约 355402 微秒,提升约 30%。这个结果符合预期,但也说明优化幅度并非数量级。对于现代模拟器或高性能环境,这种差异可能微不足道;但在 NES 实机或资源受限的嵌入式场景中,减少一次查表和额外存储仍有实际价值。

❓

Q&A

NES红白机的屏幕分辨率是多少?

NES红白机的屏幕分辨率为256x240。

什么是nametable的镜像计算?

nametable的镜像计算是为了复用背景图案,通过映射不同的nametable地址来减少内存使用。

NES中使用的Attribute Table有什么作用?

Attribute Table用于存放每个tile的属性,如颜色和翻转信息。

有哪些常见的镜像计算方式?

常见的镜像计算方式有垂直镜像和水平镜像。

新方法的镜像计算性能如何?

新方法比旧方法快约30%。

如何优化镜像计算的代码?

通过位运算和模运算简化了水平镜像的计算逻辑,减少了寻址操作。

🏷️

标签

➡️

继续阅读