diff --git a/src/ftdi/abstract-ftd2xx-win32.cc b/src/ftdi/abstract-ftd2xx-win32.cc new file mode 100644 index 000000000..2a6d0f6cc --- /dev/null +++ b/src/ftdi/abstract-ftd2xx-win32.cc @@ -0,0 +1,256 @@ +/***s************************************************************************ + * Copyright (C) 2019 PCSX-Redux authors * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN + +#include +#include + +#include +#include +#include +#include +#include + +#include "ftd2xx.h" +#include "ftdi/abstract.h" + +namespace PCSX { +namespace FTDI { +namespace Private { +class DeviceData { + public: + FT_HANDLE m_handle = nullptr; + HANDLE m_event = nullptr; + enum { + STATE_CLOSED, + STATE_OPEN_PENDING, + STATE_OPENED, + STATE_CLOSE_PENDING, + } m_state = STATE_CLOSED; +}; +} // namespace Private +} // namespace FTDI +} // namespace PCSX + +static PCSX::FTDI::Device* s_devices = nullptr; +static unsigned s_numDevs = 0; +static HANDLE s_thread; +static std::atomic_bool s_exitThread; +static bool s_threadRunning = false; +static HANDLE s_kickEvent = nullptr; +static std::shared_mutex s_listLock; +static unsigned s_numOpened = 0; + +static PCSX::GUI* s_gui = nullptr; + +static void asyncCallbackTrampoline(uv_async_t* handle) { + PCSX::FTDI::Device* device = (PCSX::FTDI::Device*)handle->data; + device->asyncCallback(); +} + +static void asyncCloseCallbackTrampoline(uv_handle_t* handle) { + PCSX::FTDI::Device* device = reinterpret_cast(handle->data); + device->asyncCloseCallback(); +} + +PCSX::FTDI::Device::Device() { + uv_async_init(s_gui->loop(), &m_async, asyncCallbackTrampoline); + m_async.data = this; +} + +PCSX::FTDI::Device::~Device() { + assert(m_private->m_state == Private::DeviceData::STATE_CLOSED); + assert(!m_private->m_event); + assert(!m_private->m_handle); + delete m_private; + uv_loop_t* loop = m_async.loop; + uv_close(reinterpret_cast(&m_async), asyncCloseCallbackTrampoline); + while (!m_asyncClosed) uv_run(loop, UV_RUN_ONCE); +} + +void PCSX::FTDI::Device::open() { + std::unique_lock guard(s_listLock); + assert(m_private->m_state == Private::DeviceData::STATE_CLOSED); + m_private->m_state = Private::DeviceData::STATE_OPEN_PENDING; + SetEvent(s_kickEvent); +} +void PCSX::FTDI::Device::close() { + std::unique_lock guard(s_listLock); + assert(m_private->m_state == Private::DeviceData::STATE_OPENED); + m_private->m_state = Private::DeviceData::STATE_CLOSE_PENDING; + SetEvent(s_kickEvent); +} +bool PCSX::FTDI::Device::isOpened() const { return m_private->m_state == Private::DeviceData::STATE_OPENED; } +bool PCSX::FTDI::Device::isBusy() const { + return m_private->m_state == Private::DeviceData::STATE_CLOSE_PENDING || + m_private->m_state == Private::DeviceData::STATE_OPEN_PENDING; +} + +void PCSX::FTDI::Devices::scan() { + FT_STATUS status; + DWORD numDevs = 0; + + std::unique_lock guard(s_listLock); + // we can't modify the list if there's any device that's still opened + if (s_numDevs != 0) return; + + delete[] s_devices; + s_numDevs = 0; + status = FT_CreateDeviceInfoList(&numDevs); + + if (status != FT_OK || numDevs == 0) return; + s_numDevs = numDevs; + + FT_DEVICE_LIST_INFO_NODE* nodes = new FT_DEVICE_LIST_INFO_NODE[numDevs]; + + status = FT_GetDeviceInfoList(nodes, &numDevs); + + if (status == FT_OK && numDevs != 0) { + s_devices = new Device[numDevs]; + for (DWORD i = 0; i < numDevs; i++) { + const FT_DEVICE_LIST_INFO_NODE* n = nodes + i; + s_devices[i].m_locked = n->Flags & FT_FLAGS_OPENED; + s_devices[i].m_highSpeed = n->Flags & FT_FLAGS_HISPEED; + s_devices[i].m_vendorID = (n->ID >> 16) & 0xffff; + s_devices[i].m_deviceID = n->ID & 0xffff; + s_devices[i].m_type = n->Type; + s_devices[i].m_serial = n->SerialNumber; + s_devices[i].m_description = n->Description; + s_devices[i].m_private = new Private::DeviceData(); + } + } + + delete[] nodes; +} + +void PCSX::FTDI::Devices::iterate(std::function iter) { + std::shared_lock guard(s_listLock); + for (unsigned i = 0; i < s_numDevs; i++) { + if (!iter(s_devices[i])) break; + } +} + +void PCSX::FTDI::Devices::threadProc() { + SetThreadDescription(GetCurrentThread(), L"abstract ftd2xx thread"); + while (!s_exitThread) { + std::vector objects; + std::vector devices; + objects.push_back(s_kickEvent); + devices.push_back(nullptr); + { + std::shared_lock guard(s_listLock); + + for (unsigned i = 0; i < s_numDevs; i++) { + auto& device = s_devices[i]; + switch (device.m_private->m_state) { + case Private::DeviceData::STATE_OPEN_PENDING: + s_numOpened++; + FT_OpenEx(const_cast(device.m_serial.c_str()), FT_OPEN_BY_SERIAL_NUMBER, + &device.m_private->m_handle); + device.m_private->m_event = CreateEvent(nullptr, FALSE, FALSE, L"Event for FTDI device"); + FT_SetEventNotification(device.m_private->m_handle, + FT_EVENT_RXCHAR | FT_EVENT_MODEM_STATUS | FT_EVENT_LINE_STATUS, + device.m_private->m_event); + device.m_private->m_state = Private::DeviceData::STATE_OPENED; + case Private::DeviceData::STATE_OPENED: + objects.push_back(device.m_private->m_event); + devices.push_back(&device); + break; + case Private::DeviceData::STATE_CLOSE_PENDING: + s_numOpened--; + FT_Close(device.m_private->m_handle); + CloseHandle(device.m_private->m_event); + device.m_private->m_handle = nullptr; + device.m_private->m_event = nullptr; + device.m_private->m_state = Private::DeviceData::STATE_CLOSED; + break; + } + } + } + DWORD idx; + do { + assert(objects.size() <= MAXIMUM_WAIT_OBJECTS); + idx = WaitForMultipleObjects(objects.size(), objects.data(), FALSE, INFINITE); + Device* device = devices[idx - WAIT_OBJECT_0]; + if (!device) continue; + DWORD events; + FT_GetEventStatus(device->m_private->m_handle, &events); + printf("%i", events); + } while (idx != WAIT_OBJECT_0); + } + CloseHandle(s_kickEvent); + s_kickEvent = nullptr; + s_exitThread = false; + s_threadRunning = false; +} + +static DWORD WINAPI threadProcTrampoline(LPVOID parameter) { + PCSX::FTDI::Devices::threadProc(); + return 0; +} + +void PCSX::FTDI::Devices::startThread() { + assert(!s_threadRunning); + s_kickEvent = CreateEvent(nullptr, FALSE, FALSE, L"abstract ftd2xx kick event"); + s_threadRunning = true; + s_thread = CreateThread(nullptr, 0, threadProcTrampoline, nullptr, 0, nullptr); +} + +void PCSX::FTDI::Devices::stopThread() { + assert(s_threadRunning); + s_exitThread = true; + SetEvent(s_kickEvent); + WaitForSingleObject(s_thread, INFINITE); + s_thread = nullptr; + assert(!s_threadRunning); +} + +bool PCSX::FTDI::Devices::isThreadRunning() { return s_threadRunning; } + +void PCSX::FTDI::Devices::shutdown() { + if (!isThreadRunning()) startThread(); + { + bool run = true; + while (run) { + run = false; + std::unique_lock guard(s_listLock); + for (unsigned i = 0; i < s_numDevs; i++) { + auto& device = s_devices[i]; + switch (device.m_private->m_state) { + case Private::DeviceData::STATE_OPENED: + device.close(); + case Private::DeviceData::STATE_CLOSE_PENDING: + case Private::DeviceData::STATE_OPEN_PENDING: + run = true; + break; + } + } + } + } + stopThread(); + delete[] s_devices; + s_numDevs = 0; +} + +void PCSX::FTDI::Devices::setGUI(GUI* gui) { s_gui = gui; } + +#endif diff --git a/src/ftdi/abstract-libusb-posix.cc b/src/ftdi/abstract-libusb-posix.cc new file mode 100644 index 000000000..c041a5e39 --- /dev/null +++ b/src/ftdi/abstract-libusb-posix.cc @@ -0,0 +1,30 @@ +/*************************************************************************** + * Copyright (C) 2019 PCSX-Redux authors * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#ifndef _WIN32 + +#include "ftdi/abstract.h" + +static std::vector s_devices; + +void PCSX::FTDI::Devices::scan() { abort(); } + +const std::vector& PCSX::FTDI::Devices::get() { return s_devices; } + +#endif diff --git a/src/ftdi/abstract.h b/src/ftdi/abstract.h new file mode 100644 index 000000000..6e23e323e --- /dev/null +++ b/src/ftdi/abstract.h @@ -0,0 +1,115 @@ +/*************************************************************************** + * Copyright (C) 2020 PCSX-Redux authors * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#pragma once + +#include + +#include +#include +#include + +#include "gui/gui.h" +#include "support/slice.h" + +namespace PCSX { + +namespace FTDI { + +class Devices; +namespace Private { +class DeviceData; +} +class Device { + public: + Device(); + ~Device(); + bool isLocked() const { return m_locked; } + bool isHighSpeed() const { return m_highSpeed; } + uint16_t getVendorID() const { return m_vendorID; } + uint16_t getDeviceID() const { return m_deviceID; } + uint32_t getType() const { return m_type; } + const std::string& getSerial() const { return m_serial; } + const std::string& getDescription() const { return m_description; } + + bool isOpened() const; + bool isBusy() const; + + void open(); + void close(); + + // technically private, but difficult to enforce properly + void asyncCallback() {} + void asyncCloseCallback() { m_asyncClosed = true; } + + private: + bool m_locked = false; + bool m_highSpeed = false; + uint16_t m_vendorID = 0; + uint16_t m_deviceID = 0; + uint32_t m_type = 0; + std::string m_serial = ""; + std::string m_description = ""; + + Private::DeviceData* m_private = nullptr; + + static const unsigned SLICES_COUNT = 256; + Slice m_slices[SLICES_COUNT]; + std::atomic_uint16_t m_slicesIndexes = 0; + + uv_async_t m_async; + bool m_asyncClosed = false; + + unsigned usedSlices() { + uint16_t indexes = m_slicesIndexes.load(); + unsigned first = indexes & 0xff; + unsigned last = (indexes >> 8) & 0xff; + if (last < first) last += 256; + return last - first; + } + + unsigned availableSlices() { return 256 - usedSlices(); } + + Slice& allocateSlice() { + while (availableSlices() == 0) + ; + uint16_t indexes = m_slicesIndexes.fetch_add(0x100); + return m_slices[(indexes >> 8) & 0xff]; + } + + friend class Devices; +}; + +class Devices { + public: + static void scan(); + static void shutdown(); + static void iterate(std::function); + static bool isThreadRunning(); + static void startThread(); + static void stopThread(); + static void setGUI(GUI*); + + // technically private, but difficult to enforce properly + static void threadProc(); +}; + +} // namespace FTDI + +} // namespace PCSX diff --git a/src/gui/gui.cc b/src/gui/gui.cc index 2c02e7e52..7a57a5834 100644 --- a/src/gui/gui.cc +++ b/src/gui/gui.cc @@ -465,6 +465,7 @@ void PCSX::GUI::endFrame() { ImGui::MenuItem(_("Show ImGui Demo"), nullptr, &m_showDemo); ImGui::Separator(); ImGui::MenuItem(_("About"), nullptr, &m_showAbout); + ImGui::MenuItem(_("FTDI"), nullptr, &m_showFTDI); ImGui::EndMenu(); } ImGui::Separator(); @@ -572,6 +573,10 @@ void PCSX::GUI::endFrame() { m_breakpoints.draw(_("Breakpoints")); } + if (m_showFTDI) { + m_ftdi.draw(_("FTDI")); + } + about(); biosCounters(); interruptsScaler(); diff --git a/src/gui/gui.h b/src/gui/gui.h index 8c4436b52..e88ab07bb 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -24,18 +24,17 @@ #include -#include "flags.h" - -#include "imgui.h" -#include "imgui_memory_editor/imgui_memory_editor.h" - #include "core/system.h" +#include "flags.h" #include "gui/widgets/assembly.h" #include "gui/widgets/breakpoints.h" #include "gui/widgets/filedialog.h" +#include "gui/widgets/ftdi.h" #include "gui/widgets/log.h" #include "gui/widgets/registers.h" #include "gui/widgets/vram-viewer.h" +#include "imgui.h" +#include "imgui_memory_editor/imgui_memory_editor.h" #include "main/settings.h" #if defined(__MACOSX__) @@ -50,6 +49,17 @@ namespace PCSX { class GUI final { public: + static void DButton(const char *label, bool enabled, std::function clicked) { + if (!enabled) { + const ImVec4 lolight = ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]; + ImGui::PushStyleColor(ImGuiCol_Button, lolight); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, lolight); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, lolight); + } + if (ImGui::Button(label) && enabled) clicked(); + if (!enabled) ImGui::PopStyleColor(3); + } + GUI(const flags::args &args) : m_args(args) {} void init(); void close(); @@ -95,6 +105,8 @@ class GUI final { } } + uv_loop_t *loop() { return &m_loop; } + private: GLFWwindow *m_window = nullptr; int &m_glfwPosX = settings.get().value; @@ -132,6 +144,7 @@ class GUI final { bool m_showDemo = false; bool m_showAbout = false; bool m_showInterruptsScaler = false; + bool m_showFTDI = false; Widgets::Log m_log = {settings.get().value}; struct MemoryEditorWrapper { MemoryEditorWrapper() { @@ -173,6 +186,8 @@ class GUI final { Widgets::VRAMViewer m_clutVRAMviewer; Widgets::VRAMViewer m_VRAMviewers[4]; + Widgets::FTDI m_ftdi = {m_showFTDI}; + uv_loop_t m_loop; }; diff --git a/src/gui/widgets/assembly.cc b/src/gui/widgets/assembly.cc index 750f07979..b3707756c 100644 --- a/src/gui/widgets/assembly.cc +++ b/src/gui/widgets/assembly.cc @@ -31,6 +31,7 @@ #include "core/disr3000a.h" #include "core/psxmem.h" #include "core/r3000a.h" +#include "gui/gui.h" #include "gui/widgets/assembly.h" #include "imgui_memory_editor/imgui_memory_editor.h" @@ -70,17 +71,6 @@ uint32_t virtToReal(uint32_t virt) { return pc; }; -void DButton(const char* label, bool enabled, std::function clicked) { - if (!enabled) { - const ImVec4 lolight = ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]; - ImGui::PushStyleColor(ImGuiCol_Button, lolight); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, lolight); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, lolight); - } - if (ImGui::Button(label) && enabled) clicked(); - if (!enabled) ImGui::PopStyleColor(3); -} - class DummyAsm : public PCSX::Disasm { virtual void Invalid() final {} virtual void OpCode(const char* str) final {} @@ -504,15 +494,15 @@ void PCSX::Widgets::Assembly::draw(psxRegisters* registers, Memory* memory, cons ImGui::SameLine(); ImGui::Checkbox(_("Follow PC"), &m_followPC); ImGui::SameLine(); - DButton(_("Pause"), g_system->running(), [&]() mutable { g_system->pause(); }); + GUI::DButton(_("Pause"), g_system->running(), [&]() mutable { g_system->pause(); }); ImGui::SameLine(); - DButton(_("Resume"), !g_system->running(), [&]() mutable { g_system->resume(); }); + GUI::DButton(_("Resume"), !g_system->running(), [&]() mutable { g_system->resume(); }); ImGui::SameLine(); - DButton(_("Step In"), !g_system->running(), [&]() mutable { g_emulator.m_debug->stepIn(); }); + GUI::DButton(_("Step In"), !g_system->running(), [&]() mutable { g_emulator.m_debug->stepIn(); }); ImGui::SameLine(); - DButton(_("Step Over"), !g_system->running(), [&]() mutable { g_emulator.m_debug->stepOver(); }); + GUI::DButton(_("Step Over"), !g_system->running(), [&]() mutable { g_emulator.m_debug->stepOver(); }); ImGui::SameLine(); - DButton(_("Step Out"), !g_system->running(), [&]() mutable { g_emulator.m_debug->stepOut(); }); + GUI::DButton(_("Step Out"), !g_system->running(), [&]() mutable { g_emulator.m_debug->stepOut(); }); if (!g_system->running()) { if (ImGui::IsKeyPressed(GLFW_KEY_F10)) { g_emulator.m_debug->stepOver(); @@ -693,17 +683,17 @@ void PCSX::Widgets::Assembly::draw(psxRegisters* registers, Memory* memory, cons std::string contextMenuTitle = "assembly address menu "; contextMenuTitle += dispAddr; if (ImGui::BeginPopupContextItem(contextMenuTitle.c_str())) { - DButton(_("Run to cursor"), !PCSX::g_system->running(), [&]() mutable { + GUI::DButton(_("Run to cursor"), !PCSX::g_system->running(), [&]() mutable { PCSX::g_emulator.m_debug->addBreakpoint(dispAddr, Debug::BE, true); ImGui::CloseCurrentPopup(); PCSX::g_system->resume(); }); - DButton(_("Set Breakpoint here"), !hasBP, [&]() mutable { + GUI::DButton(_("Set Breakpoint here"), !hasBP, [&]() mutable { PCSX::g_emulator.m_debug->addBreakpoint(dispAddr, Debug::BE); ImGui::CloseCurrentPopup(); hasBP = true; }); - DButton(_("Remove breakpoint from here"), hasBP, [&]() mutable { + GUI::DButton(_("Remove breakpoint from here"), hasBP, [&]() mutable { PCSX::g_emulator.m_debug->eraseBP(currentBP); ImGui::CloseCurrentPopup(); hasBP = false; diff --git a/src/gui/widgets/ftdi.cc b/src/gui/widgets/ftdi.cc new file mode 100644 index 000000000..5c55d1d12 --- /dev/null +++ b/src/gui/widgets/ftdi.cc @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2020 PCSX-Redux authors * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#include "gui/widgets/ftdi.h" + +#include "core/system.h" +#include "ftdi/abstract.h" +#include "gui/gui.h" + +void PCSX::Widgets::FTDI::draw(const char* title) { + if (!ImGui::Begin(title, &m_show)) { + ImGui::End(); + return; + } + + if (ImGui::Button(_("Scan"))) ::PCSX::FTDI::Devices::scan(); + + bool isThreadRunning = ::PCSX::FTDI::Devices::isThreadRunning(); + GUI::DButton("Start Thread", !isThreadRunning, []() { ::PCSX::FTDI::Devices::startThread(); }); + GUI::DButton("Stop Thread", isThreadRunning, []() { ::PCSX::FTDI::Devices::stopThread(); }); + + unsigned count = 0; + ::PCSX::FTDI::Devices::iterate([&count](::PCSX::FTDI::Device& d) mutable { + count++; + return true; + }); + + ImGui::Text((std::to_string(count) + " devices detected").c_str()); + ImGui::Separator(); + ::PCSX::FTDI::Device* devToClose = nullptr; + ::PCSX::FTDI::Device* devToOpen = nullptr; + ::PCSX::FTDI::Devices::iterate([&](::PCSX::FTDI::Device& d) mutable { + ImGui::Text("Vendor Id: %04x", d.getVendorID()); + ImGui::Text("Device Id: %04x", d.getDeviceID()); + ImGui::Text("Type: %i", d.getType()); + ImGui::Text("Serial: %s", d.getSerial().c_str()); + ImGui::Text("Description: %s", d.getDescription().c_str()); + ImGui::Text("Locked: %s", d.isLocked() ? "true" : "false"); + ImGui::Text("High Speed: %s", d.isHighSpeed() ? "true" : "false"); + ImGui::Text("Opened: %s", d.isOpened() ? "true" : "false"); + if (d.isOpened() && !d.isBusy()) { + if (ImGui::Button("Close")) { + devToClose = &d; + } + } else if (!d.isBusy()) { + if (ImGui::Button("Open")) { + devToOpen = &d; + } + } else { + ImGui::Text("Device is busy"); + } + ImGui::Separator(); + return true; + }); + ImGui::End(); + + if (devToClose) devToClose->close(); + if (devToOpen) devToOpen->open(); +} diff --git a/src/gui/widgets/ftdi.h b/src/gui/widgets/ftdi.h new file mode 100644 index 000000000..db790929c --- /dev/null +++ b/src/gui/widgets/ftdi.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * Copyright (C) 2020 PCSX-Redux authors * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#pragma once + +#include + +#include "imgui.h" + +namespace PCSX { +namespace Widgets { + +class FTDI { + public: + FTDI(bool& show) : m_show(show) {} + void draw(const char* title); + + bool& m_show; +}; + +} // namespace Widgets +} // namespace PCSX diff --git a/src/main/main.cc b/src/main/main.cc index 95bd2c633..5a8f639a6 100644 --- a/src/main/main.cc +++ b/src/main/main.cc @@ -30,6 +30,7 @@ #include "core/r3000a.h" #include "core/sstate.h" #include "flags.h" +#include "ftdi/abstract.h" #include "gui/gui.h" #include "spu/interface.h" #include "support/slice.h" @@ -169,7 +170,6 @@ using json = nlohmann::json; int main(int argc, char **argv) { const flags::args args(argc, argv); - PCSX::Slice slice; if (args.get("dumpproto")) { PCSX::SaveStates::ProtoFile::dumpSchema(std::cout); @@ -198,6 +198,7 @@ int main(int argc, char **argv) { LoadPlugins(); PCSX::g_emulator.m_gpu->open(s_gui); PCSX::g_emulator.m_spu->open(); + PCSX::FTDI::Devices::setGUI(s_gui); PCSX::g_emulator.EmuInit(); PCSX::g_emulator.EmuReset(); @@ -226,6 +227,8 @@ int main(int argc, char **argv) { PCSX::g_emulator.m_gpu->shutdown(); PCSX::g_emulator.m_cdrom->m_iso.shutdown(); + PCSX::FTDI::Devices::shutdown(); + s_gui->close(); delete s_gui; diff --git a/src/support/slice.h b/src/support/slice.h index 82e9f2a4e..16d27f492 100644 --- a/src/support/slice.h +++ b/src/support/slice.h @@ -26,25 +26,23 @@ namespace PCSX { class Slice { public: - Slice() : m_isInlined(false), m_isOwned(false), m_size(0) { - m_data.ptr = nullptr; - } + Slice() : m_isInlined(false), m_isOwned(false), m_size(0) { m_data.ptr = nullptr; } ~Slice() { maybeFree(); } - void copy(const void * data, uint32_t size) { + void copy(const void *data, uint32_t size) { assert(size < (1 << 30)); maybeFree(); m_size = size; m_isOwned = true; if (size > sizeof(m_data.inlined)) { m_isInlined = false; - m_data.ptr = (uint8_t *) malloc(size); + m_data.ptr = (uint8_t *)malloc(size); memcpy(m_data.ptr, data, size); } else { m_isInlined = true; memcpy(m_data.inlined, data, size); } } - void acquire(void * data, uint32_t size) { + void acquire(void *data, uint32_t size) { assert(size < (1 << 30)); maybeFree(); m_size = size; @@ -52,21 +50,24 @@ class Slice { m_isInlined = false; m_data.ptr = data; } - void borrow(const void * data, uint32_t size) { + void borrow(const void *data, uint32_t size) { assert(size < (1 << 30)); maybeFree(); m_size = size; m_isOwned = false; m_isInlined = false; - m_data.ptr = const_cast(data); + m_data.ptr = const_cast(data); } - const void * data() { return m_isInlined ? m_data.inlined : m_data.ptr; } + const void *data() { return m_isInlined ? m_data.inlined : m_data.ptr; } const uint32_t size() { return m_size; } + private: - void maybeFree() { if (m_isOwned && !m_isInlined) free(m_data.ptr); } + void maybeFree() { + if (m_isOwned && !m_isInlined) free(m_data.ptr); + } union { uint8_t inlined[24]; - void * ptr; + void *ptr; } m_data; bool m_isInlined : 1; bool m_isOwned : 1; diff --git a/vsprojects/ftdi/ftdi.vcxproj b/vsprojects/ftdi/ftdi.vcxproj new file mode 100644 index 000000000..1779a1dd4 --- /dev/null +++ b/vsprojects/ftdi/ftdi.vcxproj @@ -0,0 +1,172 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {832D8D53-3EE4-43D7-B5DF-48B249CE0709} + ftdi + 10.0 + + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ..\..\src;..\..\third_party;..\..\third_party\imgui;..\..\third_party\imgui_club;..\..\third_party\libuv\include + stdcpp17 + + + Console + true + + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ..\..\src;..\..\third_party;..\..\third_party\imgui;..\..\third_party\imgui_club;..\..\third_party\libuv\include + stdcpp17 + + + Console + true + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ..\..\src;..\..\third_party;..\..\third_party\imgui;..\..\third_party\imgui_club;..\..\third_party\libuv\include + stdcpp17 + + + Console + true + true + true + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ..\..\src;..\..\third_party;..\..\third_party\imgui;..\..\third_party\imgui_club;..\..\third_party\libuv\include + stdcpp17 + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/vsprojects/ftdi/ftdi.vcxproj.filters b/vsprojects/ftdi/ftdi.vcxproj.filters new file mode 100644 index 000000000..c3ce23f24 --- /dev/null +++ b/vsprojects/ftdi/ftdi.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/vsprojects/ftdi/packages.config b/vsprojects/ftdi/packages.config new file mode 100644 index 000000000..1cf8b5eae --- /dev/null +++ b/vsprojects/ftdi/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/vsprojects/gui/gui.vcxproj b/vsprojects/gui/gui.vcxproj index f53bcfc4b..76e8aa086 100644 --- a/vsprojects/gui/gui.vcxproj +++ b/vsprojects/gui/gui.vcxproj @@ -142,6 +142,7 @@ + @@ -151,6 +152,7 @@ + diff --git a/vsprojects/gui/gui.vcxproj.filters b/vsprojects/gui/gui.vcxproj.filters index 69f2657a5..b32dd4e2f 100644 --- a/vsprojects/gui/gui.vcxproj.filters +++ b/vsprojects/gui/gui.vcxproj.filters @@ -42,6 +42,9 @@ Source Files\widgets + + Source Files\widgets + @@ -68,6 +71,9 @@ Header Files\widgets + + Header Files\widgets + diff --git a/vsprojects/includes.props b/vsprojects/includes.props index 1c325ade7..b6d6fafcd 100644 --- a/vsprojects/includes.props +++ b/vsprojects/includes.props @@ -8,6 +8,8 @@ true + + diff --git a/vsprojects/pcsx-redux.sln b/vsprojects/pcsx-redux.sln index 6deefe10c..039fbd4d7 100644 --- a/vsprojects/pcsx-redux.sln +++ b/vsprojects/pcsx-redux.sln @@ -37,6 +37,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImGuiColorTextEdit", "ImGui EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libuv", "libuv\libuv.vcxproj", "{4B88E4F6-56B3-4F66-BEE8-0A4A21937BEE}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftdi", "ftdi\ftdi.vcxproj", "{832D8D53-3EE4-43D7-B5DF-48B249CE0709}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "support", "support\support.vcxproj", "{70340FF5-B49D-453F-A4F0-75EFB08E0DF0}" EndProject Global @@ -135,6 +137,14 @@ Global {4B88E4F6-56B3-4F66-BEE8-0A4A21937BEE}.Release|x64.Build.0 = Release|x64 {4B88E4F6-56B3-4F66-BEE8-0A4A21937BEE}.Release|x86.ActiveCfg = Release|Win32 {4B88E4F6-56B3-4F66-BEE8-0A4A21937BEE}.Release|x86.Build.0 = Release|Win32 + {832D8D53-3EE4-43D7-B5DF-48B249CE0709}.Debug|x64.ActiveCfg = Debug|x64 + {832D8D53-3EE4-43D7-B5DF-48B249CE0709}.Debug|x64.Build.0 = Debug|x64 + {832D8D53-3EE4-43D7-B5DF-48B249CE0709}.Debug|x86.ActiveCfg = Debug|Win32 + {832D8D53-3EE4-43D7-B5DF-48B249CE0709}.Debug|x86.Build.0 = Debug|Win32 + {832D8D53-3EE4-43D7-B5DF-48B249CE0709}.Release|x64.ActiveCfg = Release|x64 + {832D8D53-3EE4-43D7-B5DF-48B249CE0709}.Release|x64.Build.0 = Release|x64 + {832D8D53-3EE4-43D7-B5DF-48B249CE0709}.Release|x86.ActiveCfg = Release|Win32 + {832D8D53-3EE4-43D7-B5DF-48B249CE0709}.Release|x86.Build.0 = Release|Win32 {70340FF5-B49D-453F-A4F0-75EFB08E0DF0}.Debug|x64.ActiveCfg = Debug|x64 {70340FF5-B49D-453F-A4F0-75EFB08E0DF0}.Debug|x64.Build.0 = Debug|x64 {70340FF5-B49D-453F-A4F0-75EFB08E0DF0}.Debug|x86.ActiveCfg = Debug|Win32 @@ -160,6 +170,7 @@ Global {BF968FD3-EF46-45AF-B74E-46A41A96276F} = {008A2872-432F-480B-828D-FF9AAA4846BC} {CBF9B825-F140-4A02-8A3F-059103D6CA90} = {64A05F50-3203-42CC-B632-09D6EE6EA856} {4B88E4F6-56B3-4F66-BEE8-0A4A21937BEE} = {64A05F50-3203-42CC-B632-09D6EE6EA856} + {832D8D53-3EE4-43D7-B5DF-48B249CE0709} = {008A2872-432F-480B-828D-FF9AAA4846BC} {70340FF5-B49D-453F-A4F0-75EFB08E0DF0} = {008A2872-432F-480B-828D-FF9AAA4846BC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/vsprojects/pcsx-redux/packages.config b/vsprojects/pcsx-redux/packages.config index 36c05cdf8..484bb9ea4 100644 --- a/vsprojects/pcsx-redux/packages.config +++ b/vsprojects/pcsx-redux/packages.config @@ -1,5 +1,6 @@  + \ No newline at end of file diff --git a/vsprojects/pcsx-redux/pcsx-redux.vcxproj b/vsprojects/pcsx-redux/pcsx-redux.vcxproj index 2d32f6b6c..5dfd69c48 100644 --- a/vsprojects/pcsx-redux/pcsx-redux.vcxproj +++ b/vsprojects/pcsx-redux/pcsx-redux.vcxproj @@ -158,6 +158,9 @@ {9372d878-f76c-418b-8e2a-8e9896ff575b} + + {832d8d53-3ee4-43d7-b5df-48b249ce0709} + {6ec7fdf3-1418-40bd-8584-1eea34ac3e3e} @@ -204,6 +207,7 @@ + @@ -211,5 +215,6 @@ + \ No newline at end of file