Как проверить чип-8 на правильность обработки команд?
Я написал большую часть эмулятора / интерпретатора CHIP-8 на Java и около половины программ, которые я запускаю, но другие либо не получают ничего, обычно зацикливаются или отображают данные, но искажаются. Как я могу проверить, чтобы найти инструкцию, которая работает неправильно?
Вот инструкции, которые я написал:
public static void CLS() {
System.out.println("CLS");
execLog[0]++;
displayClear();
}
public static void RET() {
System.out.println("RET");
execLog[1]++;
pop();
}
public static void JP(short nnn) {
System.out.println("JP " + (nnn & 0x00000FFF));
execLog[2]++;
PC = (short) (nnn - 2);
}
public static void CALL(short nnn) {
System.out.println("CALL " + (nnn & 0x00000FFF));
execLog[3]++;
push(nnn);
}
public static void SEbyte(byte Vx, byte kk) {
System.out.println("SE V" + (Vx & 0x0000000F) + ", " +(kk & 0x000000FF));
execLog[4]++;
if(V[Vx] == kk) {
PC = (short) (PC + 2);
}
}
public static void SNEbyte(byte Vx, byte kk) {
System.out.println("SNE V" + (Vx & 0x0000000F) + ", " +(kk & 0x000000FF));
execLog[5]++;
if(V[Vx] != kk) {
PC = (short) (PC + 2);
}
}
public static void SEreg(byte Vx, byte Vy) {
System.out.println("SE V" + (Vx & 0x0000000F) + ", V" +(Vy & 0x0000000F));
execLog[6]++;
if(V[Vx] == V[Vy]) {
PC = (short) (PC + 2);
}
}
public static void SNEreg(byte Vx, byte Vy) {
System.out.println("SNE V" + (Vx & 0x0000000F) + ", V" +(Vy & 0x0000000F));
execLog[7]++;
if(V[Vx] != V[Vy]) {
PC = (short) (PC + 2);
}
}
public static void LDbyte(byte Vx, byte kk) {
System.out.println("LD V" + (Vx & 0x0000000F) + ", " +(kk & 0x000000FF));
execLog[8]++;
V[Vx] = kk;
}
public static void ADDbyte(byte Vx, byte kk) {
System.out.println("ADD V" + (Vx & 0x0000000F) + ", " +(kk & 0x000000FF));
execLog[9]++;
V[Vx] += kk;
}
public static void LDreg(byte Vx, byte Vy) {
System.out.println("LD V" + (Vx & 0x0000000F) + ", V" +(Vy & 0x0000000F));
execLog[10]++;
V[Vx] = V[Vy];
}
public static void OR(byte Vx, byte Vy) {
System.out.println("OR V" + (Vx & 0x0000000F) + ", V" +(Vy & 0x0000000F));
execLog[11]++;
V[Vx] = (byte) (V[Vx] | V[Vy]);
}
public static void AND(byte Vx, byte Vy) {
System.out.println("AND V" + (Vx & 0x0000000F) + ", V" +(Vy & 0x0000000F));
execLog[12]++;
V[Vx] = (byte) (V[Vx] & V[Vy]);
}
public static void XOR(byte Vx, byte Vy) {
System.out.println("XOR V" + (Vx & 0x0000000F) + ", V" +(Vy & 0x0000000F));
execLog[0]++;
V[Vx] = (byte) (V[Vx] ^ V[Vy]);
}
public static void ADDreg(byte Vx, byte Vy) {
System.out.println("ADD V" + (Vx & 0x0000000F) + ", V" +(Vy & 0x0000000F));
execLog[13]++;
int t = (byte) (V[Vx] + V[Vy]);
if(t > 255) {
Vf = 1;
V[15] = Vf;
}
else{
Vf = 0;
V[15] = Vf;
}
V[Vx] = (byte) (t & 0x000000FF);
}
public static void SUB(byte Vx,byte Vy) {
System.out.println("SUB V" + (Vx & 0x0000000F) + ", V" +(Vy & 0x0000000F));
execLog[14]++;
if(V[Vx] > V[Vy]) {
Vf = 1;
V[15] = Vf;
} else {
Vf = 0;
V[15] = Vf;
}
V[Vx] = (byte) (V[Vx] - V[Vy]);
}
public static void SHR(byte Vx, byte Vy) {
System.out.println("SHR V" + (Vx & 0x0000000F) + ", V" +(Vy & 0x0000000F));
execLog[15]++;
if((V[Vx] & 0x01) > 0) {
Vf = 1;
V[15] = Vf;
} else {
Vf = 0;
V[15] = Vf;
}
V[Vx] = (byte) (V[Vx] << 1);
}
public static void SUBN(byte Vx, byte Vy) {
System.out.println("SUBN V" + (Vx & 0x0000000F) + ", V" +(Vy & 0x0000000F));
execLog[16]++;
if(V[Vy] > V[Vx]) {
Vf = 1;
V[15] = Vf;
} else {
Vf = 0;
V[15] = Vf;
}
V[Vy] = (byte) (V[Vy] - V[Vx]);
}
public static void SHL(byte Vx,byte Vy) {
System.out.println("SHL V" + (Vx & 0x0000000F) + ", V" +(Vy & 0x0000000F));
execLog[17]++;
/*if((V[Vx] >> 7) > 0) {
Vf = 1;
} else {
Vf = 0;
}
V[Vx] = (byte) (V[Vx] >> 1);*/
Vf = (byte) ((V[Vy] >> 7)&0x000000001);
V[15] = Vf;
V[Vy] = (byte) (V[Vy] << 1);
V[Vx] = V[Vy];
}
public static void LDi(short nnn) {
System.out.println("LD I, "+ (nnn & 0x00000FFF));
execLog[18]++;
I = (short) (nnn & 0x00000FFF);
}
public static void JPoffset(short nnn) {
System.out.println("JP " + (nnn & 0x00000FFF));
execLog[19]++;
PC = (short) (nnn + V[0] - 2);
}
public static void RND (byte Vx, byte kk) {
System.out.println("RND V" + (Vx & 0x0000000F) + ", " +(kk & 0x000000FF));
execLog[20]++;
Random rand = new Random();
int n = rand.nextInt(256);
V[Vx] = (byte) (kk & n);
}
public static void DRW (byte Vx, byte Vy,byte nibble) {
System.out.println("DRW V" + (Vx & 0x0000000F) + ", V" + (Vy & 0x0000000F) + " ," + (nibble & 0x0000000F));
execLog[21]++;
boolean[] pixels = new boolean[8];
System.out.println("Vx: " + V[Vx] + " \nVy: " + V[Vy] + "\nI: " + I);
int b = I;
for(int j = 0;j < nibble;j++) {
System.out.println("Memory: "+ (ram[b]&0x000000FF));
byte c = ram[b];
for(int i = 7;i>-1;i--) {
//System.out.println(Integer.toBinaryString(c));
//System.out.println(c&0x00001);
try {
//System.out.println("c:" + Integer.toBinaryString(c));
//System.out.println("Printing Pixel " + (V[Vx]&0x000000FF) + ", " + (V[Vy]&0x000000FF) + ", " + i + ", " + j);
if((c&0x000000001)>0) {
pixelFill((int)(V[Vx]&0x000000FF)+i,(int)(V[Vy]&0x000000FF)+j,true);
//pixelFill(16,16,true);
}
else {
pixelFill((int)(V[Vx]&0x000000FF)+i,(int)(V[Vy]&0x000000FF)+j,false);
// System.out.println("Erasing Pixel");
}
}
catch(Exception e) {
}
c = (byte) ((c >> 1));
}
b = b + 1;
}
}
public static void SKP (byte Vx) {
System.out.println("SKP V" + (Vx & 0x0000000F));
execLog[22]++;
}
public static void SKNP (byte Vx) {
System.out.println("SKNP V" + (Vx & 0x0000000F));
execLog[23]++;
}
public static void LDdt(byte Vx) {
System.out.println("LD V" + (Vx & 0x0000000F) + ", DT");
execLog[24]++;
V[Vx] = dT;
}
public static void LDk(byte Vx) {
System.out.println("LD V" + (Vx & 0x0000000F) + ", K");
execLog[25]++;
}
public static void LDdtset(byte Vx) {
System.out.println("LD DT, V" + (Vx & 0x0000000F));
execLog[26]++;
dT = V[Vx];
}
public static void LDstset(byte Vx) {
System.out.println("LD ST, V" + (Vx & 0x0000000F));
execLog[27]++;
sT = V[Vx];
}
public static void ADDi(byte Vx) {
System.out.println("ADD I, V" + (Vx & 0x0000000F));
execLog[28]++;
I += V[Vx];
}
public static void LDf(byte Vx) {
System.out.println("LD F, V" + (Vx & 0x0000000F));
execLog[29]++;
switch(V[Vx] & 0x0000F) {
case 0x0: I = 0x000; break;
case 0x1: I = 0x005; break;
case 0x2: I = 0x00A; break;
case 0x3: I = 0x00F; break;
case 0x4: I = 0x014; break;
case 0x5: I = 0x019; break;
case 0x6: I = 0x01E; break;
case 0x7: I = 0x023; break;
case 0x8: I = 0x028; break;
case 0x9: I = 0x02D; break;
case 0xA: I = 0x032; break;
case 0xB: I = 0x037; break;
case 0xC: I = 0x03C; break;
case 0xD: I = 0x041; break;
case 0xE: I = 0x046; break;
case 0xF: I = 0x04B; break;
}
// I = (short) (V[Vx] * 5);
System.out.println("+++++++++++++" + I);
}
public static void LDb(byte Vx) {
System.out.println("LD B, V" + (Vx & 0x0000000F));
execLog[30]++;
ram[I+0] = (byte) ((((V[Vx] % 1000) / 100) & 0x000000FF));
ram[I+1] = (byte) ((((V[Vx] % 100) / 10) & 0x000000FF));
ram[I+2] = (byte) ((((V[Vx] % 10) / 1) & 0x000000FF));
}
public static void LDidump(byte Vx) {
System.out.println("LD [I], V" + (Vx & 0x0000000F));
execLog[31]++;
for(int x = 0;x < Vx;x++) {
ram[I+x] = V[x];
}
}
public static void LDiload(byte Vx) {
System.out.println("LD V" + (Vx & 0x0000000F) + ", [I]");
execLog[32]++;
for(int x = 0;x < Vx;x++) {
V[x] = ram[I+x];
}
}