This commit is contained in:
Robin Hübner 2018-09-30 22:25:40 +02:00
parent 4d8fc5814b
commit 5be7d9ce1a
1 changed files with 43 additions and 41 deletions

View File

@ -466,7 +466,8 @@ struct Chip8Status {
igText("OpCode: 0x%04X", emu_.cpu.opcode); igText("OpCode: 0x%04X", emu_.cpu.opcode);
igText("PC:"); igText("PC:");
igSameLine(); igSameLine();
igDragInt("##pc", cast(int*)&emu_.cpu.pc, 0.5f, 0, emu_.ram.length); igText("pc: 0x%04X (%hu)", emu_.cpu.pc, emu_.cpu.pc);
// igDragInt("##pc", cast(int*)&emu_.cpu.pc, 0.5f, 0, emu_.ram.length);
igText("Registers (v0 - vF)"); igText("Registers (v0 - vF)");
igColumns(4, null, false); igColumns(4, null, false);
@ -629,9 +630,9 @@ struct Chip8 {
void step() { void step() {
cpu.opcode = ram[cpu.pc] << 8 | ram[cpu.pc + 1]; cpu.opcode = ram[cpu.pc] << 8 | ram[cpu.pc + 1];
auto pc_target = cast(ProgramCounter)(cpu.pc + 2); ushort pc_target = cast(ProgramCounter)(cpu.pc + 2u);
writefln("opcode: 0x%X", cpu.opcode); // writefln("opcode: 0x%X, pc: 0x%X : %d", cpu.opcode, cpu.pc, cpu.pc);
switch (cpu.opcode & 0xF000) with (cpu) { switch (cpu.opcode & 0xF000) with (cpu) {
@ -669,7 +670,7 @@ struct Chip8 {
case 0x3000: // 0x3XNN Skips the next instruction if VX equals NN. case 0x3000: // 0x3XNN Skips the next instruction if VX equals NN.
if (cpu.v[cpu.opcode.x] == (cpu.opcode.nn)) { if (cpu.v[cpu.opcode.x] == (cpu.opcode.nn)) {
pc_target += 2; pc_target += 2u;
} }
break; break;
@ -677,7 +678,7 @@ struct Chip8 {
case 0x4000: // 0x4XNN Skips the next instruction if VX doesn't equal NN. case 0x4000: // 0x4XNN Skips the next instruction if VX doesn't equal NN.
if (cpu.v[cpu.opcode.x] != (cpu.opcode.nn)) { if (cpu.v[cpu.opcode.x] != (cpu.opcode.nn)) {
pc_target += 2; pc_target += 2u;
} }
break; break;
@ -685,13 +686,12 @@ struct Chip8 {
case 0x5000: // 0x5XYO Skips the next instruction if VX equals VY. case 0x5000: // 0x5XYO Skips the next instruction if VX equals VY.
if (cpu.v[cpu.opcode.x] == cpu.v[cpu.opcode.y]) { if (cpu.v[cpu.opcode.x] == cpu.v[cpu.opcode.y]) {
pc_target += 2; pc_target += 2u;
} }
break; break;
case 0x6000: // 0x6XNN Sets VX to NN. case 0x6000: // 0x6XNN Sets VX to NN.
writefln("%d, %d", cpu.opcode.x, cpu.opcode & 0x00FF);
cpu.v[cpu.opcode.x] = cpu.opcode.nn; cpu.v[cpu.opcode.x] = cpu.opcode.nn;
break; break;
@ -701,8 +701,8 @@ struct Chip8 {
case 0x8000: case 0x8000:
auto x = cpu.opcode.x; ubyte x = cpu.opcode.x;
auto y = cpu.opcode.y; ubyte y = cpu.opcode.y;
switch (cpu.opcode.n) { switch (cpu.opcode.n) {
@ -723,8 +723,8 @@ struct Chip8 {
break; break;
case 0x0004: // 0x8XY4 Adds VY to VX. VF is set to 1 when there's a carry, and to 0 when there isn't. case 0x0004: // 0x8XY4 Adds VY to VX. VF is set to 1 when there's a carry, and to 0 when there isn't.
auto vx = cpu.v[x]; ubyte vx = cpu.v[x];
auto vy = cpu.v[y]; ubyte vy = cpu.v[y];
if (cast(ushort)vx + cast(ushort)vy > 255) { if (cast(ushort)vx + cast(ushort)vy > 255) {
cpu.v[0xF] = 1; cpu.v[0xF] = 1;
} else { } else {
@ -734,8 +734,8 @@ struct Chip8 {
break; break;
case 0x0005: // 0x8XY5 VY is subtracted from VX. VF is set to 0 when there's a borrow, and 1 when there isn't. case 0x0005: // 0x8XY5 VY is subtracted from VX. VF is set to 0 when there's a borrow, and 1 when there isn't.
auto vx = cpu.v[x]; ubyte vx = cpu.v[x];
auto vy = cpu.v[y]; ubyte vy = cpu.v[y];
if (vx > vy) { if (vx > vy) {
cpu.v[0xF] = 1; cpu.v[0xF] = 1;
} else { } else {
@ -746,26 +746,26 @@ struct Chip8 {
case 0x0006: // 0x8XY6 Shifts VX right by one. VF is set to the value of the least significant bit of VX before the shift. case 0x0006: // 0x8XY6 Shifts VX right by one. VF is set to the value of the least significant bit of VX before the shift.
auto vx = cpu.v[x]; ubyte vx = cpu.v[x];
cpu.v[0xF] = (vx & 0b10000000) >> 7; cpu.v[0xF] = vx & 0x1;
cpu.v[x] >>= 1; cpu.v[x] >>= 1;
break; break;
case 0x0007: // 0x8XY7 Sets VX to VY minus VX. VF is set to 0 when there's a borrow, and 1 when there isn't. case 0x0007: // 0x8XY7 Sets VX to VY minus VX. VF is set to 0 when there's a borrow, and 1 when there isn't.
auto vx = cpu.v[x]; ubyte vx = cpu.v[x];
auto vy = cpu.v[y]; ubyte vy = cpu.v[y];
if (vy > vx) { if (vy > vx) {
cpu.v[0xF] = 1; cpu.v[0xF] = 1;
} else { } else {
cpu.v[0xF] = 0; cpu.v[0xF] = 0;
} }
cpu.v[x] = cast(Register)(vy - vx); // TODO borrow flag cpu.v[x] = cast(Register)(vy - vx);
break; break;
case 0x000E: // 0x8XYE Shifts VX left by one. VF is set to the value of the most significant bit of VX before the shift. case 0x000E: // 0x8XYE Shifts VX left by one. VF is set to the value of the most significant bit of VX before the shift.
auto vx = cpu.v[x]; ubyte vx = cpu.v[x];
cpu.v[0xF] = (vx & 0b10000000) >> 7; cpu.v[0xF] = vx >> 7;
cpu.v[x] <<= 1; cpu.v[x] <<= 1;
break; break;
@ -780,7 +780,7 @@ struct Chip8 {
case 0x9000: // 0x9XYO Skips the next instruction if VX doesn't equal VY. case 0x9000: // 0x9XYO Skips the next instruction if VX doesn't equal VY.
if (cpu.v[cpu.opcode.x] != cpu.v[cpu.opcode.y]) { if (cpu.v[cpu.opcode.x] != cpu.v[cpu.opcode.y]) {
pc_target += 2; // do skip yes pc_target += 2u; // do skip yes
} }
break; break;
@ -796,7 +796,7 @@ struct Chip8 {
case 0xC000: // 0xCXNN Sets VX to the result of a bitwise and operation on a random number and NN. case 0xC000: // 0xCXNN Sets VX to the result of a bitwise and operation on a random number and NN.
import std.random : uniform; import std.random : uniform;
auto x = cpu.opcode.x; ubyte x = cpu.opcode.x;
cpu.v[x] = uniform(Register.min, Register.max) & (cpu.opcode & 0x00FF); cpu.v[x] = uniform(Register.min, Register.max) & (cpu.opcode & 0x00FF);
break; break;
@ -808,29 +808,25 @@ struct Chip8 {
// If N is greater than 1, second line continues at position VX, VY+1, and so on. // If N is greater than 1, second line continues at position VX, VY+1, and so on.
case 0xD000: case 0xD000:
auto spr_addr = cpu.i; ProgramCounter spr_addr = cpu.i;
auto x = cpu.opcode.x; ubyte x = cpu.opcode.x;
auto y = cpu.opcode.y; ubyte y = cpu.opcode.y;
auto n = cpu.opcode.n; ubyte n = cpu.opcode.n;
foreach(int row; 0 .. n) { foreach(int row; 0 .. n) {
ushort pixel = ram[spr_addr + row]; ushort pixel = ram[spr_addr + row];
foreach (int col; 0 .. 8) { foreach (int col; 0 .. 8) {
if ((pixel & 0x80) > 0) { if ((pixel & (0x80 >> col)) != 0) {
auto x_off = (x + col) % 64; ubyte x_off = cast(ubyte)((x + col) % 64);
auto y_off = (y + row) % 32; ubyte y_off = cast(ubyte)((y + row) % 32);
auto offset = x_off + (y_off * 64); ushort offset = x_off + (y_off * 64);
if (screen_buf[offset] == 1) { if (screen_buf[offset] == 1) {
cpu.v[0xF] = 1; cpu.v[0xF] = 1;
} else {
cpu.v[0xF] = 0;
} }
screen_buf[offset] ^= 1; screen_buf[offset] ^= 1;
writefln("write to offset: %d", offset);
} }
pixel <<= 1;
} }
} }
@ -841,8 +837,8 @@ struct Chip8 {
case 0xE000: case 0xE000:
auto x = cpu.opcode.x; ubyte x = cpu.opcode.x;
auto key = cpu.v[x]; ubyte key = cpu.v[x];
switch (cpu.opcode & 0x000F) { switch (cpu.opcode & 0x000F) {
@ -883,13 +879,19 @@ struct Chip8 {
break; break;
case 0x001E: // 0xFX1E Adds VX to I. case 0x001E: // 0xFX1E Adds VX to I.
if (cpu.i + cpu.v[cpu.opcode.x] > 0xFF) {
cpu.v[0xF] = 1;
} else {
cpu.v[0xF] = 0;
}
cpu.i += cpu.v[cpu.opcode.x]; cpu.i += cpu.v[cpu.opcode.x];
break; break;
case 0x0029: // 0xFX29 Sets I to the location of the sprite for the character in VX. case 0x0029: // 0xFX29 Sets I to the location of the sprite for the character in VX.
auto vx = cpu.v[cpu.opcode.x]; ubyte vx = cpu.v[cpu.opcode.x];
ushort char_addr = 0x200 + (vx * 40); // base of char sprites + value of vx * bits per character // ushort char_addr = 0x200 + (vx * 40); // base of char sprites + value of vx * bits per character
ushort char_addr = vx * 0x5;
cpu.i = char_addr; cpu.i = char_addr;
break; break;
@ -898,7 +900,7 @@ struct Chip8 {
// the middle digit at I plus 1, and the least significant digit at I plus 2. // the middle digit at I plus 1, and the least significant digit at I plus 2.
case 0x0033: case 0x0033:
auto vx = cpu.v[cpu.opcode.x]; ubyte vx = cpu.v[cpu.opcode.x];
ram[cpu.i] = vx / 100; ram[cpu.i] = vx / 100;
ram[cpu.i + 1] = (vx / 10) % 10; ram[cpu.i + 1] = (vx / 10) % 10;
ram[cpu.i + 2] = (vx % 100) % 10; ram[cpu.i + 2] = (vx % 100) % 10;
@ -906,7 +908,7 @@ struct Chip8 {
case 0x0055: // 0xFX55 Stores V0 to VX in memory starting at address I. case 0x0055: // 0xFX55 Stores V0 to VX in memory starting at address I.
auto addr = cpu.i; IndexRegister addr = cpu.i;
foreach (reg; cpu.v) { foreach (reg; cpu.v) {
ram[addr++] = reg; ram[addr++] = reg;
} }
@ -915,7 +917,7 @@ struct Chip8 {
case 0x0065: // 0xFX65 Fills V0 to VX with values from memory starting at address I. case 0x0065: // 0xFX65 Fills V0 to VX with values from memory starting at address I.
auto addr = cpu.i; IndexRegister addr = cpu.i;
foreach (ref reg; cpu.v) { foreach (ref reg; cpu.v) {
reg = ram[addr++]; reg = ram[addr++];
} }