assembly/disassembly stuff
This commit is contained in:
		
							parent
							
								
									d0b7670eca
								
							
						
					
					
						commit
						ead5f8c370
					
				
							
								
								
									
										199
									
								
								source/app.d
								
								
								
								
							
							
						
						
									
										199
									
								
								source/app.d
								
								
								
								
							| 
						 | 
				
			
			@ -346,12 +346,181 @@ struct PixelBuffer {
 | 
			
		|||
 | 
			
		||||
} // PixelBuffer
 | 
			
		||||
 | 
			
		||||
struct Assembler {
 | 
			
		||||
 | 
			
		||||
	enum OpCode {
 | 
			
		||||
 | 
			
		||||
		CLS, // CLS
 | 
			
		||||
 | 
			
		||||
		RET, // RET
 | 
			
		||||
		CALL, // CALL addr
 | 
			
		||||
 | 
			
		||||
		ADD, // ADD Vx, Vy
 | 
			
		||||
			 // ADD Vx, byte
 | 
			
		||||
			 // ADD I, Vx
 | 
			
		||||
		SUB, // SUB Vx, Vy
 | 
			
		||||
			 // SUB Vx, byte
 | 
			
		||||
		SUBN, // SUBN Vx, Vy
 | 
			
		||||
 | 
			
		||||
		SE, // SE Vx, Vy
 | 
			
		||||
			// SE Vx, byte
 | 
			
		||||
		SNE, // SNE Vx, byte
 | 
			
		||||
		SKP, // SKP Vx
 | 
			
		||||
		SKNP, // SKNP Vx
 | 
			
		||||
 | 
			
		||||
		SHL, // SHL Vx {, Vy}
 | 
			
		||||
		SHR, // SHR Vx {, Vy}
 | 
			
		||||
		XOR, // XOR Vx, Vy
 | 
			
		||||
		AND, // AND Vx, Vy
 | 
			
		||||
		OR, // OR Vx, Vy
 | 
			
		||||
 | 
			
		||||
		LD, // LD Vx, DT
 | 
			
		||||
			// LD DT, Vx
 | 
			
		||||
			// LD ST, Vx
 | 
			
		||||
			// LD Vx, K
 | 
			
		||||
			// LD [I], Vx
 | 
			
		||||
			// LD Vx, [I]
 | 
			
		||||
		
 | 
			
		||||
		RND // RND Vx, byte
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	enum Parameter {
 | 
			
		||||
 | 
			
		||||
		Vx,
 | 
			
		||||
		Vy,
 | 
			
		||||
 | 
			
		||||
		DT,
 | 
			
		||||
		ST,
 | 
			
		||||
		K,
 | 
			
		||||
		
 | 
			
		||||
		addr,
 | 
			
		||||
		val
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct Instruction {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	import std.array;
 | 
			
		||||
 | 
			
		||||
	Appender!string dissassembly_data;
 | 
			
		||||
 | 
			
		||||
	void assemble(const char* input) {
 | 
			
		||||
 | 
			
		||||
	} // assemble
 | 
			
		||||
 | 
			
		||||
	void assemble(const char[] input) {
 | 
			
		||||
 | 
			
		||||
	} // assemble
 | 
			
		||||
 | 
			
		||||
	const (char)[] disassemble(ubyte[] instructions) {
 | 
			
		||||
 | 
			
		||||
		import std.range : chunks;
 | 
			
		||||
 | 
			
		||||
		foreach (ref ubyte[] i; instructions.chunks(2)) {
 | 
			
		||||
 | 
			
		||||
			ushort opcode = (*(cast(ushort*)(i.ptr)));
 | 
			
		||||
 | 
			
		||||
			switch (opcode & 0xF000) {
 | 
			
		||||
				case 0x0000:
 | 
			
		||||
					switch (opcode & 0x0FFF) {
 | 
			
		||||
						case 0x00E0: // 0x00E0 Clears the screen.
 | 
			
		||||
 | 
			
		||||
						case 0x00EE: // 0x00EE Returns from a subroutine.
 | 
			
		||||
						default: // 0x0NNN Calls RCA 1802 program at address NNN. Not necessary for most ROMs.
 | 
			
		||||
							//assert(0, "0x0NNN RCA 1802 program opcode not implemented!");
 | 
			
		||||
							break;
 | 
			
		||||
					}
 | 
			
		||||
					break;
 | 
			
		||||
				case 0x1000: // 0x1NNN Jumps to address NNN.
 | 
			
		||||
				case 0x2000: // 0x2NNN Calls subroutine at NNN.
 | 
			
		||||
				case 0x3000: // 0x3XNN Skips the next instruction if VX equals NN.
 | 
			
		||||
				case 0x4000: // 0x4XNN Skips the next instruction if VX doesn't equal NN.
 | 
			
		||||
				case 0x5000: // 0x5XYO Skips the next instruction if VX equals VY.
 | 
			
		||||
				case 0x6000: // 0x6XNN Sets VX to NN.
 | 
			
		||||
				case 0x7000: // 0x7XNN Adds NN to VX.
 | 
			
		||||
				case 0x8000:
 | 
			
		||||
					switch (opcode) {
 | 
			
		||||
 | 
			
		||||
						case 0x0000: // 0x8XY0 Sets VX to the value of VY.
 | 
			
		||||
						case 0x0001: // 0x8XY1 Sets VX to VX or VY.
 | 
			
		||||
						case 0x0002: // 0x8XY2	Sets VX to VX and VY.
 | 
			
		||||
						case 0x0003: // 0x8XY3 Sets VX to VX xor VY.
 | 
			
		||||
						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 0x0005: // 0x8XY5 VY is subtracted from VX. VF is set to 0 when there's a borrow, and 1 when there isn't.
 | 
			
		||||
						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 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 0x000E: // 0x8XYE Shifts VX left by one. VF is set to the value of the most significant bit of VX before the shift.
 | 
			
		||||
						default: // unhandled for some reason
 | 
			
		||||
							writefln("unknown opcode: 0x%x", opcode);
 | 
			
		||||
							break;
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case 0x9000: // 0x9XYO Skips the next instruction if VX doesn't equal VY.
 | 
			
		||||
				case 0xA000: // 0xANNN  Sets I to the address NNN.
 | 
			
		||||
				case 0xB000: // 0xBNNN Jumps to the address NNN plus V0.
 | 
			
		||||
				case 0xC000: // 0xCXNN Sets VX to the result of a bitwise and operation on a random number and NN.
 | 
			
		||||
 | 
			
		||||
				// 0xDXYN
 | 
			
		||||
				// Sprites stored in memory at location in index register (I), 8bits wide.
 | 
			
		||||
				// Wraps around the screen. If when drawn, clears a pixel, register VF is set to 1 otherwise it is zero.
 | 
			
		||||
				// All drawing is XOR drawing (i.e. it toggles the screen pixels).
 | 
			
		||||
				// Sprites are drawn starting at position VX, VY. N is the number of 8bit rows that need to be drawn.
 | 
			
		||||
				// If N is greater than 1, second line continues at position VX, VY+1, and so on.
 | 
			
		||||
				case 0xD000:
 | 
			
		||||
				case 0xE000:
 | 
			
		||||
					switch (opcode & 0x000F) {
 | 
			
		||||
						case 0x000E: // 0xEX9E Skips the next instruction if the key stored in VX is pressed.
 | 
			
		||||
						case 0x0001: // 0xEXA1 Skips the next instruction if the key stored in VX isn't pressed.
 | 
			
		||||
						default: //unhandled for some reason
 | 
			
		||||
							writefln("unknown opcode: 0x%x", opcode);
 | 
			
		||||
							break;
 | 
			
		||||
					}
 | 
			
		||||
					break;
 | 
			
		||||
				case 0xF000:
 | 
			
		||||
					switch (opcode & 0x00FF) {
 | 
			
		||||
						case 0x0007: // 0xFX07 Sets VX to the value of the delay timer.
 | 
			
		||||
						case 0x000A: // 0xFX0A A key press is awaited, and then stored in VX.
 | 
			
		||||
						case 0x0015: // 0xFX15 Sets the delay timer to VX.
 | 
			
		||||
						case 0x0018: // 0xFX18 Sets the sound timer to VX.
 | 
			
		||||
						case 0x001E: // 0xFX1E Adds VX to I.
 | 
			
		||||
						case 0x0029: // 0xFX29 Sets I to the location of the sprite for the character in VX.
 | 
			
		||||
						// 0xFX33 Stores the Binary-coded decimal representation of VX,
 | 
			
		||||
						//  with the most significant of three digits at the address in I,
 | 
			
		||||
						//  the middle digit at I plus 1, and the least significant digit at I plus 2.
 | 
			
		||||
						case 0x0033:
 | 
			
		||||
						case 0x0055: // 0xFX55 Stores V0 to VX in memory starting at address I.
 | 
			
		||||
						case 0x0065: // 0xFX65 Fills V0 to VX with values from memory starting at address I.
 | 
			
		||||
						default: // unhandled for some reason
 | 
			
		||||
							writefln("unknown opcode: 0x%x", opcode);
 | 
			
		||||
							break;
 | 
			
		||||
					}
 | 
			
		||||
					break;
 | 
			
		||||
				default:
 | 
			
		||||
					writefln("unknown opcode: 0x%x", opcode);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		return "";
 | 
			
		||||
 | 
			
		||||
	} // dissassemble
 | 
			
		||||
 | 
			
		||||
} // Assembler
 | 
			
		||||
 | 
			
		||||
struct Chip8Status {
 | 
			
		||||
 | 
			
		||||
	//emu ptr
 | 
			
		||||
	// emu ptr
 | 
			
		||||
	Emulator* run_;
 | 
			
		||||
	Chip8* emu_;
 | 
			
		||||
 | 
			
		||||
	// loaded program
 | 
			
		||||
	const (char)* loaded_program;
 | 
			
		||||
 | 
			
		||||
	// mem editor
 | 
			
		||||
	// MemoryEditor mem_editor_;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -389,6 +558,8 @@ struct Chip8Status {
 | 
			
		|||
 | 
			
		||||
	void resetShortcut() {
 | 
			
		||||
 | 
			
		||||
		loaded_program = null;
 | 
			
		||||
 | 
			
		||||
		emu_.reset();
 | 
			
		||||
		
 | 
			
		||||
	} // resetShortcut
 | 
			
		||||
| 
						 | 
				
			
			@ -397,6 +568,7 @@ struct Chip8Status {
 | 
			
		|||
 | 
			
		||||
		import std.file : read;
 | 
			
		||||
 | 
			
		||||
		loaded_program = "chip8_picture.ch8";
 | 
			
		||||
		auto buf = read("programs/chip8_picture.ch8");
 | 
			
		||||
		emu_.load(0x200, buf); // do ze load yes, will copy all the data in
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -463,14 +635,19 @@ struct Chip8Status {
 | 
			
		|||
			igBegin("Emulator Status");
 | 
			
		||||
 | 
			
		||||
			igBeginChild("General");
 | 
			
		||||
			igText("OpCode: 0x%04X", emu_.cpu.opcode);
 | 
			
		||||
			igText("PC:");
 | 
			
		||||
			if (!loaded_program) {
 | 
			
		||||
				igText("Loaded Program: none");
 | 
			
		||||
			} else {
 | 
			
		||||
				igText("Loaded Program: %s", loaded_program);
 | 
			
		||||
			}
 | 
			
		||||
			igText("Opcode: 0x%04X", emu_.cpu.opcode);
 | 
			
		||||
			igSameLine();
 | 
			
		||||
			igText("pc: 0x%04X (%hu)", emu_.cpu.pc, emu_.cpu.pc);
 | 
			
		||||
			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)");
 | 
			
		||||
			igColumns(4, null, false);
 | 
			
		||||
			igIndent();
 | 
			
		||||
 | 
			
		||||
			auto n = 0;
 | 
			
		||||
			foreach (ref chunk; emu_.cpu.v[].chunks(4)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -483,12 +660,24 @@ struct Chip8Status {
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			igColumns(1, null, false);
 | 
			
		||||
			igUnindent();
 | 
			
		||||
 | 
			
		||||
			igText("Index Register: 0x%04X", emu_.cpu.i);
 | 
			
		||||
			igText("Delay Timer: 0x%04X", emu_.cpu.delay_timer);
 | 
			
		||||
			igText("Sound Timer: 0x%04X", emu_.cpu.sound_timer);
 | 
			
		||||
 | 
			
		||||
			if(igButton("Step")) {
 | 
			
		||||
			if (igButton("Reload")) {
 | 
			
		||||
				resetShortcut();
 | 
			
		||||
				loadShortcut();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			igSameLine();
 | 
			
		||||
 | 
			
		||||
			if (igButton("Reset")) {
 | 
			
		||||
				resetShortcut();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (igButton("Step")) {
 | 
			
		||||
				emu_.step();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue