sanity
This commit is contained in:
parent
f0d309f925
commit
4d8fc5814b
96
source/app.d
96
source/app.d
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue