如何学习编程游戏控制台模拟器(具体是硬件知识)?

时间:2012-10-29 18:03:51

标签: c console hardware emulation video-game-consoles

之前我曾问过一个类似的问题,关于如何编写模拟器,当我看到答案并查找一些开源游戏模拟器时,我发现除了对“低”的中间理解之外还有更多需要等级“语言(即C)。我真正想知道的是,我需要了解HARDWARE才能编程这样的模拟器。我正在接近Java的“相当不错”,但这对我没什么帮助。我已经开始学习C了,我现在已经走了很长一段路,但我很想知道我必须要在硬件上学习什么才能编写这样的控制台模拟器。

我问这个问题的原因是我一直在互联网上搜索有关模拟的书籍和来源,每当我遇到模拟器教程时,它总是喜欢“你需要对C有一个基本的了解能够遵循这个教程“当我尝试遵循它时我不能,因为我不知道到底是怎么编程的。我对硬件一无所知。 (我的父亲努力将他的显示器连接到他的电脑上,可能更了解它)

所以我的问题是,我需要学习什么(微处理器,内存等?)并且有没有任何好的资源可以教我这些东西,而不必为了它或其他东西上大学(已经做软件工程)?

如果这不是一个真正的问题,或者不够清楚,或者类似的话,我道歉。我对这个问题非常感兴趣。

4 个答案:

答案 0 :(得分:11)

认为这可能更适合programmers.stackexchange.com,但无论如何:

我不会说你需要任何具体的知识。了解微处理器和内存管理的工作方式将对汇编程序知识有很大的帮助(因为你实际上是在为汇编程序代码编写解释器)。假设您已经知道目标硬件是如何工作的,那么您基本上要做的就是实现以下组件(即假冒真实硬件并模仿/模仿它的行为):

  • 模拟CPU解析并运行机器代码。
  • 模拟输入组件(将键盘,鼠标或操纵杆输入等内容转换为CPU可访问的“引脚信号”)。
  • 模拟输出组件(将图像和音频数据转换为可见的内容,例如在屏幕上显示某些内容或生成类似真实硬件组件的声音)。
  • 模拟其他组件,如内存包,内置电池,盒式磁带,扩展芯片等。

作为一般建议,我会说忘记现在编写任何模拟器。而是通过尝试编写自己的字节码解释器来开始简单的事情。

例如,您可以使用简单的伪代码序列:

x = 5
y = 10
print(x + y)

用伪装配器编写,可能是这样的:

mov x, 5
mov y, 10
add x, y // to be honest, this is essentially x += y; not just x + y
prt x
end

现在用(代码)数字替换所有指令。所有变量都用数字代替:

0x01 0x00 0x05
0x01 0x01 0x0a
0x02 0x00 0x01
0x03 0x00
0x00

这可能看起来有点奇怪,但我保持了上面的顺序和换行符。请注意,我已将0x01用于第一条指令,而不是0x00。这只是为了方便,所以我可以使用0x00进行“NOOP / no操作”或作为终结符(如本例所示)。现在只需删除换行符,你最终会得到自定义字节码。

char code[] = {0x01, 0x00, 0x05, 0x01, 0x01, 0x0a, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00};

要运行此代码,您可以编写一个简单的“模拟器”。它只有一个有限的指令集,但它会工作。我实际上没有测试这段代码,所以请记住,我可能在某些时候搞砸了。但是,它应足以让您了解如何/如何做。请注意,在此示例中,我不分割数据存储器和指令存储器。这会增加现在不需要的复杂性。

int pos = 0; // essentially being our "instruction pointer"
char registers[10];
while(code[pos]) { // still some instruction
    switch(code[pos++]) { // determine what to do and move the instruction pointer
    // 0x00 isn't handled here, as that's part of our loop already
    case 0x01: // mov(e)
        registers[code[pos++]] = code[pos++]; // read the value into the register
        break;
    case 0x02: // add
        registers[code[pos++]] += registers[code[pos++]];
        break;
    case 0x03: // prn
        printf("%d", registers[code[pos++]]);
        break;
    }
}

一旦你理解我在这里做了什么,我很确定你应该更容易理解其他来源。哦,这是一个有趣的事实:如果你是出于教育目的而不仅仅是为了编写一个高效的模拟器,你可以开始使用Java。它将不那么优化和慢,但你基本上可以做同样的事情,甚至可能至少在你的路上移除障碍。

快速说明:在上面的例子中,你可以让第二个帖子不断在屏幕上写下registers[]的内容。这样你就可以基本上模拟一些视频硬件(例如电视屏幕或LED)。

如果您正在寻找更多可供阅读的资源,我会尝试使用一些简单的处理器并开始学习汇编程序代码。如果可能,选择一个非常简单的架构。概念总是相同的,但随着越来越多的指令集,地址空间虚拟化等事情可能会变得复杂。

答案 1 :(得分:1)

我建议学习汇编语言,以获得您需要的基本知识。如果你对例如super nintnedo感兴趣,你会尝试学习65816-assembly,它是该控制台使用的处理器的汇编语言。要开始使用,您可以在此处开始阅读:http://en.wikibooks.org/wiki/Super_NES_Programming。其他控制台也存在类似的资源。我还建议使用具有调试功能的仿真器,例如Geiger的调试snes9x,它将让您逐步执行游戏,转储它正在执行的操作,检查内存等。但这些都与编写控制台没有直接关系模拟器,它将为您提供一些您正在寻找的背景。

老实说,如果C看起来对你来说完全陌生,那么在尝试组装之前最好先学习一些。 C比汇编更抽象,但仍然会为你提供许多重要概念的基础,最重要的是指针。

但基本上,模拟器的作用是逐步执行游戏的机器代码,按指令执行指令。控制台是一个相当复杂的野兽,有几个处理器和协处理器以及相关的硬件协同工作。所以你应该从一个更简单的模拟器开始,它只模拟CPU,而忽略其余的。学习程序集对此非常有用的原因是程序集与模拟器应该处理的机器代码进行1:1的转换。

答案 2 :(得分:1)

如果你说,你对硬件一无所知,那么编写模拟器并不容易。理解硬件的基本功能比了解任何特定的编程语言可能更为公正。

我可以推荐Noam Nisan和Shimon Schocken的书计算系统元素及其相关的互联网资源(http://www.nand2tetris.org/)。这本书带你从简单的nand gate到构建一个功能计算机,然后编写汇编程序,编译器和操作系统,最后是俄罗斯方块游戏。在每个级别,您都可以“构建自己的”或使用网络可用的答案为下一个级别构建。

答案 3 :(得分:0)

首先,编程模拟器需要来自多个域的知识。您需要牢牢掌握的两个重要领域是计算机架构和您选择的编程语言。如果您根本没有编程经验,那么创建模拟器并不是一个好主意。话虽如此,只要您了解它,就可以使用您希望的任何语言创建模拟器!

为了理解系统是如何工作的,建议你了解一下计算机体系结构。我推荐阅读一本关于这个主题的好书,例如Computer Architecture: A Quantitative Approach,对于大多数架构课程来说,这是一本非常常见的书。

一旦掌握了系统如何运行(CPU,内存,寄存器,指令集等)的工作(基本)知识,您就可以尝试模拟您选择的系统。在这个阶段,我建议您尽可能多地了解您所选择的系统。 Zophar.net在许多视频游戏控制台上收集了很多技术文档。

一旦掌握了想要模拟的系统的工作知识,我建议编写代码来读取ROM文件并提取文件内容(特别是说明)。下一步是模拟架构的CPU并为每条指令编写处理程序。我通过在从ROM加载的实际指令上运行CPU来测试CPU。在实现了大量指令后,您可以开始实现其他子系统,例如图形和事件/中断系统。我通常实现的最终系统是声音。

(无耻的插件)我在一本名为Emulation - Step by Step的书中写了更多这些内容,我希望在几个月内发表。我还没有看到关于这个主题的另一本书,这是可耻的,因为它是一个如此有趣的主题!