mor stuff, mostly ui
This commit is contained in:
parent
0a08fa128b
commit
1aff62163a
104
source/app.d
104
source/app.d
|
@ -21,6 +21,12 @@ struct Chip8Status {
|
||||||
Disassembly
|
Disassembly
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum DisassemblyMode {
|
||||||
|
Linear,
|
||||||
|
Recursive,
|
||||||
|
Dynamic
|
||||||
|
}
|
||||||
|
|
||||||
private {
|
private {
|
||||||
|
|
||||||
Chip8* emu_;
|
Chip8* emu_;
|
||||||
|
@ -29,11 +35,13 @@ struct Chip8Status {
|
||||||
int range_end_;
|
int range_end_;
|
||||||
|
|
||||||
// disassembly state
|
// disassembly state
|
||||||
|
DisassemblyMode ass_mode_;
|
||||||
Instr[] disassembly_;
|
Instr[] disassembly_;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize(Chip8* emu) {
|
void initialize(Chip8* emu) {
|
||||||
|
mode_ = ViewMode.Disassembly;
|
||||||
emu_ = emu;
|
emu_ = emu;
|
||||||
} // initialize
|
} // initialize
|
||||||
|
|
||||||
|
@ -55,39 +63,54 @@ struct Chip8Status {
|
||||||
default: return "%s";
|
default: return "%s";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // formatQual
|
||||||
|
|
||||||
void disassemble() {
|
void disassemble() {
|
||||||
ubyte[] instrs = emu_.ram[range_start_ .. range_end_];
|
ubyte[] instrs = emu_.ram[range_start_ .. range_end_];
|
||||||
disassembly_ = Assembler.disassemble(instrs);
|
disassembly_ = Assembler.disassemble(instrs);
|
||||||
writefln("%s", disassembly_);
|
} // disassemble
|
||||||
}
|
|
||||||
|
|
||||||
void setRange(ushort start, ushort end) {
|
void setRange(ushort start, ushort end) {
|
||||||
range_start_ = start;
|
range_start_ = start;
|
||||||
range_end_ = end;
|
range_end_ = end;
|
||||||
}
|
} // setRange
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
disassembly_ = null;
|
||||||
|
} // reset
|
||||||
|
|
||||||
void draw() {
|
void draw() {
|
||||||
|
|
||||||
import std.range : chunks;
|
import std.range : chunks;
|
||||||
|
|
||||||
if (mode_ == ViewMode.Memory) igBegin("Emulator Assembly - Memory View");
|
igBegin("Emulator Assembly");
|
||||||
else if (mode_ == ViewMode.Disassembly) igBegin("Emulator Assembly - Disassembly View");
|
igRadioButton("Memory View", cast(int*)&mode_, cast(int)ViewMode.Memory); igSameLine();
|
||||||
|
igRadioButton("Disassembly View", cast(int*)&mode_, cast(int)ViewMode.Disassembly);
|
||||||
if (igButton("Switch Mode")) {
|
|
||||||
mode_ = cast(ViewMode)((mode_ + 1) % 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode_ == ViewMode.Memory) {
|
if (mode_ == ViewMode.Memory) {
|
||||||
} else if (mode_ == ViewMode.Disassembly) {
|
} else if (mode_ == ViewMode.Disassembly) {
|
||||||
igInputInt("Range Start: ", &range_start_);
|
igInputInt("Range Start ", &range_start_);
|
||||||
igInputInt("Range End: ", &range_end_);
|
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")) {
|
if (igButton("Disassemble")) {
|
||||||
|
final switch (ass_mode_) with (DisassemblyMode) {
|
||||||
|
case Linear:
|
||||||
disassemble();
|
disassemble();
|
||||||
|
break;
|
||||||
|
case Recursive:
|
||||||
|
break;
|
||||||
|
case Dynamic:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (range_start_ < 0) range_start_ = 0;
|
if (range_start_ < 0) range_start_ = 0;
|
||||||
if (range_start_ > ushort.max) range_start_ = 0;
|
if (range_start_ > ushort.max) range_start_ = 0;
|
||||||
|
|
||||||
|
@ -102,7 +125,20 @@ struct Chip8Status {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
} else if (mode_ == ViewMode.Disassembly) {
|
} else if (mode_ == ViewMode.Disassembly) {
|
||||||
|
|
||||||
|
int cur_offset = range_start_;
|
||||||
foreach (ref instr; disassembly_) {
|
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) {
|
switch (instr.args) {
|
||||||
case 3:
|
case 3:
|
||||||
|
|
||||||
|
@ -111,12 +147,12 @@ struct Chip8Status {
|
||||||
|
|
||||||
Arg a1_arg;
|
Arg a1_arg;
|
||||||
auto a1 = instr.a1(a1_arg);
|
auto a1 = instr.a1(a1_arg);
|
||||||
igText(formatQual(a1_arg), a1, true);
|
igText(formatQual(a1_arg, true), a1);
|
||||||
igSameLine();
|
igSameLine();
|
||||||
|
|
||||||
Arg a2_arg;
|
Arg a2_arg;
|
||||||
auto a2 = instr.a2(a2_arg);
|
auto a2 = instr.a2(a2_arg);
|
||||||
igText(formatQual(a2_arg), a2, true);
|
igText(formatQual(a2_arg, true), a2);
|
||||||
igSameLine();
|
igSameLine();
|
||||||
|
|
||||||
Arg a3_arg;
|
Arg a3_arg;
|
||||||
|
@ -132,7 +168,7 @@ struct Chip8Status {
|
||||||
|
|
||||||
Arg a1_arg;
|
Arg a1_arg;
|
||||||
auto a1 = instr.a1(a1_arg);
|
auto a1 = instr.a1(a1_arg);
|
||||||
igText(formatQual(a1_arg), a1, true);
|
igText(formatQual(a1_arg, true), a1);
|
||||||
igSameLine();
|
igSameLine();
|
||||||
|
|
||||||
Arg a2_arg;
|
Arg a2_arg;
|
||||||
|
@ -221,6 +257,7 @@ struct Chip8Status {
|
||||||
loaded_program = null;
|
loaded_program = null;
|
||||||
|
|
||||||
emu_.reset();
|
emu_.reset();
|
||||||
|
ass_.reset();
|
||||||
|
|
||||||
} // resetShortcut
|
} // resetShortcut
|
||||||
|
|
||||||
|
@ -232,6 +269,7 @@ struct Chip8Status {
|
||||||
auto buf = read("programs/chip8_picture.ch8");
|
auto buf = read("programs/chip8_picture.ch8");
|
||||||
emu_.load(0x200, buf); // do ze load yes, will copy all the data in
|
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_.setRange(cast(ushort)0x200, cast(ushort)(0x200 + cast(ushort)buf.length));
|
||||||
|
ass_.reset();
|
||||||
|
|
||||||
} // loadShortcut
|
} // loadShortcut
|
||||||
|
|
||||||
|
@ -417,6 +455,25 @@ pure
|
||||||
|
|
||||||
struct Chip8 {
|
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 OpCode = ushort;
|
||||||
alias ProgramCounter = ushort;
|
alias ProgramCounter = ushort;
|
||||||
alias Memory = ubyte[4096];
|
alias Memory = ubyte[4096];
|
||||||
|
@ -461,8 +518,18 @@ struct Chip8 {
|
||||||
|
|
||||||
ram[offset .. offset + data.length] = cast(ubyte[])data[];
|
ram[offset .. offset + data.length] = cast(ubyte[])data[];
|
||||||
|
|
||||||
|
loadFont(); // again
|
||||||
|
|
||||||
} // load
|
} // load
|
||||||
|
|
||||||
|
void loadFont() {
|
||||||
|
|
||||||
|
foreach (i, b; chip8_fontset) {
|
||||||
|
ram[i] = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // loadFont
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
|
|
||||||
reset_flag = true;
|
reset_flag = true;
|
||||||
|
@ -655,7 +722,7 @@ struct Chip8 {
|
||||||
|
|
||||||
import std.random : uniform;
|
import std.random : uniform;
|
||||||
ubyte x = cpu.opcode.x;
|
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;
|
break;
|
||||||
|
|
||||||
// 0xDXYN
|
// 0xDXYN
|
||||||
|
@ -706,6 +773,7 @@ struct Chip8 {
|
||||||
|
|
||||||
case 0x0001: // 0xEXA1 Skips the next instruction if the key stored in VX isn't pressed.
|
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);
|
writefln("0xEXA1: skip instruction if VX not pressed: %x", key);
|
||||||
|
pc_target += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: //unhandled for some reason
|
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.
|
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 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 = 0x200 + (vx * 40); // base of char sprites + value of vx * bits per character
|
||||||
// immutable ushort char_addr = vx * 0x5;
|
immutable ushort char_addr = vx * 0x05;
|
||||||
cpu.i = char_addr;
|
cpu.i = char_addr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -260,6 +260,9 @@ struct Assembler {
|
||||||
auto instr_output = Appender!(Instruction[])();
|
auto instr_output = Appender!(Instruction[])();
|
||||||
|
|
||||||
foreach (ref ubyte[] i; instructions.chunks(2)) {
|
foreach (ref ubyte[] i; instructions.chunks(2)) {
|
||||||
|
|
||||||
|
if (i.length != 2) break;
|
||||||
|
|
||||||
ushort opcode = i[0] << 8 | i[1];
|
ushort opcode = i[0] << 8 | i[1];
|
||||||
|
|
||||||
switch (opcode & 0xF000) {
|
switch (opcode & 0xF000) {
|
||||||
|
@ -273,7 +276,8 @@ struct Assembler {
|
||||||
break;
|
break;
|
||||||
default: // 0x0NNN Calls RCA 1802 program at address NNN. Not necessary for most ROMs. | SYS addr
|
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!");
|
//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;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue