c - 如何学习对游戏机模拟器进行编程(特别是硬件知识)?

标签 c console hardware emulation video-game-consoles

<分区>

我之前问过一个类似的问题,关于如何编写模拟器,当我看到答案并查找一些开源 gameboy 模拟器时,我发现需要的不仅仅是对“低”的中级理解级”语言(即 C)。我真正想知道的是,我需要了解有关硬件的哪些知识才能对这样的仿真器进行编程。我即将在 Java 方面“相当不错”,但这对我没有太大帮助。我已经开始学习 C,现在我已经走了很长一段路,但我很想知道我必须在硬件上学习什么才能编写这样一个控制台模拟器。

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

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

如果这不是一个真正的问题,或者不够清楚,或者类似的问题,我深表歉意。我只是对这个主题很感兴趣。

最佳答案

认为这可能更适合 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/无操作”或作为终止符(如本例)。现在只需删除换行符,您最终将获得自定义字节代码。

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)。

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

关于c - 如何学习对游戏机模拟器进行编程(特别是硬件知识)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13127212/

相关文章:

android - 为什么在库和内核层之间有一个额外的层(HAL)?

javascript - js 范围和属性枚举

C++ 在没有打开控制台的情况下启动程序

c++ - 在新窗口中创建线程 C++

c - 在操作系统中安装编译器

c - 从 C 中的文件加载数据

ios - 我将如何着手编程蓝牙发射器以与 iOS 或 Android 一起使用?

hardware - 用于多显示器物理设置的描述文件

c++ - 定点硬件光线追踪产品补偿

c - 重命名功能?