diff --git a/.gitmodules b/.gitmodules index 9d75e9cd..ded5d14b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,7 +4,3 @@ [submodule "external/nativefiledialog-extended"] path = external/nativefiledialog-extended url = https://github.com/btzy/nativefiledialog-extended -[submodule "external/capstone"] - path = external/capstone - url = https://github.com/capstone-engine/capstone - branch = next diff --git a/external/capstone b/external/capstone deleted file mode 160000 index 0d0e6843..00000000 --- a/external/capstone +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0d0e684358afd0889b98deaf3941caa9c6855cae diff --git a/external/parallel-rdp/CMakeLists.txt b/external/parallel-rdp/CMakeLists.txt index 141615f7..d3ec29d4 100644 --- a/external/parallel-rdp/CMakeLists.txt +++ b/external/parallel-rdp/CMakeLists.txt @@ -70,7 +70,6 @@ target_include_directories(parallel-rdp PUBLIC ../imgui ../imgui/imgui ../imgui/imgui/backends - ../capstone/include . ) diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index c31ce6c2..6a5e8fe9 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -11,7 +11,6 @@ target_include_directories(frontend PUBLIC . .. ../../external - ../../external/capstone/include ../../external/parallel-rdp ../../external/parallel-rdp/parallel-rdp-standalone/vulkan ../../external/parallel-rdp/parallel-rdp-standalone/util diff --git a/src/frontend/imgui/CMakeLists.txt b/src/frontend/imgui/CMakeLists.txt index 2341ab52..1651270b 100644 --- a/src/frontend/imgui/CMakeLists.txt +++ b/src/frontend/imgui/CMakeLists.txt @@ -9,15 +9,7 @@ find_package(fmt REQUIRED) add_library(frontend-imgui STATIC Window.cpp - Window.hpp - widgets.cpp - debugger.hpp - debugger.cpp - debugger/cpu/decode.hpp - debugger/cop0/decode.hpp - debugger/fpu/decode.hpp - debugger/rsp/decode.hpp - debugger/debugger_common.hpp) + Window.hpp) target_include_directories(frontend-imgui PUBLIC . @@ -28,7 +20,6 @@ target_include_directories(frontend-imgui PUBLIC ../../n64/core/cpu ../../n64/core/cpu/registers ../../../external - ../../../external/capstone/include ../../../external/parallel-rdp/parallel-rdp-standalone ../../../external/parallel-rdp/parallel-rdp-standalone/vulkan ../../../external/parallel-rdp/parallel-rdp-standalone/util diff --git a/src/frontend/imgui/Window.cpp b/src/frontend/imgui/Window.cpp index 5e408416..7b97caae 100644 --- a/src/frontend/imgui/Window.cpp +++ b/src/frontend/imgui/Window.cpp @@ -140,6 +140,37 @@ ImDrawData* Window::Present(n64::Core& core) { } void Window::Render(n64::Core& core) { - MainMenuBar(core); - DebuggerWindow(core); + ImGui::PushFont(uiFont); + if(windowID == SDL_GetWindowID(SDL_GetMouseFocus())) { + ImGui::BeginMainMenuBar(); + if (ImGui::BeginMenu("File")) { + if (ImGui::MenuItem("Open", "O")) { + nfdchar_t *outpath; + const nfdu8filteritem_t filter{"Nintendo 64 roms", "n64,z64,v64,N64,Z64,V64"}; + nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr); + if (result == NFD_OKAY) { + core.LoadROM(outpath); + NFD_FreePath(outpath); + } + } + if (ImGui::MenuItem("Exit")) { + core.done = true; + } + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Emulation")) { + if (ImGui::MenuItem("Reset")) { + core.Reset(); + } + if (ImGui::MenuItem("Stop")) { + core.Stop(); + } + if (ImGui::MenuItem(core.pause ? "Resume" : "Pause", nullptr, false, core.romLoaded)) { + core.TogglePause(); + } + ImGui::EndMenu(); + } + ImGui::EndMainMenuBar(); + } + ImGui::PopFont(); } diff --git a/src/frontend/imgui/Window.hpp b/src/frontend/imgui/Window.hpp index b76ddf41..1c644e8f 100644 --- a/src/frontend/imgui/Window.hpp +++ b/src/frontend/imgui/Window.hpp @@ -20,8 +20,6 @@ private: void InitSDL(); void InitImgui(); void Render(n64::Core& core); - void MainMenuBar(n64::Core& core); - void DebuggerWindow(n64::Core& core) const; VkPhysicalDevice physicalDevice{}; VkDevice device{}; diff --git a/src/frontend/imgui/debugger.cpp b/src/frontend/imgui/debugger.cpp deleted file mode 100644 index 2bb5856f..00000000 --- a/src/frontend/imgui/debugger.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include -#include diff --git a/src/frontend/imgui/debugger.hpp b/src/frontend/imgui/debugger.hpp deleted file mode 100644 index 64b4bf82..00000000 --- a/src/frontend/imgui/debugger.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -struct Core; -// TODO: Fix syntax -static std::map> cpuInstr = { - {0b000000, special}, - {0b000001, regimm}, - {0b000010, [](u32 instr) { return fmt::format("j {:08X}", instr & 0x3FFFFFF); }}, - {0b000011, [](u32 instr) { return fmt::format("jal {:08X}", instr & 0x3FFFFFF); }}, - {0b000100, [](u32 instr) { return fmt::format("beq {}, {}, {:04X}", gprStr[RS(instr)], gprStr[RT(instr)], instr & 0xffff); }}, - {0b000101, [](u32 instr) { return fmt::format("bne {}, {}, {:04X}", gprStr[RS(instr)], gprStr[RT(instr)], instr & 0xffff); }}, - {0b000110, [](u32 instr) { return fmt::format("blez {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); }}, - {0b000111, [](u32 instr) { return fmt::format("bgtz {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); }}, - {0b001000, [](u32 instr) { return fmt::format("addi {}, {:04X}", gprStr[RS(instr)], instr & 0xFFFF); }}, - {0b001001, [](u32 instr) { return fmt::format("addiu {}, {:04X}", gprStr[RS(instr)], instr & 0x3FFFFFF); }}, - {0b001010, [](u32 instr) { return fmt::format("slti {}, {}, {:04X}", gprStr[RT(instr)], gprStr[RS(instr)], instr & 0xFFFF); }}, - {0b001011, [](u32 instr) { return fmt::format("sltiu {}, {}, {:04X}", gprStr[RT(instr)], gprStr[RS(instr)], instr & 0xFFFF); }}, - {0b001100, [](u32 instr) { return fmt::format("andi {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); }}, - {0b001101, [](u32 instr) { return fmt::format("ori {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); }}, - {0b001110, [](u32 instr) { return fmt::format("xori {}", gprStr[RS(instr)]); }}, - {0b001111, [](u32 instr) { return fmt::format("lui {}", gprStr[RS(instr)]); }}, - {0b010000, cop0decode}, - {0b010001, cop1decode}, - {0b010010, rspDecode}, - {0b010011, [](u32 instr) { return fmt::format("RESERVED"); }}, - {0b010100, [](u32 instr) { return fmt::format("beql {}, {}, {:04X}", gprStr[RS(instr)], gprStr[RT(instr)], instr & 0xffff); }}, - {0b010101, [](u32 instr) { return fmt::format("bnel {}, {}, {:04X}", gprStr[RS(instr)], gprStr[RT(instr)], instr & 0xffff); }}, - {0b010110, [](u32 instr) { return fmt::format("blezl {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); }}, - {0b010111, [](u32 instr) { return fmt::format("bgtzl {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); }}, - {0b011000, [](u32 instr) { return fmt::format("daddi {}, {}, {}", gprStr[RT(instr)], gprStr[RS(instr)], instr & 0xFFFF);}}, - {0b011001, [](u32 instr) { return fmt::format("daddiu {}, {}, {}", gprStr[RT(instr)], gprStr[RS(instr)], instr & 0xFFFF); }}, - {0b011010, [](u32 instr) { return fmt::format("ldl {:08X}", instr & 0x3FFFFFF); }}, - {0b011011, [](u32 instr) { return fmt::format("ldr {:08X}", instr & 0x3FFFFFF); }}, - {0b011100, [](u32 instr) { return fmt::format("RESERVED"); }}, - {0b011101, [](u32 instr) { return fmt::format("RESERVED"); }}, - {0b011110, [](u32 instr) { return fmt::format("RESERVED"); }}, - {0b011111, [](u32 instr) { return fmt::format("RESERVED"); }}, - {0b100000, [](u32 instr) { return fmt::format("lb {:08X}", instr & 0x3FFFFFF); }}, - {0b100001, [](u32 instr) { return fmt::format("lh {:08X}", instr & 0x3FFFFFF); }}, - {0b100010, [](u32 instr) { return fmt::format("lwl {:08X}", instr & 0x3FFFFFF); }}, - {0b100011, [](u32 instr) { return fmt::format("lw {:08X}", instr & 0x3FFFFFF); }}, - {0b100100, [](u32 instr) { return fmt::format("lbu {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); }}, - {0b100101, [](u32 instr) { return fmt::format("lhu {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); }}, - {0b100110, [](u32 instr) { return fmt::format("lwr {}", gprStr[RS(instr)]); }}, - {0b100111, [](u32 instr) { return fmt::format("lwu {}", gprStr[RS(instr)]); }}, - {0b101000, [](u32 instr) { return fmt::format("sb {:08X}", instr & 0x3FFFFFF); }}, - {0b101001, [](u32 instr) { return fmt::format("sh {:08X}", instr & 0x3FFFFFF); }}, - {0b101010, [](u32 instr) { return fmt::format("swl {:08X}", instr & 0x3FFFFFF); }}, - {0b101011, [](u32 instr) { return fmt::format("sw {:08X}", instr & 0x3FFFFFF); }}, - {0b101100, [](u32 instr) { return fmt::format("sdl {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); }}, - {0b101101, [](u32 instr) { return fmt::format("sdr {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); }}, - {0b101110, [](u32 instr) { return fmt::format("swr {}", gprStr[RS(instr)]); }}, - {0b101111, [](u32 instr) { return fmt::format("cache", gprStr[RS(instr)]); }}, - {0b110000, [](u32 instr) { return fmt::format("ll {:08X}", instr & 0x3FFFFFF); }}, - {0b110001, [](u32 instr) { return fmt::format("lwc1 {:08X}", instr & 0x3FFFFFF); }}, - {0b110010, [](u32 instr) { return fmt::format("lwc2 {:08X}", instr & 0x3FFFFFF); }}, - {0b110011, [](u32 instr) { return fmt::format("RESERVED"); }}, - {0b110100, [](u32 instr) { return fmt::format("lld {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); }}, - {0b110101, [](u32 instr) { return fmt::format("ldc1 {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); }}, - {0b110110, [](u32 instr) { return fmt::format("ldc2 {}", gprStr[RS(instr)]); }}, - {0b110111, [](u32 instr) { return fmt::format("ld {}", gprStr[RS(instr)]); }}, - {0b111000, [](u32 instr) { return fmt::format("sc {:08X}", instr & 0x3FFFFFF); }}, - {0b111001, [](u32 instr) { return fmt::format("swc1 {:08X}", instr & 0x3FFFFFF); }}, - {0b111010, [](u32 instr) { return fmt::format("swc2 {:08X}", instr & 0x3FFFFFF); }}, - {0b111011, [](u32 instr) { return fmt::format("RESERVED"); }}, - {0b111100, [](u32 instr) { return fmt::format("scd {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); }}, - {0b111101, [](u32 instr) { return fmt::format("sdc1 {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); }}, - {0b111110, [](u32 instr) { return fmt::format("sdc2 {}", gprStr[RS(instr)]); }}, - {0b111111, [](u32 instr) { return fmt::format("sd {}", gprStr[RS(instr)]); }} -}; - -struct Debugger { - util::CircularBuffer<20, std::string> disassembled; - - inline void Decode(u32 instr) { - const u8 mask = (instr >> 26) & 0x3f; - disassembled.PushValue(cpuInstr[mask](instr)); - } -}; \ No newline at end of file diff --git a/src/frontend/imgui/debugger/cop0/decode.hpp b/src/frontend/imgui/debugger/cop0/decode.hpp deleted file mode 100644 index 50e9c8f8..00000000 --- a/src/frontend/imgui/debugger/cop0/decode.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include - -inline std::string cop0decode(u32 instr) { - u8 mask_cop = (instr >> 21) & 0x1F; - u8 mask_cop2 = instr & 0x3F; - switch(mask_cop) { - case 0x00: return fmt::format("mfc0 {}, {}", gprStr[RT(instr)], cop0Str[RD(instr)]); - case 0x01: return fmt::format("dmfc0 {}, {}", gprStr[RT(instr)], cop0Str[RD(instr)]); - case 0x04: return fmt::format("mtc0 {}, {}", gprStr[RT(instr)], cop0Str[RD(instr)]); - case 0x05: return fmt::format("dmtc0 {}, {}", gprStr[RT(instr)], cop0Str[RD(instr)]); - case 0x10 ... 0x1F: - switch(mask_cop2) { - case 0x01: return fmt::format("tlbr"); - case 0x02: return fmt::format("tlbwi"); - case 0x08: return fmt::format("tlbp"); - case 0x18: return fmt::format("eret"); - default: return fmt::format("INVALID ({:08X})", instr); - } - default: return fmt::format("INVALID ({:08X})", instr); - } -} \ No newline at end of file diff --git a/src/frontend/imgui/debugger/cpu/decode.hpp b/src/frontend/imgui/debugger/cpu/decode.hpp deleted file mode 100644 index faf5b116..00000000 --- a/src/frontend/imgui/debugger/cpu/decode.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once -#include - -inline std::string special(u32 instr) { - u8 mask = (instr & 0x3F); - u8 sa = (instr >> 6) & 0x1f; - switch (mask) { - case 0: - if (mask != 0) { - return fmt::format("sll {}, {}, {:02X}", gprStr[RD(instr)], gprStr[RT(instr)], sa); - } - return "nop"; - case 0x02: return fmt::format("srl {}, {}, {:02X}", gprStr[RD(instr)], gprStr[RT(instr)], sa); - case 0x03: return fmt::format("sra {}, {}, {:02X}", gprStr[RD(instr)], gprStr[RT(instr)], sa); - case 0x04: return fmt::format("sllv {}, {}, {}", gprStr[RD(instr)], gprStr[RT(instr)], gprStr[RS(instr)]); - case 0x06: return fmt::format("srlv {}, {}, {}", gprStr[RD(instr)], gprStr[RT(instr)], gprStr[RS(instr)]); - case 0x07: return fmt::format("srav {}, {}, {}", gprStr[RD(instr)], gprStr[RT(instr)], gprStr[RS(instr)]); - case 0x08: return fmt::format("jr {}", gprStr[RS(instr)]); - case 0x09: return fmt::format("jalr {}, {}", gprStr[RD(instr)], gprStr[RS(instr)]); - case 0x0C: return fmt::format("syscall"); - case 0x0D: return fmt::format("break"); - case 0x0F: return fmt::format("sync"); - case 0x10: return fmt::format("mfhi {}", gprStr[RD(instr)]); - case 0x11: return fmt::format("mthi {}", gprStr[RS(instr)]); - case 0x12: return fmt::format("mflo {}", gprStr[RD(instr)]); - case 0x13: return fmt::format("mtlo {}", gprStr[RS(instr)]); - case 0x14: return fmt::format("dsllv {}, {}, {}", gprStr[RD(instr)], gprStr[RT(instr)], gprStr[RS(instr)]); - case 0x16: return fmt::format("dsrlv {}, {}, {}", gprStr[RD(instr)], gprStr[RT(instr)], gprStr[RS(instr)]); - case 0x17: return fmt::format("dsrav {}, {}, {}", gprStr[RD(instr)], gprStr[RT(instr)], gprStr[RS(instr)]); - case 0x18: return fmt::format("mult {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x19: return fmt::format("multu {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x1A: return fmt::format("div {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x1B: return fmt::format("divu {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x1C: return fmt::format("dmult {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x1D: return fmt::format("dmultu {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x1E: return fmt::format("ddiv {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x1F: return fmt::format("ddivu {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x20: return fmt::format("add {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x21: return fmt::format("addu {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x22: return fmt::format("sub {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x23: return fmt::format("subu {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x24: return fmt::format("and {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x25: return fmt::format("or {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x26: return fmt::format("xor {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x27: return fmt::format("nor {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x2A: return fmt::format("slt {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x2B: return fmt::format("sltu {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x2C: return fmt::format("dadd {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x2D: return fmt::format("daddu {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x2E: return fmt::format("dsub {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x2F: return fmt::format("dsubu {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x34: return fmt::format("teq {}, {}", gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x38: return fmt::format("dsll {}, {}, {:02X}", gprStr[RD(instr)], gprStr[RS(instr)], sa); - case 0x3A: return fmt::format("dsrl {}, {}, {:02X}", gprStr[RD(instr)], gprStr[RS(instr)], sa); - case 0x3B: return fmt::format("dsra {}, {}, {:02X}", gprStr[RD(instr)], gprStr[RS(instr)], sa); - case 0x3C: return fmt::format("dsll32 {}, {}, {:02X}", gprStr[RD(instr)], gprStr[RS(instr)], sa); - case 0x3E: return fmt::format("dsrl32 {}, {}, {:02X}", gprStr[RD(instr)], gprStr[RS(instr)], sa); - case 0x3F: return fmt::format("dsra32 {}, {}, {:02X}", gprStr[RD(instr)], gprStr[RS(instr)], sa); - default: - return fmt::format("INVALID ({:08X})", instr); - } -} - -inline std::string regimm(u32 instr) { - u8 mask = ((instr >> 16) & 0x1F); - // 000r_rccc - switch (mask) { // TODO: named constants for clearer code - case 0x00: return fmt::format("bltz {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); - case 0x01: return fmt::format("bgez {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); - case 0x02: return fmt::format("bltzl {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); - case 0x03: return fmt::format("bgezl {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); - case 0x10: return fmt::format("bltzal {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); - case 0x11: return fmt::format("bgezal {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); - case 0x12: return fmt::format("bltzall {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); - case 0x13: return fmt::format("bgezall {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); - default: return fmt::format("INVALID ({:08X})", instr); - } -} \ No newline at end of file diff --git a/src/frontend/imgui/debugger/debugger_common.hpp b/src/frontend/imgui/debugger/debugger_common.hpp deleted file mode 100644 index 13ca8b91..00000000 --- a/src/frontend/imgui/debugger/debugger_common.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -#include - -static const std::string gprStr[32] = { - "zero", "at", "v0", "v1", - "a0", "a1", "a2", "a3", - "t0", "t1", "t2", "t3", - "t4", "t5", "t6", "t7", - "s0", "s1", "s2", "s3", - "s4", "s5", "s6", "s7", - "t8", "t9", "k0", "k1", - "gp", "sp", "s8", "ra" -}; - -static const std::string cop0Str[32] = { - "Index", "Random", "EntryLo0", "EntryLo1", - "Context", "PageMask", "Wired", "r7", - "BadVAddr", "Count", "EntryHi", "Compare", - "Status", "Cause", "EPC", "PRId", - "Config", "LLAddr", "WatchLo", "WatchHi", - "XContext", "r21", "r22", "r23", - "r24", "r25", "Parity Error", "Cache Error", - "TagLo", "TagHi", "ErrorEPC", "r31" -}; - -static const std::string fgrStr[32] = { - "fgr0", "fgr1", "fgr2", "fgr3", - "fgr4", "fgr5", "fgr6", "fgr7", - "fgr8", "fgr9", "fgr10", "fgr11", - "fgr12", "fgr13", "fgr14", "fgr15", - "fgr16", "fgr17", "fgr18", "fgr19", - "fgr20", "fgr21", "fgr22", "fgr23", - "fgr24", "fgr25", "fgr26", "fgr27", - "fgr28", "fgr29", "fgr30", "fgr31" -}; - -static const std::string vprStr[32] = { - "vpr0", "vpr1", "vpr2", "vpr3", - "vpr4", "vpr5", "vpr6", "vpr7", - "vpr8", "vpr9", "vpr10", "vpr11", - "vpr12", "vpr13", "vpr14", "vpr15", - "vpr16", "vpr17", "vpr18", "vpr19", - "vpr20", "vpr21", "vpr22", "vpr23", - "vpr24", "vpr25", "vpr26", "vpr27", - "vpr28", "vpr29", "vpr30", "vpr31" -}; - -static const std::string vprByteStr[16] = { - "e0_8", "e1_8", "e2_8", "e3_8", - "e4_8", "e5_8", "e6_8", "e7_8", - "e8_8", "e9_8", "e10_8", "e11_8", - "e12_8", "e13_8", "e14_8", "e15_8" -}; - -static const std::string vprElementStr[8] = { - "e0_16", "e2_16", "e4_16", "e6_16", - "e8_16", "e10_16", "e12_16", "e14_16" -}; - -static const std::string vprWordStr[4] = { - "e0_32", "e4_32", "e8_32", "e12_32" -}; - -static const std::string rspControlStr[4] = { - "vco", "vcc", "vce", "vce" -}; \ No newline at end of file diff --git a/src/frontend/imgui/debugger/fpu/decode.hpp b/src/frontend/imgui/debugger/fpu/decode.hpp deleted file mode 100644 index 57d09729..00000000 --- a/src/frontend/imgui/debugger/fpu/decode.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#pragma once -#include - -inline std::string cop1decode(u32 instr) { - u8 mask_sub = (instr >> 21) & 0x1F; - u8 mask_fun = instr & 0x3F; - u8 mask_branch = (instr >> 16) & 0x1F; - switch(mask_sub) { - // 000r_rccc - case 0x00: return fmt::format("mfc1 {}, {}", gprStr[RT(instr)], fgrStr[FS(instr)]); - case 0x01: return fmt::format("dmfc1 {}, {}", gprStr[RT(instr)], fgrStr[FS(instr)]); - case 0x02: return fmt::format("cfc1 {}, {}", gprStr[RT(instr)], fgrStr[FS(instr)]); - case 0x04: return fmt::format("mtc1 {}, {}", gprStr[RT(instr)], fgrStr[FS(instr)]); - case 0x05: return fmt::format("dmtc1 {}, {}", gprStr[RT(instr)], fgrStr[FS(instr)]); - case 0x06: return fmt::format("ctc1 {}, {}", gprStr[RT(instr)], fgrStr[FS(instr)]); - case 0x08: - switch(mask_branch) { - case 0: return fmt::format("bcf {:04X}", instr & 0xffff); - case 1: return fmt::format("bct {:04X}", instr & 0xffff); - case 2: return fmt::format("bcfl {:04X}", instr & 0xffff); - case 3: return fmt::format("bctl {:04X}", instr & 0xffff); - default: return fmt::format("INVALID ({:08X})", instr); - } break; - case 0x10: // s - switch(mask_fun) { - case 0x00: return fmt::format("add.s {}, {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x01: return fmt::format("sub.s {}, {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x02: return fmt::format("mul.s {}, {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x03: return fmt::format("div.s {}, {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x04: return fmt::format("sqrt.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x05: return fmt::format("abs.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x06: return fmt::format("mov.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x07: return fmt::format("neg.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x08: return fmt::format("round.l.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x09: return fmt::format("trunc.l.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x0A: return fmt::format("ceil.l.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x0B: return fmt::format("floor.l.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x0C: return fmt::format("round.w.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x0D: return fmt::format("trunc.w.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x0E: return fmt::format("ceil.w.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x0F: return fmt::format("floor.w.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x21: return fmt::format("cvt.d.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x24: return fmt::format("cvt.w.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x25: return fmt::format("cvt.l.s {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x30: return fmt::format("c.f.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x31: return fmt::format("c.un.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x32: return fmt::format("c.eq.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x33: return fmt::format("c.ueq.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x34: return fmt::format("c.olt.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x35: return fmt::format("c.ult.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x36: return fmt::format("c.ole.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x37: return fmt::format("c.ule.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x38: return fmt::format("c.sf.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x39: return fmt::format("c.ngle.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x3A: return fmt::format("c.seq.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x3B: return fmt::format("c.ngl.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x3C: return fmt::format("c.lt.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x3D: return fmt::format("c.nge.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x3E: return fmt::format("c.le.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x3F: return fmt::format("c.ngt.s {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - default: return fmt::format("INVALID ({:08X})", instr); - } break; - case 0x11: // d - switch(mask_fun) { - case 0x00: return fmt::format("add.d {}, {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x01: return fmt::format("sub.d {}, {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x02: return fmt::format("mul.d {}, {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x03: return fmt::format("div.d {}, {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x04: return fmt::format("sqrt.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x05: return fmt::format("abs.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x06: return fmt::format("mov.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x07: return fmt::format("neg.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x08: return fmt::format("round.l.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x09: return fmt::format("trunc.l.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x0A: return fmt::format("ceil.l.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x0B: return fmt::format("floor.l.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x0C: return fmt::format("round.w.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x0D: return fmt::format("trunc.w.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x0E: return fmt::format("ceil.w.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x0F: return fmt::format("floor.w.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x20: return fmt::format("cvt.s.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x24: return fmt::format("cvt.w.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x25: return fmt::format("cvt.l.d {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x30: return fmt::format("c.f.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x31: return fmt::format("c.un.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x32: return fmt::format("c.eq.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x33: return fmt::format("c.ueq.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x34: return fmt::format("c.olt.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x35: return fmt::format("c.ult.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x36: return fmt::format("c.ole.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x37: return fmt::format("c.ule.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x38: return fmt::format("c.sf.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x39: return fmt::format("c.ngle.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x3A: return fmt::format("c.seq.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x3B: return fmt::format("c.ngl.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x3C: return fmt::format("c.lt.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x3D: return fmt::format("c.nge.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x3E: return fmt::format("c.le.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x3F: return fmt::format("c.ngt.d {}, {}", fgrStr[FS(instr)], fgrStr[FT(instr)]); - default: return fmt::format("INVALID ({:08X})", instr); - } break; - case 0x14: // w - switch(mask_fun) { - case 0x01: return fmt::format("sub.w {}, {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x02: return fmt::format("mul.w {}, {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x05: return fmt::format("abs.w {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x06: return fmt::format("mov.w {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x20: return fmt::format("cvt.s.w {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x21: return fmt::format("cvt.d.w {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - default: return fmt::format("INVALID ({:08X})", instr); - } break; - case 0x15: // l - switch(mask_fun) { - case 0x01: return fmt::format("sub.l {}, {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x02: return fmt::format("mul.l {}, {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)], fgrStr[FT(instr)]); - case 0x05: return fmt::format("abs.l {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x06: return fmt::format("mov.l {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x20: return fmt::format("cvt.s.l {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - case 0x21: return fmt::format("cvt.d.l {}, {}", fgrStr[FD(instr)], fgrStr[FS(instr)]); - default: return fmt::format("INVALID ({:08X})", instr); - } break; - default: return fmt::format("INVALID ({:08X})", instr); - } -} \ No newline at end of file diff --git a/src/frontend/imgui/debugger/rsp/decode.hpp b/src/frontend/imgui/debugger/rsp/decode.hpp deleted file mode 100644 index 835bfe2b..00000000 --- a/src/frontend/imgui/debugger/rsp/decode.hpp +++ /dev/null @@ -1,101 +0,0 @@ -#pragma once -#include - -inline std::string rspSpecial(u32 instr) { - u8 mask = instr & 0x3f; - u8 sa = (instr >> 6) & 0x1f; - switch(mask) { - case 0x00: return fmt::format("[rsp]: sll {}, {}, {:02X}", gprStr[RD(instr)], gprStr[RT(instr)], sa); - case 0x04: return fmt::format("[rsp]: sllv {}, {}, {}", gprStr[RD(instr)], gprStr[RT(instr)], gprStr[RS(instr)]); - case 0x08: return fmt::format("[rsp]: jr {}", gprStr[RS(instr)]); - case 0x0C: case 0x0D: - return fmt::format("[rsp]: break"); - case 0x20: case 0x21: - return fmt::format("[rsp]: add {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x24: return fmt::format("[rsp]: and {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x25: return fmt::format("[rsp]: or {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - case 0x27: return fmt::format("[rsp]: nor {}, {}, {}", gprStr[RD(instr)], gprStr[RS(instr)], gprStr[RT(instr)]); - default: return fmt::format("INVALID ({:08X})", instr); - } -} - -inline std::string rspRegimm(u32 instr) { - u8 mask = ((instr >> 16) & 0x1F); - switch(mask) { - case 0x00: return fmt::format("[rsp]: bltz {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); - case 0x01: return fmt::format("[rsp]: bgez {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); - default: return fmt::format("INVALID ({:08X})", instr); - } -} - -inline std::string lwc2(u32 instr) { - u8 mask = (instr >> 11) & 0x1F; - switch(mask) { - case 0x04: return fmt::format("[rsp]: lqv {}[{}], {:02X}({})", vprStr[VT(instr)], vprByteStr[BYTE_INDEX(E(instr))], instr & 0x7F, gprStr[BASE(instr)]); - default: return fmt::format("INVALID ({:08X})", instr); - } -} - -inline std::string swc2(u32 instr) { - u8 mask = (instr >> 11) & 0x1F; - switch(mask) { - case 0x04: return fmt::format("[rsp]: sqv {}[{}], {:02X}({})", vprStr[VT(instr)], vprByteStr[BYTE_INDEX(E(instr))], instr & 0x7F, gprStr[BASE(instr)]); - default: return fmt::format("INVALID ({:08X})", instr); - } -} - -inline std::string cop2decode(u32 instr) { - u8 mask = instr & 0x3F; - u8 mask_sub = (instr >> 21) & 0x1F; - switch(mask) { - case 0x00: - switch(mask_sub) { - case 0x02: return fmt::format("[rsp]: cfc2 {}, {}", gprStr[RT(instr)], rspControlStr[RD(instr) & 3]); - default: return fmt::format("INVALID ({:08X})", instr); - } - break; - case 0x13: return fmt::format("[rsp]: vabs {}, {}, {}", vprStr[VD(instr)], vprStr[VS(instr)], vprStr[VT(instr)]); - case 0x1D: return fmt::format("[rsp]: vsar {}, {}, {}", vprStr[VD(instr)], vprStr[VS(instr)], vprStr[VT(instr)]); - case 0x21: return fmt::format("[rsp]: veq {}, {}, {}", vprStr[VD(instr)], vprStr[VS(instr)], vprStr[VT(instr)]); - case 0x22: return fmt::format("[rsp]: vne {}, {}, {}", vprStr[VD(instr)], vprStr[VS(instr)], vprStr[VT(instr)]); - case 0x33: return fmt::format("[rsp]: vmov {}[{}], {}[{}]", vprStr[VD(instr)], vprElementStr[DE(instr)], vprStr[VT(instr)], vprElementStr[E(instr)]); - default: return fmt::format("INVALID ({:08X})", instr); - } -} - -inline std::string rspCop0Decode(u32 instr) { - u8 mask = (instr >> 21) & 0x1F; - switch(mask) { - case 0x00: return fmt::format("[rsp]: mfc0 {}, {}", gprStr[RT(instr)], cop0Str[RD(instr)]); - case 0x04: return fmt::format("[rsp]: mtc0 {}, {}", gprStr[RT(instr)], cop0Str[RD(instr)]); - default: return fmt::format("INVALID ({:08X})", instr); - } -} - -inline std::string rspDecode(u32 instr) { - u8 mask = (instr >> 26) & 0x3F; - switch(mask) { - case 0x00: return special(instr); - case 0x01: return regimm(instr); - case 0x02: return fmt::format("[rsp]: j {:04X}", instr & 0xffff); - case 0x03: return fmt::format("[rsp]: jal {:04X}", instr & 0xffff); - case 0x04: return fmt::format("[rsp]: beq {}, {}, {:04X}", gprStr[RT(instr)], gprStr[RS(instr)], instr & 0xffff); - case 0x05: return fmt::format("[rsp]: bne {}, {}, {:04X}", gprStr[RT(instr)], gprStr[RS(instr)], instr & 0xffff); - case 0x07: return fmt::format("[rsp]: bgtz {}, {:04X}", gprStr[RS(instr)], instr & 0xffff); - case 0x08: case 0x09: - return fmt::format("[rsp]: addi {}, {}, {:04X}", gprStr[RT(instr)], gprStr[RS(instr)], instr & 0xffff); - case 0x0C: return fmt::format("[rsp]: andi {}, {}, {:04X}", instr); - case 0x0D: return fmt::format("[rsp]: ori {}, {}, {:04X}", instr); - case 0x0F: return fmt::format("[rsp]: lui {}, {:04X}", gprStr[RT(instr)], instr & 0xffff); - case 0x10: return rspCop0Decode(instr); - case 0x12: return cop2decode(instr); - case 0x21: return fmt::format("[rsp]: lh {}, {:04X}({})", gprStr[RT(instr)], instr & 0xffff, gprStr[BASE(instr)]); - case 0x23: return fmt::format("[rsp]: lw {}, {:04X}({})", gprStr[RT(instr)], instr & 0xffff, gprStr[BASE(instr)]); - case 0x28: return fmt::format("[rsp]: sb {}, {:04X}({})", gprStr[RT(instr)], instr & 0xffff, gprStr[BASE(instr)]); - case 0x29: return fmt::format("[rsp]: sh {}, {:04X}({})", gprStr[RT(instr)], instr & 0xffff, gprStr[BASE(instr)]); - case 0x2B: return fmt::format("[rsp]: sw {}, {:04X}({})", gprStr[RT(instr)], instr & 0xffff, gprStr[BASE(instr)]); - case 0x32: return lwc2(instr); - case 0x3A: return swc2(instr); - default: return fmt::format("INVALID ({:08X})", instr); - } -} \ No newline at end of file diff --git a/src/frontend/imgui/widgets.cpp b/src/frontend/imgui/widgets.cpp deleted file mode 100644 index 1c61ee6a..00000000 --- a/src/frontend/imgui/widgets.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include -#include - -void Window::MainMenuBar(n64::Core& core) { - ImGui::PushFont(uiFont); - if(windowID == SDL_GetWindowID(SDL_GetMouseFocus())) { - ImGui::BeginMainMenuBar(); - if (ImGui::BeginMenu("File")) { - if (ImGui::MenuItem("Open", "O")) { - nfdchar_t *outpath; - const nfdu8filteritem_t filter{"Nintendo 64 roms", "n64,z64,v64,N64,Z64,V64"}; - nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr); - if (result == NFD_OKAY) { - core.LoadROM(outpath); - NFD_FreePath(outpath); - } - } - if (ImGui::MenuItem("Exit")) { - core.done = true; - } - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Emulation")) { - if (ImGui::MenuItem("Reset")) { - core.Reset(); - } - if (ImGui::MenuItem("Stop")) { - core.Stop(); - } - if (ImGui::MenuItem(core.pause ? "Resume" : "Pause", nullptr, false, core.romLoaded)) { - core.TogglePause(); - } - ImGui::EndMenu(); - } - ImGui::EndMainMenuBar(); - } - ImGui::PopFont(); -} - -void Window::DebuggerWindow(n64::Core& core) const { - ImGui::PushFont(uiFont); - ImGui::Begin("Debugger"); - ImGui::PushFont(codeFont); - ImGui::Text("%s", core.Decode(core.mem.Read(core.cpu.regs, core.cpu.regs.pc, core.cpu.regs.pc)).c_str()); - ImGui::PopFont(); - ImGui::End(); - ImGui::PopFont(); -} \ No newline at end of file diff --git a/src/n64/CMakeLists.txt b/src/n64/CMakeLists.txt index 5a745c51..e772f8ba 100644 --- a/src/n64/CMakeLists.txt +++ b/src/n64/CMakeLists.txt @@ -15,5 +15,4 @@ target_include_directories(n64 PUBLIC ../frontend/imgui/debugger ../../external ../../external/imgui/imgui - ../../external/imgui/imgui/backends - ../../external/capstone/include) + ../../external/imgui/imgui/backends) diff --git a/src/n64/Core.cpp b/src/n64/Core.cpp index 906f1827..6704aa7c 100644 --- a/src/n64/Core.cpp +++ b/src/n64/Core.cpp @@ -3,7 +3,6 @@ #include #include #include -#include namespace n64 { Core::Core() { @@ -31,32 +30,29 @@ void Core::Reset() { void Core::LoadROM(const std::string& rom_) { rom = rom_; mem.LoadROM(rom); - pause = false; + pause = true; romLoaded = true; } -void Core::Step() { - MMIO& mmio = mem.mmio; - cpu.Step(mem); - mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp); -} - void Core::Run(Window& window) { MMIO& mmio = mem.mmio; int cycles = 0; for(int field = 0; field < mmio.vi.numFields; field++) { + int frameCycles = 0; if(!pause && romLoaded) { for (int i = 0; i < mmio.vi.numHalflines; i++) { if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) { InterruptRaise(mmio.mi, cpu.regs, Interrupt::VI); } - for(;cycles <= mmio.vi.cyclesPerHalfline; cycles++) { + for(;cycles <= mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) { cpu.Step(mem); mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp); mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp); mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp); mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp); + + mmio.ai.Step(mem, cpu.regs, 1); } cycles -= mmio.vi.cyclesPerHalfline; @@ -67,6 +63,9 @@ void Core::Run(Window& window) { } UpdateScreenParallelRdp(*this, window, GetVI()); + + int missedCycles = N64_CYCLES_PER_FRAME - frameCycles; + mmio.ai.Step(mem, cpu.regs, missedCycles); } else if(pause && romLoaded) { UpdateScreenParallelRdp(*this, window, GetVI()); } else if(pause && !romLoaded) { diff --git a/src/n64/Core.hpp b/src/n64/Core.hpp index df1e260c..1e5be72a 100644 --- a/src/n64/Core.hpp +++ b/src/n64/Core.hpp @@ -3,7 +3,6 @@ #include #include #include -#include struct Window; namespace n64 { @@ -12,13 +11,14 @@ struct Core { Core(); void Stop(); void Reset(); - void Step(); void LoadROM(const std::string&); void Run(Window&); void UpdateController(const u8*); void TogglePause() { pause = !pause; } VI& GetVI() { return mem.mmio.vi; } + u32 breakpoint = 0; + bool pause = true; bool romLoaded = false; SDL_GameController* gamepad; diff --git a/src/n64/core/CMakeLists.txt b/src/n64/core/CMakeLists.txt index 019bebe9..12557287 100644 --- a/src/n64/core/CMakeLists.txt +++ b/src/n64/core/CMakeLists.txt @@ -4,7 +4,6 @@ project(core) add_subdirectory(cpu) add_subdirectory(../../../external/parallel-rdp temp) -add_subdirectory(../../../external/capstone temp1) find_package(fmt REQUIRED) find_package(SDL2 REQUIRED) @@ -50,7 +49,6 @@ target_include_directories(core PUBLIC ../../../external/imgui/imgui ../../../external/imgui/imgui/debugger ../../../external/imgui/imgui/backends - ../../../external/capstone/include mmio) -target_link_libraries(core PUBLIC SDL2main SDL2 fmt cpu parallel-rdp capstone) +target_link_libraries(core PUBLIC SDL2main SDL2 fmt cpu parallel-rdp) diff --git a/src/n64/core/Cpu.cpp b/src/n64/core/Cpu.cpp index 759a7bca..483cefb7 100644 --- a/src/n64/core/Cpu.cpp +++ b/src/n64/core/Cpu.cpp @@ -8,20 +8,6 @@ void Cpu::Reset() { regs.Reset(); } -Cpu::Cpu() { - if (cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64, &handle)) { - util::panic("Could not initialize capstone!\n"); - } - - if (cs_option(handle, CS_OPT_UNSIGNED, CS_OPT_ON)) { - util::panic("Could not initialize capstone!\n"); - } -} - -Cpu::~Cpu() { - cs_close(&handle); -} - inline bool ShouldServiceInterrupt(Registers& regs) { bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0; bool interrupts_enabled = regs.cop0.status.ie == 1; @@ -37,7 +23,7 @@ inline void CheckCompareInterrupt(MI& mi, Registers& regs) { regs.cop0.count &= 0x1FFFFFFFF; if(regs.cop0.count == (u64)regs.cop0.compare << 1) { regs.cop0.cause.ip7 = 1; - UpdateInterrupt(mi, regs); + //UpdateInterrupt(mi, regs); } } @@ -55,7 +41,7 @@ void FireException(Registers& regs, ExceptionCode code, int cop, s64 pc) { bool old_exl = regs.cop0.status.exl; if(!regs.cop0.status.exl) { - if(regs.prevDelaySlot) { // TODO: cached value of delay_slot should be used, but Namco Museum breaks! + if(regs.delaySlot) { // TODO: cached value of delay_slot should be used, but Namco Museum breaks! regs.cop0.cause.branchDelay = true; pc -= 4; } else { @@ -102,31 +88,15 @@ inline void HandleInterrupt(Registers& regs) { } } -void Cpu::LogInstruction(u32 instruction) { -#ifndef NDEBUG - count = cs_disasm(handle, reinterpret_cast(&instruction), 4, regs.pc, 0, &insn); -#endif - - if (count > 0) { - for(auto j = 0; j < count; j++) { - util::logdebug("0x{:016X}:\t{}\t\t{}\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); - } - cs_free(insn, count); - } else { - util::logdebug("Failed to disassemble 0x{:08X}!", instruction); - } -} - void Cpu::Step(Mem& mem) { regs.gpr[0] = 0; + CheckCompareInterrupt(mem.mmio.mi, regs); + regs.prevDelaySlot = regs.delaySlot; regs.delaySlot = false; - CheckCompareInterrupt(mem.mmio.mi, regs); - u32 instruction = mem.Read(regs, regs.pc, regs.pc); - //LogInstruction(instruction); HandleInterrupt(regs); diff --git a/src/n64/core/Cpu.hpp b/src/n64/core/Cpu.hpp index bef8bcac..9397f505 100644 --- a/src/n64/core/Cpu.hpp +++ b/src/n64/core/Cpu.hpp @@ -1,22 +1,17 @@ #pragma once #include #include -#include namespace n64 { struct Cpu { - Cpu(); - ~Cpu(); + Cpu() = default; + ~Cpu() = default; void Reset(); void Step(Mem&); Registers regs; private: - csh handle{}; - cs_insn *insn = nullptr; - size_t count{}; friend struct Cop1; - void LogInstruction(u32); void special(Mem&, u32); void regimm(u32); void Exec(Mem&, u32); diff --git a/src/n64/core/cpu/CMakeLists.txt b/src/n64/core/cpu/CMakeLists.txt index d3356ab0..e8065672 100644 --- a/src/n64/core/cpu/CMakeLists.txt +++ b/src/n64/core/cpu/CMakeLists.txt @@ -16,7 +16,6 @@ add_library(cpu target_include_directories(cpu PUBLIC registers . .. ../../../../external - ../../../../external/capstone/include ../../../../src ../../ ) diff --git a/src/n64/core/cpu/Registers.hpp b/src/n64/core/cpu/Registers.hpp index ce4bf366..d427181e 100644 --- a/src/n64/core/cpu/Registers.hpp +++ b/src/n64/core/cpu/Registers.hpp @@ -12,7 +12,6 @@ struct Registers { Cop1 cop1; s64 oldPC, pc, nextPC; s64 hi, lo; - bool LLBit; bool prevDelaySlot, delaySlot; }; } diff --git a/src/n64/core/cpu/decode.cpp b/src/n64/core/cpu/decode.cpp index d8cd05fd..0217e889 100644 --- a/src/n64/core/cpu/decode.cpp +++ b/src/n64/core/cpu/decode.cpp @@ -20,7 +20,7 @@ void Cpu::special(Mem& mem, u32 instr) { case 0x09: jalr(instr); break; case 0x0C: FireException(regs, ExceptionCode::Syscall, 0, regs.oldPC); break; case 0x0D: FireException(regs, ExceptionCode::Breakpoint, 0, regs.oldPC); break; - case 0x0F: break; + case 0x0F: break; // SYNC case 0x10: mfhi(instr); break; case 0x11: mthi(instr); break; case 0x12: mflo(instr); break; @@ -58,7 +58,7 @@ void Cpu::special(Mem& mem, u32 instr) { case 0x3E: dsrl32(instr); break; case 0x3F: dsra32(instr); break; default: - util::panic("Unimplemented special {} {}", (mask >> 3) & 7, mask & 7); + util::panic("Unimplemented special {} {} (pc: {:+016X})", (mask >> 3) & 7, mask & 7, regs.oldPC); } } diff --git a/src/n64/core/cpu/instructions.cpp b/src/n64/core/cpu/instructions.cpp index 81d8b25b..912bf1de 100644 --- a/src/n64/core/cpu/instructions.cpp +++ b/src/n64/core/cpu/instructions.cpp @@ -205,7 +205,7 @@ void Cpu::ll(Mem& mem, u32 instr) { FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC); } - regs.LLBit = true; + regs.cop0.llbit = true; regs.cop0.LLAddr = address; regs.gpr[RT(instr)] = mem.Read(regs, address, regs.oldPC); @@ -249,7 +249,7 @@ void Cpu::lld(Mem& mem, u32 instr) { FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC); } - regs.LLBit = true; + regs.cop0.llbit = true; regs.cop0.LLAddr = address; s64 value = mem.Read(regs, address, regs.oldPC); @@ -316,12 +316,12 @@ void Cpu::sc(Mem& mem, u32 instr) { FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC); } - if(regs.LLBit) { + if(regs.cop0.llbit) { mem.Write(regs, address, regs.gpr[RT(instr)], regs.oldPC); } - regs.gpr[RT(instr)] = (s64)((u64)regs.LLBit); - regs.LLBit = false; + regs.gpr[RT(instr)] = (s64)((u64)regs.cop0.llbit); + regs.cop0.llbit = false; } void Cpu::scd(Mem& mem, u32 instr) { @@ -331,12 +331,12 @@ void Cpu::scd(Mem& mem, u32 instr) { FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC); } - if(regs.LLBit) { + if(regs.cop0.llbit) { mem.Write(regs, address, regs.gpr[RT(instr)], regs.oldPC); } - regs.gpr[RT(instr)] = (s64)((u64)regs.LLBit); - regs.LLBit = false; + regs.gpr[RT(instr)] = (s64)((u64)regs.cop0.llbit); + regs.cop0.llbit = false; } void Cpu::sh(Mem& mem, u32 instr) { diff --git a/src/n64/core/cpu/registers/Cop0.cpp b/src/n64/core/cpu/registers/Cop0.cpp index 52d0df2f..ddf53f2c 100644 --- a/src/n64/core/cpu/registers/Cop0.cpp +++ b/src/n64/core/cpu/registers/Cop0.cpp @@ -82,7 +82,10 @@ void Cop0::SetReg(u8 addr, T value) { cause.ip7 = 0; compare = value; } break; - case 12: status.raw = value & STATUS_MASK; break; + case 12: + status.raw &= ~STATUS_MASK; + status.raw |= value & STATUS_MASK; + break; case 13: { Cop0Cause tmp{}; tmp.raw = value; @@ -220,7 +223,9 @@ void Cop0::decode(Registers& regs, Mem& mem, u32 instr) { case 0x01: tlbr(regs); break; case 0x02: tlbwi(regs); break; case 0x08: tlbp(regs); break; - case 0x18: eret(regs); break; + case 0x18: + eret(regs); + break; default: util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016lX})", mask_cop2 >> 3, mask_cop2 & 7, instr, regs.oldPC); } break; diff --git a/src/n64/core/cpu/registers/Cop0.hpp b/src/n64/core/cpu/registers/Cop0.hpp index f2044802..6122af9b 100644 --- a/src/n64/core/cpu/registers/Cop0.hpp +++ b/src/n64/core/cpu/registers/Cop0.hpp @@ -2,7 +2,7 @@ #include namespace n64 { -#define STATUS_MASK 0xFF77FFFF +#define STATUS_MASK 0xFF57FFFF struct Cpu; struct Registers; @@ -161,6 +161,12 @@ struct Cop0 { void Reset(); + bool kernel_mode; + bool supervisor_mode; + bool user_mode; + bool is_64bit_addressing; + bool llbit; + PageMask pageMask{}; EntryHi entryHi{}; EntryLo entryLo0{}, entryLo1{}; diff --git a/src/n64/core/cpu/registers/cop0instructions.cpp b/src/n64/core/cpu/registers/cop0instructions.cpp index 0db9c583..d4ca147b 100644 --- a/src/n64/core/cpu/registers/cop0instructions.cpp +++ b/src/n64/core/cpu/registers/cop0instructions.cpp @@ -27,6 +27,7 @@ void Cop0::eret(Registers& regs) { regs.SetPC((s64)EPC); status.exl = false; } + llbit = false; } diff --git a/src/util.hpp b/src/util.hpp index 3c4a1c4a..6e2cd14e 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -19,6 +19,7 @@ enum MessageType : u8 { template constexpr void print(const std::string& fmt, Args... args) { +#ifndef __WIN32 if constexpr(messageType == Error) { fmt::print(fmt::emphasis::bold | fg(fmt::color::red), fmt, args...); exit(-1); @@ -27,6 +28,14 @@ constexpr void print(const std::string& fmt, Args... args) { } else if constexpr(messageType == Info) { fmt::print(fmt, args...); } +#else + if constexpr(messageType == Error) { + fmt::print(fmt, args...); + exit(-1); + } else { + fmt::print(fmt, args...); + } +#endif } template