From b4c5c7a3e48e1b2b65c262c7683ad959289d0361 Mon Sep 17 00:00:00 2001 From: SimoZ64 Date: Mon, 5 May 2025 22:15:45 +0200 Subject: [PATCH] Compiles! --- external/parallel-rdp/ParallelRDPWrapper.cpp | 10 +- resources/frag.spv | Bin 1844 -> 0 bytes resources/frag.spv.h | 156 +++++++++++++++ resources/vert.spv | Bin 1064 -> 0 bytes resources/vert.spv.h | 91 +++++++++ src/backend/CMakeLists.txt | 2 +- src/backend/core/Mem.hpp | 3 +- src/frontend/CMakeLists.txt | 33 ++-- src/frontend/EmuThread.cpp | 6 +- src/frontend/EmuThread.hpp | 4 +- src/frontend/ImGuiImpl/Combobox.hpp | 8 +- src/frontend/ImGuiImpl/Menu.hpp | 74 ++++++++ src/frontend/ImGuiImpl/PopupWindow.hpp | 33 ++++ src/frontend/ImGuiImpl/Slider.hpp | 4 +- src/frontend/ImGuiImpl/StatusBar.hpp | 28 +++ src/frontend/ImGuiImpl/TabBar.hpp | 14 +- src/frontend/KaizenGui.cpp | 190 +++++++++---------- src/frontend/KaizenGui.hpp | 40 ++-- src/frontend/MainWindow.cpp | 153 --------------- src/frontend/MainWindow.hpp | 37 ---- src/frontend/RenderWidget.cpp | 8 +- src/frontend/SettingsWindow.cpp | 106 +++++------ src/frontend/SettingsWindow.hpp | 16 +- src/frontend/main.cpp | 2 +- src/utils/MemoryHelpers.hpp | 2 + 25 files changed, 598 insertions(+), 422 deletions(-) delete mode 100644 resources/frag.spv create mode 100644 resources/frag.spv.h delete mode 100644 resources/vert.spv create mode 100644 resources/vert.spv.h create mode 100644 src/frontend/ImGuiImpl/Menu.hpp create mode 100644 src/frontend/ImGuiImpl/PopupWindow.hpp create mode 100644 src/frontend/ImGuiImpl/StatusBar.hpp delete mode 100644 src/frontend/MainWindow.cpp delete mode 100644 src/frontend/MainWindow.hpp diff --git a/external/parallel-rdp/ParallelRDPWrapper.cpp b/external/parallel-rdp/ParallelRDPWrapper.cpp index 23adf78a..aff415af 100644 --- a/external/parallel-rdp/ParallelRDPWrapper.cpp +++ b/external/parallel-rdp/ParallelRDPWrapper.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include using namespace Vulkan; using namespace RDP; @@ -98,13 +100,11 @@ void ParallelRDP::Init(const std::shared_ptr &factory, const st fragLayout.sets[0].fp_mask = 1; fragLayout.sets[0].array_size[0] = 1; - auto fullscreenQuadVert = Util::ReadFileBinary("resources/vert.spv"); - auto fullscreenQuadFrag = Util::ReadFileBinary("resources/frag.spv"); - auto sizeVert = fullscreenQuadVert.size(); - auto sizeFrag = fullscreenQuadFrag.size(); + auto sizeVert = sizeof(vertex_shader); + auto sizeFrag = sizeof(fragment_shader); fullscreen_quad_program = wsi->get_device().request_program( - reinterpret_cast(fullscreenQuadVert.data()), sizeVert, reinterpret_cast(fullscreenQuadFrag.data()), + reinterpret_cast(vertex_shader), sizeVert, reinterpret_cast(fragment_shader), sizeFrag, &vertLayout, &fragLayout); auto aligned_rdram = reinterpret_cast(rdram); diff --git a/resources/frag.spv b/resources/frag.spv deleted file mode 100644 index 5a0382be85febc88aa6e3d68a110491c5444e1c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1844 zcmZQ(Qf6mhU}WH8;AQY+fB-=TCI&_Z1_o{hHZbk(6YQf`T#}+^Vrl?V!NaQBIK_xE@A zag9$dD2OjEsmw`@&&kY7jZeueN=+`wEK3Ec<3LiEnU|bXnu4r=m4O9pKFnTL24)6M z1_p-GG6n_^8|03%&@cv&I$j0_hT!C))YLo%1~vv(1`r?Q*5b^nR1ggl1Nl2YEv-1U z1Y`ya13$<-s76)>R zhaAWf1_lNXB)gT-#6Wg~#5fp0`k29P1ce#M3{ZH&%mDF0c7oJ{i~#XLb}E55V7)91 zAig4$FU-IM4tqs#EHHrCVhqd-Yzzzx3JeSk;tVVdpg02YLG~#yurPq!01^XX5TAZ}=97(jfGzd&w~V_*Th6{Hq~LF)M!7{GA>3TKdd5FZqlp!gAGU||q|+6~gL z4dn|$?EvW)g6apE2a^|r`bUI;i9w2ifdOQWG}IiB6i6M2F9YI$#aS3+86a*3`3)ow zqCtKJDS`3TK^%q#dk`O_Ul-~QP`Fq#fYJ*nErP;|g~0}#mKhj8;vj#4_@KA}

=H zcCfe|*lv(|2nLyN#J~a$Z&183Ff`apGH^0DLd^z+0oVyp0>+nSU}kV)U;wKFg^4p% z9wY{`8^j02Gf3EsffXFDpu7m;gWU6jfr){Y0pwOle1gIr6rQ%w_~rrUagh0}45089 zW?%rPcThaQ)QB)JFo49H8Cbz_FUr8c0MZ8%cVvL*6Nl;p#ScuM1UOwWFmyomNrK~x zfdM3L2hFD-F_0OcI0B_@ko!P!2QmW`Px1^53?T6x46NYz2Bl|^7%2W$FtC8dKxrN% z{+)rDK?US-1_p*-3@i*FaZp|YiGjia#D>|W3Qb$ccBwHiFo48&LG99DU|;}=f#U8b z0~6S6kU1dpzA~_b?bc*qU;x<-3S*FZkR330X)!P`faF2$(m`?;NL-tNfdM22G7rRt zxl0e~E>QY|g@HZ;0|Q7L76zaK7$gP?1CYC5=74CJy9}XrgWL*I53&R1E+Ym829P|+ zT_#BG0*MvVhtRaw|wZ z$PSP@tdQIRQe(-$z+lh7zyNXwhz&|Fpgac3S0F!w)Pv+eYCz!x$`7s#4B#>k#0RBu zH>jH;uK3j+f~ZenI0h{Makz#zoHz#zlGz`)GF%)rFJz;K9>fq{jAi^1I|-re8d-N!XP zxu77vxTG>CH9jXZFEu_TvnVyWB(p3Pq>ckgU1nZ#PH76V0#*hV24wqK8Q2)O85kJS zbK(P1i^5WiN>VF8?qGw8gV-Rs{Nl`#%=|nCHU@UEdXOK%;+c6R!I@R5AayV~kekzU z;+=Cc3tTdbOA_;vQ{nnRz6Z&b=H$TTSQ(fZK>h}q!OFl2_J07(LIwr~kUS_n%0j~! zJQ!HP_Jh=d+zp~(Vjwqx#6UDm4CEG&7|33j7>ErL1BHV-12fn>kUDn;7O>rNAVV1# z7(jfGy)eEo0~0tt6u~jW0A`CZFf*_*Ffb@EFffQSurRPQFo5|Wvqc$Lz%dMx0~x6e z<#RHCQVl4ML9q%^4-%7uhB?d(E(Qh$5LRGdVc-F$2T;0VV6cYrL16~+3&K>3= zL40W_A7&ni4+=Yw`(XNI!TK5O%@|n0VFwB$kPt}C4+bU%Rt5$JTLu;ekQu_zd=SV0 zN}&u4VhjunATf}7n3y^#&!8~qV_*flL7stu0VD=;cK}oj6qg`A2sc8-6d4#8Kx#p9AaguORj diff --git a/resources/vert.spv.h b/resources/vert.spv.h new file mode 100644 index 00000000..5aa4174f --- /dev/null +++ b/resources/vert.spv.h @@ -0,0 +1,91 @@ +constexpr unsigned char vertex_shader[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x0D, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00, + 0x04, 0x00, 0x0A, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x63, 0x70, 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, + 0x6C, 0x69, 0x6E, 0x65, 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, + 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, + 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, + 0x65, 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, + 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x67, 0x6C, 0x5F, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73, 0x69, 0x74, + 0x69, 0x6F, 0x6E, 0x00, 0x06, 0x00, 0x07, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x69, 0x6E, 0x74, + 0x53, 0x69, 0x7A, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x43, + 0x6C, 0x69, 0x70, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x00, + 0x06, 0x00, 0x07, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x67, 0x6C, 0x5F, 0x43, 0x75, 0x6C, 0x6C, 0x44, 0x69, 0x73, 0x74, 0x61, + 0x6E, 0x63, 0x65, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x03, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x76, 0x55, 0x56, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x06, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3F, 0x20, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x00, 0x05, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x1A, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x8E, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; diff --git a/src/backend/CMakeLists.txt b/src/backend/CMakeLists.txt index d656ead3..ad78fd97 100644 --- a/src/backend/CMakeLists.txt +++ b/src/backend/CMakeLists.txt @@ -4,4 +4,4 @@ file(GLOB HEADERS *.hpp) add_subdirectory(core) add_library(backend ${SOURCES} ${HEADERS}) -target_link_libraries(backend PRIVATE core) \ No newline at end of file +target_link_libraries(backend PRIVATE core) diff --git a/src/backend/core/Mem.hpp b/src/backend/core/Mem.hpp index 9f9fa035..f7c565a7 100644 --- a/src/backend/core/Mem.hpp +++ b/src/backend/core/Mem.hpp @@ -2,12 +2,13 @@ #include #include #include -#include #include #include #include #include #include +#include +#include namespace n64 { struct ROMHeader { diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index 1d9f8ef1..2e84a4f2 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -3,6 +3,7 @@ project(kaizen) if (WIN32) add_compile_definitions(NOMINMAX) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif () if(APPLE) @@ -10,9 +11,13 @@ if(APPLE) enable_language(OBJC) endif() +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + include_directories( . ../ + ../../ ../utils ../backend ../backend/core @@ -40,6 +45,7 @@ include_directories( ../../external/capstone/include ../../external/imgui ../../external/imgui/backends + ../../external/nfd/src/include ../../external/cflags/include ImGuiImpl/ ) @@ -65,22 +71,27 @@ else() set(ARM64 FALSE) endif() +set(SIMD_FLAG NULL) + if(ARM64 AND APPLE) message("Defining USE_NEON...") add_compile_definitions(USE_NEON) - set(HAS_SIMD TRUE) + add_compile_definitions(SIMD_SUPPORT) +elseif(NOT ARM64) + if(MSVC) + set(SIMD_FLAG /arch:AVX) + else() + set(SIMD_FLAG -msse4.1) + endif() + check_c_compiler_flag(${SIMD_FLAG} HAS_SIMD) +else() + message("Compiling on an unsupported Arm device! Good Luck!") endif() -if(NOT ARM64) - check_c_compiler_flag(-msse4.1 HAS_SIMD) -endif () - if (HAS_SIMD) message("Defining SIMD_SUPPORT...") add_compile_definitions(SIMD_SUPPORT) - if(NOT ARM64) - add_compile_options(-msse3 -msse4.1) - endif() + add_compile_options(${SIMD_FLAG}) endif () if (${CMAKE_BUILD_TYPE} MATCHES Debug) @@ -97,6 +108,7 @@ add_subdirectory(../../external/unarr unarr) add_subdirectory(../../external/SDL SDL) add_subdirectory(../../external/cflags cflags) add_subdirectory(../../external/imgui imgui) +add_subdirectory(../../external/nfd nfd) set(CAPSTONE_ARCHITECTURE_DEFAULT OFF) set(CAPSTONE_MIPS_SUPPORT ON) set(CAPSTONE_X86_SUPPORT ON) @@ -110,8 +122,6 @@ add_executable(kaizen RenderWidget.hpp EmuThread.hpp EmuThread.cpp - MainWindow.hpp - MainWindow.cpp SettingsWindow.hpp SettingsWindow.cpp CPUSettings.hpp @@ -124,9 +134,8 @@ add_executable(kaizen Debugger.hpp Debugger.cpp) -target_link_libraries(kaizen PUBLIC imgui SDL3::SDL3 SDL3::SDL3-static cflags::cflags discord-rpc fmt mio nlohmann_json parallel-rdp capstone backend) +target_link_libraries(kaizen PUBLIC imgui nfd SDL3::SDL3 SDL3::SDL3-static cflags::cflags discord-rpc fmt mio nlohmann_json parallel-rdp capstone backend) target_compile_definitions(kaizen PUBLIC SDL_MAIN_HANDLED) -set_target_properties(kaizen PROPERTIES CXX_STANDARD 20 CXX_STANDARD_REQUIRED ON) file(COPY ../../resources/ DESTINATION ${PROJECT_BINARY_DIR}/resources/) file(REMOVE diff --git a/src/frontend/EmuThread.cpp b/src/frontend/EmuThread.cpp index 9e6703c9..fdb7eb0f 100644 --- a/src/frontend/EmuThread.cpp +++ b/src/frontend/EmuThread.cpp @@ -1,7 +1,7 @@ #include #include -EmuThread::EmuThread(const std::shared_ptr &core, std::string &fps, RenderWidget &renderWidget, +EmuThread::EmuThread(const std::shared_ptr &core, double &fps, RenderWidget &renderWidget, SettingsWindow &settings) noexcept : renderWidget(renderWidget), core(core), settings(settings), fps(fps) {} @@ -16,7 +16,7 @@ void EmuThread::start() noexcept { auto sampledFps = 0; static bool oneSecondPassed = false; - fps = fmt::format("{:.2f} FPS", 1000.0 / avgFps); + fps = 1000.0 / avgFps; while (!interruptionRequested) { const auto startFrameTime = std::chrono::high_resolution_clock::now(); @@ -44,7 +44,7 @@ void EmuThread::start() noexcept { lastSample = endFrameTime; avgFps /= sampledFps; sampledFps = 0; - fps = fmt::format("{:.2f} FPS", 1000.0 / avgFps); + fps = 1000.0 / avgFps; } } SetRender(false); diff --git a/src/frontend/EmuThread.hpp b/src/frontend/EmuThread.hpp index 510869b3..9b0193b0 100644 --- a/src/frontend/EmuThread.hpp +++ b/src/frontend/EmuThread.hpp @@ -12,7 +12,7 @@ class EmuThread final { RenderWidget &renderWidget; public: - explicit EmuThread(const std::shared_ptr &, std::string &, RenderWidget &, SettingsWindow &) noexcept; + explicit EmuThread(const std::shared_ptr &, double &, RenderWidget &, SettingsWindow &) noexcept; void start() noexcept; void TogglePause() const noexcept; @@ -24,6 +24,6 @@ public: bool interruptionRequested = false, isRunning = false; std::shared_ptr core; SettingsWindow &settings; - std::string& fps; + double& fps; std::thread thread; }; diff --git a/src/frontend/ImGuiImpl/Combobox.hpp b/src/frontend/ImGuiImpl/Combobox.hpp index cdc1215b..8d97e7e7 100644 --- a/src/frontend/ImGuiImpl/Combobox.hpp +++ b/src/frontend/ImGuiImpl/Combobox.hpp @@ -14,7 +14,7 @@ struct ComboItem { return ret; } - const std::string& getLabel() { return label; } + const std::string& getLabel() const { return label; } void setLabel(const std::string& text) { label = text; } private: bool enabled = true; @@ -24,9 +24,9 @@ private: struct Combobox { Combobox(std::string label, std::vector items, std::string preview = "", bool enabled = true) : label(label), items(items), preview(preview), enabled(enabled) {} - void addItem(ComboItem& item) { - if(std::find(items.begin(), items.end(), - [&item](ComboItem& a) { return a.getLabel() == item.getLabel(); }) != items.end()) + void addItem(const ComboItem& item) { + if(std::find_if(items.begin(), items.end(), + [&item](const ComboItem& a) { return a.getLabel() == item.getLabel(); }) != items.end()) return; items.push_back(item); diff --git a/src/frontend/ImGuiImpl/Menu.hpp b/src/frontend/ImGuiImpl/Menu.hpp new file mode 100644 index 00000000..e85d4146 --- /dev/null +++ b/src/frontend/ImGuiImpl/Menu.hpp @@ -0,0 +1,74 @@ +#pragma once +#include +#include +#include +#include + +namespace gui { +struct MenuItem { + MenuItem(const std::string& label, std::function&& func = nullptr, bool enabled = true) : label(label), exec(std::move(func)), enabled(enabled) {} + bool render() { + bool ret = false; + ImGui::BeginDisabled(!enabled); + if(ImGui::MenuItem(label.c_str())) { + if(exec) + exec(); + ret = true; + } + ImGui::EndDisabled(); + return ret; + } + + void setEnabled(bool v) { enabled = v; } +private: + bool enabled = true; + std::string label; + std::function exec; +}; + +struct Menu { + Menu(const std::string& label, const std::vector& items = {}, bool enabled = true) : label(label), items(items), enabled(enabled) {} + void addMenuItem(const MenuItem& item) { items.push_back(item); } + bool render() { + bool ret = false; + ImGui::BeginDisabled(!enabled); + if(ImGui::BeginMenu(label.c_str())) { + for(auto& item : items) { + ret |= item.render(); + } + ImGui::EndMenu(); + } + ImGui::EndDisabled(); + return ret; + } + void setEnabled(bool v) { enabled = v; } +private: + std::vector items{}; + std::string label{}; + bool enabled = true; +}; + +template +struct MenuBar { + MenuBar(bool enabled = true) : enabled(enabled) {} + void addMenu(const Menu& menu) { menus.push_back(menu); } + bool render() { + bool ret = false; + ImGui::BeginDisabled(!enabled); + auto beginMenuBar = main ? &ImGui::BeginMainMenuBar : &ImGui::BeginMenuBar; + auto endMenuBar = main ? &ImGui::EndMainMenuBar : &ImGui::EndMenuBar; + if(beginMenuBar()) { + for(auto& menu : menus) { + ret |= menu.render(); + } + endMenuBar(); + } + ImGui::EndDisabled(); + return ret; + } + void setEnabled(bool v) { enabled = v; } +private: + bool enabled = true; + std::vector

menus{}; +}; +} \ No newline at end of file diff --git a/src/frontend/ImGuiImpl/PopupWindow.hpp b/src/frontend/ImGuiImpl/PopupWindow.hpp new file mode 100644 index 00000000..071b2e70 --- /dev/null +++ b/src/frontend/ImGuiImpl/PopupWindow.hpp @@ -0,0 +1,33 @@ +#include +#include +#include + +namespace gui { +struct PopupWindow { + PopupWindow(const std::string& title, std::function&& func = nullptr, bool opened = true) : title(title), exec(func), opened(opened) {} + void setFunc(std::function&& func) { + exec = func; + } + + bool render() { + ImGui::OpenPopup(title.c_str()); + ImVec2 center = ImGui::GetMainViewport()->GetCenter(); + ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); + + if (ImGui::BeginPopupModal(title.c_str(), &opened, ImGuiWindowFlags_AlwaysAutoResize)) + { + if(exec) + exec(); + ImGui::EndPopup(); + + return true; + } + + return false; + } +private: + std::function exec; + std::string title; + bool opened = true; +}; +} \ No newline at end of file diff --git a/src/frontend/ImGuiImpl/Slider.hpp b/src/frontend/ImGuiImpl/Slider.hpp index a870c633..6d716ca4 100644 --- a/src/frontend/ImGuiImpl/Slider.hpp +++ b/src/frontend/ImGuiImpl/Slider.hpp @@ -5,8 +5,8 @@ namespace gui { template struct Slider { - Slider(const std::string& label, T min = 0, T max = 0, T default = 0) - : val(default), label(label), min(min), max(max) { } + Slider(const std::string& label, T min = 0, T max = 0, T initial_value = 0) + : val(initial_value), label(label), min(min), max(max) { } void setValue(T v) { val = v; } bool render() { diff --git a/src/frontend/ImGuiImpl/StatusBar.hpp b/src/frontend/ImGuiImpl/StatusBar.hpp new file mode 100644 index 00000000..a95b83e3 --- /dev/null +++ b/src/frontend/ImGuiImpl/StatusBar.hpp @@ -0,0 +1,28 @@ +#include +#include + +namespace gui { +struct StatusBar { + StatusBar(std::function&& func = nullptr, bool enabled = true) : exec(func), enabled(enabled) {} + + bool render() { + float statusWindowHeight = ImGui::GetFrameHeight() * 1.4f; + ImGuiViewport* viewport = ImGui::GetMainViewport(); + + ImVec2 statusBarSize, statusBarPos; + + ImGui::SetNextWindowPos(statusBarPos); + ImGui::SetNextWindowSize(statusBarSize); + ImGui::SetNextWindowViewport(viewport->ID); + + ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoDocking; + ImGui::Begin("StatusBar", nullptr, windowFlags); + if(exec) + exec(); + ImGui::End(); + } +private: + std::function exec = nullptr; + bool enabled = true; +}; +} \ No newline at end of file diff --git a/src/frontend/ImGuiImpl/TabBar.hpp b/src/frontend/ImGuiImpl/TabBar.hpp index 01acfe5f..6f79c0cd 100644 --- a/src/frontend/ImGuiImpl/TabBar.hpp +++ b/src/frontend/ImGuiImpl/TabBar.hpp @@ -2,18 +2,19 @@ #include #include #include +#include namespace gui { struct TabItem { - TabItem(std::string label, void(*func)(TabItem*, void* userData) = nullptr, void* userData = nullptr, bool enabled = true) : exec(func), enabled(enabled), userData(userData) {} + TabItem(std::string label, std::function&& func, bool enabled = true) : exec(std::move(func)), enabled(enabled) {} bool render() { bool ret = false; ImGui::BeginDisabled(!enabled); if(ImGui::BeginTabItem(label.c_str())) { if(exec) - exec(this, userData); + exec(); ImGui::EndTabItem(); ret = true; } @@ -23,15 +24,12 @@ struct TabItem { private: bool enabled = true; std::string label; - void(*exec)(TabItem*, void* userData); - void* userData; + std::function exec; }; struct TabBar { - TabBar(std::string label) : label(label) {} - void addTab(TabItem tabItem) { - tabs.push_back(tabItem); - } + TabBar(std::string label, const std::vector& items = {}) : label(label), tabs(items) {} + void addTab(TabItem tabItem) { tabs.push_back(tabItem); } bool render() { bool ret = false; diff --git a/src/frontend/KaizenGui.cpp b/src/frontend/KaizenGui.cpp index 223b8e4a..10751cba 100644 --- a/src/frontend/KaizenGui.cpp +++ b/src/frontend/KaizenGui.cpp @@ -1,125 +1,105 @@ -#include #include +#include +#include +#include -namespace fs = std::filesystem; +KaizenGui::KaizenGui() noexcept : core(std::make_shared()), vulkanWidget(core), emuThread(core, fpsCounter, vulkanWidget, settingsWindow) { + emuExitFunc = [&]() { + quit = true; + if (emuThread.isRunning) { + emuThread.requestInterruption(); + while (emuThread.isRunning) {} + } + }; + + menuBar.addMenu({"File", + { + {"Open", [&]() { + NFD::Guard guard; + NFD::UniquePath path; + nfdfilteritem_t filterItem = {"Nintendo 64 roms", "n64,z64,v64,N64,Z64,V64"}; -KaizenGui::KaizenGui() noexcept : mainWindow(core), emuThread(core, mainWindow.fpsCounter, mainWindow.vulkanWidget, settingsWindow) { - // debugger = std::make_unique(); + auto result = NFD::OpenDialog(path, &filterItem, 1); + if(result == NFD_CANCEL) return; + if(result == NFD_ERROR) + Util::panic("Error: {}", NFD::GetError()); + LoadROM(path.get()); + }}, + {"Exit", std::move(emuExitFunc)} + } + }); - ConnectMainWindowSignalsToSlots(); - Util::RPC::GetInstance().Update(Util::RPC::Idling); + menuBar.addMenu({"Emulation", + { + actionPause, + actionStop, + actionReset, + {"Settings", [&]() { + settingsWindow.render(); + }}, + } + }); + + menuBar.addMenu({"Help", + { + {"About", [&]() { + gui::PopupWindow about{"About Kaizen", [&]() { + ImGui::Text("Kaizen is a Nintendo 64 emulator that strives"); + ImGui::Text("to offer a friendly user experience and compatibility."); + ImGui::Text("Kaizen is licensed under the BSD 3-clause license."); + ImGui::Text("Nintendo 64 is a registered trademarks of Nintendo Co., Ltd."); + }}; + }}, + } + }); } -void KaizenGui::ConnectMainWindowSignalsToSlots() noexcept { - connect(settingsWindow.get(), &SettingsWindow::regrabKeyboard, this, [&] { grabKeyboard(); }); +void KaizenGui::LoadROM(const std::string &path) noexcept { + actionPause.setEnabled(true); + actionReset.setEnabled(true); + actionStop.setEnabled(true); + emuThread.start(); + emuThread.core->LoadROM(path); + const auto gameNameDB = emuThread.core->cpu->GetMem().rom.gameNameDB; + Util::RPC::GetInstance().Update(Util::RPC::Playing, gameNameDB); +} - connect(settingsWindow.get(), &SettingsWindow::gotClosed, this, - [&] { mainWindow->vulkanWidget->wsiPlatform->EnableEventPolling(); }); - - connect(settingsWindow.get(), &SettingsWindow::gotOpened, this, - [&] { mainWindow->vulkanWidget->wsiPlatform->DisableEventPolling(); }); - - connect(mainWindow.get(), &MainWindow::OpenSettings, this, [this] { settingsWindow->show(); }); - // connect(mainWindow.get(), &MainWindow::OpenDebugger, this, [this] { debugger->show(); }); - connect(mainWindow.get(), &MainWindow::OpenROM, this, &KaizenGui::LoadROM); - connect(mainWindow.get(), &MainWindow::Exit, this, &KaizenGui::Quit); - connect(mainWindow.get(), &MainWindow::Reset, emuThread.get(), &EmuThread::Reset); - connect(mainWindow.get(), &MainWindow::Stop, this, [this] { emuThread->requestInterruption(); }); - connect(mainWindow.get(), &MainWindow::Pause, emuThread.get(), &EmuThread::TogglePause); +void KaizenGui::handleEvents() { + SDL_Event e; + while(SDL_PollEvent(&e)) { + switch(e.type) { + case SDL_EVENT_QUIT: + emuExitFunc(); + break; + } + } } int KaizenGui::run() { - bool inputForEmu = true; + while(!quit) { + handleEvents(); - if(settingsWindow.render()) { - inputForEmu = false; + menuBar.render(); + + // TODO VULKAN CANVAS + + gui::StatusBar statusBar{[&]() { + ImGui::Text("GUI FPS: %.2f, Emulation FPS: %.2f", ImGui::GetIO().Framerate, fpsCounter); + }}; + + statusBar.render(); } - mainWindow.render(); - return 0; } -void KaizenGui::LoadROM(const QString &path) const noexcept { - mainWindow->actionPause->setEnabled(true); - mainWindow->actionReset->setEnabled(true); - mainWindow->actionStop->setEnabled(true); - emuThread->start(); - emuThread->core->LoadROM(path.toStdString()); - const auto gameNameDB = emuThread->core->cpu->GetMem().rom.gameNameDB; - mainWindow->setWindowTitle(emuThread->core->cpu->GetMem().rom.gameNameDB.c_str()); - Util::RPC::GetInstance().Update(Util::RPC::Playing, gameNameDB); -} - -void KaizenGui::Quit() const noexcept { - if (emuThread) { - emuThread->requestInterruption(); - while (emuThread->isRunning) {} - } - QApplication::quit(); -} - -void KaizenGui::LoadTAS(const QString &path) const noexcept { - if (emuThread->core->LoadTAS(fs::path(path.toStdString()))) { - const auto gameNameDB = emuThread->core->cpu->GetMem().rom.gameNameDB; - const auto movieName = fs::path(path.toStdString()).stem().string(); +void KaizenGui::LoadTAS(const std::string &path) const noexcept { + if (emuThread.core->LoadTAS(fs::path(path))) { + const auto gameNameDB = emuThread.core->cpu->GetMem().rom.gameNameDB; + const auto movieName = fs::path(path).stem().string(); Util::RPC::GetInstance().Update(Util::RPC::MovieReplay, gameNameDB, movieName); return; } - Util::panic("Could not load TAS movie {}!", path.toStdString()); -} - -void KaizenGui::keyPressEvent(QKeyEvent *e) { - if (settingsWindow->inputSettings->selectedDeviceIsNotKeyboard) - return; - - emuThread->core->pause = true; - n64::Mem &mem = emuThread->core->cpu->GetMem(); - n64::PIF &pif = mem.mmio.si.pif; - - const auto k = static_cast(e->key()); - for (int i = 0; i < 14; i++) { - if (k == settingsWindow->keyMap[i]) - pif.UpdateButton(0, static_cast(i), true); - } - - if (k == settingsWindow->keyMap[14]) - pif.UpdateAxis(0, n64::Controller::Axis::Y, 86); - if (k == settingsWindow->keyMap[15]) - pif.UpdateAxis(0, n64::Controller::Axis::Y, -86); - if (k == settingsWindow->keyMap[16]) - pif.UpdateAxis(0, n64::Controller::Axis::X, -86); - if (k == settingsWindow->keyMap[17]) - pif.UpdateAxis(0, n64::Controller::Axis::X, 86); - - emuThread->core->pause = false; - QWidget::keyPressEvent(e); -} - -void KaizenGui::keyReleaseEvent(QKeyEvent *e) { - if (settingsWindow->inputSettings->selectedDeviceIsNotKeyboard) - return; - - emuThread->core->pause = true; - n64::Mem &mem = emuThread->core->cpu->GetMem(); - n64::PIF &pif = mem.mmio.si.pif; - - const auto k = static_cast(e->key()); - for (int i = 0; i < 14; i++) { - if (k == settingsWindow->keyMap[i]) - pif.UpdateButton(0, static_cast(i), false); - } - - if (k == settingsWindow->keyMap[14]) - pif.UpdateAxis(0, n64::Controller::Axis::Y, 0); - if (k == settingsWindow->keyMap[15]) - pif.UpdateAxis(0, n64::Controller::Axis::Y, 0); - if (k == settingsWindow->keyMap[16]) - pif.UpdateAxis(0, n64::Controller::Axis::X, 0); - if (k == settingsWindow->keyMap[17]) - pif.UpdateAxis(0, n64::Controller::Axis::X, 0); - - emuThread->core->pause = false; - QWidget::keyReleaseEvent(e); -} + Util::panic("Could not load TAS movie {}!", path); +} \ No newline at end of file diff --git a/src/frontend/KaizenGui.hpp b/src/frontend/KaizenGui.hpp index 5111879b..2c2726af 100644 --- a/src/frontend/KaizenGui.hpp +++ b/src/frontend/KaizenGui.hpp @@ -1,24 +1,28 @@ #pragma once -#include +#include +#include +#include #include -#include -#include -#include -#include +#include -class KaizenGui { +class KaizenGui final { public: - KaizenGui() noexcept; - void LoadTAS(const std::string &path) const noexcept; - void LoadROM(const std::string &path) const noexcept; - int run(); - -private: - void Quit() const noexcept; - void ConnectMainWindowSignalsToSlots() noexcept; - MainWindow mainWindow; - SettingsWindow settingsWindow; - EmuThread emuThread; - // std::unique_ptr debugger; + explicit KaizenGui() noexcept; + double fpsCounter; + gui::MenuBar menuBar; + gui::MenuItem actionPause{"Pause"}, actionStop{"Stop"}, actionReset{"Reset"}; std::shared_ptr core; + EmuThread emuThread; + SettingsWindow settingsWindow; + RenderWidget vulkanWidget; + + int run(); + void LoadTAS(const std::string &path) const noexcept; + void LoadROM(const std::string &path) noexcept; +private: + bool quit = false; + void handleEvents(); + std::function emuExitFunc; + + bool textPauseToggle = false; }; diff --git a/src/frontend/MainWindow.cpp b/src/frontend/MainWindow.cpp deleted file mode 100644 index c9d8579c..00000000 --- a/src/frontend/MainWindow.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include - -MainWindow::MainWindow(const std::shared_ptr &core) noexcept : vulkanWidget(core) { - /* if (objectName().isEmpty()) - setObjectName("MainWindow"); - resize(800, 646); - actionOpenDebuggerWindow = std::make_unique(this); - actionOpenDebuggerWindow->setObjectName("actionOpenDebuggerWindow"); - actionAbout = std::make_unique(this); - actionAbout->setObjectName("actionAbout"); - actionOpen = std::make_unique(this); - actionOpen->setObjectName("actionOpen"); - actionExit = std::make_unique(this); - actionExit->setObjectName("actionExit"); - actionPause = std::make_unique(this); - actionPause->setObjectName("actionPause"); - actionReset = std::make_unique(this); - actionReset->setObjectName("actionReset"); - actionStop = std::make_unique(this); - actionStop->setObjectName("actionStop"); - actionSettings = std::make_unique(this); - actionSettings->setObjectName("actionSettings"); - centralwidget = std::make_unique(this); - centralwidget->setObjectName("centralwidget"); - verticalLayout = std::make_unique(); - verticalLayout->setSpacing(0); - verticalLayout->setObjectName("verticalLayout"); - verticalLayout->setContentsMargins(0, 0, 0, 0); - - verticalLayout->addWidget(vulkanWidget.get()); - - centralwidget->setLayout(verticalLayout.get()); - - setCentralWidget(centralwidget.get()); - menubar = std::make_unique(this); - menubar->setObjectName("menubar"); - menubar->setGeometry(QRect(0, 0, 800, 22)); - menuFile = std::make_unique(menubar.get()); - menuFile->setObjectName("menuFile"); - menuEmulation = std::make_unique(menubar.get()); - menuEmulation->setObjectName("menuEmulation"); - menuTools = std::make_unique(menubar.get()); - menuTools->setObjectName("menuTools"); - menuAbout = std::make_unique(menubar.get()); - menuAbout->setObjectName("menuAbout"); - setMenuBar(menubar.get()); - statusbar = std::make_unique(this); - statusbar->setObjectName("statusbar"); - fpsCounter = std::make_unique("Not playing"); - statusbar->addPermanentWidget(fpsCounter.get()); - setStatusBar(statusbar.get()); - - menubar->addAction(menuFile->menuAction()); - menubar->addAction(menuEmulation->menuAction()); - menubar->addAction(menuTools->menuAction()); - menubar->addAction(menuAbout->menuAction()); - menuFile->addAction(actionOpen.get()); - menuFile->addAction(actionExit.get()); - menuEmulation->addAction(actionSettings.get()); - menuEmulation->addAction(actionPause.get()); - menuEmulation->addAction(actionReset.get()); - menuEmulation->addAction(actionStop.get()); - menuTools->addAction(actionOpenDebuggerWindow.get()); - menuAbout->addAction(actionAbout.get()); - - Retranslate(); - - QMetaObject::connectSlotsByName(this); - actionPause->setDisabled(true); - actionReset->setDisabled(true); - actionStop->setDisabled(true); - vulkanWidget->hide(); - ConnectSignalsToSlots();*/ -} - -void MainWindow::Retranslate() { - /*setWindowTitle(QCoreApplication::translate("MainWindow", "Kaizen", nullptr)); - actionOpenDebuggerWindow->setText(QCoreApplication::translate("MainWindow", "CPU Debugger", nullptr)); - actionOpenDebuggerWindow->setStatusTip(QCoreApplication::translate( - "MainWindow", "Open the CPU debugger window which allows you see registers, memory and disassembled code", - nullptr)); - actionAbout->setText(QCoreApplication::translate("MainWindow", "About Kaizen", nullptr)); - actionAbout->setStatusTip(QCoreApplication::translate("MainWindow", "About this emulator", nullptr)); - actionOpen->setText(QCoreApplication::translate("MainWindow", "Open...", nullptr)); - actionOpen->setStatusTip(QCoreApplication::translate("MainWindow", "Open a ROM", nullptr)); - actionOpen->setShortcut(QCoreApplication::translate("MainWindow", "Ctrl+O", nullptr)); - actionExit->setText(QCoreApplication::translate("MainWindow", "Exit", nullptr)); - actionExit->setStatusTip(QCoreApplication::translate("MainWindow", "Quit the emulator", nullptr)); - actionPause->setText(QCoreApplication::translate("MainWindow", "Pause", nullptr)); - actionPause->setStatusTip(QCoreApplication::translate("MainWindow", "Pause the emulation", nullptr)); - actionReset->setText(QCoreApplication::translate("MainWindow", "Reset", nullptr)); - actionReset->setStatusTip(QCoreApplication::translate("MainWindow", "Reset the emulation", nullptr)); - actionStop->setText(QCoreApplication::translate("MainWindow", "Stop", nullptr)); - actionStop->setStatusTip(QCoreApplication::translate("MainWindow", "Stop the emulation", nullptr)); - actionSettings->setText(QCoreApplication::translate("MainWindow", "Settings", nullptr)); - actionSettings->setToolTip(QCoreApplication::translate("MainWindow", "Settings", nullptr)); - actionSettings->setStatusTip(QCoreApplication::translate("MainWindow", "Open the settings window", nullptr)); - menuFile->setTitle(QCoreApplication::translate("MainWindow", "File", nullptr)); - menuEmulation->setTitle(QCoreApplication::translate("MainWindow", "Emulation", nullptr)); - menuTools->setTitle(QCoreApplication::translate("MainWindow", "Tools", nullptr)); - menuAbout->setTitle(QCoreApplication::translate("MainWindow", "Help", nullptr)); - */ -} // retranslateUi - -void MainWindow::ConnectSignalsToSlots() noexcept { - /* connect(actionOpen.get(), &QAction::triggered, this, [this]() { - const QString file_name = QFileDialog::getOpenFileName( - this, "Nintendo 64 executable", QString(), - "All supported types (*.zip *.ZIP *.7z *.7Z *.rar *.RAR *.tar *.TAR *.n64 *.N64 *.v64 *.V64 *.z64 *.Z64)"); - - if (!file_name.isEmpty()) { - emit OpenROM(file_name); - vulkanWidget->show(); - } - }); - - connect(actionExit.get(), &QAction::triggered, this, [this]() { emit Exit(); }); - - connect(this, &MainWindow::destroyed, this, [this]() { emit Exit(); }); - - connect(actionReset.get(), &QAction::triggered, this, [this]() { emit Reset(); }); - - connect(actionStop.get(), &QAction::triggered, this, [this]() { - setWindowTitle("Kaizen"); - vulkanWidget->hide(); - actionPause->setDisabled(true); - actionReset->setDisabled(true); - actionStop->setDisabled(true); - emit Stop(); - }); - - connect(actionPause.get(), &QAction::triggered, this, [this]() { - textPauseToggle = !textPauseToggle; - actionPause->setText(textPauseToggle ? "Resume" : "Pause"); - emit Pause(); - }); - - connect(actionAbout.get(), &QAction::triggered, this, [this]() { - QMessageBox::about(this, tr("About Kaizen"), - tr("Kaizen is a Nintendo 64 emulator that strives to offer a friendly user " - "experience and great compatibility.\n" - "Kaizen is licensed under the BSD 3-clause license.\n" - "Nintendo 64 is a registered trademarks of Nintendo Co., Ltd.")); - }); - - connect(actionSettings.get(), &QAction::triggered, this, [this]() { emit OpenSettings(); }); - connect(actionOpenDebuggerWindow.get(), &QAction::triggered, this, [this]() { emit OpenDebugger(); }); - */ -} - -bool MainWindow::render() { - -} \ No newline at end of file diff --git a/src/frontend/MainWindow.hpp b/src/frontend/MainWindow.hpp deleted file mode 100644 index 162e326f..00000000 --- a/src/frontend/MainWindow.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include -#include - -class MainWindow final { -public: - explicit MainWindow(const std::shared_ptr &) noexcept; - std::string fpsCounter; - RenderWidget vulkanWidget; - - bool render(); - -//std::unique_ptr actionOpenDebuggerWindow{}; -//std::unique_ptr actionAbout{}; -//std::unique_ptr actionOpen{}; -//std::unique_ptr actionExit{}; -//std::unique_ptr actionPause{}; -//std::unique_ptr actionReset{}; -//std::unique_ptr actionStop{}; -//std::unique_ptr actionSettings{}; -//std::unique_ptr centralwidget{}; -//std::unique_ptr verticalLayout{}; -//std::unique_ptr vulkanWidget{}; -//std::unique_ptr menubar{}; -//std::unique_ptr menuFile{}; -//std::unique_ptr menuEmulation{}; -//std::unique_ptr menuTools{}; -//std::unique_ptr menuAbout{}; -//std::unique_ptr statusbar{}; -//std::unique_ptr fpsCounter{}; - -private: - void Retranslate(); - void ConnectSignalsToSlots() noexcept; - - bool textPauseToggle = false; -}; diff --git a/src/frontend/RenderWidget.cpp b/src/frontend/RenderWidget.cpp index 60c05e72..11151d06 100644 --- a/src/frontend/RenderWidget.cpp +++ b/src/frontend/RenderWidget.cpp @@ -9,11 +9,11 @@ RenderWidget::RenderWidget(const std::shared_ptr &core) { } imGuiVkInstanceFactory = std::make_shared(); - windowHandle()->setVulkanInstance(&imGuiVkInstanceFactory->handle); - windowHandle()->create(); + //windowHandle()->setVulkanInstance(&imGuiVkInstanceFactory->create_instance()); + //windowHandle()->create(); - wsiPlatform = std::make_shared(core, windowHandle()); - windowInfo = std::make_shared(windowHandle()); + //wsiPlatform = std::make_shared(core, windowHandle()); + // windowInfo = std::make_shared(windowHandle()); } void ImGuiWSIPlatform::poll_input() { diff --git a/src/frontend/SettingsWindow.cpp b/src/frontend/SettingsWindow.cpp index 9cf0615e..16360081 100644 --- a/src/frontend/SettingsWindow.cpp +++ b/src/frontend/SettingsWindow.cpp @@ -1,76 +1,76 @@ #include #include +#include +#include +#include std::string savePath; -SettingsWindow::SettingsWindow() { - settings = JSONOpenOrCreate("resources/settings.json"); - - savePath = JSONGetField(settings, "general", "savePath"); - +SettingsWindow::SettingsWindow() : settings{JSONOpenOrCreate("resources/settings.json")} { keyMap = inputSettings.GetMappedKeys(); - savesFolder.setName(fmt::format(savesFolder.getName(), savePath)); + savesFolder.setName(fmt::format("Save path: {}", + JSONGetField(settings, "general", "savePath"))); - tabs.addTab({"General", [](gui::TabItem* tab, void* userData) { - SettingsWindow* sW = (SettingsWindow*)userData; - if(sW->savesFolder.render()) { - // TODO: HANDLE FILE DIALOG savePath = QFileDialog::getExistingDirectory(this, tr("Select directory")).toStdString(); - sW->savesFolder.setName(fmt::format(sW->savesFolder.getName(), savePath)); - JSONSetField(sW->settings, "general", "savePath", savePath); - sW->apply.setEnabled(true); + tabs.addTab({"General", [&]() { + if(savesFolder.render()) { + NFD::Guard guard; + NFD::UniquePath outPath; + + auto result = NFD::PickFolder(outPath); + if(result == NFD_CANCEL) + return; + if(result == NFD_ERROR) + Util::panic("Error: {}", NFD::GetError()); + + savesFolder.setName(fmt::format("Save path: {}", outPath.get())); + JSONSetField(settings, "general", "savePath", outPath.get()); + apply.setEnabled(true); } - }, this}); + }}); - tabs.addTab({"CPU", [](gui::TabItem* tab, void* userData) { - SettingsWindow* sW = (SettingsWindow*)userData; - CPUSettings& cS = sW->cpuSettings; - gui::PushButton& apply = sW->apply; - - if(cS.render()) { - if(cS.getModified()) - sW->apply.setEnabled(true); - } - }, this}); - - tabs.addTab({"Audio", [](gui::TabItem* tab, void* userData) { - SettingsWindow* sW = (SettingsWindow*)userData; - AudioSettings& aS = sW->audioSettings; - gui::PushButton& apply = sW->apply; - if(aS.render()) { - if(aS.getModified()) + tabs.addTab({"CPU", [&]() { + if(cpuSettings.render()) { + if(cpuSettings.getModified()) apply.setEnabled(true); } - }, this}); + }}); - tabs.addTab({"Input", [](gui::TabItem* tab, void* userData) { - SettingsWindow* sW = (SettingsWindow*)userData; - sW->inputSettings.render(); - InputSettings& iS = sW->inputSettings; - gui::PushButton& apply = sW->apply; - - if(iS.render()) { - if(iS.getModified()) + tabs.addTab({"Audio", [&]() { + if(audioSettings.render()) { + if(audioSettings.getModified()) apply.setEnabled(true); } - }, this}); + }}); + + tabs.addTab({"Input", [&]() { + if(inputSettings.render()) { + if(inputSettings.getModified()) + apply.setEnabled(true); + } + }}); apply.setEnabled(false); + + canvas.setFunc([&]() { + tabs.render(); + + if(apply.render()) { + auto newMap = inputSettings.GetMappedKeys(); + if (keyMap != newMap) + keyMap = newMap; + + apply.setEnabled(false); + std::ofstream file("resources/settings.json"); + file << settings; + file.close(); + } + }); } bool SettingsWindow::render() { - tabs.render(); - - if(apply.render()) { - auto newMap = inputSettings.GetMappedKeys(); - if (keyMap != newMap) - keyMap = newMap; - - apply.setEnabled(false); - std::ofstream file("resources/settings.json"); - file << settings; - file.close(); - } + if(canvas.render()) + return true; return false; } \ No newline at end of file diff --git a/src/frontend/SettingsWindow.hpp b/src/frontend/SettingsWindow.hpp index 7de70166..160570f3 100644 --- a/src/frontend/SettingsWindow.hpp +++ b/src/frontend/SettingsWindow.hpp @@ -3,25 +3,17 @@ #include #include #include +#include #include #include class SettingsWindow final { gui::PushButton cancel{"Cancel"}, apply{"Apply", "", false}, savesFolder{"Open", "Save path: {}"}; + gui::PopupWindow canvas{"Settings"}; + nlohmann::json settings; CPUSettings cpuSettings{settings}; AudioSettings audioSettings{settings}; InputSettings inputSettings{settings}; - //std::unique_ptr cancel = std::make_unique("Cancel"); - //std::unique_ptr apply = std::make_unique("Apply"); - //std::unique_ptr iconProv = std::make_unique(); - //std::unique_ptr folderBtn = std::make_unique(iconProv->icon(QFileIconProvider::Folder), ""); - //std::unique_ptr folderLabelPrefix = std::make_unique("Save files' path: "); - //std::unique_ptr folderLabel; - //std::unique_ptr generalLayout = std::make_unique(); - //std::unique_ptr generalLayoutV = std::make_unique(); - //std::unique_ptr tabs = std::make_unique(); - //std::unique_ptr mainLayout = std::make_unique(); - //std::unique_ptr buttonsLayout = std::make_unique(); public: bool render(); SettingsWindow(); @@ -29,7 +21,5 @@ public: [[nodiscard]] float getVolumeR() const { return audioSettings.volumeR.getValue() / 100.f; } std::array keyMap{}; - nlohmann::json settings; gui::TabBar tabs{"SettingsTabs"}; - //std::unique_ptr generalSettings{}; }; diff --git a/src/frontend/main.cpp b/src/frontend/main.cpp index 2e5f6f49..31753596 100644 --- a/src/frontend/main.cpp +++ b/src/frontend/main.cpp @@ -2,7 +2,7 @@ #include int main(int argc, char **argv) { - KaizenGui kaizenGui; + KaizenGui kaizenGui; cflags::cflags flags; std::string romPath; std::string moviePath; diff --git a/src/utils/MemoryHelpers.hpp b/src/utils/MemoryHelpers.hpp index 5204ed99..5a8ad0a6 100644 --- a/src/utils/MemoryHelpers.hpp +++ b/src/utils/MemoryHelpers.hpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include namespace Util { template