Compare commits
5 Commits
ab4a43163a
...
a1a52024c8
| Author | SHA1 | Date | |
|---|---|---|---|
|
a1a52024c8
|
|||
|
a477a21d7f
|
|||
|
a803e733da
|
|||
|
b9d2377088
|
|||
|
d8e3aa16f8
|
@@ -30,8 +30,12 @@ target_sources(
|
|||||||
UI/UIManager.h
|
UI/UIManager.h
|
||||||
UI/Disassembler.cpp
|
UI/Disassembler.cpp
|
||||||
UI/Disassembler.h
|
UI/Disassembler.h
|
||||||
|
UI/RegisterView.cpp
|
||||||
|
UI/RegisterView.h
|
||||||
|
UI/StackViewer.cpp
|
||||||
|
UI/StackViewer.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_compile_options(-Wall -Wextra -Wpedantic -Werror)
|
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE vendor)
|
target_link_libraries(${PROJECT_NAME} PRIVATE vendor)
|
||||||
|
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
||||||
|
target_link_options(${PROJECT_NAME} PRIVATE)
|
||||||
@@ -219,7 +219,7 @@ std::vector<Instruction> Interpreter::disassembly() const
|
|||||||
{
|
{
|
||||||
std::vector<Instruction> instructions(std::size(machine_state->memory) / 2);
|
std::vector<Instruction> instructions(std::size(machine_state->memory) / 2);
|
||||||
|
|
||||||
for (auto address = 0; address < std::size(machine_state->memory); address += 2)
|
for (std::size_t address = 0; address < std::size(machine_state->memory); address += 2)
|
||||||
{
|
{
|
||||||
const auto word = this->get_word(address);
|
const auto word = this->get_word(address);
|
||||||
instructions[address / 2] = (this->decode(word, address));
|
instructions[address / 2] = (this->decode(word, address));
|
||||||
@@ -287,6 +287,7 @@ void Interpreter::ret() const
|
|||||||
{
|
{
|
||||||
this->machine_state->sp -= 1;
|
this->machine_state->sp -= 1;
|
||||||
this->machine_state->pc = this->machine_state->stack[this->machine_state->sp];
|
this->machine_state->pc = this->machine_state->stack[this->machine_state->sp];
|
||||||
|
this->machine_state->stack[this->machine_state->sp] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::jp_addr(const Instruction& instruction) const
|
void Interpreter::jp_addr(const Instruction& instruction) const
|
||||||
@@ -495,7 +496,7 @@ void Interpreter::drw_vx_vy_nibble(const Instruction& instruction) const
|
|||||||
const auto& vx = this->machine_state->v[instruction.x];
|
const auto& vx = this->machine_state->v[instruction.x];
|
||||||
const auto& vy = this->machine_state->v[instruction.y];
|
const auto& vy = this->machine_state->v[instruction.y];
|
||||||
auto& vf = this->machine_state->v[0xF];
|
auto& vf = this->machine_state->v[0xF];
|
||||||
auto& i = this->machine_state->i;
|
const auto& i = this->machine_state->i;
|
||||||
|
|
||||||
const uint8_t start_x = vx & 63;
|
const uint8_t start_x = vx & 63;
|
||||||
const uint8_t start_y = vy & 31;
|
const uint8_t start_y = vy & 31;
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ class Interpreter
|
|||||||
|
|
||||||
uint8_t quirks = 0;
|
uint8_t quirks = 0;
|
||||||
|
|
||||||
Instruction decode(uint16_t word, uint16_t address) const;
|
|
||||||
void execute_instruction(const Instruction& instruction);
|
void execute_instruction(const Instruction& instruction);
|
||||||
|
|
||||||
void sys_addr() const;
|
void sys_addr() const;
|
||||||
@@ -64,6 +63,7 @@ class Interpreter
|
|||||||
public:
|
public:
|
||||||
explicit Interpreter(std::shared_ptr<MachineState> machine_state);
|
explicit Interpreter(std::shared_ptr<MachineState> machine_state);
|
||||||
uint16_t get_word(uint16_t address) const;
|
uint16_t get_word(uint16_t address) const;
|
||||||
|
Instruction decode(uint16_t word, uint16_t address) const;
|
||||||
std::vector<Instruction> disassembly() const;
|
std::vector<Instruction> disassembly() const;
|
||||||
|
|
||||||
void tick();
|
void tick();
|
||||||
|
|||||||
@@ -18,13 +18,15 @@ Machine::Machine() :
|
|||||||
graphics{std::make_shared<Graphics>()},
|
graphics{std::make_shared<Graphics>()},
|
||||||
callback_manager(std::make_shared<CallbackManager>()),
|
callback_manager(std::make_shared<CallbackManager>()),
|
||||||
|
|
||||||
interpreter{std::make_unique<Interpreter>(this->machine_state)},
|
interpreter{std::make_shared<Interpreter>(this->machine_state)},
|
||||||
ui_manager{std::make_unique<UIManager>(this->graphics, this->machine_state, this->callback_manager)},
|
ui_manager{
|
||||||
running{false},
|
std::make_unique<UIManager>(this->graphics, this->machine_state, this->interpreter, this->callback_manager)
|
||||||
|
},
|
||||||
ips{60},
|
ips{60},
|
||||||
last_update_time{0},
|
last_update_time{0},
|
||||||
accumulator{0},
|
accumulator{0},
|
||||||
target_cycle_time{1.0 / this->ips}
|
target_cycle_time{1.0 / this->ips},
|
||||||
|
running{false}
|
||||||
{
|
{
|
||||||
this->register_callbacks();
|
this->register_callbacks();
|
||||||
this->callback_manager->trigger(this->callback_manager->ips_callback, this->ips);
|
this->callback_manager->trigger(this->callback_manager->ips_callback, this->ips);
|
||||||
@@ -37,8 +39,6 @@ void Machine::iterate()
|
|||||||
this->execute_interpreter();
|
this->execute_interpreter();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->callback_manager->trigger(this->callback_manager->disassembly_callback, this->interpreter->disassembly());
|
|
||||||
|
|
||||||
this->graphics->start();
|
this->graphics->start();
|
||||||
this->ui_manager->render();
|
this->ui_manager->render();
|
||||||
this->graphics->end();
|
this->graphics->end();
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class Machine
|
|||||||
std::shared_ptr<Graphics> graphics;
|
std::shared_ptr<Graphics> graphics;
|
||||||
std::shared_ptr<CallbackManager> callback_manager;
|
std::shared_ptr<CallbackManager> callback_manager;
|
||||||
|
|
||||||
std::unique_ptr<Interpreter> interpreter;
|
std::shared_ptr<Interpreter> interpreter;
|
||||||
std::unique_ptr<UIManager> ui_manager;
|
std::unique_ptr<UIManager> ui_manager;
|
||||||
|
|
||||||
int ips;
|
int ips;
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ struct CallbackManager
|
|||||||
std::vector<std::function<void(int)>> step_callback;
|
std::vector<std::function<void(int)>> step_callback;
|
||||||
std::vector<std::function<void(int)>> ips_callback;
|
std::vector<std::function<void(int)>> ips_callback;
|
||||||
std::vector<std::function<void()>> reload_callback;
|
std::vector<std::function<void()>> reload_callback;
|
||||||
std::vector<std::function<void(const std::vector<Instruction>)>> disassembly_callback;
|
|
||||||
|
|
||||||
template <typename Func, typename... Args>
|
template <typename Func, typename... Args>
|
||||||
void trigger(const std::vector<Func>& callbacks, Args&&... args)
|
void trigger(const std::vector<Func>& callbacks, Args&&... args)
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ void ControlPanel::render()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Text("Status: %s", "Stopped");
|
ImGui::Text("Status: %s", run ? "Running" : "Stopped");
|
||||||
|
|
||||||
ImGui::SeparatorText("Debug");
|
ImGui::SeparatorText("Debug");
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ void ControlPanel::on_click_load_rom()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControlPanel::on_callback_load_rom(void* self, const char* const* filelist, int filter)
|
void ControlPanel::on_callback_load_rom(void* self, const char* const* filelist, int)
|
||||||
{
|
{
|
||||||
const auto control_panel = static_cast<ControlPanel*>(self);
|
const auto control_panel = static_cast<ControlPanel*>(self);
|
||||||
|
|
||||||
|
|||||||
@@ -9,16 +9,13 @@
|
|||||||
Disassembler::Disassembler(
|
Disassembler::Disassembler(
|
||||||
std::shared_ptr<Graphics> graphics,
|
std::shared_ptr<Graphics> graphics,
|
||||||
std::shared_ptr<MachineState> machine_state,
|
std::shared_ptr<MachineState> machine_state,
|
||||||
|
std::shared_ptr<Interpreter> interpreter,
|
||||||
std::shared_ptr<CallbackManager> callback_manager) :
|
std::shared_ptr<CallbackManager> callback_manager) :
|
||||||
graphis{std::move(graphics)},
|
graphis{std::move(graphics)},
|
||||||
machine_state{std::move(machine_state)},
|
machine_state{std::move(machine_state)},
|
||||||
|
interpreter{std::move(interpreter)},
|
||||||
callback_manager{std::move(callback_manager)}
|
callback_manager{std::move(callback_manager)}
|
||||||
{
|
{
|
||||||
this->callback_manager->disassembly_callback.push_back(std::bind(
|
|
||||||
&Disassembler::on_disassembly_callback,
|
|
||||||
this,
|
|
||||||
std::placeholders::_1
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disassembler::render()
|
void Disassembler::render()
|
||||||
@@ -26,40 +23,58 @@ void Disassembler::render()
|
|||||||
if (ImGui::Begin("Chip-8 - Disassembly"))
|
if (ImGui::Begin("Chip-8 - Disassembly"))
|
||||||
{
|
{
|
||||||
ImGui::Checkbox("Follow", &this->follow);
|
ImGui::Checkbox("Follow", &this->follow);
|
||||||
|
ImGui::Checkbox("Show odd instructions", &this->show_odd);
|
||||||
|
|
||||||
ImGuiListClipper clipper;
|
ImGuiListClipper clipper;
|
||||||
clipper.Begin(this->disassembly.size());
|
clipper.Begin((machine_state->memory.size() / (this->show_odd ? 1 : 2)) - ((this->show_odd ? 1 : 0)));
|
||||||
ImGui::BeginChild("##instructions");
|
ImGui::BeginChild("##instructions");
|
||||||
|
|
||||||
if (this->follow)
|
if (this->follow)
|
||||||
{
|
{
|
||||||
size_t pc_index = machine_state->pc / 2;
|
|
||||||
const float line_h = ImGui::GetTextLineHeightWithSpacing();
|
const float line_h = ImGui::GetTextLineHeightWithSpacing();
|
||||||
|
|
||||||
if (pc_index < disassembly.size())
|
const auto current_pc = machine_state->pc / (this->show_odd ? 1 : 2);
|
||||||
{
|
|
||||||
const float window_h = ImGui::GetWindowHeight();
|
const float window_h = ImGui::GetWindowHeight();
|
||||||
const float target_y = pc_index * line_h;
|
const float target_y = current_pc * line_h;
|
||||||
const float scroll_y = target_y - (window_h * 0.1f) + (line_h * 0.1f);
|
const float scroll_y = target_y - (window_h * 0.1f) + (line_h * 0.1f);
|
||||||
ImGui::SetScrollY(scroll_y);
|
ImGui::SetScrollY(scroll_y);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
while (clipper.Step())
|
while (clipper.Step())
|
||||||
{
|
{
|
||||||
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
|
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
|
||||||
{
|
{
|
||||||
const auto& instruction = this->disassembly[i];
|
const auto address = i * (this->show_odd ? 1 : 2);
|
||||||
auto line = this->build_line(instruction);
|
auto line = this->build_line(
|
||||||
if (instruction.address == machine_state->pc)
|
this->interpreter->decode(
|
||||||
|
this->interpreter->get_word(address),
|
||||||
|
address
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (address == machine_state->pc)
|
||||||
|
{
|
||||||
|
if (address % 2 == 0)
|
||||||
{
|
{
|
||||||
ImGui::TextColored(ImVec4(1, 1, 0, 1), "%s", line.c_str());
|
ImGui::TextColored(ImVec4(1, 1, 0, 1), "%s", line.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
ImGui::TextColored(ImVec4(1, 1, 0, 1), "%s", line.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (address % 2 == 0)
|
||||||
{
|
{
|
||||||
ImGui::TextUnformatted(line.c_str());
|
ImGui::TextUnformatted(line.c_str());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGui::TextColored(ImVec4(1, 1, 1, .5), "%s", line.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
@@ -67,14 +82,32 @@ void Disassembler::render()
|
|||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disassembler::on_disassembly_callback(const std::vector<Instruction>& disassembly)
|
|
||||||
{
|
|
||||||
this->disassembly = disassembly;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Disassembler::build_line(const Instruction instruction) const
|
std::string Disassembler::build_line(const Instruction instruction) const
|
||||||
{
|
{
|
||||||
const std::string addr_prefix = std::format("0x{:0>4x} | ", instruction.address);
|
std::string addr_prefix;
|
||||||
|
if (instruction.address == machine_state->pc)
|
||||||
|
{
|
||||||
|
if (instruction.address % 2 == 0)
|
||||||
|
{
|
||||||
|
addr_prefix = std::format(">0x{:0>4x} | ", instruction.address);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr_prefix = std::format("> 0x{:0>4x} | ", instruction.address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (instruction.address % 2 == 0)
|
||||||
|
{
|
||||||
|
addr_prefix = std::format(" 0x{:0>4x} | ", instruction.address);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr_prefix = std::format("- 0x{:0>4x} | ", instruction.address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (instruction.op_code)
|
switch (instruction.op_code)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "CallbackManager.h"
|
#include "CallbackManager.h"
|
||||||
#include "../Graphics/Graphics.h"
|
#include "../Graphics/Graphics.h"
|
||||||
|
#include "../Interpreter/Interpreter.h"
|
||||||
#include "../Interpreter/MachineState.h"
|
#include "../Interpreter/MachineState.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -11,21 +12,21 @@ class Disassembler
|
|||||||
{
|
{
|
||||||
std::shared_ptr<Graphics> graphis;
|
std::shared_ptr<Graphics> graphis;
|
||||||
std::shared_ptr<MachineState> machine_state;
|
std::shared_ptr<MachineState> machine_state;
|
||||||
|
std::shared_ptr<Interpreter> interpreter;
|
||||||
std::shared_ptr<CallbackManager> callback_manager;
|
std::shared_ptr<CallbackManager> callback_manager;
|
||||||
|
|
||||||
std::vector<Instruction> disassembly;
|
bool follow = true;
|
||||||
|
bool show_odd = false;
|
||||||
bool follow = false;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Disassembler(
|
Disassembler(
|
||||||
std::shared_ptr<Graphics> graphics,
|
std::shared_ptr<Graphics> graphics,
|
||||||
std::shared_ptr<MachineState> machine_state,
|
std::shared_ptr<MachineState> machine_state,
|
||||||
|
std::shared_ptr<Interpreter> interpreter,
|
||||||
std::shared_ptr<CallbackManager> callback_manager
|
std::shared_ptr<CallbackManager> callback_manager
|
||||||
);
|
);
|
||||||
|
|
||||||
void render();
|
void render();
|
||||||
void on_disassembly_callback(const std::vector<Instruction>& disassembly);
|
|
||||||
std::string build_line(Instruction instruction) const;
|
std::string build_line(Instruction instruction) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ void Display::update_texture() const
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
for (int i = 0; i < display.size(); i++)
|
for (std::size_t i = 0; i < display.size(); i++)
|
||||||
{
|
{
|
||||||
if (display[i])
|
if (display[i])
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,27 +24,32 @@ void MemoryViewer::render()
|
|||||||
ImGui::SliderInt("##memory_view_width", &width, 1, 32, "%d", ImGuiSliderFlags_AlwaysClamp);
|
ImGui::SliderInt("##memory_view_width", &width, 1, 32, "%d", ImGuiSliderFlags_AlwaysClamp);
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
|
|
||||||
|
auto total_lines = (std::size(this->machine_state->memory) + width - 1) / width;
|
||||||
|
ImGuiListClipper clipper;
|
||||||
|
clipper.Begin(total_lines);
|
||||||
|
|
||||||
auto dump_lines = this->get_memory_dump();
|
ImGui::BeginChild("##memory_view");
|
||||||
for (auto dump_line : dump_lines)
|
while (clipper.Step())
|
||||||
{
|
{
|
||||||
ImGui::TextUnformatted(dump_line.c_str());
|
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
|
||||||
|
{
|
||||||
|
ImGui::TextUnformatted(get_memory_line(i).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> MemoryViewer::get_memory_dump() const
|
std::string MemoryViewer::get_memory_line(const int line) const
|
||||||
{
|
{
|
||||||
auto& memory = this->machine_state->memory;
|
auto& memory = this->machine_state->memory;
|
||||||
|
|
||||||
const auto size = std::size(memory);
|
const auto size = std::size(memory);
|
||||||
|
const auto i = line * this->width;
|
||||||
|
|
||||||
std::vector<std::string> dump_lines;
|
|
||||||
|
|
||||||
for (auto i = 0; i < size; i += this->width)
|
|
||||||
{
|
|
||||||
std::stringstream text_builder;
|
std::stringstream text_builder;
|
||||||
|
|
||||||
text_builder << "0x";
|
text_builder << "0x";
|
||||||
text_builder << std::hex
|
text_builder << std::hex
|
||||||
<< std::setw(4)
|
<< std::setw(4)
|
||||||
@@ -53,9 +58,9 @@ std::vector<std::string> MemoryViewer::get_memory_dump() const
|
|||||||
<< static_cast<unsigned int>(i)
|
<< static_cast<unsigned int>(i)
|
||||||
<< " | ";
|
<< " | ";
|
||||||
|
|
||||||
for (auto j = 0; j < this->width; j++)
|
for (int j = 0; j < this->width; j++)
|
||||||
{
|
{
|
||||||
if (i + j >= size)
|
if (static_cast<std::size_t>(i + j) >= size)
|
||||||
{
|
{
|
||||||
text_builder << " ";
|
text_builder << " ";
|
||||||
}
|
}
|
||||||
@@ -72,9 +77,9 @@ std::vector<std::string> MemoryViewer::get_memory_dump() const
|
|||||||
|
|
||||||
text_builder << "| ";
|
text_builder << "| ";
|
||||||
|
|
||||||
for (auto j = 0; j < this->width; j++)
|
for (int j = 0; j < this->width; j++)
|
||||||
{
|
{
|
||||||
if (i + j >= size)
|
if (static_cast<std::size_t>(i + j) >= size)
|
||||||
{
|
{
|
||||||
text_builder << ".";
|
text_builder << ".";
|
||||||
}
|
}
|
||||||
@@ -92,8 +97,5 @@ std::vector<std::string> MemoryViewer::get_memory_dump() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dump_lines.push_back(text_builder.str());
|
return text_builder.str();
|
||||||
}
|
|
||||||
|
|
||||||
return dump_lines;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
void render();
|
void render();
|
||||||
std::vector<std::string> get_memory_dump() const;
|
std::string get_memory_line(int line) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
57
src/UI/RegisterView.cpp
Normal file
57
src/UI/RegisterView.cpp
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#include "RegisterView.h"
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "../Interpreter/MachineState.h"
|
||||||
|
|
||||||
|
RegisterView::RegisterView(
|
||||||
|
std::shared_ptr<Graphics> graphics,
|
||||||
|
std::shared_ptr<MachineState> machine_state,
|
||||||
|
std::shared_ptr<CallbackManager> callback_manager) :
|
||||||
|
graphics{std::move(graphics)},
|
||||||
|
machine_state{std::move(machine_state)},
|
||||||
|
callback_manager{std::move(callback_manager)}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterView::render()
|
||||||
|
{
|
||||||
|
if (ImGui::Begin("Chip8 - Registers"))
|
||||||
|
{
|
||||||
|
if (ImGui::BeginTable("Registers", 4, ImGuiTableFlags_Borders))
|
||||||
|
{
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
ImGui::Text("PC");
|
||||||
|
ImGui::Text("0x%04X", this->machine_state->pc);
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::Text("I");
|
||||||
|
ImGui::Text("0x%02X", this->machine_state->i);
|
||||||
|
|
||||||
|
ImGui::TableSetColumnIndex(2);
|
||||||
|
ImGui::Text("DT");
|
||||||
|
ImGui::Text("0x%04X", this->machine_state->dt);
|
||||||
|
|
||||||
|
ImGui::TableSetColumnIndex(3);
|
||||||
|
ImGui::Text("ST");
|
||||||
|
ImGui::Text("0x%04X", this->machine_state->st);
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
|
||||||
|
if (ImGui::BeginTable("Registers", 8, ImGuiTableFlags_Borders))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
for (int j = 0; j < 8; j++)
|
||||||
|
{
|
||||||
|
ImGui::TableSetColumnIndex(j);
|
||||||
|
ImGui::Text("V%i", i * 8 + j);
|
||||||
|
ImGui::Text("0x%02X", this->machine_state->v[i * 8 + j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
27
src/UI/RegisterView.h
Normal file
27
src/UI/RegisterView.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef REGISTERVIEW_H
|
||||||
|
#define REGISTERVIEW_H
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "CallbackManager.h"
|
||||||
|
#include "../Graphics/Graphics.h"
|
||||||
|
#include "../Interpreter/MachineState.h"
|
||||||
|
|
||||||
|
|
||||||
|
class RegisterView
|
||||||
|
{
|
||||||
|
std::shared_ptr<Graphics> graphics;
|
||||||
|
std::shared_ptr<MachineState> machine_state;
|
||||||
|
std::shared_ptr<CallbackManager> callback_manager;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RegisterView(
|
||||||
|
std::shared_ptr<Graphics> graphics,
|
||||||
|
std::shared_ptr<MachineState> machine_state,
|
||||||
|
std::shared_ptr<CallbackManager> callback_manager
|
||||||
|
);
|
||||||
|
|
||||||
|
void render();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //REGISTERVIEW_H
|
||||||
34
src/UI/StackViewer.cpp
Normal file
34
src/UI/StackViewer.cpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include "StackViewer.h"
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
|
||||||
|
StackViewer::StackViewer(
|
||||||
|
std::shared_ptr<Graphics> graphics,
|
||||||
|
std::shared_ptr<MachineState> machine_state,
|
||||||
|
std::shared_ptr<CallbackManager> callback_manager
|
||||||
|
) :
|
||||||
|
graphics{std::move(graphics)},
|
||||||
|
machine_state{std::move(machine_state)},
|
||||||
|
callback_manager{std::move(callback_manager)}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void StackViewer::render()
|
||||||
|
{
|
||||||
|
if (ImGui::Begin("Chip8 - Stack"))
|
||||||
|
{
|
||||||
|
if (ImGui::BeginTable("Stack", 2, ImGuiTableFlags_BordersV))
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < std::size(machine_state->stack); i++)
|
||||||
|
{
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
ImGui::Text("Depth %zu", i);
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::Text("0x%04X", machine_state->stack[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
25
src/UI/StackViewer.h
Normal file
25
src/UI/StackViewer.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef STACKVIEWER_H
|
||||||
|
#define STACKVIEWER_H
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "CallbackManager.h"
|
||||||
|
#include "../Graphics/Graphics.h"
|
||||||
|
#include "../Interpreter/MachineState.h"
|
||||||
|
|
||||||
|
class StackViewer
|
||||||
|
{
|
||||||
|
std::shared_ptr<Graphics> graphics;
|
||||||
|
std::shared_ptr<MachineState> machine_state;
|
||||||
|
std::shared_ptr<CallbackManager> callback_manager;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StackViewer(
|
||||||
|
std::shared_ptr<Graphics> graphics,
|
||||||
|
std::shared_ptr<MachineState> machine_state,
|
||||||
|
std::shared_ptr<CallbackManager> callback_manager);
|
||||||
|
|
||||||
|
void render();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //STACKVIEWER_H
|
||||||
@@ -2,22 +2,30 @@
|
|||||||
|
|
||||||
#include "Disassembler.h"
|
#include "Disassembler.h"
|
||||||
#include "MemoryViewer.h"
|
#include "MemoryViewer.h"
|
||||||
|
#include "RegisterView.h"
|
||||||
#include "RomInfo.h"
|
#include "RomInfo.h"
|
||||||
|
#include "StackViewer.h"
|
||||||
|
|
||||||
UIManager::UIManager(
|
UIManager::UIManager(
|
||||||
std::shared_ptr<Graphics> graphics,
|
std::shared_ptr<Graphics> graphics,
|
||||||
std::shared_ptr<MachineState> machine_state,
|
std::shared_ptr<MachineState> machine_state,
|
||||||
|
std::shared_ptr<Interpreter> interpreter,
|
||||||
std::shared_ptr<CallbackManager> callback_manager
|
std::shared_ptr<CallbackManager> callback_manager
|
||||||
) :
|
) :
|
||||||
graphics{std::move(graphics)},
|
graphics{std::move(graphics)},
|
||||||
machine_state{std::move(machine_state)},
|
machine_state{std::move(machine_state)},
|
||||||
|
interpreter{std::move(interpreter)},
|
||||||
callback_manager{std::move(callback_manager)},
|
callback_manager{std::move(callback_manager)},
|
||||||
|
|
||||||
display{std::make_unique<Display>(this->graphics, this->machine_state)},
|
display{std::make_unique<Display>(this->graphics, this->machine_state)},
|
||||||
control_panel{std::make_unique<ControlPanel>(this->graphics, this->machine_state, this->callback_manager)},
|
control_panel{std::make_unique<ControlPanel>(this->graphics, this->machine_state, this->callback_manager)},
|
||||||
rom_info{std::make_unique<RomInfo>(this->graphics, this->machine_state, this->callback_manager)},
|
rom_info{std::make_unique<RomInfo>(this->graphics, this->machine_state, this->callback_manager)},
|
||||||
memory_viewer{std::make_unique<MemoryViewer>(this->graphics, this->machine_state, this->callback_manager)},
|
memory_viewer{std::make_unique<MemoryViewer>(this->graphics, this->machine_state, this->callback_manager)},
|
||||||
disassembler{std::make_unique<Disassembler>(this->graphics, this->machine_state, this->callback_manager)}
|
disassembler{
|
||||||
|
std::make_unique<Disassembler>(this->graphics, this->machine_state, this->interpreter, this->callback_manager)
|
||||||
|
},
|
||||||
|
register_view{std::make_unique<RegisterView>(this->graphics, this->machine_state, this->callback_manager)},
|
||||||
|
stack_viewer{std::make_unique<StackViewer>(this->graphics, this->machine_state, this->callback_manager)}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,4 +36,6 @@ void UIManager::render()
|
|||||||
this->rom_info->render();
|
this->rom_info->render();
|
||||||
this->memory_viewer->render();
|
this->memory_viewer->render();
|
||||||
this->disassembler->render();
|
this->disassembler->render();
|
||||||
|
this->register_view->render();
|
||||||
|
this->stack_viewer->render();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,24 +7,31 @@
|
|||||||
#include "Disassembler.h"
|
#include "Disassembler.h"
|
||||||
#include "Display.h"
|
#include "Display.h"
|
||||||
#include "MemoryViewer.h"
|
#include "MemoryViewer.h"
|
||||||
|
#include "RegisterView.h"
|
||||||
#include "RomInfo.h"
|
#include "RomInfo.h"
|
||||||
|
#include "StackViewer.h"
|
||||||
#include "../Graphics/Graphics.h"
|
#include "../Graphics/Graphics.h"
|
||||||
|
#include "../Interpreter/Interpreter.h"
|
||||||
|
|
||||||
class UIManager
|
class UIManager
|
||||||
{
|
{
|
||||||
std::shared_ptr<Graphics> graphics;
|
std::shared_ptr<Graphics> graphics;
|
||||||
std::shared_ptr<MachineState> machine_state;
|
std::shared_ptr<MachineState> machine_state;
|
||||||
|
std::shared_ptr<Interpreter> interpreter;
|
||||||
std::shared_ptr<CallbackManager> callback_manager;
|
std::shared_ptr<CallbackManager> callback_manager;
|
||||||
std::unique_ptr<Display> display;
|
std::unique_ptr<Display> display;
|
||||||
std::unique_ptr<ControlPanel> control_panel;
|
std::unique_ptr<ControlPanel> control_panel;
|
||||||
std::unique_ptr<RomInfo> rom_info;
|
std::unique_ptr<RomInfo> rom_info;
|
||||||
std::unique_ptr<MemoryViewer> memory_viewer;
|
std::unique_ptr<MemoryViewer> memory_viewer;
|
||||||
std::unique_ptr<Disassembler> disassembler;
|
std::unique_ptr<Disassembler> disassembler;
|
||||||
|
std::unique_ptr<RegisterView> register_view;
|
||||||
|
std::unique_ptr<StackViewer> stack_viewer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UIManager(
|
UIManager(
|
||||||
std::shared_ptr<Graphics> graphics,
|
std::shared_ptr<Graphics> graphics,
|
||||||
std::shared_ptr<MachineState> machine_state,
|
std::shared_ptr<MachineState> machine_state,
|
||||||
|
std::shared_ptr<Interpreter> interpreter,
|
||||||
std::shared_ptr<CallbackManager> callback_manager
|
std::shared_ptr<CallbackManager> callback_manager
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include "Machine.h"
|
#include "Machine.h"
|
||||||
|
|
||||||
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[])
|
SDL_AppResult SDL_AppInit(void** appstate, [[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
|
||||||
{
|
{
|
||||||
auto machine = std::make_unique<Machine>();
|
auto machine = std::make_unique<Machine>();
|
||||||
*appstate = machine.release();
|
*appstate = machine.release();
|
||||||
@@ -33,7 +33,7 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
|
|||||||
return SDL_APP_CONTINUE;
|
return SDL_APP_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_AppQuit(void* appstate, SDL_AppResult result)
|
void SDL_AppQuit(void* appstate, [[maybe_unused]] SDL_AppResult result)
|
||||||
{
|
{
|
||||||
std::unique_ptr<Machine> chip8(static_cast<Machine*>(appstate));
|
std::unique_ptr<Machine> chip8(static_cast<Machine*>(appstate));
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user