操作码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中提到的。