#pragma once #include #include #include #include "Cafe/HW/MMU/MMU.h" #include "util/helpers/helpers.h" #include "gui/helpers/wxCustomEvents.h" enum SearchDataType { SearchDataType_None, SearchDataType_String, SearchDataType_Float, SearchDataType_Double, SearchDataType_Int8, SearchDataType_Int16, SearchDataType_Int32, SearchDataType_Int64, }; struct TableEntry_t { uint32 address; const char description[32]; SearchDataType type; bool freeze; uint16 dataLen; uint8* data; }; class MemorySearcherTool : public wxFrame { public: MemorySearcherTool(wxFrame* parent); virtual ~MemorySearcherTool(); void OnTimerTick(wxTimerEvent& event); void OnClose(wxCloseEvent&); void OnSearch(wxCommandEvent&); void OnSearchFinished(wxCommandEvent& event); void OnUpdateGauge(wxSetGaugeValue& event); void OnFilter(wxCommandEvent& event); void OnResultListClick(wxMouseEvent& event); void OnEntryListRightClick(wxDataViewEvent& event); //void OnEntryListRightClick2(wxContextMenuEvent& event); void OnPopupClick(wxCommandEvent& event); void OnItemEdited(wxDataViewEvent& event); private: void Reset(); bool VerifySearchValue() const; void FillResultList(); void RefreshResultList(); void RefreshStashList(); void SetSearchDataType(); void Load(); void Save(); static bool IsAddressValid(uint32 addr); template bool ConvertStringToType(const char* inValue, T& outValue) const { std::istringstream iss(inValue); iss >> std::noskipws >> outValue; return iss && iss.eof(); } using ListType_t = std::vector>; ListType_t SearchValues(SearchDataType type, void* ptr, uint32 size) { /*if (type == SearchDataType_String) return SearchValues((const char* )ptr, size); else */if (type == SearchDataType_Float) return SearchValues((float*)ptr, size); else if (type == SearchDataType_Double) return SearchValues((double*)ptr, size); else if (type == SearchDataType_Int8) return SearchValues((sint8*)ptr, size); else if (type == SearchDataType_Int16) return SearchValues((sint16*)ptr, size); else if (type == SearchDataType_Int32) return SearchValues((sint32*)ptr, size); else if (type == SearchDataType_Int64) return SearchValues((sint64*)ptr, size); return {}; } ListType_t FilterValues(SearchDataType type) { /*if (type == SearchDataType_String) return FilterValues(); else */if (type == SearchDataType_Float) return FilterValues(); else if (type == SearchDataType_Double) return FilterValues(); else if (type == SearchDataType_Int8) return FilterValues(); else if (type == SearchDataType_Int16) return FilterValues(); else if (type == SearchDataType_Int32) return FilterValues(); else if (type == SearchDataType_Int64) return FilterValues(); return {}; } constexpr static int kGaugeStep = 0x10000; template ListType_t SearchValues(T* ptr, uint32 size) { const auto value = m_textValue->GetValue(); const auto* string_value = value.c_str().AsChar(); const auto search_value = ConvertString(string_value); const auto* end = (T*)((uint8*)ptr + size - sizeof(T)); uint32 counter = 0; std::vector> result; for (; ptr < end; ++ptr) { if (!m_running) return result; const auto tmp = (betype*)ptr; if (equals(search_value, tmp->value())) result.emplace_back(ptr); counter += sizeof(T); if(counter >= kGaugeStep) { wxQueueEvent(this, new wxSetGaugeValue(1, m_gauge)); counter -= kGaugeStep; } } return result; } template ListType_t FilterValues() { const auto value = m_textValue->GetValue(); const auto* string_value = value.c_str().AsChar(); const auto search_value = ConvertString(string_value); ListType_t newSearchBuffer; newSearchBuffer.reserve(m_searchBuffer.size()); for (const auto& it : m_searchBuffer) { if (!m_running) return newSearchBuffer; const auto tmp = (betype*)it.GetPtr(); if (equals(search_value , tmp->value())) newSearchBuffer.emplace_back(it); wxQueueEvent(this, new wxSetGaugeValue(1, m_gauge)); } return newSearchBuffer; } wxDECLARE_EVENT_TABLE(); SearchDataType m_searchDataType = SearchDataType_None; wxComboBox* m_cbDataType; wxTextCtrl* m_textValue; wxButton *m_buttonStart, *m_buttonFilter; wxListCtrl* m_listResults; wxDataViewListCtrl* m_listEntryTable; wxStaticText* m_textEntryTable; wxGauge* m_gauge; wxTimer* m_refresh_timer; ListType_t m_searchBuffer; std::vector m_tableEntries; std::mutex m_mutex; std::thread m_worker; std::atomic_bool m_running = true; std::atomic_bool m_search_running = false; std::vector> m_search_jobs; bool m_clear_state = false; }; template <> bool MemorySearcherTool::ConvertStringToType(const char* inValue, sint8& outValue) const; // //template //void MemorySearcherTool::FilterValues() //{ // auto s1 = m_textValue->GetValue(); // auto s2 = s1.c_str(); // auto stringValue = s2.AsChar(); // // T filterValue; // ConvertStringToType(stringValue, filterValue); // // std::vector newSearchBuffer; // newSearchBuffer.reserve(m_searchBuffer.size()); // // uint32 gaugeValue = 0; // uint32 count = m_searchBuffer.size(); // uint32 counter = 0; // // for (auto it = m_searchBuffer.begin(); it != m_searchBuffer.end(); ++it) // { // if (m_running) // return; // // T value = memory_read(*it); // if constexpr (std::is_same::value) // { // //float value1 = filterValue * 0.95f; // float diff = filterValue - value; // diff = fabs(diff); // if(diff < value*0.05f) // { // newSearchBuffer.push_back(*it); // } // // } // else // { // if (value == filterValue) // { // newSearchBuffer.push_back(*it); // } // } // // ++counter; // uint32 newValue = counter * 100 / count; // if (newValue > gaugeValue + GAUGE_STEP_SIZE) // { // gaugeValue = newValue; // m_gaugeValue = newValue; // } // } // // m_mutex.lock(); // m_searchBuffer = newSearchBuffer; // m_gaugeValue = 100; // m_mutex.unlock(); // m_isSearchFinished = true; //} //