首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何学习编写游戏控制台仿真器(特别是硬件知识)?

如何学习编写游戏控制台仿真器(特别是硬件知识)?
EN

Stack Overflow用户
提问于 2012-10-30 02:03:51
回答 4查看 9.1K关注 0票数 3

我以前问过一个类似的问题,关于如何编写仿真器,当我看到答案并查阅了一些开源的游戏男孩仿真器时,我发现需要的远不止是对“低级”语言(即C语言)的中等理解。我真正想知道的是,我需要了解哪些关于硬件的知识才能编写这样的仿真器。我在Java方面已经接近“相当好”了,但这对我帮助不大。我已经开始学习C语言,现在已经走了很长一段路,但我有兴趣知道我必须在硬件上学习什么才能编写这样的控制台仿真器。

我问这个问题的原因是我一直在互联网上搜索关于仿真的书籍和资源,每当我遇到仿真器教程时,总是像是“你需要对C语言有基本的理解才能遵循本教程”,而当我试图遵循它时,我做不到,仅仅是因为我不知道该死的编程是什么。我对硬件一无所知。(我的父亲正在努力将他的显示器连接到他的电脑上,他可能对此了解得更多)

所以我的问题是,我需要学习什么(微处理器、内存等)?有没有什么好的资源可以教我不用上大学就能学到这些东西(已经在做软件工程了)?

如果这不是一个真正的问题,或者不够清楚,或者诸如此类的事情,我道歉。我只是对这个话题很感兴趣。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-10-30 02:30:35

我认为这可能更适合programmers.stackexchange.com,但不管怎样:

我不会说你需要任何特定的知识。了解微处理器和内存管理是如何工作的将会有很大帮助,汇编程序知识也是如此(因为您实际上是在为类似汇编程序的代码编写解释器)。假设你已经知道你的目标硬件是如何工作的,你所要做的就是实现以下组件(例如,伪造真实的硬件并模拟/模拟它的行为):

  • 模拟中央处理器解析和运行机器代码。
  • 模拟输入组件(将键盘、鼠标或操纵杆输入转换为中央处理器可访问的“引脚信号”)。
  • 模拟输出组件(将图像和音频数据转换为可视数据,例如在屏幕上显示某些内容或生成与真实硬件相似的声音)。

模拟其他组件,如内存包、内置电池、磁带盒、扩展芯片等。

作为一个一般性的建议,我会说暂时忘记编写任何仿真器。取而代之的是,从一些简单的东西开始,尝试编写自己的字节码解释器。

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

代码语言:javascript
运行
复制
x = 5
y = 10
print(x + y)

用伪汇编语言编写,这可能是这样的:

代码语言:javascript
运行
复制
mov x, 5
mov y, 10
add x, y // to be honest, this is essentially x += y; not just x + y
prt x
end

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

代码语言:javascript
运行
复制
0x01 0x00 0x05
0x01 0x01 0x0a
0x02 0x00 0x01
0x03 0x00
0x00

这看起来可能有点奇怪,但我保留了上面的顺序和换行符。请注意,我对第一条指令使用的是0x01,而不是0x00。这只是为了方便起见,所以我可以将0x00用于"NOOP/no operation“或作为一个终止符(如本例所示)。现在只要去掉换行符,你就得到了本质上的自定义字节代码。

代码语言:javascript
运行
复制
char code[] = {0x01, 0x00, 0x05, 0x01, 0x01, 0x0a, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00};

要运行这段代码,您可以编写一个简单的“模拟器”。它只有一个有限的指令集,但它可以工作。我实际上没有测试这段代码,所以请记住,我可能在某个时候搞砸了。然而,它应该足以给你一个如何/做什么的想法。请注意,在本例中,我没有将数据内存和指令内存分开。这将增加更多的复杂性,目前并不真正需要。

代码语言:javascript
运行
复制
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)。

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

票数 11
EN

Stack Overflow用户

发布于 2012-10-30 02:21:02

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

不过,老实说,如果C对你来说完全陌生,那么在尝试汇编之前最好先学习一些。C语言比汇编语言抽象得多,但仍然可以让你了解许多重要的概念,最重要的是指针。

但基本上,仿真器所做的是遍历游戏的机器代码,逐条指令地执行它。控制台是一个相当复杂的野兽,有几个处理器和协处理器以及相关的硬件同时工作。因此,您可能应该从一个更简单的仿真器开始,该仿真器只仿真CPU,而忽略其余部分。学习汇编对此如此有用的原因是,汇编与仿真器应该处理的机器代码有1:1的转换。

票数 1
EN

Stack Overflow用户

发布于 2012-10-30 19:05:12

如果如您所说,您对硬件一无所知,那么编写仿真器将不是一件容易的事情。了解硬件的基本功能可能比了解任何特定的编程语言更重要。

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13127212

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档