diff --git a/Externals/SlippiLib/SlippiLib.vcxproj b/Externals/SlippiLib/SlippiLib.vcxproj index 1e7592cf73..f88cbb8062 100644 --- a/Externals/SlippiLib/SlippiLib.vcxproj +++ b/Externals/SlippiLib/SlippiLib.vcxproj @@ -72,7 +72,7 @@ StaticLibrary true - v141 + v142 Unicode @@ -92,7 +92,7 @@ StaticLibrary false - v141 + v142 true Unicode diff --git a/Externals/nlohmann/nlohmann.vcxproj b/Externals/nlohmann/nlohmann.vcxproj index bece14785e..938e45452e 100644 --- a/Externals/nlohmann/nlohmann.vcxproj +++ b/Externals/nlohmann/nlohmann.vcxproj @@ -71,7 +71,7 @@ Application true - v141 + v142 MultiByte @@ -91,7 +91,7 @@ Application false - v141 + v142 true MultiByte diff --git a/Externals/open-vcdiff/open-vcdiff.vcxproj b/Externals/open-vcdiff/open-vcdiff.vcxproj index 750776ad56..d544d2c6e0 100644 --- a/Externals/open-vcdiff/open-vcdiff.vcxproj +++ b/Externals/open-vcdiff/open-vcdiff.vcxproj @@ -114,7 +114,7 @@ StaticLibrary true - v141 + v142 Unicode @@ -134,7 +134,7 @@ StaticLibrary false - v141 + v142 true Unicode diff --git a/Externals/semver/semver.vcxproj b/Externals/semver/semver.vcxproj index 3b6090c384..5e97617f89 100644 --- a/Externals/semver/semver.vcxproj +++ b/Externals/semver/semver.vcxproj @@ -73,7 +73,7 @@ StaticLibrary true - v141 + v142 MultiByte @@ -93,7 +93,7 @@ StaticLibrary false - v141 + v142 true MultiByte diff --git a/Source/Core/Common/BreakPoints.cpp b/Source/Core/Common/BreakPoints.cpp index 6d15c4f3fb..8575316461 100644 --- a/Source/Core/Common/BreakPoints.cpp +++ b/Source/Core/Common/BreakPoints.cpp @@ -9,6 +9,8 @@ #include "Common/BreakPoints.h" #include "Common/CommonTypes.h" #include "Common/DebugInterface.h" +#include "Core/Core.h" + #include "Core/PowerPC/JitCommon/JitBase.h" #include "Core/PowerPC/JitCommon/JitCache.h" @@ -168,29 +170,52 @@ void MemChecks::AddFromStrings(const TMemChecksStr& mcstrs) } } +bool MemChecks::OverlapsMemcheck(u32 address, u32 length) const +{ + if (!HasAny()) + return false; + + const u32 page_end_suffix = length - 1; + const u32 page_end_address = address | page_end_suffix; + + return std::any_of(m_MemChecks.cbegin(), m_MemChecks.cend(), [&](const auto &mc) { + return ((mc.StartAddress | page_end_suffix) == page_end_address || + (mc.EndAddress | page_end_suffix) == page_end_address) || + ((mc.StartAddress | page_end_suffix) < page_end_address && + (mc.EndAddress | page_end_suffix) > page_end_address); + }); +} + void MemChecks::Add(const TMemCheck& _rMemoryCheck) { + + if (GetMemCheck(_rMemoryCheck.StartAddress) != nullptr) + return; + bool had_any = HasAny(); - if (GetMemCheck(_rMemoryCheck.StartAddress) == nullptr) + Core::RunAsCPUThread([&] { m_MemChecks.push_back(_rMemoryCheck); - // If this is the first one, clear the JIT cache so it can switch to - // watchpoint-compatible code. - if (!had_any && jit) - jit->ClearCache(); + // If this is the first one, clear the JIT cache so it can switch to + // watchpoint-compatible code. + if (!had_any && jit) + jit->ClearCache(); + }); + } void MemChecks::Remove(u32 _Address) { - for (auto i = m_MemChecks.begin(); i != m_MemChecks.end(); ++i) - { - if (i->StartAddress == _Address) - { - m_MemChecks.erase(i); - return; - } - } - if (!HasAny() && jit) - jit->ClearCache(); + const auto iter = std::find_if(m_MemChecks.cbegin(), m_MemChecks.cend(), + [_Address](const auto &check) { return check.StartAddress == _Address; }); + + if (iter == m_MemChecks.cend()) + return; + + Core::RunAsCPUThread([&] { + m_MemChecks.erase(iter); + if (!HasAny()) + jit->ClearCache(); + }); } TMemCheck* MemChecks::GetMemCheck(u32 address) diff --git a/Source/Core/Common/BreakPoints.h b/Source/Core/Common/BreakPoints.h index a82ac40eb1..cb65660e7c 100644 --- a/Source/Core/Common/BreakPoints.h +++ b/Source/Core/Common/BreakPoints.h @@ -105,6 +105,8 @@ class MemChecks void Add(const TMemCheck& _rMemoryCheck); // memory breakpoint + bool OverlapsMemcheck(u32 address, u32 length) const; + TMemCheck* GetMemCheck(u32 address); void Remove(u32 _Address); diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 29aef2e709..38df176da9 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -838,6 +838,19 @@ bool PauseAndLock(bool do_lock, bool unpause_on_unlock) return was_unpaused; } +void RunAsCPUThread(std::function function) +{ + const bool is_cpu_thread = IsCPUThread(); + bool was_unpaused = false; + if (!is_cpu_thread) + was_unpaused = PauseAndLock(true, true); + + function(); + + if (!is_cpu_thread) + PauseAndLock(false, was_unpaused); +} + // Display FPS info // This should only be called from VI void VideoThrottle() diff --git a/Source/Core/Core/Core.h b/Source/Core/Core/Core.h index fbfde70b90..2e630c253b 100644 --- a/Source/Core/Core/Core.h +++ b/Source/Core/Core/Core.h @@ -76,6 +76,15 @@ void RequestRefreshInfo(); void UpdateTitle(); +// Run a function as the CPU thread. +// +// If called from the Host thread, the CPU thread is paused and the current thread temporarily +// becomes the CPU thread while running the function. +// If called from the CPU thread, the function will be run directly. +// +// This should only be called from the CPU thread or the host thread. +void RunAsCPUThread(std::function function); + // waits until all systems are paused and fully idle, and acquires a lock on that state. // or, if doLock is false, releases a lock on that state and optionally unpauses. // calls must be balanced (once with doLock true, then once with doLock false) but may be recursive. diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index f23c3f24e5..adcdba77dc 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -453,266 +453,12 @@ u32 HostRead_Instruction(const u32 address) static __forceinline void Memcheck(u32 address, u32 var, bool write, int size) { - //********************************************************************* - //* How to test memory sections - //********************************************************************* - // 1. Uncomment once of the memory analysis blocks below - // 2. Start the application (release version is fine) - // 3. At a bp somewhere before where you want to start looking for mem access - // 4. Once hit, add a MBP in code section (something that will never get hit) - // and turn off JIT Core - // 5. Start the emulation again and memory accesses should get logged - // 6. Make sure you have logging enabled for MI memmap - - //********************************************************************* - //* Looking for heap writes? - //********************************************************************* - // if (!write || size != 4) - //{ - // return; - // } - - // static u32 heapStart = 0x80bd5c40; - // static u32 heapEnd = 0x811AD5A0; - - // static std::unordered_map visited; - - // // If we are writting to somewhere in heap, return - // if (address >= heapStart && address < heapEnd) - // return; - - // // If we are not writting a pointer the somewhere in heap, return - // if (var < heapStart || var >= heapEnd) - // return; - - // if (visited.count(address)) - // return; - - // visited[address] = true; - // ERROR_LOG(SLIPPI_ONLINE, "%x (%s) %x -> %x", PC, PowerPC::debug_interface.GetDescription(PC).c_str(), address, - // var); - - //********************************************************************* - //* Looking for camera player position memory - //********************************************************************* - // static std::unordered_map visited = {}; - // static std::unordered_map whitelist = { - // {"PlayerThink_CameraBehavior", true}, // Per-Player update camera position function - // {"CameraFunctionBlrl", true}, // Update camera position - //}; - - // static std::vector soundStuff = { - // - //}; - - // auto sceneController = ReadFromHardware(0x80479d30); - // if ((sceneController & 0xFF0000FF) != 0x08000002) - //{ - // return; - //} - - // auto isLoading = ReadFromHardware(0x80479d64); - // if (isLoading) - //{ - // return; - //} - - // if (!write) - //{ - // return; - //} - - // if (address >= 0x804dec00 && address < 0x804eec00) - //{ - // return; - //} - - // if (visited.count(address)) - //{ - // return; - //} - - // visited[address] = true; - - // for (auto it = soundStuff.begin(); it != soundStuff.end(); ++it) - //{ - // if (address >= it->address && address < it->address + it->length) - // { - // return; - // } - //} - - // if ((address & 0xFF000000) == 0xcc000000) - //{ - // return; - //} - - // std::vector callstack; - // Dolphin_Debugger::GetCallstack(callstack); - - // bool isFound = false; - // for (auto it = callstack.begin(); it != callstack.end(); ++it) - //{ - // std::string func = PowerPC::debug_interface.GetDescription(it->vAddress).c_str(); - // if (whitelist.count(func)) - // { - // isFound = true; - // break; - // } - //} - - // if (!isFound) - //{ - // return; - //} - - // NOTICE_LOG(MEMMAP, "(%s) %x (%s) | %x (%x) <-> %x", write ? "Write" : "Read", PC, - // PowerPC::debug_interface.GetDescription(PC).c_str(), var, size, address); - - //********************************************************************* - //* Looking for sound memory - //********************************************************************* - // static std::unordered_map visited = {}; - // static std::unordered_map whitelist = { - // {"__AIDHandler", true}, // lol - // {"__AXOutAiCallback", true}, // lol - // {"__AXOutNewFrame", true}, // lol - // {"__AXSyncPBs", true}, // lol - // {"SFX_PlaySFX", true}, // lol - // {"__DSPHandler", true}, - //}; - - // static std::vector soundStuff = { - // {0x804031A0, 0x24}, // [804031A0 - 804031C4) - // {0x80407FB4, 0x34C}, // [80407FB4 - 80408300) - // {0x80433C64, 0x1EE80}, // [80433C64 - 80452AE4) - // {0x804A8D78, 0x17A68}, // [804A8D78 - 804C07E0) - // {0x804C28E0, 0x399C}, // [804C28E0 - 804C627C) - // {0x804D7474, 0x8}, // [804D7474 - 804D747C) - // {0x804D74F0, 0x50}, // [804D74F0 - 804D7540) - // {0x804D7548, 0x4}, // [804D7548 - 804D754C) - // {0x804D7558, 0x24}, // [804D7558 - 804D757C) - // {0x804D7580, 0xC}, // [804D7580 - 804D758C) - // {0x804D759C, 0x4}, // [804D759C - 804D75A0) - // {0x804D7720, 0x4}, // [804D7720 - 804D7724) - // {0x804D7744, 0x4}, // [804D7744 - 804D7748) - // {0x804D774C, 0x8}, // [804D774C - 804D7754) - // {0x804D7758, 0x8}, // [804D7758 - 804D7760) - // {0x804D7788, 0x10}, // [804D7788 - 804D7798) - // {0x804D77C8, 0x4}, // [804D77C8 - 804D77CC) - // {0x804D77D0, 0x4}, // [804D77D0 - 804D77D4) - // {0x804D77E0, 0x4}, // [804D77E0 - 804D77E4) - // {0x804DE358, 0x80}, // [804DE358 - 804DE3D8) - // {0x804DE800, 0x70}, // [804DE800 - 804DE870) - //}; - - // auto sceneController = ReadFromHardware(0x80479d30); - // if ((sceneController & 0xFF0000FF) != 0x08000002) - //{ - // return; - //} - - // auto isLoading = ReadFromHardware(0x80479d64); - // if (isLoading) - //{ - // return; - //} - - // if (address >= 0x804dec00) - //{ - // return; - //} - ////if (!write) - ////{ - //// return; - ////} - - // if (visited.count(address)) - //{ - // return; - //} - - // visited[address] = true; - - // for (auto it = soundStuff.begin(); it != soundStuff.end(); ++it) - //{ - // if (address >= it->address && address < it->address + it->length) - // { - // return; - // } - //} - - // if ((address & 0xFF000000) == 0xcc000000) - //{ - // return; - //} - - // std::vector callstack; - // Dolphin_Debugger::GetCallstack(callstack); - - // bool isFound = false; - // for (auto it = callstack.begin(); it != callstack.end(); ++it) - //{ - // std::string func = PowerPC::debug_interface.GetDescription(it->vAddress).c_str(); - // if (whitelist.count(func)) - // { - // isFound = true; - // break; - // } - //} - - // if (!isFound) - //{ - // return; - //} - - // NOTICE_LOG(MEMMAP, "(%s) %x (%s) | %x (%x) <-> %x", write ? "Write" : "Read", PC, - // PowerPC::debug_interface.GetDescription(PC).c_str(), var, size, address); - - //********************************************************************* - //* Detect writes in unknown memory region - //********************************************************************* - //static std::unordered_map visited = {}; - - //auto sceneController = ReadFromHardware(0x80479d30); - //if ((sceneController & 0xFF0000FF) != 0x08000002) - //{ - // return; - //} - - //auto isLoading = ReadFromHardware(0x80479d64); - //if (isLoading) - //{ - // return; - //} - - //if (!write) - //{ - // return; - //} - - //// [804fec00 - 80BD5C40) - //if (address < 0x8071b000 || address >= 0x80bb0000) - //{ - // return; - //} - - //if (visited.count(address)) - //{ - // return; - //} - - //visited[address] = true; - - //if ((address & 0xFF000000) == 0xcc000000) - //{ - // return; - //} - - //NOTICE_LOG(MEMMAP, "(%s) %x (%s) | %x (%x) <-> %x", write ? "Write" : "Read", PC, - // PowerPC::debug_interface.GetDescription(PC).c_str(), var, size, address); + #ifndef ENABLE_MEM_CHECK + return; + #endif + if (!PowerPC::memchecks.HasAny()) + return; -#ifdef ENABLE_MEM_CHECK TMemCheck *mc = PowerPC::memchecks.GetMemCheck(address); if (mc) { @@ -736,7 +482,6 @@ static __forceinline void Memcheck(u32 address, u32 var, bool write, int size) PowerPC::ppcState.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; } } -#endif } u8 Read_U8(const u32 address) diff --git a/Source/Core/DolphinWX/Debugger/BreakpointWindow.cpp b/Source/Core/DolphinWX/Debugger/BreakpointWindow.cpp index b2845a6c4e..719558377a 100644 --- a/Source/Core/DolphinWX/Debugger/BreakpointWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/BreakpointWindow.cpp @@ -152,7 +152,10 @@ void CBreakPointWindow::OnAddBreakPoint(wxCommandEvent& WXUNUSED(event)) void CBreakPointWindow::OnAddMemoryCheck(wxCommandEvent& WXUNUSED(event)) { MemoryCheckDlg memDlg(this); - memDlg.ShowModal(); + if (memDlg.ShowModal() == wxID_OK) + { + NotifyUpdate(); + } } void CBreakPointWindow::Event_SaveAll(wxCommandEvent& WXUNUSED(event)) diff --git a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp index 5ddd14fb48..9d471dc7eb 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp @@ -513,7 +513,7 @@ wxPanel* CCodeWindow::CreateSiblingPanel(int id) panel = new CBreakPointWindow(this, Parent, IDM_BREAKPOINT_WINDOW); break; case IDM_MEMORY_WINDOW: - panel = new CMemoryWindow(Parent, IDM_MEMORY_WINDOW); + panel = new CMemoryWindow(this, Parent, IDM_MEMORY_WINDOW); break; case IDM_JIT_WINDOW: panel = new CJitWindow(Parent, IDM_JIT_WINDOW); diff --git a/Source/Core/DolphinWX/Debugger/MemoryView.cpp b/Source/Core/DolphinWX/Debugger/MemoryView.cpp index 68bf2ccbc0..0e2e8bf522 100644 --- a/Source/Core/DolphinWX/Debugger/MemoryView.cpp +++ b/Source/Core/DolphinWX/Debugger/MemoryView.cpp @@ -120,16 +120,45 @@ void CMemoryView::OnMouseDownL(wxMouseEvent& event) } else { - debugger->ToggleMemCheck(YToAddress(y), memCheckRead, memCheckWrite, memCheckLog); + ToggleMemCheck(YToAddress(y)); + + } - Refresh(); + event.Skip(); +} - // Propagate back to the parent window to update the breakpoint list. - wxCommandEvent evt(wxEVT_HOST_COMMAND, IDM_UPDATE_BREAKPOINTS); - GetEventHandler()->AddPendingEvent(evt); +void CMemoryView::ToggleMemCheck(u32 address) +{ + auto length = 15; + if (GetDataType() >= MemoryDataType::ASCII) + { + length = 3; } - event.Skip(); + TMemCheck check; + if (!PowerPC::memchecks.OverlapsMemcheck(address, length)) + { + check.StartAddress = address; + check.EndAddress = check.StartAddress + length; + check.bRange = length > 0; + check.OnRead = memCheckRead; + check.OnWrite = memCheckWrite; + check.Log = memCheckLog; + check.Break = true; + + + PowerPC::memchecks.Add(check); + } + else + { + PowerPC::memchecks.Remove(address); + } + + Refresh(); + + // Propagate back to the parent window to update the breakpoint list. + wxCommandEvent evt(wxEVT_HOST_COMMAND, IDM_UPDATE_BREAKPOINTS); + GetEventHandler()->AddPendingEvent(evt); } void CMemoryView::OnMouseMove(wxMouseEvent& event) diff --git a/Source/Core/DolphinWX/Debugger/MemoryView.h b/Source/Core/DolphinWX/Debugger/MemoryView.h index 78823f0aa0..f929eaa28c 100644 --- a/Source/Core/DolphinWX/Debugger/MemoryView.h +++ b/Source/Core/DolphinWX/Debugger/MemoryView.h @@ -25,6 +25,8 @@ class CMemoryView : public wxControl public: CMemoryView(DebugInterface* debuginterface, wxWindow* parent); + void ToggleMemCheck(u32 address); + u32 GetSelection() const { return selection; } int GetMemoryType() const { return memory; } void Center(u32 addr) @@ -73,9 +75,9 @@ class CMemoryView : public wxControl int memory; int curAddress; - bool memCheckRead; - bool memCheckWrite; - bool memCheckLog; + bool memCheckRead = false; + bool memCheckWrite = true; + bool memCheckLog = true; MemoryDataType m_data_type; MemoryDataType m_last_hex_type = MemoryDataType::U8; diff --git a/Source/Core/DolphinWX/Debugger/MemoryWindow.cpp b/Source/Core/DolphinWX/Debugger/MemoryWindow.cpp index 4ef3b448db..3624bfb8f7 100644 --- a/Source/Core/DolphinWX/Debugger/MemoryWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/MemoryWindow.cpp @@ -65,9 +65,9 @@ EVT_RADIOBUTTON(IDM_MEMCHECK_OPTIONS_CHANGE, CMemoryWindow::OnMemCheckOptionChan EVT_CHECKBOX(IDM_MEMCHECK_OPTIONS_CHANGE, CMemoryWindow::OnMemCheckOptionChange) END_EVENT_TABLE() -CMemoryWindow::CMemoryWindow(wxWindow* parent, wxWindowID id, const wxPoint& pos, +CMemoryWindow::CMemoryWindow(CCodeWindow *_pCodeWindow, wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize& size, long style, const wxString& name) - : wxPanel(parent, id, pos, size, style, name) + : wxPanel(parent, id, pos, size, style, name), m_code_window(_pCodeWindow) { DebugInterface* di = &PowerPC::debug_interface; @@ -118,7 +118,8 @@ CMemoryWindow::CMemoryWindow(wxWindow* parent, wxWindowID id, const wxPoint& pos wxStaticBoxSizer* const memcheck_options_sizer = new wxStaticBoxSizer(wxVERTICAL, this, "Memory breakpoint options"); - memcheck_options_sizer->Add(rdbReadWrite = new wxRadioButton(this, IDM_MEMCHECK_OPTIONS_CHANGE, + memcheck_options_sizer->Add( + rdbReadWrite = new wxRadioButton(this, IDM_MEMCHECK_OPTIONS_CHANGE, "Read and Write", wxDefaultPosition, wxDefaultSize, wxRB_GROUP)); memcheck_options_sizer->Add( @@ -144,10 +145,15 @@ CMemoryWindow::CMemoryWindow(wxWindow* parent, wxWindowID id, const wxPoint& pos SetSizer(sizerBig); m_rb_hex->SetValue(true); // Set defaults chkLog->SetValue(true); + rdbReadWrite->SetValue(false); + rdbWrite->SetValue(true); m_rbox_data_type->SetSelection(static_cast(memview->GetDataType())); sizerRight->Fit(this); sizerBig->Fit(this); + + // Other + Bind(wxEVT_HOST_COMMAND, &CMemoryWindow::OnHostMessage, this); } void CMemoryWindow::JumpToAddress(u32 _Address) @@ -403,3 +409,21 @@ void CMemoryWindow::OnMemCheckOptionChange(wxCommandEvent& event) else memview->SetMemCheckOptions(rdbRead->GetValue(), rdbWrite->GetValue(), chkLog->GetValue()); } + + +// ---------- +// Events + +void CMemoryWindow::OnHostMessage(wxCommandEvent &event) +{ + switch (event.GetId()) + { + case IDM_UPDATE_BREAKPOINTS: + if (m_code_window->HasPanel()) + m_code_window->GetPanel()->NotifyUpdate(); + Refresh(); + + break; + + } +} \ No newline at end of file diff --git a/Source/Core/DolphinWX/Debugger/MemoryWindow.h b/Source/Core/DolphinWX/Debugger/MemoryWindow.h index 359738182f..bd60e48b32 100644 --- a/Source/Core/DolphinWX/Debugger/MemoryWindow.h +++ b/Source/Core/DolphinWX/Debugger/MemoryWindow.h @@ -23,15 +23,15 @@ class wxRadioButton; class CMemoryWindow : public wxPanel { public: - CMemoryWindow(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, + CMemoryWindow(CCodeWindow *_pCodeWindow, wxWindow *parent, wxWindowID id = wxID_ANY, + const wxPoint &pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL | wxBORDER_NONE, const wxString& name = _("Memory")); void Repopulate(); void JumpToAddress(u32 _Address); - -private: + private: DECLARE_EVENT_TABLE() void OnDataTypeChanged(wxCommandEvent& event); @@ -44,6 +44,7 @@ class CMemoryWindow : public wxPanel void OnDumpMem2(wxCommandEvent& event); void OnDumpFakeVMEM(wxCommandEvent& event); void OnMemCheckOptionChange(wxCommandEvent& event); + void OnHostMessage(wxCommandEvent &event); wxButton* btnSearch; wxRadioButton* m_rb_ascii; diff --git a/Source/Core/DolphinWX/Dolphin.vcxproj b/Source/Core/DolphinWX/Dolphin.vcxproj index c932906e19..8ccf9fe554 100644 --- a/Source/Core/DolphinWX/Dolphin.vcxproj +++ b/Source/Core/DolphinWX/Dolphin.vcxproj @@ -72,7 +72,7 @@ /NODEFAULTLIB:libcmt /ignore:4281 %(AdditionalOptions) /NODEFAULTLIB:libcmt /ignore:4281 %(AdditionalOptions) /NODEFAULTLIB:libcmt /ignore:4281 %(AdditionalOptions) - /NODEFAULTLIB:libcmt /ignore:4281 %(AdditionalOptions) + /NODEFAULTLIB:MSVCRTD /NODEFAULTLIB:libcmt /ignore:4281 %(AdditionalOptions) Windows diff --git a/Source/Core/DolphinWX/Dolphin.vcxproj.user b/Source/Core/DolphinWX/Dolphin.vcxproj.user index 197efdde2e..ff6632116f 100644 --- a/Source/Core/DolphinWX/Dolphin.vcxproj.user +++ b/Source/Core/DolphinWX/Dolphin.vcxproj.user @@ -14,7 +14,7 @@ -d - -i "C:/test.json" + -d -i "C:/test.json" -d