操作码DXYN: 在坐标(VX,VY)处绘制一个精灵,其宽度为8像素,高度为N像素。从存储器位置I开始,每行8个像素被读取为位编码(每个字节的最高位显示在左侧);执行该指令后,I值不会改变。如上所述,如果在绘制精灵时将任何屏幕像素从设置翻转为未设置,则VF设置为1,如果没有,则将其设置为0。
基本上我有一个名为graphics的数组,它是一个双数组,由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;
}
}
在这些数组中,我正在存储如上所述的图形数据。我的问题是,当数组元素为1时,我是否只需绘制一个正方形,当它为0时,我必须清空该空格?根据关于CHIP8的博客文章,有一个额外的字体集数组,但是它的用途是什么?
我上面提到的博客文章
http://www.multigesture.net/articles/how-to-write-an-emulator-chip-8-interpreter/
谢谢。
答案 0 :(得分:5)
首先,请注意像素是有效的 - 每个字节将包含8个像素的精灵数据。换句话说,字节0xAA是具有第一,第三,第五和第七像素集的单像素高精灵。
绘制精灵时,需要遍历每一位。如果该位置1,则翻转显示中的相应位 - 0变为1,1变为0.例如,可以通过对显示字节应用XOR(^)操作来完成
但是,请注意,如果过程中任何像素从1变为0,则必须将VF设置为1,如果未设置像素,则必须设置为0 - 因此您还需要执行此操作。我觉得如果你有一个检查是否要翻转一下是最容易阅读,然后在if内部处理flipping和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中提到。