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;
 | 
			
		||||
 | 
			
		||||
		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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue