From 4c2c9b38cca7e85f560dcd429920b2d1dc806a79 Mon Sep 17 00:00:00 2001 From: ogamespec Date: Sun, 13 Aug 2023 09:53:25 +0300 Subject: [PATCH 1/3] fixed .cpp modules mentioned in comments --- README.md | 2 +- src/ai.cpp | 2 +- src/debug.h | 2 +- src/dvd.h | 2 +- src/exi.cpp | 4 ++-- src/os.cpp | 2 +- src/si.cpp | 4 ++-- src/ui.cpp | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 28d88840..fceadc82 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ make ./pureikyubu pong.dol ``` -Requirements: CMake, pthread, OpenGL, imgui, SDL2. +Requirements: CMake, pthread, OpenGL, imgui, SDL2. If cmake says that some components cannot be built, you should look for solutions on the Internet (`apt get install xxx`) as usual. ## Progress diff --git a/src/ai.cpp b/src/ai.cpp index 890ae524..e3e4d01e 100644 --- a/src/ai.cpp +++ b/src/ai.cpp @@ -442,7 +442,7 @@ namespace Flipper // --------------------------------------------------------------------------- // AI DMA and DVD Audio are played uncompetitively from different streams. - // All work on Sample Rate Conversion and sound mixing for convenience is done in Mixer (AX.cpp). + // All work on Sample Rate Conversion and sound mixing for convenience is done in Mixer (audio.cpp). static uint16_t AdjustVolume(uint16_t sampleValue, int volume) { diff --git a/src/debug.h b/src/debug.h index c147cc4c..3f5fee89 100644 --- a/src/debug.h +++ b/src/debug.h @@ -9,7 +9,7 @@ This component deals with the usual debugging tasks that all developers want to - Code profiling - Performance counters -This component no longer has anything to do with the debug console. The debug console code has been moved to the category of user interfaces and moved to the UI\\Legacy folder. +This component no longer has anything to do with the debug console. The debug console code has been moved to the category of user interfaces and moved to the debugui.cpp. ## Debug report notes diff --git a/src/dvd.h b/src/dvd.h index f5a59cc9..3aa943dd 100644 --- a/src/dvd.h +++ b/src/dvd.h @@ -14,7 +14,7 @@ This component is designed to emulate the DDU controller. DduCore provides a hos That is, DduCore honestly tries to process transactions via DDU Bus, various control signals (BRK, RST), as well as emulation of the DVD Audio stream. -On the host side (/HW/DI.cpp), the DI part is implemented, which is responsible for transmitting a 12-byte DDU command and processing following transactions via the DDU Bus (in the Immediate buffer or Main Memory via DMA). +On the host side (di.cpp), the DI part is implemented, which is responsible for transmitting a 12-byte DDU command and processing following transactions via the DDU Bus (in the Immediate buffer or Main Memory via DMA). If you are going to understand DduCore, just imagine that the DduCore API is just signals from the DDU connector (P9). diff --git a/src/exi.cpp b/src/exi.cpp index 105838b7..fdb7b080 100644 --- a/src/exi.cpp +++ b/src/exi.cpp @@ -16,8 +16,8 @@ RTC : 32-bit counter of seconds, since current millenium AD16 : This is most likely a debugging device called `Barnacle`. - memcard should be in another module (see MC.cpp) - broad band adapter should be in another module (see BBA.cpp) + memcard should be in another module (see memcard.cpp) + broad band adapter should be in another module (see bba.cpp) EXI Device Map of dedicated MX Chip : ------------------------------------- diff --git a/src/os.cpp b/src/os.cpp index fa7f1001..415c1a44 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -889,7 +889,7 @@ void OSSaveContext(void) } // OSLoadContext return is patched as RFI (not usual BLR) -// see Symbols.cpp, SYMSetHighlevel, line 97 +// see sym.cpp, SYMSetHighlevel, line 97 void OSLoadContext(void) { OSContext * c = (OSContext *)(&mi.ram[PARAM(0) & RAMMASK]); diff --git a/src/si.cpp b/src/si.cpp index 1366c6c2..f3d21066 100644 --- a/src/si.cpp +++ b/src/si.cpp @@ -8,11 +8,11 @@ SIControl si; // so all ERROR bits/status in SI regs are not used in emulator. // polling intervals are also not critical. all controllers are polled -// before VI blank (in VI.cpp) +// before VI blank (in vi.cpp) // SI_EXILK is not used (same as EXI clock timing, because of instant EXI transfers) -// SI.cpp polling schematics : +// si.cpp polling schematics : /*/ ----- | OUT | diff --git a/src/ui.cpp b/src/ui.cpp index 3bc40b94..45b48b81 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -2120,7 +2120,7 @@ Interesting to track : namespace UI { - // Global instance of the utility, which is controlled in the UserWindow.cpp module + // Global instance of the utility, which is controlled in the ui.cpp module PerfMetrics* g_perfMetrics = nullptr; @@ -2336,7 +2336,7 @@ static void load_path() } } -/* Called after loading of new file (see Emulator\Loader.cpp). */ +/* Called after loading of new file */ bool AddSelectorPath(const std::wstring& fullPath) { auto path = std::wstring(fullPath); From e545b56e381f5d9a1fffae8896aae7d5a3d6a3b1 Mon Sep 17 00:00:00 2001 From: ogamespec Date: Sun, 13 Aug 2023 10:03:03 +0300 Subject: [PATCH 2/3] Minimize/maximize boxes for the main window --- scripts/pureikyubu.vcxproj | 6 +++--- src/jdi.cpp | 2 +- src/ui.h | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/scripts/pureikyubu.vcxproj b/scripts/pureikyubu.vcxproj index e6568ad1..56d699d1 100644 --- a/scripts/pureikyubu.vcxproj +++ b/scripts/pureikyubu.vcxproj @@ -97,19 +97,19 @@ - + + true true true true - + true true true true - diff --git a/src/jdi.cpp b/src/jdi.cpp index 86ffc1f8..dc1ade13 100644 --- a/src/jdi.cpp +++ b/src/jdi.cpp @@ -320,7 +320,7 @@ namespace JDI return value; } - // Check whether the command is implemented using JDI. Used for compatibility with the old cmd.cpp implementation in the debugger. + // Check whether the command is implemented using JDI. bool JdiHub::CommandExists(const std::string& cmd) { bool exists = false; diff --git a/src/ui.h b/src/ui.h index 36256f87..15aebb15 100644 --- a/src/ui.h +++ b/src/ui.h @@ -348,9 +348,8 @@ void EditFileFilter(HWND hwnd); #ifdef _WINDOWS -/* WS_CLIPCHILDREN and WS_CLIPSIBLINGS are need for OpenGL, but GX plugin */ -/* should take care about proper window style itself !! */ -constexpr int WIN_STYLE = WS_OVERLAPPED | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_SIZEBOX; +/* WS_CLIPCHILDREN and WS_CLIPSIBLINGS are need for OpenGL */ +constexpr int WIN_STYLE = WS_OVERLAPPEDWINDOW | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_SIZEBOX; /* Status bar parts enumerator */ enum class STATUS_ENUM From 2a3ad124ee4611b67710b10547d4ddb106d6b6c6 Mon Sep 17 00:00:00 2001 From: ogamespec Date: Sun, 13 Aug 2023 10:31:32 +0300 Subject: [PATCH 3/3] Simplified uisimple.cpp --- CMakeLists.txt | 1 + scripts/pureikyubu.vcxproj | 2 + scripts/pureikyubu.vcxproj.filters | 6 + src/pch.h | 1 + src/ui.cpp | 291 ---------------------------- src/ui.h | 83 -------- src/uijdi.cpp | 298 +++++++++++++++++++++++++++++ src/uijdi.h | 76 ++++++++ src/uisimple.cpp | 280 ++------------------------- 9 files changed, 396 insertions(+), 642 deletions(-) create mode 100644 src/uijdi.cpp create mode 100644 src/uijdi.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 742caa0b..8c6a8b1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ add_executable (pureikyubu src/sym.cpp src/tev.cpp src/tx.cpp + src/uijdi.cpp src/uisimple.cpp src/utils.cpp src/vi.cpp diff --git a/scripts/pureikyubu.vcxproj b/scripts/pureikyubu.vcxproj index 56d699d1..a1ee837c 100644 --- a/scripts/pureikyubu.vcxproj +++ b/scripts/pureikyubu.vcxproj @@ -80,6 +80,7 @@ + @@ -159,6 +160,7 @@ + true true diff --git a/scripts/pureikyubu.vcxproj.filters b/scripts/pureikyubu.vcxproj.filters index 63ad50e1..c42db31a 100644 --- a/scripts/pureikyubu.vcxproj.filters +++ b/scripts/pureikyubu.vcxproj.filters @@ -205,6 +205,9 @@ Header Files + + Header Files + @@ -390,5 +393,8 @@ imgui + + Source Files + \ No newline at end of file diff --git a/src/pch.h b/src/pch.h index eb20c07e..562b4862 100644 --- a/src/pch.h +++ b/src/pch.h @@ -113,6 +113,7 @@ namespace Flipper #include "config.h" #include "main.h" +#include "uijdi.h" #include "ui.h" #define _TB(s) diff --git a/src/ui.cpp b/src/ui.cpp index 45b48b81..c4d5966e 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -553,297 +553,6 @@ namespace UI } -// JDI Communication. - -namespace UI -{ - JdiClient* Jdi; - - JdiClient::JdiClient() - { - } - - JdiClient::~JdiClient() - { - } - - // Generic - - std::string JdiClient::GetVersion() - { - char str[0x100] = { 0 }; - - bool res = CallJdiReturnString("GetVersion", str, sizeof(str) - 1); - if (!res) - { - throw "GetVersion failed!"; - } - - return std::string(str); - } - - void JdiClient::ExecuteCommand(const std::string& cmdline) - { - bool res = CallJdiNoReturn(cmdline.c_str()); - if (!res) - { - throw "ExecuteCommand failed!"; - } - } - - // Methods for controlling an optical drive - - bool JdiClient::DvdMount(const std::string& path) - { - char cmd[0x1000] = { 0 }; - - sprintf_s(cmd, sizeof(cmd), "MountIso \"%s\"", path.c_str()); - - bool mountResult = false; - - bool res = CallJdiReturnBool(cmd, &mountResult); - if (!res) - { - throw "MountIso failed!"; - } - - return mountResult; - } - - bool JdiClient::DvdMountSDK(const std::string& path) - { - char cmd[0x1000] = { 0 }; - - sprintf_s(cmd, sizeof(cmd), "MountSDK \"%s\"", path.c_str()); - - bool mountResult = false; - - bool res = CallJdiReturnBool(cmd, &mountResult); - if (!res) - { - throw "MountIso failed!"; - } - - return mountResult; - } - - void JdiClient::DvdUnmount() - { - ExecuteCommand("UnmountDvd"); - } - - void JdiClient::DvdSeek(int offset) - { - CallJdi(("DvdSeek " + std::to_string(offset)).c_str()); - } - - void JdiClient::DvdRead(std::vector& data) - { - Json::Value* dataJson = CallJdi(("DvdRead " + std::to_string(data.size())).c_str()); - - int i = 0; - - for (auto it = dataJson->children.begin(); it != dataJson->children.end(); ++it) - { - data[i++] = (*it)->value.AsUint8; - } - - delete dataJson; - } - - uint32_t JdiClient::DvdOpenFile(const std::string& filename) - { - Json::Value* offsetJson = CallJdi(("DvdOpenFile \"" + filename + "\"").c_str()); - - uint32_t offsetValue = (uint32_t)offsetJson->value.AsInt; - - delete offsetJson; - - return offsetValue; - } - - bool JdiClient::DvdCoverOpened() - { - Json::Value* dvdInfo = CallJdi("DvdInfo 1"); // silent mode - - bool lidStatusOpened = false; - - for (auto it = dvdInfo->children.begin(); it != dvdInfo->children.end(); ++it) - { - if ((*it)->type == Json::ValueType::Bool) - { - lidStatusOpened = (*it)->value.AsBool; - break; - } - } - - delete dvdInfo; - - return lidStatusOpened; - } - - void JdiClient::DvdOpenCover() - { - ExecuteCommand("OpenLid"); - } - - void JdiClient::DvdCloseCover() - { - ExecuteCommand("CloseLid"); - } - - std::string JdiClient::DvdRegionById(char* DiskId) - { - char regionName[0x20] = { 0, }; - - char cmd[0x20]; - sprintf_s(cmd, sizeof(cmd), "DvdRegionById %c%c%c%c", DiskId[0], DiskId[1], DiskId[2], DiskId[3]); - - CallJdiReturnString(cmd, regionName, sizeof(regionName) - 1); - - return regionName; - } - - /// - /// Get DVD mount status. The DvdInfo command is used - /// - /// The path to the image when mounting a file or the path to the folder when mounting as a DolphinSDK virtual disk. - /// Mount method (ISO / virtual disk as folder) - /// Disk mounted or not - bool JdiClient::DvdIsMounted(std::string& path, bool& mountedIso) - { - Json::Value* value = CallJdi("DvdInfo"); - - for (auto it = value->children.begin(); it != value->children.end(); ++it) - { - Json::Value* entry = *it; - - switch (entry->type) - { - case Json::ValueType::String: - path = Util::WstringToString(entry->value.AsString); - break; - } - } - - bool mounted = !path.empty(); - mountedIso = Util::FileExists(path); - - delete value; - - return mounted; - } - - // Configuration access - - std::string JdiClient::GetConfigString(const std::string& var, const std::string& path) - { - Json::Value* value = CallJdi(("GetConfigString " + path + " " + var).c_str()); - std::string res = Util::WstringToString(value->children.front()->value.AsString); - delete value; - return res; - } - - void JdiClient::SetConfigString(const std::string& var, const std::string& newVal, const std::string& path) - { - char cmd[0x200] = { 0, }; - sprintf_s(cmd, sizeof(cmd), "SetConfigString %s %s \"%s\"", path.c_str(), var.c_str(), newVal.c_str()); - CallJdi(cmd); - } - - int JdiClient::GetConfigInt(const std::string& var, const std::string& path) - { - Json::Value* value = CallJdi(("GetConfigInt " + path + " " + var).c_str()); - int res = (int)value->children.front()->value.AsInt; - delete value; - return res; - } - - void JdiClient::SetConfigInt(const std::string& var, int newVal, const std::string& path) - { - CallJdi(("SetConfigInt " + path + " " + var + " " + std::to_string(newVal)).c_str()); - } - - bool JdiClient::GetConfigBool(const std::string& var, const std::string& path) - { - Json::Value* value = CallJdi(("GetConfigBool " + path + " " + var).c_str()); - bool res = value->children.front()->value.AsBool; - delete value; - return res; - } - - void JdiClient::SetConfigBool(const std::string& var, bool newVal, const std::string& path) - { - CallJdi(("SetConfigBool " + path + " " + var + " " + (newVal ? "true" : "false")).c_str()); - } - - // Emulator controls - - void JdiClient::LoadFile(const std::string& filename) - { - char cmd[0x1000] = { 0 }; - - sprintf_s(cmd, sizeof(cmd), "load \"%s\"", filename.c_str()); - - bool res = CallJdiNoReturn(cmd); - if (!res) - { - throw "load failed!"; - } - } - - void JdiClient::Unload() - { - ExecuteCommand("unload"); - } - - void JdiClient::Run() - { - ExecuteCommand("run"); - } - - void JdiClient::Stop() - { - ExecuteCommand("stop"); - } - - void JdiClient::Reset() - { - ExecuteCommand("reset"); - } - - // Performance Counters, SystemTime - - int64_t JdiClient::GetPerformanceCounter(int counter) - { - Json::Value* value = CallJdi(("GetPerformanceCounter " + std::to_string(counter)).c_str()); - int64_t res = value->value.AsInt; - delete value; - return res; - } - - void JdiClient::ResetPerformanceCounter(int counter) - { - ExecuteCommand(("ResetPerformanceCounter " + std::to_string(counter)).c_str()); - } - - std::string JdiClient::GetSystemTime() - { - uint64_t tbr = 0; - Json::Value* value = CallJdi("OSDateTime"); - std::string res = Util::WstringToString(value->children.front()->value.AsString); - delete value; - return res; - } - - bool JdiClient::JitcEnabled() - { - return false; - } - -} - - // Basic application output diff --git a/src/ui.h b/src/ui.h index 15aebb15..b017dcbb 100644 --- a/src/ui.h +++ b/src/ui.h @@ -87,89 +87,6 @@ namespace UI -// This module is used to communicate with the JDI host. The host can be on the network, in a pluggable DLL or statically linked. - -// Now there is a fundamental limitation - all strings are Ansi (std::string). Historically, this is due to the fact that all commands were typed in the debug console. In time, we will move to Unicode (std::wstring). - -namespace JDI -{ - typedef Json::Value* (*CmdDelegate)(std::vector& args); - typedef void (*JdiReflector)(); -} - -namespace UI -{ - class JdiClient - { - public: - - JdiClient(); - ~JdiClient(); - - // Generic - - std::string GetVersion(); - void ExecuteCommand(const std::string& cmdline); - - // Methods for controlling an optical drive - - bool DvdMount(const std::string& path); - bool DvdMountSDK(const std::string& path); - void DvdUnmount(); - - void DvdSeek(int offset); - void DvdRead(std::vector& data); - - uint32_t DvdOpenFile(const std::string& filename); - - bool DvdCoverOpened(); - void DvdOpenCover(); - void DvdCloseCover(); - - std::string DvdRegionById(char* DiskId); - - bool DvdIsMounted(std::string& path, bool& mountedIso); - - // Configuration access - - std::string GetConfigString(const std::string& var, const std::string& path); - void SetConfigString(const std::string& var, const std::string& newVal, const std::string& path); - int GetConfigInt(const std::string& var, const std::string& path); - void SetConfigInt(const std::string& var, int newVal, const std::string& path); - bool GetConfigBool(const std::string& var, const std::string& path); - void SetConfigBool(const std::string& var, bool newVal, const std::string& path); - - // Emulator controls - - void LoadFile(const std::string& filename); - void Unload(); - void Run(); - void Stop(); - void Reset(); - - // Debug interface - - std::string DebugChannelToString(int chan); - void QueryDebugMessages(std::list>& queue); - int64_t GetResetGekkoMipsCounter(); - - // Performance Counters, SystemTime - - int64_t GetPerformanceCounter(int counter); - void ResetPerformanceCounter(int counter); - std::string GetSystemTime(); - - // Misc - - bool JitcEnabled(); - - }; - - extern JdiClient* Jdi; -} - - - // version info #define APPNAME L"プレイキューブ" #define APPDESC L"Nintendo GameCube Emulator" diff --git a/src/uijdi.cpp b/src/uijdi.cpp new file mode 100644 index 00000000..8b62e7b4 --- /dev/null +++ b/src/uijdi.cpp @@ -0,0 +1,298 @@ +#include "pch.h" + +// JDI Communication. + +namespace UI +{ + JdiClient* Jdi; + + JdiClient::JdiClient() + { + } + + JdiClient::~JdiClient() + { + } + + // Generic + + std::string JdiClient::GetVersion() + { + char str[0x100] = { 0 }; + + bool res = CallJdiReturnString("GetVersion", str, sizeof(str) - 1); + if (!res) + { + throw "GetVersion failed!"; + } + + return std::string(str); + } + + void JdiClient::ExecuteCommand(const std::string& cmdline) + { + bool res = CallJdiNoReturn(cmdline.c_str()); + if (!res) + { + throw "ExecuteCommand failed!"; + } + } + + // Methods for controlling an optical drive + + bool JdiClient::DvdMount(const std::string& path) + { + char cmd[0x1000] = { 0 }; + + sprintf(cmd, "MountIso \"%s\"", path.c_str()); + + bool mountResult = false; + + bool res = CallJdiReturnBool(cmd, &mountResult); + if (!res) + { + throw "MountIso failed!"; + } + + return mountResult; + } + + bool JdiClient::DvdMountSDK(const std::string& path) + { + char cmd[0x1000] = { 0 }; + + sprintf(cmd, "MountSDK \"%s\"", path.c_str()); + + bool mountResult = false; + + bool res = CallJdiReturnBool(cmd, &mountResult); + if (!res) + { + throw "MountIso failed!"; + } + + return mountResult; + } + + void JdiClient::DvdUnmount() + { + ExecuteCommand("UnmountDvd"); + } + + void JdiClient::DvdSeek(int offset) + { + CallJdi(("DvdSeek " + std::to_string(offset)).c_str()); + } + + void JdiClient::DvdRead(std::vector& data) + { + Json::Value* dataJson = CallJdi(("DvdRead " + std::to_string(data.size())).c_str()); + + int i = 0; + + for (auto it = dataJson->children.begin(); it != dataJson->children.end(); ++it) + { + data[i++] = (*it)->value.AsUint8; + } + + delete dataJson; + } + + uint32_t JdiClient::DvdOpenFile(const std::string& filename) + { + Json::Value* offsetJson = CallJdi(("DvdOpenFile \"" + filename + "\"").c_str()); + + uint32_t offsetValue = (uint32_t)offsetJson->value.AsInt; + + delete offsetJson; + + return offsetValue; + } + + bool JdiClient::DvdCoverOpened() + { + Json::Value* dvdInfo = CallJdi("DvdInfo 1"); // silent mode + + bool lidStatusOpened = false; + + for (auto it = dvdInfo->children.begin(); it != dvdInfo->children.end(); ++it) + { + if ((*it)->type == Json::ValueType::Bool) + { + lidStatusOpened = (*it)->value.AsBool; + break; + } + } + + delete dvdInfo; + + return lidStatusOpened; + } + + void JdiClient::DvdOpenCover() + { + ExecuteCommand("OpenLid"); + } + + void JdiClient::DvdCloseCover() + { + ExecuteCommand("CloseLid"); + } + + std::string JdiClient::DvdRegionById(char* DiskId) + { + char regionName[0x20] = { 0, }; + + char cmd[0x20]; + sprintf(cmd, "DvdRegionById %c%c%c%c", DiskId[0], DiskId[1], DiskId[2], DiskId[3]); + + CallJdiReturnString(cmd, regionName, sizeof(regionName) - 1); + + return regionName; + } + + /// + /// Get DVD mount status. The DvdInfo command is used + /// + /// The path to the image when mounting a file or the path to the folder when mounting as a DolphinSDK virtual disk. + /// Mount method (ISO / virtual disk as folder) + /// Disk mounted or not + bool JdiClient::DvdIsMounted(std::string& path, bool& mountedIso) + { + Json::Value* value = CallJdi("DvdInfo"); + + for (auto it = value->children.begin(); it != value->children.end(); ++it) + { + Json::Value* entry = *it; + + switch (entry->type) + { + case Json::ValueType::String: + path = Util::WstringToString(entry->value.AsString); + break; + } + } + + bool mounted = !path.empty(); + mountedIso = Util::FileExists(path); + + delete value; + + return mounted; + } + + // Configuration access + + std::string JdiClient::GetConfigString(const std::string& var, const std::string& path) + { + Json::Value* value = CallJdi(("GetConfigString " + path + " " + var).c_str()); + std::string res = Util::WstringToString(value->children.front()->value.AsString); + delete value; + return res; + } + + void JdiClient::SetConfigString(const std::string& var, const std::string& newVal, const std::string& path) + { + char cmd[0x200] = { 0, }; + sprintf(cmd, "SetConfigString %s %s \"%s\"", path.c_str(), var.c_str(), newVal.c_str()); + CallJdi(cmd); + } + + int JdiClient::GetConfigInt(const std::string& var, const std::string& path) + { + Json::Value* value = CallJdi(("GetConfigInt " + path + " " + var).c_str()); + int res = (int)value->children.front()->value.AsInt; + delete value; + return res; + } + + void JdiClient::SetConfigInt(const std::string& var, int newVal, const std::string& path) + { + CallJdi(("SetConfigInt " + path + " " + var + " " + std::to_string(newVal)).c_str()); + } + + bool JdiClient::GetConfigBool(const std::string& var, const std::string& path) + { + Json::Value* value = CallJdi(("GetConfigBool " + path + " " + var).c_str()); + bool res = value->children.front()->value.AsBool; + delete value; + return res; + } + + void JdiClient::SetConfigBool(const std::string& var, bool newVal, const std::string& path) + { + CallJdi(("SetConfigBool " + path + " " + var + " " + (newVal ? "true" : "false")).c_str()); + } + + // Emulator controls + + void JdiClient::LoadFile(const std::string& filename) + { + char cmd[0x1000] = { 0 }; + + sprintf(cmd, "load \"%s\"", filename.c_str()); + + bool res = CallJdiNoReturn(cmd); + if (!res) + { + throw "load failed!"; + } + } + + void JdiClient::Unload() + { + ExecuteCommand("unload"); + } + + void JdiClient::Run() + { + ExecuteCommand("run"); + } + + void JdiClient::Stop() + { + ExecuteCommand("stop"); + } + + void JdiClient::Reset() + { + ExecuteCommand("reset"); + } + + // Performance Counters, SystemTime + + int64_t JdiClient::GetPerformanceCounter(int counter) + { + Json::Value* value = CallJdi(("GetPerformanceCounter " + std::to_string(counter)).c_str()); + int64_t res = value->value.AsInt; + delete value; + return res; + } + + void JdiClient::ResetPerformanceCounter(int counter) + { + ExecuteCommand(("ResetPerformanceCounter " + std::to_string(counter)).c_str()); + } + + std::string JdiClient::GetSystemTime() + { + uint64_t tbr = 0; + Json::Value* value = CallJdi("OSDateTime"); + std::string res = Util::WstringToString(value->children.front()->value.AsString); + delete value; + return res; + } + + bool JdiClient::JitcEnabled() + { + return false; + } + + int64_t JdiClient::GetResetGekkoMipsCounter() + { + int gekkoMips; + CallJdiReturnInt("GetPerformanceCounter 0", &gekkoMips); + CallJdiNoReturn("ResetPerformanceCounter 0"); + return gekkoMips; + } +} diff --git a/src/uijdi.h b/src/uijdi.h new file mode 100644 index 00000000..3225b9e1 --- /dev/null +++ b/src/uijdi.h @@ -0,0 +1,76 @@ +#pragma once + +// This module is used to communicate with the JDI host. The host can be on the network, in a pluggable DLL or statically linked. + +// Now there is a fundamental limitation - all strings are Ansi (std::string). Historically, this is due to the fact that all commands were typed in the debug console. In time, we will move to Unicode (std::wstring). + +namespace UI +{ + class JdiClient + { + public: + + JdiClient(); + ~JdiClient(); + + // Generic + + std::string GetVersion(); + void ExecuteCommand(const std::string& cmdline); + + // Methods for controlling an optical drive + + bool DvdMount(const std::string& path); + bool DvdMountSDK(const std::string& path); + void DvdUnmount(); + + void DvdSeek(int offset); + void DvdRead(std::vector& data); + + uint32_t DvdOpenFile(const std::string& filename); + + bool DvdCoverOpened(); + void DvdOpenCover(); + void DvdCloseCover(); + + std::string DvdRegionById(char* DiskId); + + bool DvdIsMounted(std::string& path, bool& mountedIso); + + // Configuration access + + std::string GetConfigString(const std::string& var, const std::string& path); + void SetConfigString(const std::string& var, const std::string& newVal, const std::string& path); + int GetConfigInt(const std::string& var, const std::string& path); + void SetConfigInt(const std::string& var, int newVal, const std::string& path); + bool GetConfigBool(const std::string& var, const std::string& path); + void SetConfigBool(const std::string& var, bool newVal, const std::string& path); + + // Emulator controls + + void LoadFile(const std::string& filename); + void Unload(); + void Run(); + void Stop(); + void Reset(); + + // Debug interface + + std::string DebugChannelToString(int chan); + void QueryDebugMessages(std::list>& queue); + int64_t GetResetGekkoMipsCounter(); + + // Performance Counters, SystemTime + + int64_t GetPerformanceCounter(int counter); + void ResetPerformanceCounter(int counter); + std::string GetSystemTime(); + + // Misc + + bool JitcEnabled(); + + }; + + extern JdiClient* Jdi; +} diff --git a/src/uisimple.cpp b/src/uisimple.cpp index cec7707f..3484f213 100644 --- a/src/uisimple.cpp +++ b/src/uisimple.cpp @@ -1,268 +1,5 @@ #include "pch.h" -// JDI Communication. - -namespace UI -{ - JdiClient SimpleJdi; // Singletone. - - JdiClient::JdiClient() - { - EMUCtor(); - - } - - JdiClient::~JdiClient() - { - EMUDtor(); - } - - // Generic - - std::string JdiClient::GetVersion() - { - char str[0x100] = { 0 }; - - bool res = CallJdiReturnString("GetVersion", str, sizeof(str) - 1); - if (!res) - { - throw "GetVersion failed!"; - } - - return std::string(str); - } - - void JdiClient::ExecuteCommand(const std::string& cmdline) - { - bool res = CallJdiNoReturn(cmdline.c_str()); - if (!res) - { - throw "ExecuteCommand failed!"; - } - } - - // Methods for controlling an optical drive - - bool JdiClient::DvdMount(const std::string& path) - { - char cmd[0x1000] = { 0 }; - - sprintf(cmd, "MountIso \"%s\"", path.c_str()); - - bool mountResult = false; - - bool res = CallJdiReturnBool(cmd, &mountResult); - if (!res) - { - throw "MountIso failed!"; - } - - return mountResult; - } - - void JdiClient::DvdUnmount() - { - ExecuteCommand("UnmountDvd"); - } - - void JdiClient::DvdSeek(int offset) - { - CallJdi(("DvdSeek " + std::to_string(offset)).c_str()); - } - - void JdiClient::DvdRead(std::vector& data) - { - Json::Value* dataJson = CallJdi(("DvdRead " + std::to_string(data.size())).c_str()); - - int i = 0; - - for (auto it = dataJson->children.begin(); it != dataJson->children.end(); ++it) - { - data[i++] = (*it)->value.AsUint8; - } - - delete dataJson; - } - - uint32_t JdiClient::DvdOpenFile(const std::string& filename) - { - Json::Value* offsetJson = CallJdi(("DvdOpenFile \"" + filename + "\"").c_str()); - - uint32_t offsetValue = (uint32_t)offsetJson->value.AsInt; - - delete offsetJson; - - return offsetValue; - } - - bool JdiClient::DvdCoverOpened() - { - Json::Value* dvdInfo = CallJdi("DvdInfo"); - - bool lidStatusOpened = false; - - for (auto it = dvdInfo->children.begin(); it != dvdInfo->children.end(); ++it) - { - if ((*it)->type == Json::ValueType::Bool) - { - lidStatusOpened = (*it)->value.AsBool; - break; - } - } - - delete dvdInfo; - - return lidStatusOpened; - } - - void JdiClient::DvdOpenCover() - { - ExecuteCommand("OpenLid"); - } - - void JdiClient::DvdCloseCover() - { - ExecuteCommand("CloseLid"); - } - - // Configuration access - - std::string JdiClient::GetConfigString(const std::string& var, const std::string& path) - { - Json::Value* value = CallJdi(("GetConfigString " + path + " " + var).c_str()); - std::string res = Util::WstringToString(value->children.front()->value.AsString); - delete value; - return res; - } - - void JdiClient::SetConfigString(const std::string& var, const std::string& newVal, const std::string& path) - { - char cmd[0x200] = { 0, }; - sprintf(cmd, "SetConfigString %s %s \"%s\"", path.c_str(), var.c_str(), newVal.c_str()); - CallJdi(cmd); - } - - int JdiClient::GetConfigInt(const std::string& var, const std::string& path) - { - Json::Value* value = CallJdi(("GetConfigInt " + path + " " + var).c_str()); - int res = (int)value->children.front()->value.AsInt; - delete value; - return res; - } - - void JdiClient::SetConfigInt(const std::string& var, int newVal, const std::string& path) - { - CallJdi(("SetConfigInt " + path + " " + var + " " + std::to_string(newVal)).c_str()); - } - - bool JdiClient::GetConfigBool(const std::string& var, const std::string& path) - { - Json::Value* value = CallJdi(("GetConfigBool " + path + " " + var).c_str()); - bool res = value->children.front()->value.AsBool; - delete value; - return res; - } - - void JdiClient::SetConfigBool(const std::string& var, bool newVal, const std::string& path) - { - CallJdi(("SetConfigBool " + path + " " + var + " " + (newVal ? "true" : "false")).c_str()); - } - - // Emulator controls - - void JdiClient::LoadFile(const std::string& filename) - { - char cmd[0x1000] = { 0 }; - - sprintf(cmd, "load \"%s\"", filename.c_str()); - - bool res = CallJdiNoReturn(cmd); - if (!res) - { - throw "load failed!"; - } - } - - void JdiClient::Unload() - { - ExecuteCommand("unload"); - } - - void JdiClient::Run() - { - ExecuteCommand("run"); - } - - void JdiClient::Stop() - { - ExecuteCommand("stop"); - } - - void JdiClient::Reset() - { - ExecuteCommand("reset"); - } - - std::string JdiClient::DebugChannelToString(int chan) - { - char str[0x100] = { 0 }; - char cmd[0x30] = { 0, }; - - sprintf(cmd, "GetChannelName %i", chan); - - bool res = CallJdiReturnString(cmd, str, sizeof(str) - 1); - if (!res) - { - throw "GetChannelName failed!"; - } - - return std::string(str); - } - - void JdiClient::QueryDebugMessages(std::list>& queue) - { - Json::Value* value = CallJdi("qd"); - if (value == nullptr) - { - throw "QueryDebugMessages failed!"; - } - - if (value->type != Json::ValueType::Array) - { - throw "QueryDebugMessages invalid format!"; - } - - auto it = value->children.begin(); - - while (it != value->children.end()) - { - Json::Value* channel = *it; - ++it; - - Json::Value* message = *it; - ++it; - - if (channel->type != Json::ValueType::Int || message->type != Json::ValueType::String) - { - throw "QueryDebugMessages invalid format of array key-values!"; - } - - queue.push_back(std::pair((int)channel->value.AsInt, Util::WstringToString(message->value.AsString))); - } - - delete value; - } - - int64_t JdiClient::GetResetGekkoMipsCounter() - { - int gekkoMips; - CallJdiReturnInt("GetPerformanceCounter 0", &gekkoMips); - CallJdiNoReturn("ResetPerformanceCounter 0"); - return gekkoMips; - } - -} - Json::Value* CmdUIError(std::vector& args) { std::string text = ""; @@ -303,7 +40,7 @@ Json::Value* CmdUIReport(std::vector& args) Json::Value* CmdGetRenderTarget(std::vector& args) { - // Playground doesn't return any RenderTarget. + // SimpleUI doesn't return any RenderTarget. Json::Value* value = new Json::Value(); value->type = Json::ValueType::Int; @@ -328,20 +65,25 @@ int main(int argc, char** argv) return -1; } + EMUCtor(); + + // Create an interface for communicating with the emulator core + UI::Jdi = new UI::JdiClient; + // Add UI methods JdiAddNode(UI_JDI_JSON, UIReflector); // Say hello - printf("pureikyubu, Nintendo GameCube emulator version %s\n", UI::SimpleJdi.GetVersion().c_str()); + printf("pureikyubu, Nintendo GameCube emulator version %s\n", UI::Jdi->GetVersion().c_str()); // Load file and run printf("Press any key to stop emulation...\n\n"); - UI::SimpleJdi.LoadFile(argv[1]); - UI::SimpleJdi.Run(); + UI::Jdi->LoadFile(argv[1]); + UI::Jdi->Run(); Debug::debugger = new Debug::Debugger(); // Wait key press.. @@ -356,9 +98,11 @@ int main(int argc, char** argv) // Unload - UI::SimpleJdi.Unload(); + UI::Jdi->Unload(); JdiRemoveNode(UI_JDI_JSON); + delete UI::Jdi; delete Debug::debugger; + EMUDtor(); printf("\nThank you for flying pureikyubu airlines!\n"); return 0;