mor stuff, mostly ui

This commit is contained in:
Robin Hübner 2018-10-05 16:16:21 +02:00
parent 0a08fa128b
commit 1aff62163a
2 changed files with 97 additions and 25 deletions

View File

@ -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,39 +63,54 @@ 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")) {
final switch (ass_mode_) with (DisassemblyMode) {
case Linear:
disassemble();
break;
case Recursive:
break;
case Dynamic:
break;
}
}
}
if (range_start_ < 0) range_start_ = 0;
if (range_start_ > ushort.max) 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;

View File

@ -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;