From 1aff62163a07aa6788acdef21a31e7ee09772c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20H=C3=BCbner?= Date: Fri, 5 Oct 2018 16:16:21 +0200 Subject: [PATCH] mor stuff, mostly ui --- source/app.d | 116 +++++++++++++++++++++++++++++++++++---------- source/assembler.d | 6 ++- 2 files changed, 97 insertions(+), 25 deletions(-) diff --git a/source/app.d b/source/app.d index 525b423..69ac313 100644 --- a/source/app.d +++ b/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; diff --git a/source/assembler.d b/source/assembler.d index 92e5f6f..9fc9516 100644 --- a/source/assembler.d +++ b/source/assembler.d @@ -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;