void CMemoryWindow::OnSearch(wxCommandEvent& event) { wxBusyCursor hourglass_cursor; u8* ram_ptr = nullptr; u32 ram_size = 0; // NOTE: We're assuming the base address is zero. switch (memview->GetMemoryType()) { case 0: default: if (Memory::m_pRAM) { ram_ptr = Memory::m_pRAM; ram_size = Memory::REALRAM_SIZE; } break; case 1: { u8* aram = DSP::GetARAMPtr(); if (aram) { ram_ptr = aram; ram_size = DSP::ARAM_SIZE; } } break; } if (!ram_ptr) { m_search_result_msg->SetLabel(_("Memory Not Ready")); return; } std::vector<u8> search_bytes; wxString search_val = valbox->GetValue(); if (m_rb_hex->GetValue()) { search_val.Trim(true).Trim(false); // If there's a trailing nybble, stick a zero in front to make it a byte if (search_val.size() & 1) search_val.insert(0, 1, '0'); search_bytes.reserve(search_val.size() / 2); wxString conversion_buffer(2, ' '); for (std::size_t i = 0; i < search_val.size(); i += 2) { unsigned long byte = 0; conversion_buffer[0] = search_val[i]; conversion_buffer[1] = search_val[i + 1]; if (!conversion_buffer.ToULong(&byte, 16)) { m_search_result_msg->SetLabel(_("Not Valid Hex")); return; } search_bytes.push_back(static_cast<u8>(byte)); } } else { const auto& bytes = search_val.ToUTF8(); search_bytes.assign(bytes.data(), bytes.data() + bytes.length()); } search_val.Clear(); // For completeness if (search_bytes.size() > ram_size) { m_search_result_msg->SetLabel(_("Value Too Large")); return; } if (search_bytes.empty()) { m_search_result_msg->SetLabel(_("No Value Given")); return; } // Search starting from specified address if there is one. u32 addr = 0; // Base address { wxString addr_val = addrbox->GetValue(); addr_val.Trim(true).Trim(false); if (!addr_val.empty()) { unsigned long addr_ul = 0; if (addr_val.ToULong(&addr_ul, 16)) { addr = static_cast<u32>(addr_ul); // Don't find the result we're already looking at if (m_continue_search && addr == m_last_search_address) addr += 1; } } } // If the current address doesn't leave enough bytes to search then we're done. if (addr >= ram_size - search_bytes.size()) { m_search_result_msg->SetLabel(_("Address Out of Range")); return; } u8* end = &ram_ptr[ram_size - search_bytes.size() + 1]; u8* ptr = &ram_ptr[addr]; while (true) { ptr = std::find(ptr, end, search_bytes[0]); if (ptr == end) { m_search_result_msg->SetLabel(_("No Match")); break; } if (std::equal(search_bytes.begin(), search_bytes.end(), ptr)) { m_search_result_msg->SetLabel(_("Match Found")); u32 offset = static_cast<u32>(ptr - ram_ptr); // NOTE: SetValue() generates a synthetic wxEVT_TEXT addrbox->SetValue(wxString::Format("%08x", offset)); m_last_search_address = offset; m_continue_search = true; break; } ++ptr; } }
void CMemoryWindow::Search(SearchType search_type) { u8* ram_ptr = nullptr; std::size_t ram_size = 0; u32 base_address = 0; switch (m_memory_view->GetMemoryType()) { case 0: default: if (Memory::m_pRAM) { ram_ptr = Memory::m_pRAM; ram_size = Memory::REALRAM_SIZE; base_address = 0x80000000; } break; case 1: { u8* aram = DSP::GetARAMPtr(); if (aram) { ram_ptr = aram; ram_size = DSP::ARAM_SIZE; base_address = 0x0c005000; } } break; } if (!ram_ptr) { m_search_result_msg->SetLabel(_("Memory Not Ready")); return; } std::vector<u8> search_bytes; wxString search_val = m_value_text_ctrl->GetValue(); if (m_rb_hex->GetValue()) { search_val.Trim(true).Trim(false); // If there's a trailing nybble, stick a zero in front to make it a byte if (search_val.size() & 1) search_val.insert(0, 1, '0'); search_bytes.reserve(search_val.size() / 2); wxString conversion_buffer(2, ' '); for (std::size_t i = 0; i < search_val.size(); i += 2) { unsigned long byte = 0; conversion_buffer[0] = search_val[i]; conversion_buffer[1] = search_val[i + 1]; if (!conversion_buffer.ToULong(&byte, 16)) { m_search_result_msg->SetLabel(_("Not Valid Hex")); return; } search_bytes.push_back(static_cast<u8>(byte)); } } else { const auto& bytes = search_val.ToUTF8(); search_bytes.assign(bytes.data(), bytes.data() + bytes.length()); } search_val.Clear(); // For completeness if (search_bytes.size() > ram_size) { m_search_result_msg->SetLabel(_("Value Too Large")); return; } if (search_bytes.empty()) { m_search_result_msg->SetLabel(_("No Value Given")); return; } // Search starting from specified address if there is one. u32 addr = 0; // Physical address { wxString addr_val = m_address_search_ctrl->GetValue(); addr_val.Trim(true).Trim(false); if (!addr_val.empty()) { unsigned long addr_ul = 0; if (addr_val.ToULong(&addr_ul, 16)) { addr = static_cast<u32>(addr_ul); // Get physical address if (addr >= base_address) addr -= base_address; // Don't find the result we're already looking at if (m_continue_search && addr == m_last_search_address && search_type == SearchType::FindNext) { addr += 1; } } } } // If the current address doesn't leave enough bytes to search then we're done. if (addr >= ram_size - search_bytes.size()) { m_search_result_msg->SetLabel(_("Address Out of Range")); return; } const u8* ptr; const u8* end; if (search_type == SearchType::FindNext) { const u8* begin = &ram_ptr[addr]; end = &ram_ptr[ram_size - search_bytes.size() + 1]; ptr = std::search(begin, end, search_bytes.begin(), search_bytes.end()); } else { const u8* begin = ram_ptr; end = &ram_ptr[addr + search_bytes.size() - 1]; ptr = std::find_end(begin, end, search_bytes.begin(), search_bytes.end()); } if (ptr != end) { m_search_result_msg->SetLabel(_("Match Found")); u32 offset = static_cast<u32>(ptr - ram_ptr); // NOTE: SetValue() generates a synthetic wxEVT_TEXT m_address_search_ctrl->SetValue(wxString::Format("%08x", base_address + offset)); m_last_search_address = offset; m_continue_search = true; return; } m_search_result_msg->SetLabel(_("No Match")); }