mor stuff, mostly ui
This commit is contained in:
		
							parent
							
								
									0a08fa128b
								
							
						
					
					
						commit
						1aff62163a
					
				
							
								
								
									
										116
									
								
								source/app.d
								
								
								
								
							
							
						
						
									
										116
									
								
								source/app.d
								
								
								
								
							| 
						 | 
				
			
			@ -21,6 +21,12 @@ struct Chip8Status {
 | 
			
		|||
			Disassembly
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		enum DisassemblyMode {
 | 
			
		||||
			Linear,
 | 
			
		||||
			Recursive,
 | 
			
		||||
			Dynamic
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private {
 | 
			
		||||
 | 
			
		||||
			Chip8* emu_;
 | 
			
		||||
| 
						 | 
				
			
			@ -29,22 +35,24 @@ struct Chip8Status {
 | 
			
		|||
			int range_end_;
 | 
			
		||||
 | 
			
		||||
			// disassembly state
 | 
			
		||||
			DisassemblyMode ass_mode_;
 | 
			
		||||
			Instr[] disassembly_;
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void initialize(Chip8* emu) {
 | 
			
		||||
			mode_ = ViewMode.Disassembly;
 | 
			
		||||
			emu_ = emu;
 | 
			
		||||
		} // initialize
 | 
			
		||||
		
 | 
			
		||||
		static const (char)* formatQual(Arg a, bool with_comma = false) {
 | 
			
		||||
			if (with_comma) {
 | 
			
		||||
				switch (a) with (Arg) {
 | 
			
		||||
					case Vx, Vy, V0: return "V%hu, ";
 | 
			
		||||
					case nibble: return "%01X, ";
 | 
			
		||||
					case beit: return "0x%02X, ";
 | 
			
		||||
					case addr: return "0x%03X, ";
 | 
			
		||||
					default: return "%s, ";
 | 
			
		||||
					case Vx, Vy, V0: return "V%hu,";
 | 
			
		||||
					case nibble: return "%01X,";
 | 
			
		||||
					case beit: return "0x%02X,";
 | 
			
		||||
					case addr: return "0x%03X,";
 | 
			
		||||
					default: return "%s,";
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				switch (a) with (Arg) {
 | 
			
		||||
| 
						 | 
				
			
			@ -55,37 +63,52 @@ struct Chip8Status {
 | 
			
		|||
					default: return "%s";
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		} // formatQual
 | 
			
		||||
 | 
			
		||||
		void disassemble() {
 | 
			
		||||
			ubyte[] instrs = emu_.ram[range_start_ .. range_end_];
 | 
			
		||||
			disassembly_ = Assembler.disassemble(instrs);
 | 
			
		||||
			writefln("%s", disassembly_);
 | 
			
		||||
		}
 | 
			
		||||
		} // disassemble
 | 
			
		||||
 | 
			
		||||
		void setRange(ushort start, ushort end) {
 | 
			
		||||
			range_start_ = start;
 | 
			
		||||
			range_end_ = end;
 | 
			
		||||
		}
 | 
			
		||||
		} // setRange
 | 
			
		||||
 | 
			
		||||
		void reset() {
 | 
			
		||||
			disassembly_ = null;
 | 
			
		||||
		} // reset
 | 
			
		||||
 | 
			
		||||
		void draw() {
 | 
			
		||||
 | 
			
		||||
			import std.range : chunks;
 | 
			
		||||
 | 
			
		||||
			if (mode_ == ViewMode.Memory) igBegin("Emulator Assembly - Memory View");
 | 
			
		||||
			else if (mode_ == ViewMode.Disassembly) igBegin("Emulator Assembly - Disassembly View");
 | 
			
		||||
 | 
			
		||||
			if (igButton("Switch Mode")) {
 | 
			
		||||
				mode_ = cast(ViewMode)((mode_ + 1) % 2);
 | 
			
		||||
			}
 | 
			
		||||
			igBegin("Emulator Assembly");
 | 
			
		||||
			igRadioButton("Memory View", cast(int*)&mode_, cast(int)ViewMode.Memory); igSameLine();
 | 
			
		||||
			igRadioButton("Disassembly View", cast(int*)&mode_, cast(int)ViewMode.Disassembly);
 | 
			
		||||
 | 
			
		||||
			if (mode_ == ViewMode.Memory) {
 | 
			
		||||
			} else if (mode_ == ViewMode.Disassembly) {
 | 
			
		||||
				igInputInt("Range Start: ", &range_start_);
 | 
			
		||||
				igInputInt("Range End: ", &range_end_);
 | 
			
		||||
				igInputInt("Range Start ", &range_start_);
 | 
			
		||||
				igInputInt("Range End ", &range_end_);
 | 
			
		||||
				igNewLine();
 | 
			
		||||
 | 
			
		||||
				igText("Disassembly Mode");
 | 
			
		||||
				igRadioButton("Linear", cast(int*)&ass_mode_, cast(int)DisassemblyMode.Linear); igSameLine();
 | 
			
		||||
				igRadioButton("Recursive", cast(int*)&ass_mode_, cast(int)DisassemblyMode.Recursive); igSameLine();
 | 
			
		||||
				igRadioButton("Dynamic", cast(int*)&ass_mode_, cast(int)DisassemblyMode.Dynamic);
 | 
			
		||||
				if (igButton("Disassemble")) {
 | 
			
		||||
					disassemble();
 | 
			
		||||
					final switch (ass_mode_) with (DisassemblyMode) {
 | 
			
		||||
						case Linear:
 | 
			
		||||
							disassemble();
 | 
			
		||||
							break;
 | 
			
		||||
						case Recursive:
 | 
			
		||||
							break;
 | 
			
		||||
						case Dynamic:
 | 
			
		||||
							break;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			if (range_start_ < 0) range_start_ = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +125,20 @@ struct Chip8Status {
 | 
			
		|||
				}
 | 
			
		||||
				*/
 | 
			
		||||
			} else if (mode_ == ViewMode.Disassembly) {
 | 
			
		||||
 | 
			
		||||
				int cur_offset = range_start_;
 | 
			
		||||
				foreach (ref instr; disassembly_) {
 | 
			
		||||
 | 
			
		||||
					if (emu_.cpu.pc == cur_offset) {
 | 
			
		||||
						igTextColored(ImColor(0, 255, 0), "0x%03X |", cur_offset);
 | 
			
		||||
						cur_offset += 2;
 | 
			
		||||
						igSameLine();
 | 
			
		||||
					} else {
 | 
			
		||||
						igText("0x%03X |", cur_offset);
 | 
			
		||||
						cur_offset += 2;
 | 
			
		||||
						igSameLine();
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					switch  (instr.args) {
 | 
			
		||||
						case 3:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -111,12 +147,12 @@ struct Chip8Status {
 | 
			
		|||
 | 
			
		||||
							Arg a1_arg;
 | 
			
		||||
							auto a1 = instr.a1(a1_arg);
 | 
			
		||||
							igText(formatQual(a1_arg), a1, true);
 | 
			
		||||
							igText(formatQual(a1_arg, true), a1);
 | 
			
		||||
							igSameLine();
 | 
			
		||||
 | 
			
		||||
							Arg a2_arg;
 | 
			
		||||
							auto a2 = instr.a2(a2_arg);
 | 
			
		||||
							igText(formatQual(a2_arg), a2, true);
 | 
			
		||||
							igText(formatQual(a2_arg, true), a2);
 | 
			
		||||
							igSameLine();
 | 
			
		||||
 | 
			
		||||
							Arg a3_arg;
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +168,7 @@ struct Chip8Status {
 | 
			
		|||
 | 
			
		||||
							Arg a1_arg;
 | 
			
		||||
							auto a1 = instr.a1(a1_arg);
 | 
			
		||||
							igText(formatQual(a1_arg), a1, true);
 | 
			
		||||
							igText(formatQual(a1_arg, true), a1);
 | 
			
		||||
							igSameLine();
 | 
			
		||||
 | 
			
		||||
							Arg a2_arg;
 | 
			
		||||
| 
						 | 
				
			
			@ -221,6 +257,7 @@ struct Chip8Status {
 | 
			
		|||
		loaded_program = null;
 | 
			
		||||
 | 
			
		||||
		emu_.reset();
 | 
			
		||||
		ass_.reset();
 | 
			
		||||
		
 | 
			
		||||
	} // resetShortcut
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -232,6 +269,7 @@ struct Chip8Status {
 | 
			
		|||
		auto buf = read("programs/chip8_picture.ch8");
 | 
			
		||||
		emu_.load(0x200, buf); // do ze load yes, will copy all the data in
 | 
			
		||||
		ass_.setRange(cast(ushort)0x200, cast(ushort)(0x200 + cast(ushort)buf.length));
 | 
			
		||||
		ass_.reset();
 | 
			
		||||
 | 
			
		||||
	} // loadShortcut
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -417,6 +455,25 @@ pure
 | 
			
		|||
 | 
			
		||||
struct Chip8 {
 | 
			
		||||
 | 
			
		||||
	ubyte[80] chip8_fontset = [
 | 
			
		||||
		0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
 | 
			
		||||
		0x20, 0x60, 0x20, 0x20, 0x70, // 1
 | 
			
		||||
		0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
 | 
			
		||||
		0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
 | 
			
		||||
		0x90, 0x90, 0xF0, 0x10, 0x10, // 4
 | 
			
		||||
		0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
 | 
			
		||||
		0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
 | 
			
		||||
		0xF0, 0x10, 0x20, 0x40, 0x40, // 7
 | 
			
		||||
		0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
 | 
			
		||||
		0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
 | 
			
		||||
		0xF0, 0x90, 0xF0, 0x90, 0x90, // A
 | 
			
		||||
		0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
 | 
			
		||||
		0xF0, 0x80, 0x80, 0x80, 0xF0, // C
 | 
			
		||||
		0xE0, 0x90, 0x90, 0x90, 0xE0, // D
 | 
			
		||||
		0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
 | 
			
		||||
		0xF0, 0x80, 0xF0, 0x80, 0x80  // F
 | 
			
		||||
	];
 | 
			
		||||
 | 
			
		||||
	alias OpCode = ushort;
 | 
			
		||||
	alias ProgramCounter = ushort;
 | 
			
		||||
	alias Memory = ubyte[4096];
 | 
			
		||||
| 
						 | 
				
			
			@ -461,8 +518,18 @@ struct Chip8 {
 | 
			
		|||
 | 
			
		||||
		ram[offset .. offset + data.length] = cast(ubyte[])data[];
 | 
			
		||||
 | 
			
		||||
		loadFont(); // again
 | 
			
		||||
 | 
			
		||||
	} // load
 | 
			
		||||
 | 
			
		||||
	void loadFont() {
 | 
			
		||||
 | 
			
		||||
		foreach (i, b; chip8_fontset) {
 | 
			
		||||
			ram[i] = b;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	} // loadFont
 | 
			
		||||
 | 
			
		||||
	void reset() {
 | 
			
		||||
			
 | 
			
		||||
		reset_flag = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -655,7 +722,7 @@ struct Chip8 {
 | 
			
		|||
 | 
			
		||||
				import std.random : uniform;
 | 
			
		||||
				ubyte x = cpu.opcode.x;
 | 
			
		||||
				cpu.v[x] = uniform(Register.min, Register.max) & (cpu.opcode & 0x00FF);
 | 
			
		||||
				cpu.v[x] = uniform(Register.min, Register.max) & x;
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			// 0xDXYN
 | 
			
		||||
| 
						 | 
				
			
			@ -706,6 +773,7 @@ struct Chip8 {
 | 
			
		|||
 | 
			
		||||
					case 0x0001: // 0xEXA1 Skips the next instruction if the key stored in VX isn't pressed.
 | 
			
		||||
						writefln("0xEXA1: skip instruction if VX not pressed: %x", key);
 | 
			
		||||
						pc_target += 2;
 | 
			
		||||
						break;
 | 
			
		||||
 | 
			
		||||
					default: //unhandled for some reason
 | 
			
		||||
| 
						 | 
				
			
			@ -748,8 +816,8 @@ struct Chip8 {
 | 
			
		|||
					case 0x0029: // 0xFX29 Sets I to the location of the sprite for the character in VX.
 | 
			
		||||
 | 
			
		||||
						immutable ubyte vx = cpu.v[cpu.opcode.x];
 | 
			
		||||
						immutable ushort char_addr = 0x200 + (vx * 40); // base of char sprites + value of vx * bits per character
 | 
			
		||||
						// immutable ushort char_addr = vx * 0x5;
 | 
			
		||||
						// immutable ushort char_addr = 0x200 + (vx * 40); // base of char sprites + value of vx * bits per character
 | 
			
		||||
						immutable ushort char_addr = vx * 0x05;
 | 
			
		||||
						cpu.i = char_addr;
 | 
			
		||||
						break;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -260,6 +260,9 @@ struct Assembler {
 | 
			
		|||
		auto instr_output = Appender!(Instruction[])();
 | 
			
		||||
 | 
			
		||||
		foreach (ref ubyte[] i; instructions.chunks(2)) {
 | 
			
		||||
 | 
			
		||||
			if (i.length != 2) break;
 | 
			
		||||
 | 
			
		||||
			ushort opcode = i[0] << 8 | i[1];
 | 
			
		||||
 | 
			
		||||
			switch (opcode & 0xF000) {
 | 
			
		||||
| 
						 | 
				
			
			@ -273,7 +276,8 @@ struct Assembler {
 | 
			
		|||
							break;
 | 
			
		||||
						default: // 0x0NNN Calls RCA 1802 program at address NNN. Not necessary for most ROMs. | SYS addr
 | 
			
		||||
							//assert(0, "0x0NNN RCA 1802 program opcode not implemented!");
 | 
			
		||||
							instr_output ~= Instruction(opcode, OpCode.SYS, Argument.addr);
 | 
			
		||||
							// instr_output ~= Instruction(opcode, OpCode.SYS, Argument.addr);
 | 
			
		||||
							instr_output ~= Instruction(opcode, OpCode.UNK);
 | 
			
		||||
							break;
 | 
			
		||||
					}
 | 
			
		||||
					break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue