首页 时政热点 科技头条 智能AI 安全攻防 数码硬件 开发者生态 归档 标签 关于

用 Odin 编写的 NES 模拟器

摘要

A NES emulator written in Odin I made a NES emulator in Odin ! Github link Intro I’ve started this project in late June of 2024. I’ve worked on it in my spare time off and on. I decided to put a pause...

the emulator NES and that project run about The Odin
2026-11-15 1 阅读 约6分钟阅读 frostbyte7
分享:
字号:
用 Odin 编写的 NES 模拟器 我用 Odin 制作了一个 NES 模拟器! Github 链接简介 我于 2024 年 6 月下旬开始了这个项目。我在业余时间断断续续地研究它。我决定在 2025 年 1 月暂停这个项目,专注于其他事情。我学到了很多关于:NES 架构,可能还了解游戏机架构的一般位和字节、十六进制表示法和按位运算。奥丁编程语言。我以前没有在严肃的项目中使用过它。计算机如何工作。 CPU 指令、“周期”等 仿真。这很难。向模拟器开发者致敬!这是一次疯狂的旅程。我玩得很开心,但在最后,当我试图让模拟器“完全”准确时,我也遭受了更多的痛苦。您可以阅读 Github 自述文件以获取有关该项目的更多信息。具有足够的仿真精度,可以完美运行 Battletoads 和数百种其他游戏。具有一些调试功能的调试器视图 与模拟器交互的菜单视图 保存状态 控制器支持 CRT 着色器切换(部分) 声音 支持的映射器:NROM、MMC1、UXROM、CNROM、MMC3、GxROM、AxROM 制作模拟器 我见过有人说制作 NES 模拟器是一个简单的周末项目,坦率地说,我发现这令人困惑。因为显然不是。我花了 7 个月的时间才让我的模拟器达到现在的样子。我认为他们真正的意思是让 NES 模拟器“工作”需要很短的时间。就像让大金刚跑起来一样。这是真的。您可以很快达到 80% 甚至 90%。最后10%需要很长很长的时间。 NES 硬件有许多特性,需要模拟这些特性才能运行某些游戏。许多游戏都依赖于非常特定的 NES 行为。如果你没有正确实施,他们就不会运行。很多挑战都与时间有关。 CPU 和 PPU(NES 中处理图形渲染的芯片)并行运行并相互通信。这个时机需要非常准确,否则可能会发生很多错误的事情。大多数游戏都可以在不太准确的模拟器上正常运行,但很多游戏都不能,并且它们需要您更详细地考虑问题。另一个问题是映射器。映射器是我们所说的一种盒式磁带的实现。你看,NES 游戏是装在卡带中的,而卡带不仅仅是数据。它们是具有自己的行为和额外资源(例如只读存储器和可写存储器)的电路。有些带有额外的音频功能,但我还没有实现。无论如何,如果您希望该卡带中的游戏在您的游戏中运行,则必须实现这些映射器。它们完成了 NES 的电路。在某种程度上,它们是 NES 硬件的一部分。有很多映射器,但只需实现几个就可以支持很多游戏。我在实现一些映射器时遇到了麻烦,其中一些仍然执行得很糟糕,导致一些游戏无法运行。我发现很难理解一些映射器文档。我认为制作模拟器的最大挑战是知道要实现什么。有关硬件的信息,以及需要模拟哪些硬件才能让游戏在模拟器中运行。值得庆幸的是,NES 的在线文档非常丰富。我使用了很多资源,例如:如果没有这些资源以及 nesdev 不和谐人员的帮助,我将无法完成这一切。 Odin 在制作这个项目时我学到了很多关于 Odin 的知识。我认为它就像手套一样适合这个项目。我觉得,作为一种非常简单、强类型的类 C 语言,它给了我想要的所有自由,使得制作模拟器比使用其他语言容易得多。让我失望的一件事是 Odin 没有自动整数提升。在进行数字计算时,Odin 永远不会将类型提升为更大的类型。这导致了一些错误。但我把这一切归咎于我和我习惯了 C 的整数提升。我学到的一件有趣的事情是制定一些内存分配策略。 Odin 没有自动内存管理,因此您必须想出聪明的方法来处理内存。我很高兴思考应该如何最好地处理记忆。我不需要做任何复杂的事情。我主要使用一个临时分配器来清除每一帧,一个全局堆分配器用于需要永远存在的东西,以及一个 NES Arena 分配器用于任何需要在 NES 会话中生存的东西。我发现内存分配很有趣。我必须学习的另一件事是如何序列化 Odin 对象。我使用了 CBOR 库,但遇到了一些问题。我认为我的代码由于库中的错误而行为异常,但现在已经解决了。它只是遇到了麻烦,因为我创建了一些奇怪的类型,它不知道如何序列化。一旦我学会了如何正确编写类型的自定义处理,一切都会完美运行。这是 cbor 不知道如何序列化的棘手类型之一: PpuCtrl :: struct #raw_union { // VPHB SINN using flags : bit_field u8 { n : u8 | 2、我:u8 | 1 , s : u8 | 1 ,
这篇文章对您有帮助吗?

订阅66必读

每日精选科技资讯,直达你的邮箱