This commit is contained in:
Robin Hübner 2018-09-30 21:42:26 +02:00
parent f0d309f925
commit 4d8fc5814b
1 changed files with 43 additions and 53 deletions

View File

@ -397,7 +397,7 @@ struct Chip8Status {
import std.file : read; import std.file : read;
auto buf = read("programs/chip8_picture.ch8"); auto buf = read("programs/sqrt.ch8");
emu_.load(0x200, buf); // do ze load yes, will copy all the data in emu_.load(0x200, buf); // do ze load yes, will copy all the data in
} // loadShortcut } // loadShortcut
@ -539,39 +539,28 @@ struct Chip8Status {
} // Chip8Status } // Chip8Status
// this is a collosally awful solution, but if it works :D pure
string doCapture(string sym, uint start, uint end)(){ @property {
ubyte x(ref ushort oc) {
import std.string : format; return (oc & 0x0F00) >> 8;
enum bits = end - start;
static if (bits > 16) {
alias RT = uint;
} else static if (bits > 8) {
alias RT = ushort;
} else {
alias RT = ubyte;
} }
auto str = "0b"; ubyte y(ref ushort oc) {
foreach (i; 0 .. end) { return (oc & 0x00F0) >> 4;
if (i >= start) str ~= "1";
else str ~= "0";
} }
return format(q{ ubyte n(ref ushort oc) {
%s result = ((%s & %s) >> %d); return oc & 0x000F;
return result; }
}, RT.stringof, sym, str, start);
} // doCapture ubyte nn(ref ushort oc) {
return (oc & 0x00FF);
}
auto capture(uint start, uint end)(ushort op) { ushort nnn(ref ushort oc) {
return (oc & 0x0FFF);
enum str = doCapture!(op.stringof, start, end)(); }
mixin(str); }
} // capture
struct Chip8 { struct Chip8 {
@ -668,18 +657,18 @@ struct Chip8 {
break; break;
case 0x1000: // 0x1NNN Jumps to address NNN. case 0x1000: // 0x1NNN Jumps to address NNN.
pc_target = cpu.opcode.capture!(0, 12); pc_target = cpu.opcode.nnn;
break; break;
case 0x2000: // 0x2NNN Calls subroutine at NNN. case 0x2000: // 0x2NNN Calls subroutine at NNN.
stack[sp++] = cpu.pc; stack[sp++] = cpu.pc;
pc_target = cpu.opcode & 0x0FFF; pc_target = cpu.opcode.nnn;
break; break;
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.capture!(8, 12)] == cpu.opcode.capture!(0, 8)) { if (cpu.v[cpu.opcode.x] == (cpu.opcode.nn)) {
pc_target += 2; pc_target += 2;
} }
@ -687,7 +676,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.capture!(8, 12)] != cpu.opcode.capture!(0, 8)) { if (cpu.v[cpu.opcode.x] != (cpu.opcode.nn)) {
pc_target += 2; pc_target += 2;
} }
@ -695,26 +684,27 @@ 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.capture!(8, 12)] == cpu.v[cpu.opcode.capture!(4, 8)]) { if (cpu.v[cpu.opcode.x] == cpu.v[cpu.opcode.y]) {
pc_target += 2; pc_target += 2;
} }
break; break;
case 0x6000: // 0x6XNN Sets VX to NN. case 0x6000: // 0x6XNN Sets VX to NN.
cpu.v[cpu.opcode.capture!(8, 12)] = cpu.opcode.capture!(0, 8); writefln("%d, %d", cpu.opcode.x, cpu.opcode & 0x00FF);
cpu.v[cpu.opcode.x] = cpu.opcode.nn;
break; break;
case 0x7000: // 0x7XNN Adds NN to VX. case 0x7000: // 0x7XNN Adds NN to VX.
cpu.v[cpu.opcode.capture!(8, 12)] += cpu.opcode.capture!(0, 8); cpu.v[cpu.opcode.x] += cpu.opcode.nn;
break; break;
case 0x8000: case 0x8000:
auto x = cpu.opcode.capture!(8, 12); auto x = cpu.opcode.x;
auto y = cpu.opcode.capture!(4, 8); auto y = cpu.opcode.y;
switch (cpu.opcode & 0x000F) { switch (cpu.opcode.n) {
case 0x0000: // 0x8XY0 Sets VX to the value of VY. case 0x0000: // 0x8XY0 Sets VX to the value of VY.
cpu.v[x] = cpu.v[y]; cpu.v[x] = cpu.v[y];
@ -789,25 +779,25 @@ 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.capture!(8, 12)] != cpu.v[cpu.opcode.capture!(4, 8)]) { if (cpu.v[cpu.opcode.x] != cpu.v[cpu.opcode.y]) {
pc_target += 2; // do skip yes pc_target += 2; // do skip yes
} }
break; break;
case 0xA000: // 0xANNN Sets I to the address NNN. case 0xA000: // 0xANNN Sets I to the address NNN.
cpu.i = cpu.opcode.capture!(0, 12); cpu.i = cpu.opcode.nnn;
break; break;
case 0xB000: // 0xBNNN Jumps to the address NNN plus V0. case 0xB000: // 0xBNNN Jumps to the address NNN plus V0.
pc_target = cast(ProgramCounter)(cpu.opcode.capture!(0, 12) + cpu.v[0x0]); pc_target = cast(ProgramCounter)(cpu.opcode.nnn + cpu.v[0x0]);
break; break;
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.capture!(0, 8); auto x = cpu.opcode.x;
cpu.v[x] = uniform(Register.min, Register.max) & cpu.opcode.capture!(0, 8); cpu.v[x] = uniform(Register.min, Register.max) & (cpu.opcode & 0x00FF);
break; break;
// 0xDXYN // 0xDXYN
@ -819,9 +809,9 @@ struct Chip8 {
case 0xD000: case 0xD000:
auto spr_addr = cpu.i; auto spr_addr = cpu.i;
auto x = cpu.opcode.capture!(8, 12); auto x = cpu.opcode.x;
auto y = cpu.opcode.capture!(4, 8); auto y = cpu.opcode.y;
auto n = cpu.opcode.capture!(0, 4); auto n = cpu.opcode.n;
foreach(int row; 0 .. n) { foreach(int row; 0 .. n) {
@ -851,7 +841,7 @@ struct Chip8 {
case 0xE000: case 0xE000:
auto x = cpu.opcode.capture!(8, 12); auto x = cpu.opcode.x;
auto key = cpu.v[x]; auto key = cpu.v[x];
switch (cpu.opcode & 0x000F) { switch (cpu.opcode & 0x000F) {
@ -877,7 +867,7 @@ struct Chip8 {
switch (cpu.opcode & 0x00FF) { switch (cpu.opcode & 0x00FF) {
case 0x0007: // 0xFX07 Sets VX to the value of the delay timer. case 0x0007: // 0xFX07 Sets VX to the value of the delay timer.
cpu.v[cpu.opcode.capture!(8, 12)] = cpu.delay_timer; cpu.v[cpu.opcode.x] = cpu.delay_timer;
break; break;
case 0x000A: // 0xFX0A A key press is awaited, and then stored in VX. case 0x000A: // 0xFX0A A key press is awaited, and then stored in VX.
@ -885,20 +875,20 @@ struct Chip8 {
break; break;
case 0x0015: // 0xFX15 Sets the delay timer to VX. case 0x0015: // 0xFX15 Sets the delay timer to VX.
cpu.delay_timer = cpu.v[cpu.opcode.capture!(8, 12)]; cpu.delay_timer = cpu.v[cpu.opcode.x];
break; break;
case 0x0018: // 0xFX18 Sets the sound timer to VX. case 0x0018: // 0xFX18 Sets the sound timer to VX.
cpu.sound_timer = cpu.v[cpu.opcode.capture!(8, 12)]; cpu.sound_timer = cpu.v[cpu.opcode.x];
break; break;
case 0x001E: // 0xFX1E Adds VX to I. case 0x001E: // 0xFX1E Adds VX to I.
cpu.i += cpu.v[cpu.opcode.capture!(8, 12)]; 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.capture!(8, 12)]; auto 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
cpu.i = char_addr; cpu.i = char_addr;
break; break;
@ -908,7 +898,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.capture!(8, 12)]; auto 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;