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;
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
} // loadShortcut
@ -539,39 +539,28 @@ struct Chip8Status {
} // Chip8Status
// this is a collosally awful solution, but if it works :D
string doCapture(string sym, uint start, uint end)(){
import std.string : format;
enum bits = end - start;
static if (bits > 16) {
alias RT = uint;
} else static if (bits > 8) {
alias RT = ushort;
} else {
alias RT = ubyte;
pure
@property {
ubyte x(ref ushort oc) {
return (oc & 0x0F00) >> 8;
}
auto str = "0b";
foreach (i; 0 .. end) {
if (i >= start) str ~= "1";
else str ~= "0";
ubyte y(ref ushort oc) {
return (oc & 0x00F0) >> 4;
}
return format(q{
%s result = ((%s & %s) >> %d);
return result;
}, RT.stringof, sym, str, start);
ubyte n(ref ushort oc) {
return oc & 0x000F;
}
} // doCapture
ubyte nn(ref ushort oc) {
return (oc & 0x00FF);
}
auto capture(uint start, uint end)(ushort op) {
enum str = doCapture!(op.stringof, start, end)();
mixin(str);
} // capture
ushort nnn(ref ushort oc) {
return (oc & 0x0FFF);
}
}
struct Chip8 {
@ -668,18 +657,18 @@ struct Chip8 {
break;
case 0x1000: // 0x1NNN Jumps to address NNN.
pc_target = cpu.opcode.capture!(0, 12);
pc_target = cpu.opcode.nnn;
break;
case 0x2000: // 0x2NNN Calls subroutine at NNN.
stack[sp++] = cpu.pc;
pc_target = cpu.opcode & 0x0FFF;
pc_target = cpu.opcode.nnn;
break;
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;
}
@ -687,7 +676,7 @@ struct Chip8 {
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;
}
@ -695,26 +684,27 @@ struct Chip8 {
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;
}
break;
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;
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;
case 0x8000:
auto x = cpu.opcode.capture!(8, 12);
auto y = cpu.opcode.capture!(4, 8);
auto x = cpu.opcode.x;
auto y = cpu.opcode.y;
switch (cpu.opcode & 0x000F) {
switch (cpu.opcode.n) {
case 0x0000: // 0x8XY0 Sets VX to the value of VY.
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.
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
}
break;
case 0xA000: // 0xANNN Sets I to the address NNN.
cpu.i = cpu.opcode.capture!(0, 12);
cpu.i = cpu.opcode.nnn;
break;
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;
case 0xC000: // 0xCXNN Sets VX to the result of a bitwise and operation on a random number and NN.
import std.random : uniform;
auto x = cpu.opcode.capture!(0, 8);
cpu.v[x] = uniform(Register.min, Register.max) & cpu.opcode.capture!(0, 8);
auto x = cpu.opcode.x;
cpu.v[x] = uniform(Register.min, Register.max) & (cpu.opcode & 0x00FF);
break;
// 0xDXYN
@ -819,9 +809,9 @@ struct Chip8 {
case 0xD000:
auto spr_addr = cpu.i;
auto x = cpu.opcode.capture!(8, 12);
auto y = cpu.opcode.capture!(4, 8);
auto n = cpu.opcode.capture!(0, 4);
auto x = cpu.opcode.x;
auto y = cpu.opcode.y;
auto n = cpu.opcode.n;
foreach(int row; 0 .. n) {
@ -851,7 +841,7 @@ struct Chip8 {
case 0xE000:
auto x = cpu.opcode.capture!(8, 12);
auto x = cpu.opcode.x;
auto key = cpu.v[x];
switch (cpu.opcode & 0x000F) {
@ -877,7 +867,7 @@ struct Chip8 {
switch (cpu.opcode & 0x00FF) {
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;
case 0x000A: // 0xFX0A A key press is awaited, and then stored in VX.
@ -885,20 +875,20 @@ struct Chip8 {
break;
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;
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;
case 0x001E: // 0xFX1E Adds VX to I.
cpu.i += cpu.v[cpu.opcode.capture!(8, 12)];
cpu.i += cpu.v[cpu.opcode.x];
break;
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
cpu.i = char_addr;
break;
@ -908,7 +898,7 @@ struct Chip8 {
// the middle digit at I plus 1, and the least significant digit at I plus 2.
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 + 1] = (vx / 10) % 10;
ram[cpu.i + 2] = (vx % 100) % 10;