在构建芯片 8 仿真器时,我遇到了芯片 8 信息的 2 个主要来源似乎不同的问题,这对整个芯片 8 解释器有影响。
一方面,我们有维基百科,它在操作码 FX65 下告诉我们
“用从地址 I 开始的内存中的值填充 V0 到 VX(包括 VX)。对于每个写入的值,I 增加 1。”
其中“对于写入的每个值,I 增加 1。” 是重要的部分。
遵循此结果会产生以下代码:
for(int i = 0; i <= ((opcode & 0x0F00) >> 8); ++i) {
V[i] = memory[I];
++I;
}
Run Code Online (Sandbox Code Playgroud)
另一方面,我们有cowgod的chip-8 参考,几乎每个教程都链接到的参考,它告诉我们以下内容
“解释器从位置 I 开始的内存读取值到寄存器 V0 到 Vx。”
应用此逻辑会产生以下代码(这也是大多数芯片 8 实现使用的实现):
for(int i = 0; i <= ((opcode & 0x0F00) >> 8); ++i) {
V[i] = memory[I …Run Code Online (Sandbox Code Playgroud) 我一直在研究CHIP8仿真器,并且正在notepad ++中使用十六进制编辑器来查看十六进制值。我碰巧注意到,某些游戏(例如David Winter的“ Blitz”)具有奇数个字节。


在CHIP8中,每个操作码长2个字节,因此应该有偶数个字节,对吗?
操作码DXYN:在坐标(VX,VY)处绘制一个精灵,其宽度为8个像素,高度为N个像素。从内存位置I开始,将每行8像素读取为位编码(每个字节的最高有效位显示在左侧);执行此指令后,我的值不变。如上所述,如果在绘制精灵时将任何屏幕像素从设置翻转为未设置,则VF设置为1,否则未设置为0。
基本上,我有一个称为图形的数组,它是一个由64行新数组构成的双精度数组,每行32列。
//Creating new double arrays for storing graphics data
graphics = new Array(GFX_WIDTH);
for(var i = 0; i < graphics .length; i++){
graphics [i] = new Array(GFX_HEIGHT);
for(var j = 0; j < graphics [i].length; j++){
graphics [i][j] = 0;
}
}
Run Code Online (Sandbox Code Playgroud)
在这些数组中,如上所述,我正在存储图形数据。我的问题是,当数组元素为1时我是否只需要画一个正方形,而当数组元素为0时我是否要清空该空间?根据有关CHIP8的博客文章,字体集还有一个额外的数组,但是它的用途是什么?
我上面提到的博客文章
http://www.multigesture.net/articles/how-to-write-an-emulator-chip-8-interpreter/
谢谢。
TL;DR我需要用 C 语言模拟一个计时器,允许并发写入和读取,同时保持 60 Hz 的恒定递减(不完全准确,但大致准确)。它将成为 Linux CHIP8 模拟器的一部分。使用具有共享内存和信号量的基于线程的方法会引发一些准确性问题,以及取决于主线程如何使用计时器的竞争条件。
设计和实现这种计时器的最佳方法是什么?
我正在用 C 语言逐个模块地编写一个 Linux CHIP8 解释器,以便深入了解仿真的世界。
我希望我的实现尽可能准确地符合规范。在这方面,计时器已被证明对我来说是最困难的模块。
以延迟计时器为例。在规范中,它是一个“特殊”寄存器,最初设置为 0。有特定的操作码可以向寄存器设置值并从寄存器中获取值。
如果寄存器中输入的值不为零,它将自动开始以 60 Hz 的频率递减,一旦达到零就停止。
我对其实施的想法包括以下内容:
使用辅助线程,通过使用以接近 60 Hz 的频率自动进行递减nanosleep()。我fork()暂时用来创建线程。
使用共享内存 viammap()来分配定时器寄存器并在其上存储其值。这种方法允许辅助线程和主线程读取和写入寄存器。
使用信号量来同步两个线程的访问。我使用sem_open()和 来创建它,并sem_wait()分别sem_post()锁定和解锁共享资源。
下面的代码片段说明了这个概念:
void *p = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
/* Error checking here */
sem_t *mutex = sem_open("timersem", O_CREAT, O_RDWR, 1);
/* Error checking and unlinking */
int *val = …Run Code Online (Sandbox Code Playgroud) 所以我一直在使用Chip-8模拟器作为我的CompSci类的最终项目,并且遇到了一个似乎超出我的代码的问题.我下载的大量演示(我确信它们是真正的Chip-8程序,而不是SuperChip或类似的东西)包含的机器指令不符合任何Chip-8操作码的格式.
http://mattmik.com/files/chip8/mastering/chip8.html
在页面的底部是所有操作码的列表,每个操作码长2个字节,以及它们中的每个半字节数字代表什么.但是,相当数量的程序具有不符合任何指令格式的指令.例如,这是一个来自其中一个的十六进制转储 - 我会在其中指出一些个别情况
0000000 6a 00 6b 04 6c 01 6d 00 6e 02 23 26 23 20 60 30
0000010 61 01 f0 15 f0 07 f1 18 30 00 12 14 22 42 23 20
0000020 7d 01 23 20 60 08 e0 a1 23 0a 4a 00 12 3e a3 62
0000030 d8 91 79 01 d8 91 4f 01 12 f4 49 18 12 e4 22 b2
0000040 12 1e 4c 01 22 6c …Run Code Online (Sandbox Code Playgroud)