操作码DXYN:
在坐标(VX,VY)处绘制一个精灵,其宽度为8个像素,高度为N个像素。从内存位置I开始,将每行8像素读取为位编码(每个字节的最高有效位显示在左侧);执行此指令后,我的值不变。如上所述,如果在绘制精灵时将任何屏幕像素从设置翻转为未设置,则VF设置为1,否则未设置为0。

基本上,我有一个称为图形的数组,它是一个由64行新数组构成的 double 数组,每行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;
            }
        }

在这些数组中,如上所述,我正在存储图形数据。我的问题是,当数组元素为1时我是否只需要画一个正方形,而当数组元素为0时我是否要清空该空间?根据有关CHIP8的博客文章,字体集还有一个额外的数组,但是它的用途是什么?

我上面提到的博客文章

http://www.multigesture.net/articles/how-to-write-an-emulator-chip-8-interpreter/

谢谢。

最佳答案

首先,请注意像素是位打包的-每个字节将包含8个像素的Sprite数据。换句话说,字节0xAA是具有第一,第三,第五和第七个像素集的单像素高的精灵。

绘制精灵时,您需要遍历每个位。如果设置了该位,则翻转显示中的相应位-0变为1,1变为0。例如,这可以通过对显示字节进行XOR(^)操作来完成。

但是请注意,如果在此过程中任何像素从1变为0,则VF必须设置为1;如果未设置任何像素,则VF必须设置为0-因此,您也需要这样做。我发现,如果您有一个if可以检查是否要翻转一点,然后在if里面同时进行翻转和VF更新,则最容易阅读。

作为引用,我自己的该操作码的Delphi实现如下所示:

procedure TChip8CPU.OpcodeD(inst: TInstruction);
var
  X, Y, cX, cY, data: byte;
begin
  Reg[$F] := 0;
  for Y := 0 to inst.NibbleArg - 1 do begin
    cY := (Reg[inst.Y] + Y) mod HEIGHT;
    data := Memory[AddressI + Y];
    for X := 0 to 7 do begin
      if (data and ($80 shr X)) <> 0 then begin
        cX := (Reg[inst.X] + X) mod WIDTH;
        if Display[cY, cX] = 1 then Reg[$F] := 1;
        Display[cY, cX] := Display[cY, cX] xor 1;
      end;
    end;
  end;
end;

请注意,对于超出屏幕边界的精灵,它们会环绕(这是由mod WIDTH / mod HEIGHT部分完成的)。这是在Cowgod's Chip-8 Technical Reference中提到的。

08-07 18:25