diff --git a/src/assembly.cpp b/src/assembly.cpp index c1485d4..c18c9fd 100644 --- a/src/assembly.cpp +++ b/src/assembly.cpp @@ -74,6 +74,13 @@ void AssemblyViewer::draw() { ImGui::SameLine(); ImGui::Text(format_data, 2, lo); + ImGui::SameLine(); + ImGui::Text(" "); + ImGui::SameLine(); + + uint16_t instr = (hi << 8) | lo; + ImGui::Text(disassembled_instruction(instr).c_str()); + if (is_greyed_out || is_current_line) { ImGui::PopStyleColor(); } @@ -90,6 +97,138 @@ void AssemblyViewer::draw() { ImGui::EndChild(); } -void AssemblyViewer::cleanup() { - spdlog::trace("Initializing AssemblyViewer"); +void AssemblyViewer::cleanup() { spdlog::trace("Initializing AssemblyViewer"); } + +std::string AssemblyViewer::disassembled_instruction(uint16_t instr) const { + int nnn = instr & 0xfff; + int n = instr & 0xf; + int nn = instr & 0xff; + int x = (instr >> 8) & 0xf; + int y = (instr >> 4) & 0xf; + + switch ((instr >> 12) & 0xf) { + case 0x0: + if (instr == 0x00e0) { + return "CLS"; + } else if (instr == 0x00ee) { + return "RET"; + } else if (((n >> 4) & 0xf) == 0xc) { + // Super Chip-48 + return fmt::format("SCD {:x}h", n); + } else if (nn == 0xfb) { + // Super Chip-48 + return "SCR"; + } else if (nn == 0xfc) { + // Super Chip-48 + return "SCL"; + } else if (nn == 0xfd) { + // Super Chip-48 + return "EXIT"; + } else if (nn == 0xfe) { + // Super Chip-48 + return "LOW"; + } else if (nn == 0xff) { + // Super Chip-48 + return "HIGH"; + } else { + return fmt::format("SYS {:03x}h", nnn); + } + case 0x1: + return fmt::format("JP {:03x}h", nnn); + case 0x2: + return fmt::format("CALL {:03x}h", nnn); + case 0x3: + return fmt::format("SE V{:x}, {:02x}h", x, nn); + case 0x4: + return fmt::format("SNE V{:x}, {:02x}h", x, nn); + case 0x5: + if (n == 0) { + return fmt::format("SE V{:x}, V{:x}", x, y); + } + break; + case 0x6: + return fmt::format("LD V{:x}, {:02x}h", x, nn); + case 0x7: + return fmt::format("ADD V{:x}, {:02x}h", x, nn); + case 0x8: + switch (n) { + case 0: + return fmt::format("LD V{:x} V{:x}", x, y); + case 1: + return fmt::format("OR V{:x}, V{:x}", x, y); + case 2: + return fmt::format("AND V{:x}, V{:x}", x, y); + case 3: + return fmt::format("XOR V{:x}, V{:x}", x, y); + case 4: + return fmt::format("ADD V{:x}, V{:x}", x, y); + case 5: + return fmt::format("SUB V{:x}, V{:x}", x, y); + case 6: + return fmt::format("SHR V{:x}, V{:x}", x, y); + case 7: + return fmt::format("SUBN V{:x}, V{:x}", x, y); + case 0xe: + return fmt::format("SHL V{:x}, V{:x}", x, y); + default: + break; + } + break; + case 0x9: + if (n == 0) { + return fmt::format("SNE V{:x}, V{:x}", x, y); + } + break; + case 0xa: + return fmt::format("LD I, {:03x}h", nnn); + case 0xb: + return fmt::format("JP V0, {:03x}h", nnn); + case 0xc: + return fmt::format("RND V{:x}, {:02x}h", x, nn); + case 0xd: + return fmt::format("DRW V{:x}, V{:x}, {:x}h", x, y, n); + case 0xe: + switch (nn) { + case 0x9e: + return fmt::format("SKP V{:x}", x); + case 0xa1: + return fmt::format("SKNP V{:x}", x); + default: + break; + } + break; + case 0xf: + switch (nn) { + case 0x07: + return fmt::format("LD V{:x}, DT", x); + case 0x0a: + return fmt::format("LD V{:x}, K", x); + case 0x15: + return fmt::format("LD DT, V{:x}", x); + case 0x18: + return fmt::format("LD ST, V{:x}", x); + case 0x1e: + return fmt::format("ADD I, V{:x}", x); + case 0x29: + return fmt::format("LD F, V{:x}", x); + case 0x33: + return fmt::format("LD B, V{:x}", x); + case 0x55: + return fmt::format("LD [I], V{:x}", x); + case 0x65: + return fmt::format("LD V{:x}, [I]", x); + // Super Chip-48 Instructions + case 0x30: + return fmt::format("LD HF, V{:x}", x); + case 0x75: + return fmt::format("LD R, V{:x}", x); + case 0x85: + return fmt::format("LD V{:x}, R", x); + default: + break; + } + break; + } + + return ""; } diff --git a/src/assembly.h b/src/assembly.h index d47e725..b260ae6 100644 --- a/src/assembly.h +++ b/src/assembly.h @@ -9,6 +9,7 @@ class AssemblyViewer { void cleanup(); private: + std::string disassembled_instruction(uint16_t instr) const; bool auto_scroll = true; const registers *regs = nullptr; diff --git a/src/interface.cpp b/src/interface.cpp index c84cde7..ebed9c7 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -63,7 +63,7 @@ void Interface::initialize() { const float frequency = 440.0f; float incr = frequency / float(kAudioSampleRate); - auto d = static_cast(buffer); + auto d = static_cast(buffer); for (unsigned int i = 0; i < frames; i++) { if (!play_sound) { @@ -71,7 +71,8 @@ void Interface::initialize() { continue; } - d[i] = static_cast(((1<<15)-1) * square(sinf(2 * PI * sine_idx))); + d[i] = + static_cast(((1 << 15) - 1) * square(sinf(2 * PI * sine_idx))); sine_idx += incr; if (sine_idx > 1.0f) sine_idx -= 1.0f; @@ -94,25 +95,28 @@ void Interface::initialize() { auto console_sink = std::make_shared(); auto formatter = std::make_shared(); - auto callback_sink = std::make_shared([=](const spdlog::details::log_msg &msg) { - spdlog::memory_buf_t formatted; - formatter->format(msg, formatted); + auto callback_sink = std::make_shared( + [=](const spdlog::details::log_msg &msg) { + spdlog::memory_buf_t formatted; + formatter->format(msg, formatted); - std::string formatted_string(formatted.begin(), formatted.size()); - app_log.add_log(formatted_string); - }); + std::string formatted_string(formatted.begin(), formatted.size()); + app_log.add_log(formatted_string); + }); std::vector sinks; sinks.push_back(console_sink); sinks.push_back(callback_sink); - auto logger = std::make_shared("", sinks.begin(), sinks.end()); + auto logger = + std::make_shared("", sinks.begin(), sinks.end()); logger->set_level(level); spdlog::set_default_logger(logger); spdlog::info("Initialized interface"); - screen.initialize(kScreenWidth, kScreenHeight, kDefaultScreenPixelSize, regs->screen.data()); + screen.initialize(kScreenWidth, kScreenHeight, kDefaultScreenPixelSize, + regs->screen.data()); assembly.initialize(regs.get()); } @@ -164,17 +168,20 @@ bool Interface::update() { static_cast(GetScreenHeight())}); ImGuiID dockspace_main_id = dockspace_id; - ImGuiID bottom = ImGui::DockBuilderSplitNode(dockspace_main_id, ImGuiDir_Down, 0.2f, nullptr, &dockspace_main_id); + ImGuiID bottom = ImGui::DockBuilderSplitNode( + dockspace_main_id, ImGuiDir_Down, 0.2f, nullptr, &dockspace_main_id); ImGuiID right = ImGui::DockBuilderSplitNode( - dockspace_main_id, ImGuiDir_Right, 0.35f, nullptr, &dockspace_main_id); + dockspace_main_id, ImGuiDir_Right, 0.5f, nullptr, &dockspace_main_id); - ImGuiID center_right = ImGui::DockBuilderSplitNode(right, ImGuiDir_Left, 0.7, nullptr, &right); + ImGuiID center_right = ImGui::DockBuilderSplitNode(right, ImGuiDir_Left, + 0.60, nullptr, &right); - ImGuiID center_right_bottom = ImGui::DockBuilderSplitNode(center_right, ImGuiDir_Down, - 0.5f, nullptr, ¢er_right); + ImGuiID center_right_bottom = ImGui::DockBuilderSplitNode( + center_right, ImGuiDir_Down, 0.5f, nullptr, ¢er_right); - ImGuiID main_bottom = ImGui::DockBuilderSplitNode(dockspace_main_id, ImGuiDir_Down, 0.1f, nullptr, &dockspace_main_id); + ImGuiID main_bottom = ImGui::DockBuilderSplitNode( + dockspace_main_id, ImGuiDir_Down, 0.1f, nullptr, &dockspace_main_id); ImGui::DockBuilderDockWindow("Instructions", right); ImGui::DockBuilderDockWindow("Memory", center_right); @@ -302,7 +309,6 @@ bool Interface::update() { } ImGui::SameLine(); ImGui::SliderInt("##Pixel Count", &random_pixel_count, 1, 100); - } ImGui::End(); } @@ -311,21 +317,23 @@ bool Interface::update() { if (ImGui::Begin("Emulation", &show_emulation)) { ImGuiStyle &style = ImGui::GetStyle(); - auto push_disabled_btn_flags = [] () { + auto push_disabled_btn_flags = []() { ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.5f, 0.5f, 0.5f, 1.0f)); }; - auto pop_disabled_btn_flags = [] () { + auto pop_disabled_btn_flags = []() { ImGui::PopItemFlag(); ImGui::PopStyleColor(); }; ImVec2 size = ImGui::GetWindowSize(); - ImVec2 frame_padding {16.0f, 8.0f}; + ImVec2 frame_padding{16.0f, 8.0f}; float num_buttons = 4.0f; float button_width = ImGui::CalcTextSize(ICON_FA_PLAY).x; - float buttons_width = (button_width + (2 * frame_padding.x) + style.ItemSpacing.x) * num_buttons; + float buttons_width = + (button_width + (2 * frame_padding.x) + style.ItemSpacing.x) * + num_buttons; float slider_width = 192.0f; ImGui::SameLine((size.x - buttons_width - slider_width) / 2); @@ -369,6 +377,7 @@ bool Interface::update() { ImGui::PushButtonRepeat(true); if (ImGui::Button(ICON_FA_FORWARD_STEP)) { + spdlog::debug("Single step"); interpreter->step(); } ImGui::PopButtonRepeat(); @@ -428,6 +437,7 @@ bool Interface::update() { if (ImGui::Begin("Keyboard", &show_keyboard)) { ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(24, 18)); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 2)); ImGui::Button("1"); ImGui::SameLine(); @@ -461,7 +471,7 @@ bool Interface::update() { ImGui::SameLine(); ImGui::Button("F"); - ImGui::PopStyleVar(2); + ImGui::PopStyleVar(3); } ImGui::End(); } @@ -573,7 +583,7 @@ void Interface::load_rom(const std::string &filename) { fs::path rom_path = filename; SetWindowTitle( fmt::format("CHIP-8 - {}", rom_path.filename().string()).c_str()); - std::ifstream in(filename, std::ios::binary | std::ifstream::ate ); + std::ifstream in(filename, std::ios::binary | std::ifstream::ate); size_t pos = in.tellg(); if (pos > (kMemSize - kRomStartIndex)) { spdlog::error("File exceeds memory size, NOT loading rom");