Как графика ЧИП 8 отображается на экране?

Код операции DXYN: рисует спрайт с координатами (VX, VY) шириной 8 пикселей и высотой N пикселей. Каждая строка из 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/

Спасибо.

1 ответ

Решение

Прежде всего, обратите внимание, что пиксели упакованы битом - каждый байт будет содержать 8 пикселей данных спрайта. Другими словами, байт 0xAA является спрайтом высотой в один пиксель с набором первого, третьего, пятого и седьмого пикселей.

При рисовании вашего спрайта, вам нужно перебирать каждый бит. Если бит установлен, вы переворачиваете соответствующий бит на вашем дисплее - 0 становится 1, а 1 становится 0. Это, например, можно сделать, применив операцию XOR (^) к вашему байту дисплея.

Тем не менее, обратите внимание, что VF должен быть установлен в 1, если какие-либо пиксели в процессе обрабатываются от 1 до 0, и 0, если ни один из пикселей не сброшен - так что вам также нужно сделать это. Я считаю, что легче всего читать, если у вас есть if, который проверяет, переворачивать или нет, а затем позаботиться о переключении и VF-обновлении внутри этого if.

Для справки, моя собственная реализация этого кода для 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.

Другие вопросы по тегам