From 8e6a4388097211bac1f9c94a064211ee4957255f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 1 Feb 2021 23:29:23 -0800 Subject: [PATCH 01/29] Mpeg: Correct incorrect upload size return. --- Core/HW/MediaEngine.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index 0a1e50f52707..d7dca481500c 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -922,8 +922,7 @@ int MediaEngine::writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int vid delete [] imgbuf; } - // Account for the y offset as well. - return videoImageSize + videoLineSize * ypos; + return videoImageSize; #endif // USE_FFMPEG return 0; } From f7740edc6db3fbc2ff54ef7e1005227398a01d94 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 2 Feb 2021 00:08:05 -0800 Subject: [PATCH 02/29] Debugger: Add more metadata for memory usage. --- CMakeLists.txt | 2 + Core/Core.vcxproj | 2 + Core/Core.vcxproj.filters | 6 + Core/Debugger/MemBlockInfo.cpp | 34 ++++++ Core/Debugger/MemBlockInfo.h | 36 ++++++ Core/ELF/ElfReader.cpp | 4 +- Core/HLE/ReplaceTables.cpp | 141 ++++++++++++------------ Core/HLE/sceAtrac.cpp | 8 +- Core/HLE/sceCcc.cpp | 26 ++--- Core/HLE/sceHeap.cpp | 2 +- Core/HLE/sceIo.cpp | 6 +- Core/HLE/sceKernelHeap.cpp | 2 +- Core/HLE/sceKernelInterrupt.cpp | 12 +- Core/HLE/sceKernelMemory.cpp | 26 +++-- Core/HLE/sceKernelThread.cpp | 7 +- Core/HLE/sceMp3.cpp | 8 +- Core/HLE/sceNet.cpp | 13 +-- Core/HW/MediaEngine.cpp | 11 +- Core/HW/SimpleAudioDec.cpp | 2 + Core/MemMap.cpp | 4 +- Core/MemMapHelpers.h | 9 +- Core/Util/BlockAllocator.cpp | 23 ++-- Core/Util/BlockAllocator.h | 5 +- GPU/Common/FramebufferManagerCommon.cpp | 12 +- GPU/GPUCommon.cpp | 11 +- GPU/Software/SoftGpu.cpp | 6 +- UWP/CoreUWP/CoreUWP.vcxproj | 2 + UWP/CoreUWP/CoreUWP.vcxproj.filters | 6 + android/jni/Android.mk | 1 + 29 files changed, 276 insertions(+), 151 deletions(-) create mode 100644 Core/Debugger/MemBlockInfo.cpp create mode 100644 Core/Debugger/MemBlockInfo.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 56f617ae1fb9..2f2a9cd8d7ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1482,6 +1482,8 @@ add_library(${CoreLibName} ${CoreLinkType} Core/Debugger/Breakpoints.cpp Core/Debugger/Breakpoints.h Core/Debugger/DebugInterface.h + Core/Debugger/MemBlockInfo.cpp + Core/Debugger/MemBlockInfo.h Core/Debugger/SymbolMap.cpp Core/Debugger/SymbolMap.h Core/Debugger/DisassemblyManager.cpp diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 065a61aff354..c0c9051d7fc8 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -429,6 +429,7 @@ + @@ -977,6 +978,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 51d07653fd1e..f66273cddd48 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -977,6 +977,9 @@ MIPS\fake + + Debugger + @@ -1670,6 +1673,9 @@ MIPS\fake + + Debugger + diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp new file mode 100644 index 000000000000..1cb51ae94929 --- /dev/null +++ b/Core/Debugger/MemBlockInfo.cpp @@ -0,0 +1,34 @@ +// Copyright (c) 2021- PPSSPP Project. + +// 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, version 2.0 or later versions. + +// 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "Core/Debugger/Breakpoints.h" +#include "Core/Debugger/MemBlockInfo.h" +#include "Core/MIPS/MIPS.h" + +void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const std::string &tag) { + NotifyMemInfoPC(flags, start, size, currentMIPS->pc, tag); +} + +void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_t pc, const std::string &tag) { + // TODO + + if (flags & MemBlockFlags::WRITE) { + CBreakPoints::ExecMemCheck(start, true, size, pc); + } else if (flags & MemBlockFlags::READ) { + CBreakPoints::ExecMemCheck(start, false, size, pc); + } +} diff --git a/Core/Debugger/MemBlockInfo.h b/Core/Debugger/MemBlockInfo.h new file mode 100644 index 000000000000..a150b2f272cc --- /dev/null +++ b/Core/Debugger/MemBlockInfo.h @@ -0,0 +1,36 @@ +// Copyright (c) 2021- PPSSPP Project. + +// 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, version 2.0 or later versions. + +// 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include +#include +#include "Common/Common.h" + +enum class MemBlockFlags { + FREE = 0, + ALLOC = 1, + SUB_ALLOC = 2, + WRITE = 4, + // Not actually logged. + READ = 8, + SUB_FREE = 16, +}; +ENUM_CLASS_BITOPS(MemBlockFlags); + +void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const std::string &tag); +void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_t pc, const std::string &tag); diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index eec53a3c2f72..17bf1f42632b 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -19,7 +19,7 @@ #include "Core/Reporting.h" #include "Core/MIPS/MIPSTables.h" #include "Core/ELF/ElfReader.h" -#include "Core/Debugger/Breakpoints.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/Debugger/SymbolMap.h" #include "Core/HLE/sceKernelMemory.h" #include "Core/HLE/sceKernelModule.h" @@ -478,7 +478,7 @@ int ElfReader::LoadInto(u32 loadAddress, bool fromTop) } memcpy(dst, src, srcSize); - CBreakPoints::ExecMemCheck(writeAddr, true, dstSize, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, writeAddr, dstSize, "ELFLoad"); DEBUG_LOG(LOADER,"Loadable Segment Copied to %08x, size %08x", writeAddr, (u32)p->p_memsz); } } diff --git a/Core/HLE/ReplaceTables.cpp b/Core/HLE/ReplaceTables.cpp index 86f696e9949f..9e30cad0dccc 100644 --- a/Core/HLE/ReplaceTables.cpp +++ b/Core/HLE/ReplaceTables.cpp @@ -24,6 +24,7 @@ #include "Common/Log.h" #include "Core/Config.h" #include "Core/Debugger/Breakpoints.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/Debugger/SymbolMap.h" #include "Core/MemMap.h" #include "Core/MIPS/JitCommon/JitCommon.h" @@ -153,8 +154,8 @@ static int Replace_memcpy() { } RETURN(destPtr); - CBreakPoints::ExecMemCheck(srcPtr, false, bytes, currentMIPS->pc); - CBreakPoints::ExecMemCheck(destPtr, true, bytes, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, "ReplaceMemcpy"); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, "ReplaceMemcpy"); return 10 + bytes / 4; // approximation } @@ -195,8 +196,8 @@ static int Replace_memcpy_jak() { currentMIPS->r[MIPS_REG_A3] = destPtr + bytes; RETURN(destPtr); - CBreakPoints::ExecMemCheck(srcPtr, false, bytes, currentMIPS->pc); - CBreakPoints::ExecMemCheck(destPtr, true, bytes, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, "ReplaceMemcpy"); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, "ReplaceMemcpy"); return 5 + bytes * 8 + 2; // approximation. This is a slow memcpy - a byte copy loop.. } @@ -223,8 +224,8 @@ static int Replace_memcpy16() { } RETURN(destPtr); - CBreakPoints::ExecMemCheck(srcPtr, false, bytes, currentMIPS->pc); - CBreakPoints::ExecMemCheck(destPtr, true, bytes, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, "ReplaceMemcpy16"); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, "ReplaceMemcpy16"); return 10 + bytes / 4; // approximation } @@ -261,8 +262,8 @@ static int Replace_memcpy_swizzled() { RETURN(0); - CBreakPoints::ExecMemCheck(srcPtr, false, pitch * h, currentMIPS->pc); - CBreakPoints::ExecMemCheck(destPtr, true, pitch * h, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, pitch * h, "ReplaceMemcpySwizzle"); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, pitch * h, "ReplaceMemcpySwizzle"); return 10 + (pitch * h) / 4; // approximation } @@ -289,8 +290,8 @@ static int Replace_memmove() { } RETURN(destPtr); - CBreakPoints::ExecMemCheck(srcPtr, false, bytes, currentMIPS->pc); - CBreakPoints::ExecMemCheck(destPtr, true, bytes, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, "ReplaceMemmove"); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, "ReplaceMemmove"); return 10 + bytes / 4; // approximation } @@ -311,7 +312,7 @@ static int Replace_memset() { } RETURN(destPtr); - CBreakPoints::ExecMemCheck(destPtr, true, bytes, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, "ReplaceMemset"); return 10 + bytes / 4; // approximation } @@ -342,7 +343,7 @@ static int Replace_memset_jak() { currentMIPS->r[MIPS_REG_A3] = -1; RETURN(destPtr); - CBreakPoints::ExecMemCheck(destPtr, true, bytes, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, "ReplaceMemset"); return 5 + bytes * 6 + 2; // approximation (hm, inspecting the disasm this should be 5 + 6 * bytes + 2, but this is what works..) } @@ -590,9 +591,9 @@ static int Replace_dl_write_matrix() { #endif } - CBreakPoints::ExecMemCheck(PARAM(2), false, count * sizeof(float), currentMIPS->pc); - CBreakPoints::ExecMemCheck(PARAM(0) + 2 * sizeof(u32), true, sizeof(u32), currentMIPS->pc); - CBreakPoints::ExecMemCheck(dlStruct[2], true, (count + 1) * sizeof(u32), currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, PARAM(2), count * sizeof(float), "ReplaceDLWriteMatrix"); + NotifyMemInfo(MemBlockFlags::WRITE, PARAM(0) + 2 * sizeof(u32), sizeof(u32), "ReplaceDLWriteMatrix"); + NotifyMemInfo(MemBlockFlags::WRITE, dlStruct[2], (count + 1) * sizeof(u32), "ReplaceDLWriteMatrix"); dlStruct[2] += (1 + count) * 4; RETURN(dlStruct[2]); @@ -640,7 +641,7 @@ static int Hook_godseaterburst_blit_texture() { const u32 fb_address = Memory::Read_U32(fb_info); if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00044000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00044000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00044000, "godseaterburst_blit_texture"); } return 0; } @@ -654,7 +655,7 @@ static int Hook_hexyzforce_monoclome_thread() { const u32 fb_address = Memory::Read_U32(fb_info); if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "hexyzforce_monoclome_thread"); } return 0; } @@ -671,7 +672,7 @@ static int Hook_topx_create_saveicon() { const u32 fb_address = currentMIPS->r[MIPS_REG_V0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00044000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00044000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00044000, "topx_create_saveicon"); } return 0; } @@ -680,7 +681,7 @@ static int Hook_ff1_battle_effect() { const u32 fb_address = currentMIPS->r[MIPS_REG_A1]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "ff1_battle_effect"); } return 0; } @@ -690,7 +691,7 @@ static int Hook_dissidia_recordframe_avi() { const u32 fb_address = currentMIPS->r[MIPS_REG_A1]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00044000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00044000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00044000, "dissidia_recordframe_avi"); } return 0; } @@ -711,7 +712,7 @@ static int Hook_brandish_download_frame() { const u32 dest_address = currentMIPS->r[MIPS_REG_A1]; if (Memory::IsRAMAddress(dest_address)) { gpu->PerformMemoryDownload(fb_address, 0x00044000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00044000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00044000, "brandish_download_frame"); } return 0; } @@ -722,7 +723,7 @@ static int Hook_growlanser_create_saveicon() { const u32 sz = fmt == GE_FORMAT_8888 ? 0x00088000 : 0x00044000; if (Memory::IsVRAMAddress(fb_address) && fmt <= 3) { gpu->PerformMemoryDownload(fb_address, sz); - CBreakPoints::ExecMemCheck(fb_address, true, sz, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, sz, "growlanser_create_saveicon"); } return 0; } @@ -733,7 +734,7 @@ static int Hook_sd_gundam_g_generation_download_frame() { const u32 sz = fmt == GE_FORMAT_8888 ? 0x00088000 : 0x00044000; if (Memory::IsVRAMAddress(fb_address) && fmt <= 3) { gpu->PerformMemoryDownload(fb_address, sz); - CBreakPoints::ExecMemCheck(fb_address, true, sz, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, sz, "sd_gundam_g_generation_download_frame"); } return 0; } @@ -742,7 +743,7 @@ static int Hook_narisokonai_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_V0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00044000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00044000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00044000, "narisokonai_download_frame"); } return 0; } @@ -751,7 +752,7 @@ static int Hook_kirameki_school_life_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A2]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "kirameki_school_life_download_frame"); } return 0; } @@ -760,7 +761,7 @@ static int Hook_orenoimouto_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A4]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "orenoimouto_download_frame"); } return 0; } @@ -769,7 +770,7 @@ static int Hook_sakurasou_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_V0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "sakurasou_download_frame"); } return 0; } @@ -778,7 +779,7 @@ static int Hook_suikoden1_and_2_download_frame_1() { const u32 fb_address = currentMIPS->r[MIPS_REG_S4]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "suikoden1_and_2_download_frame_1"); } return 0; } @@ -787,7 +788,7 @@ static int Hook_suikoden1_and_2_download_frame_2() { const u32 fb_address = currentMIPS->r[MIPS_REG_S2]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "suikoden1_and_2_download_frame_2"); } return 0; } @@ -798,7 +799,7 @@ static int Hook_rezel_cross_download_frame() { const u32 sz = fmt == GE_FORMAT_8888 ? 0x00088000 : 0x00044000; if (Memory::IsVRAMAddress(fb_address) && fmt <= 3) { gpu->PerformMemoryDownload(fb_address, sz); - CBreakPoints::ExecMemCheck(fb_address, true, sz, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, sz, "rezel_cross_download_frame"); } return 0; } @@ -807,7 +808,7 @@ static int Hook_kagaku_no_ensemble_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_V0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "kagaku_no_ensemble_download_frame"); } return 0; } @@ -816,7 +817,7 @@ static int Hook_soranokiseki_fc_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A2]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00044000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00044000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00044000, "soranokiseki_fc_download_frame"); } return 0; } @@ -837,7 +838,7 @@ static int Hook_soranokiseki_sc_download_frame() { const u32 dest_address = currentMIPS->r[MIPS_REG_A1]; if (Memory::IsRAMAddress(dest_address)) { gpu->PerformMemoryDownload(fb_address, 0x00044000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00044000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00044000, "soranokiseki_sc_download_frame"); } return 0; } @@ -846,7 +847,7 @@ static int Hook_bokunonatsuyasumi4_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A3]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00044000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00044000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00044000, "bokunonatsuyasumi4_download_frame"); } return 0; } @@ -858,7 +859,7 @@ static int Hook_danganronpa2_1_download_frame() { const u32 fb_address = fb_base + fb_offset_fix; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "danganronpa2_1_download_frame"); } return 0; } @@ -870,7 +871,7 @@ static int Hook_danganronpa2_2_download_frame() { const u32 fb_address = fb_base + fb_offset_fix; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "danganronpa2_2_download_frame"); } return 0; } @@ -882,7 +883,7 @@ static int Hook_danganronpa1_1_download_frame() { const u32 fb_address = fb_base + fb_offset_fix; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "danganronpa1_1_download_frame"); } return 0; } @@ -896,7 +897,7 @@ static int Hook_danganronpa1_2_download_frame() { const u32 fb_address = fb_base + fb_offset_fix; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "danganronpa1_2_download_frame"); } return 0; } @@ -905,7 +906,7 @@ static int Hook_kankabanchoutbr_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A1]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00044000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00044000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00044000, "kankabanchoutbr_download_frame"); } return 0; } @@ -914,7 +915,7 @@ static int Hook_orenoimouto_download_frame_2() { const u32 fb_address = currentMIPS->r[MIPS_REG_A4]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "orenoimouto_download_frame_2"); } return 0; } @@ -923,7 +924,7 @@ static int Hook_rewrite_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "rewrite_download_frame"); } return 0; } @@ -932,7 +933,7 @@ static int Hook_kudwafter_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "kudwafter_download_frame"); } return 0; } @@ -941,7 +942,7 @@ static int Hook_kumonohatateni_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "kumonohatateni_download_frame"); } return 0; } @@ -950,7 +951,7 @@ static int Hook_otomenoheihou_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "otomenoheihou_download_frame"); } return 0; } @@ -959,7 +960,7 @@ static int Hook_grisaianokajitsu_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "grisaianokajitsu_download_frame"); } return 0; } @@ -968,7 +969,7 @@ static int Hook_kokoroconnect_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A3]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "kokoroconnect_download_frame"); } return 0; } @@ -977,7 +978,7 @@ static int Hook_toheart2_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A1]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00044000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00044000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00044000, "toheart2_download_frame"); } return 0; } @@ -986,7 +987,7 @@ static int Hook_toheart2_download_frame_2() { const u32 fb_address = currentMIPS->r[MIPS_REG_A0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "toheart2_download_frame_2"); } return 0; } @@ -995,7 +996,7 @@ static int Hook_flowers_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "flowers_download_frame"); } return 0; } @@ -1004,7 +1005,7 @@ static int Hook_motorstorm_download_frame() { const u32 fb_address = Memory::Read_U32(currentMIPS->r[MIPS_REG_A1] + 0x18); if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "motorstorm_download_frame"); } return 0; } @@ -1013,7 +1014,7 @@ static int Hook_utawarerumono_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "utawarerumono_download_frame"); } return 0; } @@ -1022,7 +1023,7 @@ static int Hook_photokano_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A1]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "photokano_download_frame"); } return 0; } @@ -1031,7 +1032,7 @@ static int Hook_photokano_download_frame_2() { const u32 fb_address = currentMIPS->r[MIPS_REG_A1]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "photokano_download_frame_2"); } return 0; } @@ -1040,7 +1041,7 @@ static int Hook_gakuenheaven_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "gakuenheaven_download_frame"); } return 0; } @@ -1049,7 +1050,7 @@ static int Hook_youkosohitsujimura_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_V0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "youkosohitsujimura_download_frame"); } return 0; } @@ -1080,7 +1081,7 @@ static int Hook_sdgundamggenerationportable_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A3]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "sdgundamggenerationportable_download_frame"); } return 0; } @@ -1090,7 +1091,7 @@ static int Hook_atvoffroadfurypro_download_frame() { const u32 fb_size = (currentMIPS->r[MIPS_REG_S4] >> 3) * currentMIPS->r[MIPS_REG_S3]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, fb_size); - CBreakPoints::ExecMemCheck(fb_address, true, fb_size, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, fb_size, "atvoffroadfurypro_download_frame"); } return 0; } @@ -1100,7 +1101,7 @@ static int Hook_atvoffroadfuryblazintrails_download_frame() { const u32 fb_size = (currentMIPS->r[MIPS_REG_S3] >> 3) * currentMIPS->r[MIPS_REG_S2]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, fb_size); - CBreakPoints::ExecMemCheck(fb_address, true, fb_size, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, fb_size, "atvoffroadfuryblazintrails_download_frame"); } return 0; } @@ -1109,7 +1110,7 @@ static int Hook_littlebustersce_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_A0]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "littlebustersce_download_frame"); } return 0; } @@ -1118,7 +1119,7 @@ static int Hook_shinigamitoshoujo_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_S2]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "shinigamitoshoujo_download_frame"); } return 0; } @@ -1128,7 +1129,7 @@ static int Hook_atvoffroadfuryprodemo_download_frame() { const u32 fb_size = ((currentMIPS->r[MIPS_REG_A0] + currentMIPS->r[MIPS_REG_A1]) >> 3) * currentMIPS->r[MIPS_REG_S2]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, fb_size); - CBreakPoints::ExecMemCheck(fb_address, true, fb_size, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, fb_size, "atvoffroadfuryprodemo_download_frame"); } return 0; } @@ -1137,7 +1138,7 @@ static int Hook_unendingbloodycall_download_frame() { const u32 fb_address = currentMIPS->r[MIPS_REG_T3]; if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00088000, "unendingbloodycall_download_frame"); } return 0; } @@ -1146,7 +1147,7 @@ static int Hook_omertachinmokunookitethelegacy_download_frame() { const u32 fb_address = Memory::Read_U32(currentMIPS->r[MIPS_REG_SP] + 4); if (Memory::IsVRAMAddress(fb_address)) { gpu->PerformMemoryDownload(fb_address, 0x00044000); - CBreakPoints::ExecMemCheck(fb_address, true, 0x00044000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, 0x00044000, "omertachinmokunookitethelegacy_download_frame"); } return 0; } @@ -1166,7 +1167,7 @@ static int Hook_katamari_render_check() { const u32 totalBytes = width * heightBlocks * heightBlockCount; gpu->PerformMemoryDownload(fb_address, totalBytes); - CBreakPoints::ExecMemCheck(fb_address, true, totalBytes, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, totalBytes, "katamari_render_check"); } return 0; } @@ -1175,7 +1176,7 @@ static int Hook_katamari_screenshot_to_565() { u32 fb_address; if (GetMIPSStaticAddress(fb_address, 0x0040, 0x0044)) { gpu->PerformMemoryDownload(0x04000000 | fb_address, 0x00088000); - CBreakPoints::ExecMemCheck(0x04000000 | fb_address, true, 0x00088000, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, 0x04000000 | fb_address, 0x00088000, "katamari_screenshot_to_565"); } return 0; } @@ -1198,7 +1199,7 @@ static int Hook_marvelalliance1_copy_a1_before() { marvelalliance1_copy_size = currentMIPS->r[MIPS_REG_V0] - currentMIPS->r[MIPS_REG_V1]; gpu->PerformMemoryDownload(marvelalliance1_copy_src, marvelalliance1_copy_size); - CBreakPoints::ExecMemCheck(marvelalliance1_copy_src, true, marvelalliance1_copy_size, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, marvelalliance1_copy_src, marvelalliance1_copy_size, "marvelalliance1_copy_a1_before"); return 0; } @@ -1209,14 +1210,14 @@ static int Hook_marvelalliance1_copy_a2_before() { marvelalliance1_copy_size = currentMIPS->r[MIPS_REG_A1] - currentMIPS->r[MIPS_REG_A2]; gpu->PerformMemoryDownload(marvelalliance1_copy_src, marvelalliance1_copy_size); - CBreakPoints::ExecMemCheck(marvelalliance1_copy_src, true, marvelalliance1_copy_size, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, marvelalliance1_copy_src, marvelalliance1_copy_size, "marvelalliance1_copy_a2_before"); return 0; } static int Hook_marvelalliance1_copy_after() { gpu->PerformMemoryUpload(marvelalliance1_copy_dst, marvelalliance1_copy_size); - CBreakPoints::ExecMemCheck(marvelalliance1_copy_dst, false, marvelalliance1_copy_size, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, marvelalliance1_copy_dst, marvelalliance1_copy_size, "marvelalliance1_copy_after"); return 0; } @@ -1249,7 +1250,7 @@ static int Hook_motorstorm_pixel_read() { u32 fb_height = Memory::Read_U16(currentMIPS->r[MIPS_REG_A0] + 0x26); u32 fb_stride = Memory::Read_U16(currentMIPS->r[MIPS_REG_A0] + 0x28); gpu->PerformMemoryDownload(fb_address, fb_height * fb_stride); - CBreakPoints::ExecMemCheck(fb_address, true, fb_height * fb_stride, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, fb_height * fb_stride, "motorstorm_pixel_read"); return 0; } @@ -1259,7 +1260,7 @@ static int Hook_worms_copy_normalize_alpha() { u32 fb_size = currentMIPS->r[MIPS_REG_A2]; if (Memory::IsVRAMAddress(fb_address) && Memory::IsValidRange(fb_address, fb_size)) { gpu->PerformMemoryDownload(fb_address, fb_size); - CBreakPoints::ExecMemCheck(fb_address, true, fb_size, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address, fb_size, "worms_copy_normalize_alpha"); } return 0; } diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index bdaeea8b98bf..19861fc04560 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -26,7 +26,7 @@ #include "Core/MemMapHelpers.h" #include "Core/Reporting.h" #include "Core/Config.h" -#include "Core/Debugger/Breakpoints.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/HW/MediaEngine.h" #include "Core/HW/BufferQueue.h" @@ -1222,7 +1222,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 int avret = swr_convert(atrac->swrCtx_, &out, numSamples, inbuf, numSamples); if (outbufPtr != 0) { u32 outBytes = numSamples * atrac->outputChannels_ * sizeof(s16); - CBreakPoints::ExecMemCheck(outbufPtr, true, outBytes, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, "AtracDecode"); } if (avret < 0) { ERROR_LOG(ME, "swr_convert: Error while converting %d", avret); @@ -1244,7 +1244,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 u32 outBytes = numSamples * atrac->outputChannels_ * sizeof(s16); if (outbuf != nullptr) { memset(outbuf, 0, outBytes); - CBreakPoints::ExecMemCheck(outbufPtr, true, outBytes, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, "AtracDecode"); } } } @@ -2447,7 +2447,7 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo int avret = swr_convert(atrac->swrCtx_, &out, numSamples, (const u8**)atrac->frame_->extended_data, numSamples); u32 outBytes = numSamples * atrac->outputChannels_ * sizeof(s16); - CBreakPoints::ExecMemCheck(samplesAddr, true, outBytes, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, samplesAddr, outBytes, "AtracLowLevelDecode"); if (avret < 0) { ERROR_LOG(ME, "swr_convert: Error while converting %d", avret); } diff --git a/Core/HLE/sceCcc.cpp b/Core/HLE/sceCcc.cpp index 51da54829114..b47d805573c8 100644 --- a/Core/HLE/sceCcc.cpp +++ b/Core/HLE/sceCcc.cpp @@ -21,7 +21,7 @@ #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" -#include "Core/Debugger/Breakpoints.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/MemMap.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" @@ -118,8 +118,8 @@ static int sceCccUTF8toUTF16(u32 dstAddr, u32 dstSize, u32 srcAddr) if (dst < dstEnd) *dst++ = 0; - CBreakPoints::ExecMemCheck(srcAddr, false, utf.byteIndex(), currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstAddr, true, dst.ptr - dstAddr, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, srcAddr, utf.byteIndex(), "sceCcc"); + NotifyMemInfo(MemBlockFlags::WRITE, dstAddr, dst.ptr - dstAddr, "sceCcc"); return n; } @@ -154,8 +154,8 @@ static int sceCccUTF8toSJIS(u32 dstAddr, u32 dstSize, u32 srcAddr) if (dst < dstEnd) *dst++ = 0; - CBreakPoints::ExecMemCheck(srcAddr, false, utf.byteIndex(), currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstAddr, true, dst.ptr - dstAddr, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, srcAddr, utf.byteIndex(), "sceCcc"); + NotifyMemInfo(MemBlockFlags::WRITE, dstAddr, dst.ptr - dstAddr, "sceCcc"); return n; } @@ -185,8 +185,8 @@ static int sceCccUTF16toUTF8(u32 dstAddr, u32 dstSize, u32 srcAddr) if (dst < dstEnd) *dst++ = 0; - CBreakPoints::ExecMemCheck(srcAddr, false, utf.shortIndex() * sizeof(uint16_t), currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstAddr, true, dst.ptr - dstAddr, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, srcAddr, utf.shortIndex() * sizeof(uint16_t), "sceCcc"); + NotifyMemInfo(MemBlockFlags::WRITE, dstAddr, dst.ptr - dstAddr, "sceCcc"); return n; } @@ -221,8 +221,8 @@ static int sceCccUTF16toSJIS(u32 dstAddr, u32 dstSize, u32 srcAddr) if (dst < dstEnd) *dst++ = 0; - CBreakPoints::ExecMemCheck(srcAddr, false, utf.shortIndex() * sizeof(uint16_t), currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstAddr, true, dst.ptr - dstAddr, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, srcAddr, utf.shortIndex() * sizeof(uint16_t), "sceCcc"); + NotifyMemInfo(MemBlockFlags::WRITE, dstAddr, dst.ptr - dstAddr, "sceCcc"); return n; } @@ -257,8 +257,8 @@ static int sceCccSJIStoUTF8(u32 dstAddr, u32 dstSize, u32 srcAddr) if (dst < dstEnd) *dst++ = 0; - CBreakPoints::ExecMemCheck(srcAddr, false, sjis.byteIndex(), currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstAddr, true, dst.ptr - dstAddr, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, srcAddr, sjis.byteIndex(), "sceCcc"); + NotifyMemInfo(MemBlockFlags::WRITE, dstAddr, dst.ptr - dstAddr, "sceCcc"); return n; } @@ -293,8 +293,8 @@ static int sceCccSJIStoUTF16(u32 dstAddr, u32 dstSize, u32 srcAddr) if (dst < dstEnd) *dst++ = 0; - CBreakPoints::ExecMemCheck(srcAddr, false, sjis.byteIndex(), currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstAddr, true, dst.ptr - dstAddr, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, srcAddr, sjis.byteIndex(), "sceCcc"); + NotifyMemInfo(MemBlockFlags::WRITE, dstAddr, dst.ptr - dstAddr, "sceCcc"); return n; } diff --git a/Core/HLE/sceHeap.cpp b/Core/HLE/sceHeap.cpp index e1c802b1498b..e51f6b1d8326 100644 --- a/Core/HLE/sceHeap.cpp +++ b/Core/HLE/sceHeap.cpp @@ -202,7 +202,7 @@ static int sceHeapCreateHeap(const char* name, u32 heapSize, int attr, u32 param heap->address = addr; // Some of the heap is reserved by the implementation (the first 128 bytes, and 8 after each block.) - heap->alloc.Init(heap->address + 128, heap->size - 128); + heap->alloc.Init(heap->address + 128, heap->size - 128, true); heapList[heap->address] = heap; DEBUG_LOG(HLE, "%08x=sceHeapCreateHeap(%s, %08x, %08x, %08x)", heap->address, name, heapSize, attr, paramsPtr); return heap->address; diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 9abfd60f5168..401c1e1a8f0f 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -29,7 +29,7 @@ #include "Core/Core.h" #include "Core/Config.h" #include "Core/ConfigValues.h" -#include "Core/Debugger/Breakpoints.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/ELF/ParamSFO.h" #include "Core/MemMapHelpers.h" #include "Core/System.h" @@ -1026,7 +1026,7 @@ static bool __IoRead(int &result, int id, u32 data_addr, int size, int &us) { result = SCE_KERNEL_ERROR_ILLEGAL_ADDR; return true; } else if (Memory::IsValidAddress(data_addr)) { - CBreakPoints::ExecMemCheck(data_addr, true, size, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, data_addr, size, "IoRead"); u8 *data = (u8 *)Memory::GetPointer(data_addr); u32 validSize = Memory::ValidSize(data_addr, size); if (f->npdrm) { @@ -1162,7 +1162,7 @@ static bool __IoWrite(int &result, int id, u32 data_addr, int size, int &us) { return true; } - CBreakPoints::ExecMemCheck(data_addr, false, size, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, data_addr, size, "IoWrite"); bool useThread = __KernelIsDispatchEnabled() && ioManagerThreadEnabled && size > IO_THREAD_MIN_DATA_SIZE; if (useThread) { diff --git a/Core/HLE/sceKernelHeap.cpp b/Core/HLE/sceKernelHeap.cpp index af2cbdff1d0c..f584684cbbb9 100644 --- a/Core/HLE/sceKernelHeap.cpp +++ b/Core/HLE/sceKernelHeap.cpp @@ -60,7 +60,7 @@ static int sceKernelCreateHeap(int partitionId, int size, int flags, const char heap->name = Name ? Name : ""; // Not sure if this needs validation. heap->size = allocSize; heap->address = addr; - heap->alloc.Init(heap->address + 128, heap->size - 128); + heap->alloc.Init(heap->address + 128, heap->size - 128, true); heap->uid = uid; return hleLogSuccessInfoX(SCEKERNEL, uid); } diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 8d8e4124db02..adaabd362fad 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -29,7 +29,7 @@ #include "Core/HLE/FunctionWrappers.h" #include "Core/MIPS/MIPS.h" -#include "Core/Debugger/Breakpoints.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/HLE/sceKernel.h" #include "Core/HLE/sceKernelThread.h" #include "Core/HLE/sceKernelInterrupt.h" @@ -618,6 +618,7 @@ static u32 sceKernelMemset(u32 addr, u32 fillc, u32 n) Memory::Memset(addr, c, n); } } + NotifyMemInfo(MemBlockFlags::WRITE, addr, n, "KernelMemset"); return addr; } @@ -657,8 +658,8 @@ static u32 sceKernelMemcpy(u32 dst, u32 src, u32 size) } } - CBreakPoints::ExecMemCheck(src, false, size, currentMIPS->pc); - CBreakPoints::ExecMemCheck(dst, true, size, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, src, size, "KernelMemcpy"); + NotifyMemInfo(MemBlockFlags::WRITE, dst, size, "KernelMemcpy"); return dst; } @@ -689,6 +690,8 @@ static u32 sysclib_memcpy(u32 dst, u32 src, u32 size) { if (Memory::IsValidRange(dst, size) && Memory::IsValidRange(src, size)) { memcpy(Memory::GetPointer(dst), Memory::GetPointer(src), size); } + NotifyMemInfo(MemBlockFlags::READ, src, size, "KernelMemcpy"); + NotifyMemInfo(MemBlockFlags::WRITE, dst, size, "KernelMemcpy"); return dst; } @@ -754,6 +757,7 @@ static u32 sysclib_memset(u32 destAddr, int data, int size) { if (Memory::IsValidRange(destAddr, size)) { memset(Memory::GetPointer(destAddr), data, size); } + NotifyMemInfo(MemBlockFlags::WRITE, destAddr, size, "KernelMemset"); return 0; } @@ -786,6 +790,8 @@ static u32 sysclib_memmove(u32 dst, u32 src, u32 size) { if (Memory::IsValidRange(dst, size) && Memory::IsValidRange(src, size)) { memmove(Memory::GetPointer(dst), Memory::GetPointer(src), size); } + NotifyMemInfo(MemBlockFlags::READ, src, size, "KernelMemmove"); + NotifyMemInfo(MemBlockFlags::WRITE, dst, size, "KernelMemmove"); return 0; } diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 50b0b75fdfb6..05e4a7d8e7da 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -20,16 +20,17 @@ #include #include -#include "Common/Serialize/Serializer.h" -#include "Common/Serialize/SerializeFuncs.h" -#include "Common/Serialize/SerializeMap.h" +#include "Core/CoreTiming.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/System.h" #include "Core/MIPS/MIPS.h" #include "Core/MemMapHelpers.h" -#include "Core/CoreTiming.h" #include "Core/Reporting.h" +#include "Common/Serialize/Serializer.h" +#include "Common/Serialize/SerializeFuncs.h" +#include "Common/Serialize/SerializeMap.h" #include "Core/HLE/sceKernel.h" #include "Core/HLE/sceKernelThread.h" @@ -426,8 +427,8 @@ void __KernelFplEndCallback(SceUID threadID, SceUID prevCallbackId); void __KernelMemoryInit() { - kernelMemory.Init(PSP_GetKernelMemoryBase(), PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase()); - userMemory.Init(PSP_GetUserMemoryBase(), PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase()); + kernelMemory.Init(PSP_GetKernelMemoryBase(), PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase(), false); + userMemory.Init(PSP_GetUserMemoryBase(), PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase(), false); Memory::Memset(PSP_GetKernelMemoryBase(), 0, PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase()); Memory::Memset(PSP_GetUserMemoryBase(), 0, PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase()); INFO_LOG(SCEKERNEL, "Kernel and user memory pools initialized"); @@ -510,6 +511,7 @@ static bool __KernelUnlockFplForThread(FPL *fpl, FplWaitingThread &threadInfo, u { u32 blockPtr = fpl->address + fpl->alignedSize * blockNum; Memory::Write_U32(blockPtr, threadInfo.addrPtr); + NotifyMemInfo(MemBlockFlags::SUB_ALLOC, blockPtr, fpl->alignedSize, "FplAllocate"); } else return false; @@ -722,6 +724,7 @@ int sceKernelAllocateFpl(SceUID uid, u32 blockPtrAddr, u32 timeoutPtr) if (blockNum >= 0) { u32 blockPtr = fpl->address + fpl->alignedSize * blockNum; Memory::Write_U32(blockPtr, blockPtrAddr); + NotifyMemInfo(MemBlockFlags::SUB_ALLOC, blockPtr, fpl->alignedSize, "FplAllocate"); } else { SceUID threadID = __KernelGetCurThread(); HLEKernel::RemoveWaitingThread(fpl->waitingThreads, threadID); @@ -753,6 +756,7 @@ int sceKernelAllocateFplCB(SceUID uid, u32 blockPtrAddr, u32 timeoutPtr) if (blockNum >= 0) { u32 blockPtr = fpl->address + fpl->alignedSize * blockNum; Memory::Write_U32(blockPtr, blockPtrAddr); + NotifyMemInfo(MemBlockFlags::SUB_ALLOC, blockPtr, fpl->alignedSize, "FplAllocate"); } else { SceUID threadID = __KernelGetCurThread(); HLEKernel::RemoveWaitingThread(fpl->waitingThreads, threadID); @@ -784,6 +788,7 @@ int sceKernelTryAllocateFpl(SceUID uid, u32 blockPtrAddr) if (blockNum >= 0) { u32 blockPtr = fpl->address + fpl->alignedSize * blockNum; Memory::Write_U32(blockPtr, blockPtrAddr); + NotifyMemInfo(MemBlockFlags::SUB_ALLOC, blockPtr, fpl->alignedSize, "FplAllocate"); return 0; } else { return SCE_KERNEL_ERROR_NO_MEMORY; @@ -812,6 +817,9 @@ int sceKernelFreeFpl(SceUID uid, u32 blockPtr) return SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK; } else { if (fpl->freeBlock(blockNum)) { + u32 blockPtr = fpl->address + fpl->alignedSize * blockNum; + NotifyMemInfo(MemBlockFlags::SUB_FREE, blockPtr, fpl->alignedSize, "FplFree"); + DEBUG_LOG(SCEKERNEL, "sceKernelFreeFpl(%i, %08x)", uid, blockPtr); __KernelSortFplThreads(fpl); @@ -1503,7 +1511,7 @@ SceUID sceKernelCreateVpl(const char *name, int partition, u32 attr, u32 vplSize // A vpl normally has accounting stuff in the first 32 bytes. vpl->address = memBlockPtr + 0x20; - vpl->alloc.Init(vpl->address, vpl->nv.poolSize); + vpl->alloc.Init(vpl->address, vpl->nv.poolSize, true); vpl->header = PSPPointer::Create(memBlockPtr); vpl->header->Init(memBlockPtr, vplSize); @@ -1572,7 +1580,7 @@ static bool __KernelAllocateVpl(SceUID uid, u32 size, u32 addrPtr, u32 &error, b } else { // Padding (normally used to track the allocation.) u32 allocSize = size + 8; - addr = vpl->alloc.Alloc(allocSize, true); + addr = vpl->alloc.Alloc(allocSize, true, "VplAllocate"); } if (addr != (u32) -1) { Memory::Write_U32(addr, addrPtr); @@ -1953,6 +1961,7 @@ int __KernelFreeTls(TLSPL *tls, SceUID threadID) u32 alignedSize = (tls->ntls.blockSize + tls->alignment - 1) & ~(tls->alignment - 1); u32 freedAddress = tls->address + freeBlock * alignedSize; + NotifyMemInfo(MemBlockFlags::SUB_ALLOC, freedAddress, tls->ntls.blockSize, "TlsFree"); // Whenever freeing a block, clear it (even if it's not going to wake anyone.) Memory::Memset(freedAddress, 0, tls->ntls.blockSize); @@ -2227,6 +2236,7 @@ int sceKernelGetTlsAddr(SceUID uid) u32 alignedSize = (tls->ntls.blockSize + tls->alignment - 1) & ~(tls->alignment - 1); u32 allocAddress = tls->address + allocBlock * alignedSize; + NotifyMemInfo(MemBlockFlags::SUB_ALLOC, allocAddress, tls->ntls.blockSize, "TlsAddr"); // We clear the blocks upon first allocation (and also when they are freed, both are necessary.) if (needsClear) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 361a81824f11..f704a67f0bca 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -433,6 +433,7 @@ class PSPThread : public KernelObject { // Fill the stack. if ((nt.attr & PSP_THREAD_ATTR_NO_FILLSTACK) == 0) { Memory::Memset(currentStack.start, 0xFF, nt.stackSize); + NotifyMemInfo(MemBlockFlags::WRITE, currentStack.start, nt.stackSize, "ThreadFillStack"); } context.r[MIPS_REG_SP] = currentStack.start + nt.stackSize; currentStack.end = context.r[MIPS_REG_SP]; @@ -457,6 +458,7 @@ class PSPThread : public KernelObject { if ((nt.attr & PSP_THREAD_ATTR_CLEAR_STACK) != 0 && nt.initialStack != 0) { Memory::Memset(nt.initialStack, 0, nt.stackSize); + NotifyMemInfo(MemBlockFlags::WRITE, currentStack.start, nt.stackSize, "ThreadFreeStack"); } if (nt.attr & PSP_THREAD_ATTR_KERNEL) { @@ -483,6 +485,7 @@ class PSPThread : public KernelObject { // We still drop the threadID at the bottom and fill it, but there's no k0. Memory::Memset(currentStack.start, 0xFF, nt.stackSize); Memory::Write_U32(GetUID(), nt.initialStack); + NotifyMemInfo(MemBlockFlags::WRITE, currentStack.start, nt.stackSize, "ThreadExtendStack"); return true; } @@ -2043,8 +2046,10 @@ int __KernelStartThread(SceUID threadToStartID, int argSize, u32 argBlockPtr, bo } // Now copy argument to stack. - if (!forceArgs && Memory::IsValidAddress(argBlockPtr)) + if (!forceArgs && Memory::IsValidAddress(argBlockPtr)) { Memory::Memcpy(sp, argBlockPtr, argSize); + NotifyMemInfo(MemBlockFlags::WRITE, argBlockPtr, argSize, "ThreadStartArgs"); + } // On the PSP, there's an extra 64 bytes of stack eaten after the args. // This could be stack overflow safety, or just stack eaten by the kernel entry func. diff --git a/Core/HLE/sceMp3.cpp b/Core/HLE/sceMp3.cpp index 9b1056e943b3..de9c3fd8aed7 100644 --- a/Core/HLE/sceMp3.cpp +++ b/Core/HLE/sceMp3.cpp @@ -18,17 +18,18 @@ #include #include -#include "Common/Serialize/SerializeFuncs.h" -#include "Common/Serialize/SerializeMap.h" #include "Core/Config.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/HLE/sceKernelMemory.h" #include "Core/HLE/sceMp3.h" #include "Core/HW/MediaEngine.h" +#include "Core/HW/SimpleAudioDec.h" #include "Core/MemMap.h" #include "Core/Reporting.h" -#include "Core/HW/SimpleAudioDec.h" +#include "Common/Serialize/SerializeFuncs.h" +#include "Common/Serialize/SerializeMap.h" static const u32 ERROR_MP3_INVALID_HANDLE = 0x80671001; static const u32 ERROR_MP3_UNRESERVED_HANDLE = 0x80671102; @@ -698,6 +699,7 @@ static u32 sceMp3LowLevelDecode(u32 mp3, u32 sourceAddr, u32 sourceBytesConsumed int outpcmbytes = 0; ctx->decoder->Decode((void*)inbuff, 4096, outbuff, &outpcmbytes); + NotifyMemInfo(MemBlockFlags::WRITE, samplesAddr, outpcmbytes, "Mp3LowLevelDecode"); Memory::Write_U32(ctx->decoder->GetSourcePos(), sourceBytesConsumedAddr); Memory::Write_U32(outpcmbytes, sampleBytesAddr); diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index d95c055eacb7..94b7a67fcfae 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -678,15 +678,14 @@ static u32 sceWlanGetEtherAddr(u32 addrAddr) { Memory::Memset(addrAddr, PPSSPP_ID, 6); // Making sure the 1st 2-bits on the 1st byte of OUI are zero to prevent issue with some games (ie. Gran Turismo) addr[0] &= 0xfc; - } - else - // Read MAC Address from config - if (!ParseMacAddress(g_Config.sMACAddress.c_str(), addr)) { - ERROR_LOG(SCENET, "Error parsing mac address %s", g_Config.sMACAddress.c_str()); - Memory::Memset(addrAddr, 0, 6); } else { - CBreakPoints::ExecMemCheck(addrAddr, true, 6, currentMIPS->pc); + // Read MAC Address from config + if (!ParseMacAddress(g_Config.sMACAddress.c_str(), addr)) { + ERROR_LOG(SCENET, "Error parsing mac address %s", g_Config.sMACAddress.c_str()); + Memory::Memset(addrAddr, 0, 6); + } } + NotifyMemInfo(MemBlockFlags::WRITE, addrAddr, 6, "WlanEtherAddr"); return hleLogSuccessI(SCENET, hleDelayResult(0, "get ether mac", 200)); } diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index d7dca481500c..58bdf6cec80b 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -17,7 +17,7 @@ #include "Common/Serialize/SerializeFuncs.h" #include "Core/Config.h" -#include "Core/Debugger/Breakpoints.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/HW/MediaEngine.h" #include "Core/MemMap.h" #include "Core/MIPS/MIPS.h" @@ -816,7 +816,7 @@ int MediaEngine::writeVideoImage(u32 bufferPtr, int frameWidth, int videoPixelMo delete [] imgbuf; } - CBreakPoints::ExecMemCheck(bufferPtr, true, videoImageSize, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, bufferPtr, videoImageSize, "VideoDecode"); return videoImageSize; #endif // USE_FFMPEG @@ -871,7 +871,6 @@ int MediaEngine::writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int vid writeVideoLineRGBA(imgbuf, data, width); data += m_desWidth * sizeof(u32); imgbuf += videoLineSize; - CBreakPoints::ExecMemCheck(bufferPtr + y * frameWidth * sizeof(u32), true, width * sizeof(u32), currentMIPS->pc); } break; @@ -881,7 +880,6 @@ int MediaEngine::writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int vid writeVideoLineABGR5650(imgbuf, data, width); data += m_desWidth * sizeof(u16); imgbuf += videoLineSize; - CBreakPoints::ExecMemCheck(bufferPtr + y * frameWidth * sizeof(u16), true, width * sizeof(u16), currentMIPS->pc); } break; @@ -891,7 +889,6 @@ int MediaEngine::writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int vid writeVideoLineABGR5551(imgbuf, data, width); data += m_desWidth * sizeof(u16); imgbuf += videoLineSize; - CBreakPoints::ExecMemCheck(bufferPtr + y * frameWidth * sizeof(u16), true, width * sizeof(u16), currentMIPS->pc); } break; @@ -901,7 +898,6 @@ int MediaEngine::writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int vid writeVideoLineABGR4444(imgbuf, data, width); data += m_desWidth * sizeof(u16); imgbuf += videoLineSize; - CBreakPoints::ExecMemCheck(bufferPtr + y * frameWidth * sizeof(u16), true, width * sizeof(u16), currentMIPS->pc); } break; @@ -921,6 +917,7 @@ int MediaEngine::writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int vid DoSwizzleTex16((const u32 *)imgbuf, buffer, bxc, byc, videoLineSize); delete [] imgbuf; } + NotifyMemInfo(MemBlockFlags::WRITE, bufferPtr, videoImageSize, "VideoDecodeRange"); return videoImageSize; #endif // USE_FFMPEG @@ -995,7 +992,7 @@ int MediaEngine::getAudioSamples(u32 bufferPtr) { ERROR_LOG(ME, "Audio (%s) decode failed during video playback", GetCodecName(m_audioType)); } - CBreakPoints::ExecMemCheck(bufferPtr, true, outbytes, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, bufferPtr, outbytes, "VideoDecodeAudio"); } return 0x2000; diff --git a/Core/HW/SimpleAudioDec.cpp b/Core/HW/SimpleAudioDec.cpp index 2e9ac873d42d..8475e541a8c4 100644 --- a/Core/HW/SimpleAudioDec.cpp +++ b/Core/HW/SimpleAudioDec.cpp @@ -19,6 +19,7 @@ #include "Common/Serialize/SerializeFuncs.h" #include "Core/Config.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/HW/SimpleAudioDec.h" #include "Core/HW/MediaEngine.h" @@ -375,6 +376,7 @@ u32 AuCtx::AuDecode(u32 pcmAddr) { memset(outbuf + outpcmbufsize, 0, PCMBufSize - outpcmbufsize); } + NotifyMemInfo(MemBlockFlags::WRITE, pcmAddr, outpcmbufsize, "AuDecode"); if (pcmAddr) Memory::Write_U32(PCMBuf, pcmAddr); return outpcmbufsize; diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index d027fdd191a3..a751a94bfc40 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -38,7 +38,7 @@ #include "Core/Core.h" #include "Core/Debugger/SymbolMap.h" -#include "Core/Debugger/Breakpoints.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/Config.h" #include "Core/ConfigValues.h" #include "Core/HLE/ReplaceTables.h" @@ -468,7 +468,7 @@ void Memset(const u32 _Address, const u8 _iValue, const u32 _iLength) { Write_U8(_iValue, (u32)(_Address + i)); } - CBreakPoints::ExecMemCheck(_Address, true, _iLength, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, _Address, _iLength, "Memset"); } } // namespace diff --git a/Core/MemMapHelpers.h b/Core/MemMapHelpers.h index 9431db5c0d5c..f5bda4a6f91b 100644 --- a/Core/MemMapHelpers.h +++ b/Core/MemMapHelpers.h @@ -18,7 +18,7 @@ #pragma once #include "Common/CommonTypes.h" -#include "Core/Debugger/Breakpoints.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/MemMap.h" #include "Core/MIPS/MIPS.h" @@ -33,7 +33,7 @@ inline void Memcpy(const u32 to_address, const void *from_data, const u32 len) u8 *to = GetPointer(to_address); if (to) { memcpy(to, from_data, len); - CBreakPoints::ExecMemCheck(to_address, true, len, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, "Memcpy"); } // if not, GetPointer will log. } @@ -43,7 +43,7 @@ inline void Memcpy(void *to_data, const u32 from_address, const u32 len) const u8 *from = GetPointer(from_address); if (from) { memcpy(to_data, from, len); - CBreakPoints::ExecMemCheck(from_address, false, len, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, from_address, len, "Memcpy"); } // if not, GetPointer will log. } @@ -51,7 +51,8 @@ inline void Memcpy(void *to_data, const u32 from_address, const u32 len) inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len) { Memcpy(GetPointer(to_address), from_address, len); - CBreakPoints::ExecMemCheck(to_address, true, len, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, from_address, len, "Memcpy"); + NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, "Memcpy"); } void Memset(const u32 _Address, const u8 _Data, const u32 _iLength); diff --git a/Core/Util/BlockAllocator.cpp b/Core/Util/BlockAllocator.cpp index 7dfa4637ba75..76ac5b03d18d 100644 --- a/Core/Util/BlockAllocator.cpp +++ b/Core/Util/BlockAllocator.cpp @@ -21,6 +21,7 @@ #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" #include "Common/StringUtils.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/Util/BlockAllocator.h" #include "Core/Reporting.h" @@ -35,14 +36,14 @@ BlockAllocator::~BlockAllocator() Shutdown(); } -void BlockAllocator::Init(u32 rangeStart, u32 rangeSize) -{ +void BlockAllocator::Init(u32 rangeStart, u32 rangeSize, bool suballoc) { Shutdown(); rangeStart_ = rangeStart; rangeSize_ = rangeSize; //Initial block, covering everything top_ = new Block(rangeStart_, rangeSize_, false, NULL, NULL); bottom_ = top_; + suballoc_ = suballoc; } void BlockAllocator::Shutdown() @@ -90,7 +91,7 @@ u32 BlockAllocator::AllocAligned(u32 &size, u32 sizeGrain, u32 grain, bool fromT if (offset >= grain_) InsertFreeBefore(&b, offset); b.taken = true; - b.SetTag(tag); + b.SetAllocated(tag, suballoc_); return b.start; } else @@ -99,7 +100,7 @@ u32 BlockAllocator::AllocAligned(u32 &size, u32 sizeGrain, u32 grain, bool fromT if (offset >= grain_) InsertFreeBefore(&b, offset); b.taken = true; - b.SetTag(tag); + b.SetAllocated(tag, suballoc_); return b.start; } } @@ -120,7 +121,7 @@ u32 BlockAllocator::AllocAligned(u32 &size, u32 sizeGrain, u32 grain, bool fromT if (offset >= grain_) InsertFreeAfter(&b, offset); b.taken = true; - b.SetTag(tag); + b.SetAllocated(tag, suballoc_); return b.start; } else @@ -129,7 +130,7 @@ u32 BlockAllocator::AllocAligned(u32 &size, u32 sizeGrain, u32 grain, bool fromT if (offset >= grain_) InsertFreeAfter(&b, offset); b.taken = true; - b.SetTag(tag); + b.SetAllocated(tag, suballoc_); return b.start; } } @@ -195,7 +196,7 @@ u32 BlockAllocator::AllocAt(u32 position, u32 size, const char *tag) if (b.size != alignedSize) InsertFreeAfter(&b, b.size - alignedSize); b.taken = true; - b.SetTag(tag); + b.SetAllocated(tag, suballoc_); CheckBlocks(); return position; } @@ -205,7 +206,7 @@ u32 BlockAllocator::AllocAt(u32 position, u32 size, const char *tag) if (b.size > alignedSize) InsertFreeAfter(&b, b.size - alignedSize); b.taken = true; - b.SetTag(tag); + b.SetAllocated(tag, suballoc_); return position; } @@ -268,6 +269,7 @@ bool BlockAllocator::Free(u32 position) Block *b = GetBlockFromAddress(position); if (b && b->taken) { + NotifyMemInfo(suballoc_ ? MemBlockFlags::SUB_FREE : MemBlockFlags::FREE, b->start, b->size, ""); b->taken = false; MergeFreeBlocks(b); return true; @@ -284,6 +286,7 @@ bool BlockAllocator::FreeExact(u32 position) Block *b = GetBlockFromAddress(position); if (b && b->taken && b->start == position) { + NotifyMemInfo(suballoc_ ? MemBlockFlags::SUB_FREE : MemBlockFlags::FREE, b->start, b->size, ""); b->taken = false; MergeFreeBlocks(b); return true; @@ -485,8 +488,8 @@ BlockAllocator::Block::Block(u32 _start, u32 _size, bool _taken, Block *_prev, B truncate_cpy(tag, "(untitled)"); } -void BlockAllocator::Block::SetTag(const char *_tag) -{ +void BlockAllocator::Block::SetAllocated(const char *_tag, bool suballoc) { + NotifyMemInfo(suballoc ? MemBlockFlags::SUB_ALLOC : MemBlockFlags::ALLOC, start, size, _tag); if (_tag) truncate_cpy(tag, _tag); else diff --git a/Core/Util/BlockAllocator.h b/Core/Util/BlockAllocator.h index 32bde54aac2f..91e9642462bf 100644 --- a/Core/Util/BlockAllocator.h +++ b/Core/Util/BlockAllocator.h @@ -27,7 +27,7 @@ class BlockAllocator BlockAllocator(int grain = 16); // 16 byte granularity by default. ~BlockAllocator(); - void Init(u32 _rangeStart, u32 _rangeSize); + void Init(u32 _rangeStart, u32 _rangeSize, bool suballoc); void Shutdown(); void ListBlocks() const; @@ -62,7 +62,7 @@ class BlockAllocator struct Block { Block(u32 _start, u32 _size, bool _taken, Block *_prev, Block *_next); - void SetTag(const char *_tag); + void SetAllocated(const char *_tag, bool suballoc); void DoState(PointerWrap &p); u32 start; u32 size; @@ -78,6 +78,7 @@ class BlockAllocator u32 rangeSize_; u32 grain_; + bool suballoc_; void MergeFreeBlocks(Block *fromBlock); Block *GetBlockFromAddress(u32 addr); diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index f30a05bee54a..1da7f6acbd3b 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -28,7 +28,7 @@ #include "Core/ConfigValues.h" #include "Core/Core.h" #include "Core/CoreParameter.h" -#include "Core/Debugger/Breakpoints.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/Host.h" #include "Core/MIPS/MIPS.h" #include "Core/Reporting.h" @@ -1690,10 +1690,14 @@ void FramebufferManagerCommon::ApplyClearToMemory(int x1, int y1, int x2, int y2 const int stride = gstate.FrameBufStride(); const int width = x2 - x1; + const int byteStride = stride * bpp; + const int byteWidth = width * bpp; + for (int y = y1; y < y2; ++y) { + NotifyMemInfo(MemBlockFlags::WRITE, gstate.getFrameBufAddress() + x1 * bpp + y * byteStride, byteWidth, "FramebufferClear"); + } + // Can use memset for simple cases. Often alpha is different and gums up the works. if (singleByteClear) { - const int byteStride = stride * bpp; - const int byteWidth = width * bpp; addr += x1 * bpp; for (int y = y1; y < y2; ++y) { memset(addr + y * byteStride, clearBits, byteWidth); @@ -2166,7 +2170,7 @@ void FramebufferManagerCommon::PackFramebufferSync_(VirtualFramebuffer *vfb, int if (destPtr) { draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, x, y, w, h, destFormat, destPtr, vfb->fb_stride, "PackFramebufferSync_"); - CBreakPoints::ExecMemCheck(fb_address + dstByteOffset, true, dstSize, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address + dstByteOffset, dstSize, "FramebufferPack"); } else { ERROR_LOG(G3D, "PackFramebufferSync_: Tried to readback to bad address %08x (stride = %d)", fb_address + dstByteOffset, vfb->fb_stride); } diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 5cbc056a5e26..07139f0c04c1 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -17,6 +17,7 @@ #include "GPU/GPUState.h" #include "Core/Config.h" #include "Core/CoreTiming.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/MemMap.h" #include "Core/Host.h" #include "Core/Reporting.h" @@ -25,7 +26,6 @@ #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HLE/sceKernelThread.h" #include "Core/HLE/sceGe.h" -#include "Core/Debugger/Breakpoints.h" #include "Core/MemMapHelpers.h" #include "Core/Util/PPGeDraw.h" #include "GPU/Common/DrawEngineCommon.h" @@ -2720,14 +2720,17 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) { framebufferManager_->NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason); } - CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstBasePtr + (dstY * dstStride + dstX) * bpp, true, height * dstStride * bpp, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, srcBasePtr + (srcY * srcStride + srcX) * bpp, height * srcStride * bpp, "GPUBlockTransfer"); + NotifyMemInfo(MemBlockFlags::WRITE, dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, "GPUBlockTransfer"); // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. cyclesExecuted += ((height * width * bpp) * 16) / 10; } bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) { + NotifyMemInfo(MemBlockFlags::READ, src, size, "GPUMemcpy"); + NotifyMemInfo(MemBlockFlags::WRITE, dest, size, "GPUMemcpy"); + // Track stray copies of a framebuffer in RAM. MotoGP does this. if (framebufferManager_->MayIntersectFramebuffer(src) || framebufferManager_->MayIntersectFramebuffer(dest)) { if (!framebufferManager_->NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) { @@ -2749,6 +2752,8 @@ bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) { } bool GPUCommon::PerformMemorySet(u32 dest, u8 v, int size) { + NotifyMemInfo(MemBlockFlags::WRITE, dest, size, "GPUMemset"); + // This may indicate a memset, usually to 0, of a framebuffer. if (framebufferManager_->MayIntersectFramebuffer(dest)) { Memory::Memset(dest, v, size); diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index bff4f56be6ca..a04369a7233b 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -26,7 +26,7 @@ #include "Core/Config.h" #include "Core/ConfigValues.h" #include "Core/Core.h" -#include "Core/Debugger/Breakpoints.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/MemMap.h" #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HLE/sceGe.h" @@ -653,8 +653,8 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) { memcpy(dst, src, width * bpp); } - CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc); + NotifyMemInfo(MemBlockFlags::READ, srcBasePtr + (srcY * srcStride + srcX) * bpp, height * srcStride * bpp, "GPUBlockTransfer"); + NotifyMemInfo(MemBlockFlags::WRITE, dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, "GPUBlockTransfer"); // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. cyclesExecuted += ((height * width * bpp) * 16) / 10; diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index 8b40a36f2e1d..8f7b5103032b 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -389,6 +389,7 @@ + @@ -621,6 +622,7 @@ + diff --git a/UWP/CoreUWP/CoreUWP.vcxproj.filters b/UWP/CoreUWP/CoreUWP.vcxproj.filters index c688cd49f595..f324ec020848 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj.filters +++ b/UWP/CoreUWP/CoreUWP.vcxproj.filters @@ -563,6 +563,9 @@ Debugger + + Debugger + Debugger @@ -1372,6 +1375,9 @@ Debugger + + Debugger + Debugger diff --git a/android/jni/Android.mk b/android/jni/Android.mk index e3e9ba19ff25..c012adab9bde 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -403,6 +403,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/WebServer.cpp \ $(SRC)/Core/Debugger/Breakpoints.cpp \ $(SRC)/Core/Debugger/DisassemblyManager.cpp \ + $(SRC)/Core/Debugger/MemBlockInfo.cpp \ $(SRC)/Core/Debugger/SymbolMap.cpp \ $(SRC)/Core/Debugger/WebSocket.cpp \ $(SRC)/Core/Debugger/WebSocket/BreakpointSubscriber.cpp \ From 44a0c54538eadb1bd35d068c62d10adea8394365 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 2 Feb 2021 00:14:56 -0800 Subject: [PATCH 03/29] Debugger: Log access reason on memory breakpoint. --- Core/Debugger/Breakpoints.cpp | 21 +++++++++++---------- Core/Debugger/Breakpoints.h | 6 +++--- Core/Debugger/MemBlockInfo.cpp | 4 ++-- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Core/Debugger/Breakpoints.cpp b/Core/Debugger/Breakpoints.cpp index c988712be35d..6ee1ac8ee6b3 100644 --- a/Core/Debugger/Breakpoints.cpp +++ b/Core/Debugger/Breakpoints.cpp @@ -40,14 +40,15 @@ static std::mutex memCheckMutex_; std::vector CBreakPoints::memChecks_; std::vector CBreakPoints::cleanupMemChecks_; -void MemCheck::Log(u32 addr, bool write, int size, u32 pc) { +void MemCheck::Log(u32 addr, bool write, int size, u32 pc, const std::string &reason) { if (result & BREAK_ACTION_LOG) { + const char *type = write ? "Write" : "Read"; if (logFormat.empty()) { - NOTICE_LOG(MEMMAP, "CHK %s%i at %08x (%s), PC=%08x (%s)", write ? "Write" : "Read", size * 8, addr, g_symbolMap->GetDescription(addr).c_str(), pc, g_symbolMap->GetDescription(pc).c_str()); + NOTICE_LOG(MEMMAP, "CHK %s%i(%s) at %08x (%s), PC=%08x (%s)", type, size * 8, reason.c_str(), addr, g_symbolMap->GetDescription(addr).c_str(), pc, g_symbolMap->GetDescription(pc).c_str()); } else { std::string formatted; CBreakPoints::EvaluateLogFormat(currentDebugMIPS, logFormat, formatted); - NOTICE_LOG(MEMMAP, "CHK %s%i at %08x: %s", write ? "Write" : "Read", size * 8, addr, formatted.c_str()); + NOTICE_LOG(MEMMAP, "CHK %s%i(%s) at %08x: %s", type, size * 8, reason.c_str(), addr, formatted.c_str()); } } } @@ -62,10 +63,10 @@ BreakAction MemCheck::Apply(u32 addr, bool write, int size, u32 pc) { return BREAK_ACTION_IGNORE; } -BreakAction MemCheck::Action(u32 addr, bool write, int size, u32 pc) { +BreakAction MemCheck::Action(u32 addr, bool write, int size, u32 pc, const std::string &reason) { int mask = write ? MEMCHECK_WRITE : MEMCHECK_READ; if (cond & mask) { - Log(addr, write, size, pc); + Log(addr, write, size, pc, reason); if ((result & BREAK_ACTION_PAUSE) && coreState != CORE_POWERUP) { Core_EnableStepping(true); host->SetDebugMode(true); @@ -94,7 +95,7 @@ void MemCheck::JitBeforeAction(u32 addr, bool write, int size, u32 pc) { // We have to break to find out if it changed. Core_EnableStepping(true); } else { - Action(addr, write, size, pc); + Action(addr, write, size, pc, "CPU"); } } @@ -116,7 +117,7 @@ void MemCheck::JitCleanup(bool changed) return; if (changed) - Log(lastAddr, true, lastSize, lastPC); + Log(lastAddr, true, lastSize, lastPC, "CPU"); // Resume if it should not have gone to stepping, or if it did not change. if ((!(result & BREAK_ACTION_PAUSE) || !changed) && coreState == CORE_STEPPING) @@ -504,7 +505,7 @@ MemCheck *CBreakPoints::GetMemCheckLocked(u32 address, int size) { return 0; } -BreakAction CBreakPoints::ExecMemCheck(u32 address, bool write, int size, u32 pc) +BreakAction CBreakPoints::ExecMemCheck(u32 address, bool write, int size, u32 pc, const std::string &reason) { if (!anyMemChecks_) return BREAK_ACTION_IGNORE; @@ -514,7 +515,7 @@ BreakAction CBreakPoints::ExecMemCheck(u32 address, bool write, int size, u32 pc check->Apply(address, write, size, pc); auto copy = *check; guard.unlock(); - return copy.Action(address, write, size, pc); + return copy.Action(address, write, size, pc, reason); } return BREAK_ACTION_IGNORE; } @@ -547,7 +548,7 @@ BreakAction CBreakPoints::ExecOpMemCheck(u32 address, u32 pc) check->Apply(address, write, size, pc); auto copy = *check; guard.unlock(); - return copy.Action(address, write, size, pc); + return copy.Action(address, write, size, pc, "CPU"); } } return BREAK_ACTION_IGNORE; diff --git a/Core/Debugger/Breakpoints.h b/Core/Debugger/Breakpoints.h index bd3dd670e487..ffb9118cb52e 100644 --- a/Core/Debugger/Breakpoints.h +++ b/Core/Debugger/Breakpoints.h @@ -96,13 +96,13 @@ struct MemCheck { // Called on the stored memcheck (affects numHits, etc.) BreakAction Apply(u32 addr, bool write, int size, u32 pc); // Called on a copy. - BreakAction Action(u32 addr, bool write, int size, u32 pc); + BreakAction Action(u32 addr, bool write, int size, u32 pc, const std::string &reason); void JitBeforeApply(u32 addr, bool write, int size, u32 pc); void JitBeforeAction(u32 addr, bool write, int size, u32 pc); bool JitApplyChanged(); void JitCleanup(bool changed); - void Log(u32 addr, bool write, int size, u32 pc); + void Log(u32 addr, bool write, int size, u32 pc, const std::string &reason); bool IsEnabled() const { return (result & BREAK_ACTION_PAUSE) != 0; @@ -151,7 +151,7 @@ class CBreakPoints static bool GetMemCheck(u32 start, u32 end, MemCheck *check); static bool GetMemCheckInRange(u32 address, int size, MemCheck *check); - static BreakAction ExecMemCheck(u32 address, bool write, int size, u32 pc); + static BreakAction ExecMemCheck(u32 address, bool write, int size, u32 pc, const std::string &reason); static BreakAction ExecOpMemCheck(u32 address, u32 pc); // Executes memchecks but used by the jit. Cleanup finalizes after jit is done. diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 1cb51ae94929..09c5d2749ed5 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -27,8 +27,8 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_ // TODO if (flags & MemBlockFlags::WRITE) { - CBreakPoints::ExecMemCheck(start, true, size, pc); + CBreakPoints::ExecMemCheck(start, true, size, pc, tag); } else if (flags & MemBlockFlags::READ) { - CBreakPoints::ExecMemCheck(start, false, size, pc); + CBreakPoints::ExecMemCheck(start, false, size, pc, tag); } } From ca7d127adc06613a3fefeef41f029f6b967bace5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 2 Feb 2021 00:44:35 -0800 Subject: [PATCH 04/29] Debugger: Notate more cases of memory clears. --- Core/ELF/ElfReader.cpp | 3 ++- Core/HLE/sceKernelMemory.cpp | 5 ++++- Core/HLE/sceKernelModule.cpp | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index 17bf1f42632b..f3a3d1bcb215 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -475,10 +475,11 @@ int ElfReader::LoadInto(u32 loadAddress, bool fromTop) if (srcSize < dstSize) { memset(dst + srcSize, 0, dstSize - srcSize); //zero out bss + NotifyMemInfo(MemBlockFlags::WRITE, writeAddr + srcSize, dstSize - srcSize, "ELFZero"); } memcpy(dst, src, srcSize); - NotifyMemInfo(MemBlockFlags::WRITE, writeAddr, dstSize, "ELFLoad"); + NotifyMemInfo(MemBlockFlags::WRITE, writeAddr, srcSize, "ELFLoad"); DEBUG_LOG(LOADER,"Loadable Segment Copied to %08x, size %08x", writeAddr, (u32)p->p_memsz); } } diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 05e4a7d8e7da..50439e5d2b47 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -1965,6 +1965,7 @@ int __KernelFreeTls(TLSPL *tls, SceUID threadID) // Whenever freeing a block, clear it (even if it's not going to wake anyone.) Memory::Memset(freedAddress, 0, tls->ntls.blockSize); + NotifyMemInfo(MemBlockFlags::WRITE, freedAddress, tls->ntls.blockSize, "TlsFree"); // First, let's remove the end check for the freeing thread. auto freeingLocked = tlsplThreadEndChecks.equal_range(threadID); @@ -2239,8 +2240,10 @@ int sceKernelGetTlsAddr(SceUID uid) NotifyMemInfo(MemBlockFlags::SUB_ALLOC, allocAddress, tls->ntls.blockSize, "TlsAddr"); // We clear the blocks upon first allocation (and also when they are freed, both are necessary.) - if (needsClear) + if (needsClear) { Memory::Memset(allocAddress, 0, tls->ntls.blockSize); + NotifyMemInfo(MemBlockFlags::WRITE, allocAddress, tls->ntls.blockSize, "TlsAddr"); + } return allocAddress; } diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 5ea2a721c145..5faa9ea6ef4d 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -857,6 +857,7 @@ void PSPModule::Cleanup() { Memory::Write_U32(MIPS_MAKE_BREAK(1), nm.text_addr + i); } Memory::Memset(nm.text_addr + nm.text_size, -1, nm.data_size + nm.bss_size); + NotifyMemInfo(MemBlockFlags::WRITE, nm.text_addr + nm.text_size, nm.data_size + nm.bss_size, "ModuleClear"); // Let's also invalidate, just to make sure it's cleared out for any future data. currentMIPS->InvalidateICache(memoryBlockAddr, memoryBlockSize); From 9ead4360694a9b01cd005d8e9d52a8359d59a850 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 2 Feb 2021 00:44:52 -0800 Subject: [PATCH 05/29] Debugger: Specifically tag relocations. This is useful info. --- Core/ELF/ElfReader.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index f3a3d1bcb215..917bcb48f1ce 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -170,11 +170,7 @@ bool ElfReader::LoadRelocations(const Elf32_Rel *rels, int numRelocs) break; case R_MIPS_16: - { - char temp[256]; - op = (op & 0xFFFF0000) | (((int)(op & 0xFFFF) + (int)relocateTo) & 0xFFFF); - MIPSDisAsm(MIPSOpcode(op), 0, temp); - } + op = (op & 0xFFFF0000) | (((int)(op & 0xFFFF) + (int)relocateTo) & 0xFFFF); break; case R_MIPS_NONE: @@ -190,6 +186,7 @@ bool ElfReader::LoadRelocations(const Elf32_Rel *rels, int numRelocs) break; } Memory::Write_U32(op, addr); + NotifyMemInfo(MemBlockFlags::WRITE, addr, 4, "Relocation"); } if (numErrors) { WARN_LOG(LOADER, "%i bad relocations found!!!", numErrors); @@ -348,6 +345,7 @@ void ElfReader::LoadRelocations2(int rel_seg) } Memory::Write_U32(op, rel_offset); + NotifyMemInfo(MemBlockFlags::WRITE, addr, 4, "Relocation2"); rcount += 1; } } From ca2f7df94f53fedb2a26d36a6473b7eeedff3bd9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 2 Feb 2021 23:40:57 -0800 Subject: [PATCH 06/29] Debugger: Track memory allocations and writes. --- Core/Debugger/MemBlockInfo.cpp | 272 ++++++++++++++++++++++++++++++++- Core/Debugger/MemBlockInfo.h | 22 ++- Core/HLE/sceKernelMemory.cpp | 4 + 3 files changed, 295 insertions(+), 3 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 09c5d2749ed5..14180ec046c9 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -15,20 +15,290 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "Common/Log.h" +#include "Common/Serialize/Serializer.h" +#include "Common/Serialize/SerializeFuncs.h" #include "Core/Debugger/Breakpoints.h" #include "Core/Debugger/MemBlockInfo.h" #include "Core/MIPS/MIPS.h" +class MemSlabMap { +public: + MemSlabMap(); + ~MemSlabMap(); + + bool Mark(uint32_t addr, uint32_t size, uint32_t pc, bool allocated, const std::string &tag); + bool Find(MemBlockFlags flags, uint32_t addr, uint32_t size, std::vector &results); + void Reset(); + void DoState(PointerWrap &p); + +private: + struct Slab { + uint32_t start; + uint32_t size; + uint32_t pc; + bool allocated; + std::string tag; + Slab *prev; + Slab *next; + + void DoState(PointerWrap &p); + }; + + Slab *FindSlab(uint32_t addr); + void Clear(); + // Returns the new slab after size. + Slab *Split(Slab *slab, uint32_t size); + void MergeAdjacent(Slab *slab); + bool Same(const Slab *a, const Slab *b) const; + void Merge(Slab *a, Slab *b); + + Slab *first_ = nullptr; +}; + +static MemSlabMap allocMap; +static MemSlabMap suballocMap; +static MemSlabMap writeMap; + +MemSlabMap::MemSlabMap() { + Reset(); +} + +MemSlabMap::~MemSlabMap() { + Clear(); +} + +bool MemSlabMap::Mark(uint32_t addr, uint32_t size, uint32_t pc, bool allocated, const std::string &tag) { + uint32_t end = addr + size; + Slab *slab = FindSlab(addr); + Slab *firstMatch = nullptr; + while (slab != nullptr && slab->start < end) { + if (slab->start < addr) + slab = Split(slab, addr - slab->start); + // Don't replace slab, the return is the after part. + if (slab->start + slab->size > end) { + Split(slab, end - slab->start); + } + + slab->allocated = allocated; + if (pc != 0) + slab->pc = pc; + if (!tag.empty()) + slab->tag = tag; + + // Move on to the next one. + if (firstMatch != nullptr) + firstMatch = slab; + slab = slab->next; + } + + if (firstMatch != nullptr) { + // This will merge all those blocks to one. + MergeAdjacent(firstMatch); + return true; + } + return false; +} + +bool MemSlabMap::Find(MemBlockFlags flags, uint32_t addr, uint32_t size, std::vector &results) { + uint32_t end = addr + size; + Slab *slab = FindSlab(addr); + bool found = false; + while (slab != nullptr && slab->start < end) { + results.push_back({ flags, slab->start, slab->size, slab->pc, slab->tag, slab->allocated }); + found = true; + slab = slab->next; + } + return found; +} + +void MemSlabMap::Reset() { + Clear(); + + first_ = new Slab{ 0, UINT_MAX, 0, false, "", nullptr, nullptr }; +} + +void MemSlabMap::DoState(PointerWrap &p) { + auto s = p.Section("MemSlabMap", 1); + if (!s) + return; + + int count = 0; + if (p.mode == p.MODE_READ) { + Clear(); + Do(p, count); + + first_ = new Slab(); + first_->DoState(p); + first_->prev = nullptr; + first_->next = nullptr; + --count; + + Slab *slab = first_; + for (int i = 0; i < count; ++i) { + slab->next = new Slab(); + slab->DoState(p); + + slab->next->prev = slab; + slab = slab->next; + } + } else { + for (Slab *slab = first_; slab != nullptr; slab = slab->next) + ++count; + Do(p, count); + + first_->DoState(p); + --count; + + Slab *slab = first_; + for (int i = 0; i < count; ++i) { + slab->next->DoState(p); + slab = slab->next; + } + } +} + +void MemSlabMap::Slab::DoState(PointerWrap &p) { + auto s = p.Section("MemSlabMapSlab", 1); + if (!s) + return; + + Do(p, start); + Do(p, size); + Do(p, pc); + Do(p, allocated); + Do(p, tag); +} + +void MemSlabMap::Clear() { + Slab *s = first_; + while (s != nullptr) { + Slab *next = s->next; + delete s; + s = next; + } + first_ = nullptr; +} + +MemSlabMap::Slab *MemSlabMap::FindSlab(uint32_t addr) { + Slab *slab = first_; + while (slab != nullptr && slab->start <= addr) { + if (slab->start + slab->size > addr) + return slab; + slab = slab->next; + } + return nullptr; +} + +MemSlabMap::Slab *MemSlabMap::Split(Slab *slab, uint32_t size) { + uint32_t nextStart = slab->start + size; + uint32_t nextSize = slab->size - size; + Slab *next = new Slab{ nextStart, nextSize, slab->pc, slab->allocated, slab->tag, slab, slab->next }; + slab->next = next; + if (next->next) + next->next->prev = next; + + slab->size = size; + return next; +} + +void MemSlabMap::MergeAdjacent(Slab *slab) { + while (slab->next != nullptr && Same(slab, slab->next)) { + Merge(slab, slab->next); + } + while (slab->prev != nullptr && Same(slab, slab->prev)) { + Merge(slab, slab->prev); + } +} + +bool MemSlabMap::Same(const Slab *a, const Slab *b) const { + if (a->allocated != b->allocated) + return false; + if (a->pc != b->pc) + return false; + if (a->tag != b->tag) + return false; + return true; +} + +void MemSlabMap::Merge(Slab *a, Slab *b) { + if (a->next == b) { + _assert_(a->start + a->size == b->start); + a->next = b->next; + + if (a->next) + a->next->prev = a; + } else if (a->prev == b) { + _assert_(b->start + b->size == a->start); + a->start = b->start; + a->prev = b->prev; + + if (a->prev) + a->prev->next = a; + else if (first_ == b) + first_ = a; + } else { + _assert_(false); + } + a->size += b->size; + delete b; +} + void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const std::string &tag) { NotifyMemInfoPC(flags, start, size, currentMIPS->pc, tag); } void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_t pc, const std::string &tag) { - // TODO + if (size == 0) { + return; + } + // Clear the uncached and kernel bits. + start &= ~0xC0000000; + if (flags & MemBlockFlags::ALLOC) { + allocMap.Mark(start, size, pc, true, tag); + } else if (flags & MemBlockFlags::FREE) { + // Maintain the previous allocation tag for debugging. + allocMap.Mark(start, size, 0, false, ""); + suballocMap.Mark(start, size, 0, false, ""); + } + if (flags & MemBlockFlags::SUB_ALLOC) { + suballocMap.Mark(start, size, pc, true, tag); + } else if (flags & MemBlockFlags::SUB_FREE) { + // Maintain the previous allocation tag for debugging. + suballocMap.Mark(start, size, 0, false, ""); + } if (flags & MemBlockFlags::WRITE) { CBreakPoints::ExecMemCheck(start, true, size, pc, tag); + writeMap.Mark(start, size, pc, true, tag); } else if (flags & MemBlockFlags::READ) { CBreakPoints::ExecMemCheck(start, false, size, pc, tag); } } + +std::vector FindMemInfo(uint32_t start, uint32_t size) { + std::vector results; + allocMap.Find(MemBlockFlags::ALLOC, start, size, results); + suballocMap.Find(MemBlockFlags::SUB_ALLOC, start, size, results); + writeMap.Find(MemBlockFlags::WRITE, start, size, results); + return results; +} + +void MemBlockInfoInit() { +} + +void MemBlockInfoShutdown() { + allocMap.Reset(); + suballocMap.Reset(); + writeMap.Reset(); +} + +void MemBlockInfoDoState(PointerWrap &p) { + auto s = p.Section("MemBlockInfo", 0, 1); + if (!s) + return; + + allocMap.DoState(p); + suballocMap.DoState(p); + writeMap.DoState(p); +} diff --git a/Core/Debugger/MemBlockInfo.h b/Core/Debugger/MemBlockInfo.h index a150b2f272cc..573b6701f518 100644 --- a/Core/Debugger/MemBlockInfo.h +++ b/Core/Debugger/MemBlockInfo.h @@ -19,18 +19,36 @@ #include #include +#include #include "Common/Common.h" +class PointerWrap; + enum class MemBlockFlags { - FREE = 0, ALLOC = 1, SUB_ALLOC = 2, WRITE = 4, // Not actually logged. READ = 8, - SUB_FREE = 16, + FREE = 16, + SUB_FREE = 32, }; ENUM_CLASS_BITOPS(MemBlockFlags); +struct MemBlockInfo { + MemBlockFlags flags; + uint32_t start; + uint32_t size; + uint32_t pc; + std::string tag; + bool allocated; +}; + void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const std::string &tag); void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_t pc, const std::string &tag); + +std::vector FindMemInfo(uint32_t start, uint32_t size); + +void MemBlockInfoInit(); +void MemBlockInfoShutdown(); +void MemBlockInfoDoState(PointerWrap &p); diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 50439e5d2b47..7358dd3ffc94 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -427,6 +427,7 @@ void __KernelFplEndCallback(SceUID threadID, SceUID prevCallbackId); void __KernelMemoryInit() { + MemBlockInfoInit(); kernelMemory.Init(PSP_GetKernelMemoryBase(), PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase(), false); userMemory.Init(PSP_GetUserMemoryBase(), PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase(), false); Memory::Memset(PSP_GetKernelMemoryBase(), 0, PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase()); @@ -472,6 +473,8 @@ void __KernelMemoryDoState(PointerWrap &p) if (s >= 2) { Do(p, tlsplThreadEndChecks); } + + MemBlockInfoDoState(p); } void __KernelMemoryShutdown() @@ -487,6 +490,7 @@ void __KernelMemoryShutdown() #endif kernelMemory.Shutdown(); tlsplThreadEndChecks.clear(); + MemBlockInfoShutdown(); } enum SceKernelFplAttr From 88e2b9b740227b4a90e0da340fae7bfe19d63f80 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 2 Feb 2021 23:53:16 -0800 Subject: [PATCH 07/29] Debugger: Notate memset tags directly. --- Core/HLE/HLE.cpp | 2 +- Core/HLE/HLEHelperThread.cpp | 4 ++-- Core/HLE/sceAtrac.cpp | 2 +- Core/HLE/sceKernelMemory.cpp | 10 ++++------ Core/HLE/sceKernelModule.cpp | 3 +-- Core/HLE/sceKernelThread.cpp | 13 +++++-------- Core/HLE/sceMpeg.cpp | 2 +- Core/HLE/scePsmf.cpp | 4 ++-- Core/MemMap.cpp | 4 ++-- Core/MemMapHelpers.h | 2 +- Core/Util/PPGeDraw.cpp | 2 +- GPU/GPUCommon.cpp | 9 ++++----- 12 files changed, 25 insertions(+), 32 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 4427c6bd6c44..d31007beffcf 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -630,7 +630,7 @@ inline void CallSyscallWithFlags(const HLEFunction *info) if (flags & HLE_CLEAR_STACK_BYTES) { u32 stackStart = __KernelGetCurThreadStackStart(); if (currentMIPS->r[MIPS_REG_SP] - info->stackBytesToClear >= stackStart) { - Memory::Memset(currentMIPS->r[MIPS_REG_SP] - info->stackBytesToClear, 0, info->stackBytesToClear); + Memory::Memset(currentMIPS->r[MIPS_REG_SP] - info->stackBytesToClear, 0, info->stackBytesToClear, "HLEStackClear"); } } diff --git a/Core/HLE/HLEHelperThread.cpp b/Core/HLE/HLEHelperThread.cpp index a142820b9222..1a35395c39e6 100644 --- a/Core/HLE/HLEHelperThread.cpp +++ b/Core/HLE/HLEHelperThread.cpp @@ -59,8 +59,8 @@ HLEHelperThread::~HLEHelperThread() { } void HLEHelperThread::AllocEntry(u32 size) { - entry_ = kernelMemory.Alloc(size); - Memory::Memset(entry_, 0, size); + entry_ = kernelMemory.Alloc(size, false, "HLEHelper"); + Memory::Memset(entry_, 0, size, "HLEHelperClear"); currentMIPS->InvalidateICache(entry_, size); } diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 19861fc04560..1b3758507cb2 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -2310,7 +2310,7 @@ static u32 _sceAtracGetContextAddress(int atracID) { u32 contextsize = 256; atrac->context_ = kernelMemory.Alloc(contextsize, false, "Atrac Context"); if (atrac->context_.IsValid()) - Memory::Memset(atrac->context_.ptr, 0, 256); + Memory::Memset(atrac->context_.ptr, 0, 256, "AtracContextClear"); WARN_LOG(ME, "%08x=_sceAtracGetContextAddress(%i): allocated new context", atrac->context_.ptr, atracID); } diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 7358dd3ffc94..fa8a80b61fec 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -430,8 +430,8 @@ void __KernelMemoryInit() MemBlockInfoInit(); kernelMemory.Init(PSP_GetKernelMemoryBase(), PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase(), false); userMemory.Init(PSP_GetUserMemoryBase(), PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase(), false); - Memory::Memset(PSP_GetKernelMemoryBase(), 0, PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase()); - Memory::Memset(PSP_GetUserMemoryBase(), 0, PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase()); + Memory::Memset(PSP_GetKernelMemoryBase(), 0, PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase(), "MemInit"); + Memory::Memset(PSP_GetUserMemoryBase(), 0, PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase(), "MemInit"); INFO_LOG(SCEKERNEL, "Kernel and user memory pools initialized"); vplWaitTimer = CoreTiming::RegisterEvent("VplTimeout", __KernelVplTimeout); @@ -1968,8 +1968,7 @@ int __KernelFreeTls(TLSPL *tls, SceUID threadID) NotifyMemInfo(MemBlockFlags::SUB_ALLOC, freedAddress, tls->ntls.blockSize, "TlsFree"); // Whenever freeing a block, clear it (even if it's not going to wake anyone.) - Memory::Memset(freedAddress, 0, tls->ntls.blockSize); - NotifyMemInfo(MemBlockFlags::WRITE, freedAddress, tls->ntls.blockSize, "TlsFree"); + Memory::Memset(freedAddress, 0, tls->ntls.blockSize, "TlsFree"); // First, let's remove the end check for the freeing thread. auto freeingLocked = tlsplThreadEndChecks.equal_range(threadID); @@ -2245,8 +2244,7 @@ int sceKernelGetTlsAddr(SceUID uid) // We clear the blocks upon first allocation (and also when they are freed, both are necessary.) if (needsClear) { - Memory::Memset(allocAddress, 0, tls->ntls.blockSize); - NotifyMemInfo(MemBlockFlags::WRITE, allocAddress, tls->ntls.blockSize, "TlsAddr"); + Memory::Memset(allocAddress, 0, tls->ntls.blockSize, "TlsAddr"); } return allocAddress; diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 5faa9ea6ef4d..e3906ea6c8b6 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -856,8 +856,7 @@ void PSPModule::Cleanup() { for (u32 i = 0; i < (u32)(nm.text_size + 3); i += 4) { Memory::Write_U32(MIPS_MAKE_BREAK(1), nm.text_addr + i); } - Memory::Memset(nm.text_addr + nm.text_size, -1, nm.data_size + nm.bss_size); - NotifyMemInfo(MemBlockFlags::WRITE, nm.text_addr + nm.text_size, nm.data_size + nm.bss_size, "ModuleClear"); + Memory::Memset(nm.text_addr + nm.text_size, -1, nm.data_size + nm.bss_size, "ModuleClear"); // Let's also invalidate, just to make sure it's cleared out for any future data. currentMIPS->InvalidateICache(memoryBlockAddr, memoryBlockSize); diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index f704a67f0bca..eca32da94b50 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -432,8 +432,7 @@ class PSPThread : public KernelObject { bool FillStack() { // Fill the stack. if ((nt.attr & PSP_THREAD_ATTR_NO_FILLSTACK) == 0) { - Memory::Memset(currentStack.start, 0xFF, nt.stackSize); - NotifyMemInfo(MemBlockFlags::WRITE, currentStack.start, nt.stackSize, "ThreadFillStack"); + Memory::Memset(currentStack.start, 0xFF, nt.stackSize, "ThreadFillStack"); } context.r[MIPS_REG_SP] = currentStack.start + nt.stackSize; currentStack.end = context.r[MIPS_REG_SP]; @@ -441,7 +440,7 @@ class PSPThread : public KernelObject { context.r[MIPS_REG_SP] -= 256; context.r[MIPS_REG_K0] = context.r[MIPS_REG_SP]; u32 k0 = context.r[MIPS_REG_K0]; - Memory::Memset(k0, 0, 0x100); + Memory::Memset(k0, 0, 0x100, "ThreadK0"); Memory::Write_U32(GetUID(), k0 + 0xc0); Memory::Write_U32(nt.initialStack, k0 + 0xc8); Memory::Write_U32(0xffffffff, k0 + 0xf8); @@ -457,8 +456,7 @@ class PSPThread : public KernelObject { DEBUG_LOG(SCEKERNEL, "Freeing thread stack %s", nt.name); if ((nt.attr & PSP_THREAD_ATTR_CLEAR_STACK) != 0 && nt.initialStack != 0) { - Memory::Memset(nt.initialStack, 0, nt.stackSize); - NotifyMemInfo(MemBlockFlags::WRITE, currentStack.start, nt.stackSize, "ThreadFreeStack"); + Memory::Memset(nt.initialStack, 0, nt.stackSize, "ThreadFreeStack"); } if (nt.attr & PSP_THREAD_ATTR_KERNEL) { @@ -483,9 +481,8 @@ class PSPThread : public KernelObject { nt.stackSize = currentStack.end - currentStack.start; // We still drop the threadID at the bottom and fill it, but there's no k0. - Memory::Memset(currentStack.start, 0xFF, nt.stackSize); + Memory::Memset(currentStack.start, 0xFF, nt.stackSize, "ThreadExtendStack"); Memory::Write_U32(GetUID(), nt.initialStack); - NotifyMemInfo(MemBlockFlags::WRITE, currentStack.start, nt.stackSize, "ThreadExtendStack"); return true; } @@ -1294,7 +1291,7 @@ u32 sceKernelReferThreadStatus(u32 threadID, u32 statusPtr) Memory::Memcpy(statusPtr, &t->nt, std::min(wantedSize, (u32)sizeof(t->nt))); // TODO: What is this value? Basic tests show 0... if (wantedSize > sizeof(t->nt)) - Memory::Memset(statusPtr + sizeof(t->nt), 0, wantedSize - sizeof(t->nt)); + Memory::Memset(statusPtr + sizeof(t->nt), 0, wantedSize - sizeof(t->nt), "ThreadStatus"); } else { t->nt.nativeSize = THREADINFO_SIZE; u32 sz = std::min(THREADINFO_SIZE, wantedSize); diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index b98f57d7b409..87ab458172a0 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -1960,7 +1960,7 @@ static u32 sceMpegAtracDecode(u32 mpeg, u32 auAddr, u32 bufferAddr, int init) // We kept track of the stream number here in sceMpegGetAtracAu(). ctx->mediaengine->setAudioStream(atracAu.esBuffer); - Memory::Memset(bufferAddr, 0, MPEG_ATRAC_ES_OUTPUT_SIZE); + Memory::Memset(bufferAddr, 0, MPEG_ATRAC_ES_OUTPUT_SIZE, "MpegAtracClear"); ctx->mediaengine->getAudioSamples(bufferAddr); atracAu.pts = ctx->mediaengine->getAudioTimeStamp() + ctx->mpegFirstTimestamp; diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index c21aa4be1ddb..b49a3bc48ab4 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -965,7 +965,7 @@ static u32 scePsmfVerifyPsmf(u32 psmfAddr) } // Kurohyou 2 (at least the demo) uses an uninitialized value that happens to be zero on the PSP. // It appears to be written by scePsmfVerifyPsmf(), so we write some bytes into the stack here. - Memory::Memset(currentMIPS->r[MIPS_REG_SP] - 0x20, 0, 0x20); + Memory::Memset(currentMIPS->r[MIPS_REG_SP] - 0x20, 0, 0x20, "PsmfStack"); DEBUG_LOG(ME, "scePsmfVerifyPsmf(%08x)", psmfAddr); return 0; } @@ -1656,7 +1656,7 @@ static int scePsmfPlayerGetAudioData(u32 psmfPlayer, u32 audioDataAddr) if (psmfplayer->mediaengine->getAudioSamples(audioDataAddr) == 0) { if (psmfplayer->totalAudioStreams > 0 && (s64)psmfplayer->psmfPlayerAvcAu.pts < (s64)psmfplayer->totalDurationTimestamp - VIDEO_FRAME_DURATION_TS) { // Write zeros for any missing trailing frames so it syncs with the video. - Memory::Memset(audioDataAddr, 0, audioSamplesBytes); + Memory::Memset(audioDataAddr, 0, audioSamplesBytes, "PsmfAudioClear"); } else { ret = (int)ERROR_PSMFPLAYER_NO_MORE_DATA; } diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index a751a94bfc40..6d86bebd037a 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -459,7 +459,7 @@ void Write_Opcode_JIT(const u32 _Address, const Opcode& _Value) Memory::WriteUnchecked_U32(_Value.encoding, _Address); } -void Memset(const u32 _Address, const u8 _iValue, const u32 _iLength) { +void Memset(const u32 _Address, const u8 _iValue, const u32 _iLength, const std::string &tag) { if (IsValidRange(_Address, _iLength)) { uint8_t *ptr = GetPointerUnchecked(_Address); memset(ptr, _iValue, _iLength); @@ -468,7 +468,7 @@ void Memset(const u32 _Address, const u8 _iValue, const u32 _iLength) { Write_U8(_iValue, (u32)(_Address + i)); } - NotifyMemInfo(MemBlockFlags::WRITE, _Address, _iLength, "Memset"); + NotifyMemInfo(MemBlockFlags::WRITE, _Address, _iLength, tag); } } // namespace diff --git a/Core/MemMapHelpers.h b/Core/MemMapHelpers.h index f5bda4a6f91b..451c7237078a 100644 --- a/Core/MemMapHelpers.h +++ b/Core/MemMapHelpers.h @@ -55,7 +55,7 @@ inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len) NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, "Memcpy"); } -void Memset(const u32 _Address, const u8 _Data, const u32 _iLength); +void Memset(const u32 _Address, const u8 _Data, const u32 _iLength, const std::string &tag = "Memset"); template void ReadStruct(u32 address, T *ptr) diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index dc497a146e08..391f3aaf9c9f 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -1261,7 +1261,7 @@ bool PPGeImage::Load() { } Memory::Memcpy(texture_, textureData, dataSize); - Memory::Memset(texture_ + dataSize, 0, texSize - dataSize); + Memory::Memset(texture_ + dataSize, 0, texSize - dataSize, "PPGeTexClear"); free(textureData); lastFrame_ = gpuStats.numFlips; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 07139f0c04c1..e3b21070a9aa 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2728,8 +2728,6 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) { } bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) { - NotifyMemInfo(MemBlockFlags::READ, src, size, "GPUMemcpy"); - NotifyMemInfo(MemBlockFlags::WRITE, dest, size, "GPUMemcpy"); // Track stray copies of a framebuffer in RAM. MotoGP does this. if (framebufferManager_->MayIntersectFramebuffer(src) || framebufferManager_->MayIntersectFramebuffer(dest)) { @@ -2746,23 +2744,24 @@ bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) { return true; } + NotifyMemInfo(MemBlockFlags::READ, src, size, "GPUMemcpy"); + NotifyMemInfo(MemBlockFlags::WRITE, dest, size, "GPUMemcpy"); InvalidateCache(dest, size, GPU_INVALIDATE_HINT); GPURecord::NotifyMemcpy(dest, src, size); return false; } bool GPUCommon::PerformMemorySet(u32 dest, u8 v, int size) { - NotifyMemInfo(MemBlockFlags::WRITE, dest, size, "GPUMemset"); - // This may indicate a memset, usually to 0, of a framebuffer. if (framebufferManager_->MayIntersectFramebuffer(dest)) { - Memory::Memset(dest, v, size); + Memory::Memset(dest, v, size, "GPUMemset"); if (!framebufferManager_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { InvalidateCache(dest, size, GPU_INVALIDATE_HINT); } return true; } + NotifyMemInfo(MemBlockFlags::WRITE, dest, size, "GPUMemset"); // Or perhaps a texture, let's invalidate. InvalidateCache(dest, size, GPU_INVALIDATE_HINT); GPURecord::NotifyMemset(dest, v, size); From e7b968be7314b90d71532c558b24bdc08079aa1a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 3 Feb 2021 00:09:21 -0800 Subject: [PATCH 08/29] Debugger: Notate Memcpys directly as well. --- Core/CwCheat.cpp | 5 +++-- Core/Dialog/PSPMsgDialog.cpp | 2 +- Core/Dialog/PSPNetconfDialog.cpp | 2 +- Core/Dialog/PSPSaveDialog.cpp | 2 +- Core/HLE/HLEHelperThread.cpp | 2 +- Core/HLE/sceDmac.cpp | 3 ++- Core/HLE/sceKernelModule.cpp | 4 ++-- Core/HLE/sceKernelMsgPipe.cpp | 8 ++++---- Core/HLE/sceKernelThread.cpp | 11 +++++------ Core/HLE/sceKernelVTimer.cpp | 2 +- Core/HLE/sceMpeg.cpp | 4 ++-- Core/MemMapHelpers.h | 17 +++++++---------- Core/Util/PPGeDraw.cpp | 2 +- 13 files changed, 31 insertions(+), 33 deletions(-) diff --git a/Core/CwCheat.cpp b/Core/CwCheat.cpp index c886d3c369e2..8243d2fcc290 100644 --- a/Core/CwCheat.cpp +++ b/Core/CwCheat.cpp @@ -11,6 +11,7 @@ #include "Core/CwCheat.h" #include "Core/Config.h" #include "Core/Host.h" +#include "Core/MemMapHelpers.h" #include "Core/MIPS/MIPS.h" #include "Core/ELF/ParamSFO.h" #include "Core/System.h" @@ -924,7 +925,7 @@ void CWCheatEngine::ExecuteOp(const CheatOperation &op, const CheatCode &cheat, InvalidateICache(op.addr, op.val); InvalidateICache(op.copyBytesFrom.destAddr, op.val); - Memory::MemcpyUnchecked(op.copyBytesFrom.destAddr, op.addr, op.val); + Memory::Memcpy(op.copyBytesFrom.destAddr, op.addr, op.val, "CwCheat"); } break; @@ -1106,7 +1107,7 @@ void CWCheatEngine::ExecuteOp(const CheatOperation &op, const CheatCode &cheat, if (Memory::IsValidRange(dstAddr, val) && Memory::IsValidRange(srcAddr, val)) { InvalidateICache(dstAddr, val); InvalidateICache(srcAddr, val); - Memory::MemcpyUnchecked(dstAddr, srcAddr, val); + Memory::Memcpy(dstAddr, srcAddr, val, "CwCheat"); } // Don't perform any further action. type = -1; diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index 8361adbc3e9e..abfe39d7a085 100755 --- a/Core/Dialog/PSPMsgDialog.cpp +++ b/Core/Dialog/PSPMsgDialog.cpp @@ -344,7 +344,7 @@ int PSPMsgDialog::Update(int animSpeed) { messageDialog.result = 0; } - Memory::Memcpy(messageDialogAddr, &messageDialog ,messageDialog.common.size); + Memory::Memcpy(messageDialogAddr, &messageDialog, messageDialog.common.size, "MsgDialogParam"); return 0; } diff --git a/Core/Dialog/PSPNetconfDialog.cpp b/Core/Dialog/PSPNetconfDialog.cpp index f92385de0eb1..ee3bb1b739be 100644 --- a/Core/Dialog/PSPNetconfDialog.cpp +++ b/Core/Dialog/PSPNetconfDialog.cpp @@ -465,7 +465,7 @@ int PSPNetconfDialog::Update(int animSpeed) { } if (GetStatus() == SCE_UTILITY_STATUS_FINISHED || pendingStatus == SCE_UTILITY_STATUS_FINISHED) - Memory::Memcpy(requestAddr, &request, request.common.size); + Memory::Memcpy(requestAddr, &request, request.common.size, "NetConfDialogParam"); return 0; } diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 43877f69fc79..7dd52c896579 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -1032,7 +1032,7 @@ int PSPSaveDialog::Update(int animSpeed) } if (ReadStatus() == SCE_UTILITY_STATUS_FINISHED || pendingStatus == SCE_UTILITY_STATUS_FINISHED) - Memory::Memcpy(requestAddr, &request, request.common.size); + Memory::Memcpy(requestAddr, &request, request.common.size, "SaveDialogParam"); return 0; } diff --git a/Core/HLE/HLEHelperThread.cpp b/Core/HLE/HLEHelperThread.cpp index 1a35395c39e6..5c8a0278fbb2 100644 --- a/Core/HLE/HLEHelperThread.cpp +++ b/Core/HLE/HLEHelperThread.cpp @@ -33,7 +33,7 @@ HLEHelperThread::HLEHelperThread(const char *threadName, u32 instructions[], u32 u32 instrBytes = instrCount * sizeof(u32); u32 totalBytes = instrBytes + sizeof(u32) * 2; AllocEntry(totalBytes); - Memory::Memcpy(entry_, instructions, instrBytes); + Memory::Memcpy(entry_, instructions, instrBytes, "HelperMIPS"); // Just to simplify things, we add the return here. Memory::Write_U32(MIPS_MAKE_JR_RA(), entry_ + instrBytes + 0); diff --git a/Core/HLE/sceDmac.cpp b/Core/HLE/sceDmac.cpp index 4f186facfe7b..4defe951cac7 100644 --- a/Core/HLE/sceDmac.cpp +++ b/Core/HLE/sceDmac.cpp @@ -50,7 +50,8 @@ static int __DmacMemcpy(u32 dst, u32 src, u32 size) { skip = gpu->PerformMemoryCopy(dst, src, size); } if (!skip) { - Memory::Memcpy(dst, Memory::GetPointer(src), size); + // TODO: InvalidateICache src before copy? + Memory::Memcpy(dst, Memory::GetPointer(src), size, "DmacMemcpy"); currentMIPS->InvalidateICache(dst, size); } diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index e3906ea6c8b6..bbcf706d00e6 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1738,13 +1738,13 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str if (param.args > 0) { u32 argpAddr = param.argp; param_argp = new u8[param.args]; - Memory::Memcpy(param_argp, argpAddr, param.args); + Memory::Memcpy(param_argp, argpAddr, param.args, "KernelLoadParam"); } if (param.keyp != 0) { u32 keyAddr = param.keyp; size_t keylen = strlen(Memory::GetCharPointer(keyAddr))+1; param_key = new u8[keylen]; - Memory::Memcpy(param_key, keyAddr, (u32)keylen); + Memory::Memcpy(param_key, keyAddr, (u32)keylen, "KernelLoadParam"); } __KernelLoadReset(); diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 7ff5e423d5a5..24d538609e41 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -105,7 +105,7 @@ struct MsgPipeWaitingThread void ReadBuffer(u32 destPtr, u32 len) { - Memory::Memcpy(destPtr, bufAddr + bufSize - freeSize, len); + Memory::Memcpy(destPtr, bufAddr + bufSize - freeSize, len, "MsgPipeReadBuffer"); freeSize -= len; if (transferredBytes.IsValid()) *transferredBytes += len; @@ -113,7 +113,7 @@ struct MsgPipeWaitingThread void WriteBuffer(u32 srcPtr, u32 len) { - Memory::Memcpy(bufAddr + (bufSize - freeSize), srcPtr, len); + Memory::Memcpy(bufAddr + (bufSize - freeSize), srcPtr, len, "MsgPipeWriteBuffer"); freeSize -= len; if (transferredBytes.IsValid()) *transferredBytes += len; @@ -399,7 +399,7 @@ static int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int wa if (bytesToSend != 0) { - Memory::Memcpy(m->buffer + (m->nmp.bufSize - m->nmp.freeSize), sendBufAddr, bytesToSend); + Memory::Memcpy(m->buffer + (m->nmp.bufSize - m->nmp.freeSize), sendBufAddr, bytesToSend, "MsgPipeSend"); m->nmp.freeSize -= bytesToSend; curSendAddr += bytesToSend; sendSize -= bytesToSend; @@ -492,7 +492,7 @@ static int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSiz u32 bytesToReceive = std::min(receiveSize, m->GetUsedSize()); if (bytesToReceive != 0) { - Memory::Memcpy(curReceiveAddr, m->buffer, bytesToReceive); + Memory::Memcpy(curReceiveAddr, m->buffer, bytesToReceive, "MsgPipeReceive"); m->nmp.freeSize += bytesToReceive; memmove(Memory::GetPointer(m->buffer), Memory::GetPointer(m->buffer) + bytesToReceive, m->GetUsedSize()); curReceiveAddr += bytesToReceive; diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index eca32da94b50..e4b7d91e654c 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -940,7 +940,7 @@ void __KernelThreadingInit() lastSwitchCycles = 0; idleThreadHackAddr = kernelMemory.Alloc(blockSize, false, "threadrethack"); - Memory::Memcpy(idleThreadHackAddr, idleThreadCode, sizeof(idleThreadCode)); + Memory::Memcpy(idleThreadHackAddr, idleThreadCode, sizeof(idleThreadCode), "ThreadMIPS"); u32 pos = idleThreadHackAddr + sizeof(idleThreadCode); for (size_t i = 0; i < ARRAY_SIZE(threadHacks); ++i) { @@ -1288,7 +1288,7 @@ u32 sceKernelReferThreadStatus(u32 threadID, u32 statusPtr) t->nt.nativeSize = THREADINFO_SIZE_AFTER_260; if (wantedSize != 0) - Memory::Memcpy(statusPtr, &t->nt, std::min(wantedSize, (u32)sizeof(t->nt))); + Memory::Memcpy(statusPtr, &t->nt, std::min(wantedSize, (u32)sizeof(t->nt)), "ThreadStatus"); // TODO: What is this value? Basic tests show 0... if (wantedSize > sizeof(t->nt)) Memory::Memset(statusPtr + sizeof(t->nt), 0, wantedSize - sizeof(t->nt), "ThreadStatus"); @@ -1296,7 +1296,7 @@ u32 sceKernelReferThreadStatus(u32 threadID, u32 statusPtr) t->nt.nativeSize = THREADINFO_SIZE; u32 sz = std::min(THREADINFO_SIZE, wantedSize); if (sz != 0) - Memory::Memcpy(statusPtr, &t->nt, sz); + Memory::Memcpy(statusPtr, &t->nt, sz, "ThreadStatus"); } hleEatCycles(1400); @@ -1939,7 +1939,7 @@ SceUID __KernelSetupRootThread(SceUID moduleID, int args, const char *argp, int u32 location = currentMIPS->r[MIPS_REG_SP]; currentMIPS->r[MIPS_REG_A1] = location; if (argp) - Memory::Memcpy(location, argp, args); + Memory::Memcpy(location, argp, args, "ThreadParam"); // Let's assume same as starting a new thread, 64 bytes for safety/kernel. currentMIPS->r[MIPS_REG_SP] -= 64; @@ -2044,8 +2044,7 @@ int __KernelStartThread(SceUID threadToStartID, int argSize, u32 argBlockPtr, bo // Now copy argument to stack. if (!forceArgs && Memory::IsValidAddress(argBlockPtr)) { - Memory::Memcpy(sp, argBlockPtr, argSize); - NotifyMemInfo(MemBlockFlags::WRITE, argBlockPtr, argSize, "ThreadStartArgs"); + Memory::Memcpy(sp, argBlockPtr, argSize, "ThreadStartArgs"); } // On the PSP, there's an extra 64 bytes of stack eaten after the args. diff --git a/Core/HLE/sceKernelVTimer.cpp b/Core/HLE/sceKernelVTimer.cpp index 245db8a3953c..63efc53eda27 100644 --- a/Core/HLE/sceKernelVTimer.cpp +++ b/Core/HLE/sceKernelVTimer.cpp @@ -514,7 +514,7 @@ u32 sceKernelReferVTimerStatus(SceUID uid, u32 statusAddr) { NativeVTimer status = vt->nvt; u32 size = Memory::Read_U32(statusAddr); status.current = __getVTimerCurrentTime(vt); - Memory::Memcpy(statusAddr, &status, std::min(size, (u32)sizeof(status))); + Memory::Memcpy(statusAddr, &status, std::min(size, (u32)sizeof(status)), "VTimerStatus"); } return 0; diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 87ab458172a0..0128edef7927 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -524,8 +524,8 @@ static u32 sceMpegCreate(u32 mpegAddr, u32 dataPtr, u32 size, u32 ringbufferAddr Memory::Write_U32(mpegHandle, mpegAddr); // Initialize fake mpeg struct. - Memory::Memcpy(mpegHandle, "LIBMPEG\0", 8); - Memory::Memcpy(mpegHandle + 8, "001\0", 4); + Memory::Memcpy(mpegHandle, "LIBMPEG\0", 8, "Mpeg"); + Memory::Memcpy(mpegHandle + 8, "001\0", 4, "Mpeg"); Memory::Write_U32(-1, mpegHandle + 12); if (ringbuffer.IsValid()) { Memory::Write_U32(ringbufferAddr, mpegHandle + 16); diff --git a/Core/MemMapHelpers.h b/Core/MemMapHelpers.h index 451c7237078a..0983abdf9b7d 100644 --- a/Core/MemMapHelpers.h +++ b/Core/MemMapHelpers.h @@ -28,31 +28,28 @@ extern MIPSState *currentMIPS; namespace Memory { -inline void Memcpy(const u32 to_address, const void *from_data, const u32 len) -{ +inline void Memcpy(const u32 to_address, const void *from_data, const u32 len, const std::string &tag = "Memcpy") { u8 *to = GetPointer(to_address); if (to) { memcpy(to, from_data, len); - NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, "Memcpy"); + NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, tag); } // if not, GetPointer will log. } -inline void Memcpy(void *to_data, const u32 from_address, const u32 len) -{ +inline void Memcpy(void *to_data, const u32 from_address, const u32 len, const std::string &tag = "Memcpy") { const u8 *from = GetPointer(from_address); if (from) { memcpy(to_data, from, len); - NotifyMemInfo(MemBlockFlags::READ, from_address, len, "Memcpy"); + NotifyMemInfo(MemBlockFlags::READ, from_address, len, tag); } // if not, GetPointer will log. } -inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len) -{ +inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len, const std::string &tag = "Memcpy") { Memcpy(GetPointer(to_address), from_address, len); - NotifyMemInfo(MemBlockFlags::READ, from_address, len, "Memcpy"); - NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, "Memcpy"); + NotifyMemInfo(MemBlockFlags::READ, from_address, len, tag); + NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, tag); } void Memset(const u32 _Address, const u8 _Data, const u32 _iLength, const std::string &tag = "Memset"); diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index 391f3aaf9c9f..19041449ac2d 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -1260,7 +1260,7 @@ bool PPGeImage::Load() { return false; } - Memory::Memcpy(texture_, textureData, dataSize); + Memory::Memcpy(texture_, textureData, dataSize, "PPGeTex"); Memory::Memset(texture_ + dataSize, 0, texSize - dataSize, "PPGeTexClear"); free(textureData); From 76ae1b4d28a2a48b0ee594117fd1bdd6d9e12f0c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 3 Feb 2021 20:10:14 -0800 Subject: [PATCH 09/29] Debugger: Mark framebuffers as VRAM allocations. --- GPU/Common/FramebufferManagerCommon.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 1da7f6acbd3b..4fa5f51157ba 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1305,6 +1305,12 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, char tag[256]; snprintf(tag, sizeof(tag), "%08x_%08x_%dx%d_%s", vfb->fb_address, vfb->z_address, w, h, GeBufferFormatToString(vfb->format)); vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, 1, true, tag }); + if (Memory::IsVRAMAddress(vfb->fb_address) && vfb->fb_stride != 0) { + NotifyMemInfo(MemBlockFlags::ALLOC, vfb->fb_address, ColorBufferByteSize(vfb), tag); + } + if (Memory::IsVRAMAddress(vfb->z_address) && vfb->z_stride != 0) { + NotifyMemInfo(MemBlockFlags::ALLOC, vfb->z_address, vfb->fb_stride * vfb->height * sizeof(uint16_t), std::string("z_") + tag); + } if (old.fbo) { INFO_LOG(FRAMEBUF, "Resizing FBO for %08x : %dx%dx%s", vfb->fb_address, w, h, GeBufferFormatToString(vfb->format)); if (vfb->fbo) { From 10a77d29ab9b6a0980b157774063230db4939bfe Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 3 Feb 2021 20:46:41 -0800 Subject: [PATCH 10/29] Debugger: Track texture usage too. --- Core/Debugger/MemBlockInfo.cpp | 7 ++++ Core/Debugger/MemBlockInfo.h | 13 +++---- GPU/Common/FramebufferManagerCommon.cpp | 4 +-- GPU/Common/TextureCacheCommon.cpp | 7 ++++ GPU/GeConstants.cpp | 48 +++++++++++++++++++++++++ GPU/Vulkan/TextureCacheVulkan.cpp | 2 +- GPU/ge_constants.h | 5 ++- 7 files changed, 76 insertions(+), 10 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 14180ec046c9..80bce43f05bf 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -59,6 +59,7 @@ class MemSlabMap { static MemSlabMap allocMap; static MemSlabMap suballocMap; static MemSlabMap writeMap; +static MemSlabMap textureMap; MemSlabMap::MemSlabMap() { Reset(); @@ -268,6 +269,9 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_ // Maintain the previous allocation tag for debugging. suballocMap.Mark(start, size, 0, false, ""); } + if (flags & MemBlockFlags::TEXTURE) { + textureMap.Mark(start, size, pc, true, tag); + } if (flags & MemBlockFlags::WRITE) { CBreakPoints::ExecMemCheck(start, true, size, pc, tag); writeMap.Mark(start, size, pc, true, tag); @@ -281,6 +285,7 @@ std::vector FindMemInfo(uint32_t start, uint32_t size) { allocMap.Find(MemBlockFlags::ALLOC, start, size, results); suballocMap.Find(MemBlockFlags::SUB_ALLOC, start, size, results); writeMap.Find(MemBlockFlags::WRITE, start, size, results); + textureMap.Find(MemBlockFlags::TEXTURE, start, size, results); return results; } @@ -291,6 +296,7 @@ void MemBlockInfoShutdown() { allocMap.Reset(); suballocMap.Reset(); writeMap.Reset(); + textureMap.Reset(); } void MemBlockInfoDoState(PointerWrap &p) { @@ -301,4 +307,5 @@ void MemBlockInfoDoState(PointerWrap &p) { allocMap.DoState(p); suballocMap.DoState(p); writeMap.DoState(p); + textureMap.DoState(p); } diff --git a/Core/Debugger/MemBlockInfo.h b/Core/Debugger/MemBlockInfo.h index 573b6701f518..91e0a6f643ed 100644 --- a/Core/Debugger/MemBlockInfo.h +++ b/Core/Debugger/MemBlockInfo.h @@ -25,13 +25,14 @@ class PointerWrap; enum class MemBlockFlags { - ALLOC = 1, - SUB_ALLOC = 2, - WRITE = 4, + ALLOC = 0x0001, + SUB_ALLOC = 0x0002, + WRITE = 0x0004, + TEXTURE = 0x0008, // Not actually logged. - READ = 8, - FREE = 16, - SUB_FREE = 32, + READ = 0x0800, + FREE = 0x1000, + SUB_FREE = 0x2000, }; ENUM_CLASS_BITOPS(MemBlockFlags); diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 4fa5f51157ba..aea7f4c0fa42 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1303,13 +1303,13 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, shaderManager_->DirtyLastShader(); char tag[256]; - snprintf(tag, sizeof(tag), "%08x_%08x_%dx%d_%s", vfb->fb_address, vfb->z_address, w, h, GeBufferFormatToString(vfb->format)); + snprintf(tag, sizeof(tag), "FB_%08x_%08x_%dx%d_%s", vfb->fb_address, vfb->z_address, w, h, GeBufferFormatToString(vfb->format)); vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, 1, true, tag }); if (Memory::IsVRAMAddress(vfb->fb_address) && vfb->fb_stride != 0) { NotifyMemInfo(MemBlockFlags::ALLOC, vfb->fb_address, ColorBufferByteSize(vfb), tag); } if (Memory::IsVRAMAddress(vfb->z_address) && vfb->z_stride != 0) { - NotifyMemInfo(MemBlockFlags::ALLOC, vfb->z_address, vfb->fb_stride * vfb->height * sizeof(uint16_t), std::string("z_") + tag); + NotifyMemInfo(MemBlockFlags::ALLOC, vfb->z_address, vfb->fb_stride * vfb->height * sizeof(uint16_t), std::string("Z_") + tag); } if (old.fbo) { INFO_LOG(FRAMEBUF, "Resizing FBO for %08x : %dx%dx%s", vfb->fb_address, w, h, GeBufferFormatToString(vfb->format)); diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index ffe3769ee2c9..64c489a372cc 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -21,7 +21,9 @@ #include "Common/Profiler/Profiler.h" #include "Common/ColorConv.h" #include "Common/MemoryUtil.h" +#include "Common/StringUtils.h" #include "Core/Config.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/Reporting.h" #include "Core/System.h" #include "GPU/Common/FramebufferManagerCommon.h" @@ -1110,6 +1112,8 @@ void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes) { } } } + + NotifyMemInfo(MemBlockFlags::ALLOC, clutAddr, loadBytes, "CLUT"); } // It's possible for a game to (successfully) access outside valid memory. @@ -1294,6 +1298,9 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm int w = gstate.getTextureWidth(level); int h = gstate.getTextureHeight(level); const u8 *texptr = Memory::GetPointer(texaddr); + const uint32_t byteSize = (textureBitsPerPixel[format] * bufw * h) / 8; + + NotifyMemInfo(MemBlockFlags::TEXTURE, texaddr, byteSize, StringFromFormat("Texture_%08x_%dx%d_%s", texaddr, w, h, GeTextureFormatToString(format, clutformat))); switch (format) { case GE_TFMT_CLUT4: diff --git a/GPU/GeConstants.cpp b/GPU/GeConstants.cpp index a8a27685cb43..ab627ee4732f 100644 --- a/GPU/GeConstants.cpp +++ b/GPU/GeConstants.cpp @@ -10,6 +10,16 @@ const char *GeBufferFormatToString(GEBufferFormat fmt) { } } +const char *GEPaletteFormatToString(GEPaletteFormat pfmt) { + switch (pfmt) { + case GE_CMODE_16BIT_BGR5650: return "565"; + case GE_CMODE_16BIT_ABGR5551: return "5551"; + case GE_CMODE_16BIT_ABGR4444: return "4444"; + case GE_CMODE_32BIT_ABGR8888: return "8888"; + default: return "N/A"; + } +} + const char *GeTextureFormatToString(GETextureFormat fmt) { switch (fmt) { case GE_TFMT_5650: return "565"; @@ -26,3 +36,41 @@ const char *GeTextureFormatToString(GETextureFormat fmt) { default: return "N/A"; } } + +const char *GeTextureFormatToString(GETextureFormat tfmt, GEPaletteFormat pfmt) { + switch (tfmt) { + case GE_TFMT_CLUT4: + switch (pfmt) { + case GE_CMODE_16BIT_BGR5650: return "CLUT4_565"; + case GE_CMODE_16BIT_ABGR5551: return "CLUT4_5551"; + case GE_CMODE_16BIT_ABGR4444: return "CLUT4_4444"; + case GE_CMODE_32BIT_ABGR8888: return "CLUT4_8888"; + default: return "N/A"; + } + case GE_TFMT_CLUT8: + switch (pfmt) { + case GE_CMODE_16BIT_BGR5650: return "CLUT8_565"; + case GE_CMODE_16BIT_ABGR5551: return "CLUT8_5551"; + case GE_CMODE_16BIT_ABGR4444: return "CLUT8_4444"; + case GE_CMODE_32BIT_ABGR8888: return "CLUT8_8888"; + default: return "N/A"; + } + case GE_TFMT_CLUT16: + switch (pfmt) { + case GE_CMODE_16BIT_BGR5650: return "CLUT16_565"; + case GE_CMODE_16BIT_ABGR5551: return "CLUT16_5551"; + case GE_CMODE_16BIT_ABGR4444: return "CLUT16_4444"; + case GE_CMODE_32BIT_ABGR8888: return "CLUT16_8888"; + default: return "N/A"; + } + case GE_TFMT_CLUT32: + switch (pfmt) { + case GE_CMODE_16BIT_BGR5650: return "CLUT32_565"; + case GE_CMODE_16BIT_ABGR5551: return "CLUT32_5551"; + case GE_CMODE_16BIT_ABGR4444: return "CLUT32_4444"; + case GE_CMODE_32BIT_ABGR8888: return "CLUT32_8888"; + default: return "N/A"; + } + default: return GeTextureFormatToString(tfmt); + } +} diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 7dd3caef7b1c..4ea6b9321af5 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -862,7 +862,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { } char texName[128]{}; - snprintf(texName, sizeof(texName), "texture_%08x_%s", entry->addr, GeTextureFormatToString((GETextureFormat)entry->format)); + snprintf(texName, sizeof(texName), "texture_%08x_%s", entry->addr, GeTextureFormatToString((GETextureFormat)entry->format, gstate.getClutPaletteFormat())); image->SetTag(texName); bool allocSuccess = image->CreateDirect(cmdInit, allocator_, w * scaleFactor, h * scaleFactor, maxLevelToGenerate + 1, actualFmt, imageLayout, usage, mapping); diff --git a/GPU/ge_constants.h b/GPU/ge_constants.h index 92c06c3f1d5e..954934dcab08 100644 --- a/GPU/ge_constants.h +++ b/GPU/ge_constants.h @@ -419,7 +419,6 @@ enum GETextureFormat GE_TFMT_DXT5 = 10, }; -const char *GeTextureFormatToString(GETextureFormat tfmt); inline bool IsClutFormat(GETextureFormat tfmt) { return tfmt == GE_TFMT_CLUT4 || tfmt == GE_TFMT_CLUT8 || tfmt == GE_TFMT_CLUT16 || tfmt == GE_TFMT_CLUT32; } @@ -609,3 +608,7 @@ enum GEPaletteFormat GE_CMODE_16BIT_ABGR4444, GE_CMODE_32BIT_ABGR8888, }; + +const char *GEPaletteFormatToString(GEPaletteFormat pfmt); +const char *GeTextureFormatToString(GETextureFormat tfmt); +const char *GeTextureFormatToString(GETextureFormat tfmt, GEPaletteFormat pfmt); From c128df5c756598071b4a6a18469fb0f964f2fa50 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 3 Feb 2021 20:55:09 -0800 Subject: [PATCH 11/29] Debugger: Track ticks of allocation/write/etc. --- Core/Debugger/MemBlockInfo.cpp | 35 +++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 80bce43f05bf..0a2cc1941783 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -18,6 +18,7 @@ #include "Common/Log.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" +#include "Core/CoreTiming.h" #include "Core/Debugger/Breakpoints.h" #include "Core/Debugger/MemBlockInfo.h" #include "Core/MIPS/MIPS.h" @@ -34,13 +35,14 @@ class MemSlabMap { private: struct Slab { - uint32_t start; - uint32_t size; - uint32_t pc; - bool allocated; + uint32_t start = 0; + uint32_t size = 0; + uint64_t ticks = 0; + uint32_t pc = 0; + bool allocated = false; std::string tag; - Slab *prev; - Slab *next; + Slab *prev = nullptr; + Slab *next = nullptr; void DoState(PointerWrap &p); }; @@ -82,8 +84,10 @@ bool MemSlabMap::Mark(uint32_t addr, uint32_t size, uint32_t pc, bool allocated, } slab->allocated = allocated; - if (pc != 0) + if (pc != 0) { + slab->ticks = CoreTiming::GetTicks(); slab->pc = pc; + } if (!tag.empty()) slab->tag = tag; @@ -116,7 +120,8 @@ bool MemSlabMap::Find(MemBlockFlags flags, uint32_t addr, uint32_t size, std::ve void MemSlabMap::Reset() { Clear(); - first_ = new Slab{ 0, UINT_MAX, 0, false, "", nullptr, nullptr }; + first_ = new Slab(); + first_->size = UINT_MAX; } void MemSlabMap::DoState(PointerWrap &p) { @@ -166,6 +171,7 @@ void MemSlabMap::Slab::DoState(PointerWrap &p) { Do(p, start); Do(p, size); + Do(p, ticks); Do(p, pc); Do(p, allocated); Do(p, tag); @@ -192,9 +198,16 @@ MemSlabMap::Slab *MemSlabMap::FindSlab(uint32_t addr) { } MemSlabMap::Slab *MemSlabMap::Split(Slab *slab, uint32_t size) { - uint32_t nextStart = slab->start + size; - uint32_t nextSize = slab->size - size; - Slab *next = new Slab{ nextStart, nextSize, slab->pc, slab->allocated, slab->tag, slab, slab->next }; + Slab *next = new Slab(); + next->start = slab->start + size; + next->size = slab->size - size; + next->ticks = slab->ticks; + next->pc = slab->pc; + next->allocated = slab->allocated; + next->tag = slab->tag; + next->prev = slab; + next->next = slab->next; + slab->next = next; if (next->next) next->next->prev = next; From a590671e8c339f5fc25b510678af4643230deb9d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 5 Feb 2021 21:43:27 -0800 Subject: [PATCH 12/29] GPU: Cleanup comment. --- GPU/GPUCommon.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index e3b21070a9aa..7c47ecc958c0 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2728,13 +2728,10 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) { } bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) { - // Track stray copies of a framebuffer in RAM. MotoGP does this. if (framebufferManager_->MayIntersectFramebuffer(src) || framebufferManager_->MayIntersectFramebuffer(dest)) { if (!framebufferManager_->NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) { - // TODO: What? Why would a game copy between the mirrors? This check seems entirely - // superfluous. - // We use a little hack for Download/Upload using a VRAM mirror. + // We use a little hack for PerformMemoryDownload/PerformMemoryUpload using a VRAM mirror. // Since they're identical we don't need to copy. if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) { Memory::Memcpy(dest, src, size); From a62aa4746b909a7cd234f388562c312d0026c1f6 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 6 Feb 2021 11:44:42 -0800 Subject: [PATCH 13/29] Debugger: Speed up lookup using an index. --- Core/Debugger/MemBlockInfo.cpp | 43 ++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 0a2cc1941783..d810922439dc 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -47,6 +47,10 @@ class MemSlabMap { void DoState(PointerWrap &p); }; + static constexpr uint32_t MAX_SIZE = 0x40000000; + static constexpr uint32_t SLICES = 16384; + static constexpr uint32_t SLICE_SIZE = MAX_SIZE / SLICES; + Slab *FindSlab(uint32_t addr); void Clear(); // Returns the new slab after size. @@ -54,8 +58,10 @@ class MemSlabMap { void MergeAdjacent(Slab *slab); bool Same(const Slab *a, const Slab *b) const; void Merge(Slab *a, Slab *b); + void FillHeads(Slab *slab); Slab *first_ = nullptr; + std::vector heads_; }; static MemSlabMap allocMap; @@ -121,7 +127,9 @@ void MemSlabMap::Reset() { Clear(); first_ = new Slab(); - first_->size = UINT_MAX; + first_->size = MAX_SIZE; + + heads_.resize(SLICES, first_); } void MemSlabMap::DoState(PointerWrap &p) { @@ -136,17 +144,20 @@ void MemSlabMap::DoState(PointerWrap &p) { first_ = new Slab(); first_->DoState(p); - first_->prev = nullptr; - first_->next = nullptr; --count; + heads_.resize(SLICES, nullptr); + FillHeads(first_); + Slab *slab = first_; for (int i = 0; i < count; ++i) { slab->next = new Slab(); - slab->DoState(p); + slab->next->DoState(p); slab->next->prev = slab; slab = slab->next; + + FillHeads(slab); } } else { for (Slab *slab = first_; slab != nullptr; slab = slab->next) @@ -185,10 +196,12 @@ void MemSlabMap::Clear() { s = next; } first_ = nullptr; + heads_.clear(); } MemSlabMap::Slab *MemSlabMap::FindSlab(uint32_t addr) { - Slab *slab = first_; + // Jump ahead using our index. + Slab *slab = heads_[addr / SLICE_SIZE]; while (slab != nullptr && slab->start <= addr) { if (slab->start + slab->size > addr) return slab; @@ -212,6 +225,9 @@ MemSlabMap::Slab *MemSlabMap::Split(Slab *slab, uint32_t size) { if (next->next) next->next->prev = next; + // If the split is big, we might have to update our index. + FillHeads(next); + slab->size = size; return next; } @@ -255,9 +271,26 @@ void MemSlabMap::Merge(Slab *a, Slab *b) { _assert_(false); } a->size += b->size; + // Take over index entries b had. + FillHeads(a); delete b; } +void MemSlabMap::FillHeads(Slab *slab) { + uint32_t slice = slab->start / SLICE_SIZE; + uint32_t endSlice = (slab->start + slab->size - 1) / SLICE_SIZE; + + // For the first slice, only replace if it's the one we're removing. + if (slab->start == slice * SLICE_SIZE) { + heads_[slice] = slab; + } + + // Now replace all the rest - we definitely cover the start of them. + for (uint32_t i = slice + 1; i <= endSlice; ++i) { + heads_[i] = slab; + } +} + void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const std::string &tag) { NotifyMemInfoPC(flags, start, size, currentMIPS->pc, tag); } From 7ccb432a970eda3241a27d51824c1ccc3374ca37 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 6 Feb 2021 12:22:01 -0800 Subject: [PATCH 14/29] Debugger: Defer memory map calculations. It's not so slow, but let's defer (could even use a thread.) --- Core/Debugger/MemBlockInfo.cpp | 72 +++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 19 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index d810922439dc..1122ee58593f 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -28,7 +28,7 @@ class MemSlabMap { MemSlabMap(); ~MemSlabMap(); - bool Mark(uint32_t addr, uint32_t size, uint32_t pc, bool allocated, const std::string &tag); + bool Mark(uint32_t addr, uint32_t size, uint64_t ticks, uint32_t pc, bool allocated, const std::string &tag); bool Find(MemBlockFlags flags, uint32_t addr, uint32_t size, std::vector &results); void Reset(); void DoState(PointerWrap &p); @@ -64,10 +64,21 @@ class MemSlabMap { std::vector heads_; }; +struct PendingNotifyMem { + MemBlockFlags flags; + uint32_t start; + uint32_t size; + uint64_t ticks; + uint32_t pc; + std::string tag; +}; + +static constexpr size_t MAX_PENDING_NOTIFIES = 4096; static MemSlabMap allocMap; static MemSlabMap suballocMap; static MemSlabMap writeMap; static MemSlabMap textureMap; +static std::vector pendingNotifies; MemSlabMap::MemSlabMap() { Reset(); @@ -77,7 +88,7 @@ MemSlabMap::~MemSlabMap() { Clear(); } -bool MemSlabMap::Mark(uint32_t addr, uint32_t size, uint32_t pc, bool allocated, const std::string &tag) { +bool MemSlabMap::Mark(uint32_t addr, uint32_t size, uint64_t ticks, uint32_t pc, bool allocated, const std::string &tag) { uint32_t end = addr + size; Slab *slab = FindSlab(addr); Slab *firstMatch = nullptr; @@ -91,7 +102,7 @@ bool MemSlabMap::Mark(uint32_t addr, uint32_t size, uint32_t pc, bool allocated, slab->allocated = allocated; if (pc != 0) { - slab->ticks = CoreTiming::GetTicks(); + slab->ticks = ticks; slab->pc = pc; } if (!tag.empty()) @@ -291,6 +302,31 @@ void MemSlabMap::FillHeads(Slab *slab) { } } +void FlushPendingMemInfo() { + for (auto info : pendingNotifies) { + if (info.flags & MemBlockFlags::ALLOC) { + allocMap.Mark(info.start, info.size, info.ticks, info.pc, true, info.tag); + } else if (info.flags & MemBlockFlags::FREE) { + // Maintain the previous allocation tag for debugging. + allocMap.Mark(info.start, info.size, info.ticks, 0, false, ""); + suballocMap.Mark(info.start, info.size, info.ticks, 0, false, ""); + } + if (info.flags & MemBlockFlags::SUB_ALLOC) { + suballocMap.Mark(info.start, info.size, info.ticks, info.pc, true, info.tag); + } else if (info.flags & MemBlockFlags::SUB_FREE) { + // Maintain the previous allocation tag for debugging. + suballocMap.Mark(info.start, info.size, info.ticks, 0, false, ""); + } + if (info.flags & MemBlockFlags::TEXTURE) { + textureMap.Mark(info.start, info.size, info.ticks, info.pc, true, info.tag); + } + if (info.flags & MemBlockFlags::WRITE) { + writeMap.Mark(info.start, info.size, info.ticks, info.pc, true, info.tag); + } + } + pendingNotifies.clear(); +} + void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const std::string &tag) { NotifyMemInfoPC(flags, start, size, currentMIPS->pc, tag); } @@ -302,31 +338,26 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_ // Clear the uncached and kernel bits. start &= ~0xC0000000; - if (flags & MemBlockFlags::ALLOC) { - allocMap.Mark(start, size, pc, true, tag); - } else if (flags & MemBlockFlags::FREE) { - // Maintain the previous allocation tag for debugging. - allocMap.Mark(start, size, 0, false, ""); - suballocMap.Mark(start, size, 0, false, ""); - } - if (flags & MemBlockFlags::SUB_ALLOC) { - suballocMap.Mark(start, size, pc, true, tag); - } else if (flags & MemBlockFlags::SUB_FREE) { - // Maintain the previous allocation tag for debugging. - suballocMap.Mark(start, size, 0, false, ""); - } - if (flags & MemBlockFlags::TEXTURE) { - textureMap.Mark(start, size, pc, true, tag); + PendingNotifyMem info{ flags, start, size }; + info.ticks = CoreTiming::GetTicks(); + info.pc = pc; + info.tag = tag; + pendingNotifies.push_back(info); + + if (pendingNotifies.size() > MAX_PENDING_NOTIFIES) { + FlushPendingMemInfo(); } + if (flags & MemBlockFlags::WRITE) { CBreakPoints::ExecMemCheck(start, true, size, pc, tag); - writeMap.Mark(start, size, pc, true, tag); } else if (flags & MemBlockFlags::READ) { CBreakPoints::ExecMemCheck(start, false, size, pc, tag); } } std::vector FindMemInfo(uint32_t start, uint32_t size) { + FlushPendingMemInfo(); + std::vector results; allocMap.Find(MemBlockFlags::ALLOC, start, size, results); suballocMap.Find(MemBlockFlags::SUB_ALLOC, start, size, results); @@ -336,6 +367,7 @@ std::vector FindMemInfo(uint32_t start, uint32_t size) { } void MemBlockInfoInit() { + pendingNotifies.reserve(MAX_PENDING_NOTIFIES); } void MemBlockInfoShutdown() { @@ -343,6 +375,7 @@ void MemBlockInfoShutdown() { suballocMap.Reset(); writeMap.Reset(); textureMap.Reset(); + pendingNotifies.clear(); } void MemBlockInfoDoState(PointerWrap &p) { @@ -350,6 +383,7 @@ void MemBlockInfoDoState(PointerWrap &p) { if (!s) return; + FlushPendingMemInfo(); allocMap.DoState(p); suballocMap.DoState(p); writeMap.DoState(p); From 53b8b8721e040b4e95f510d1688962a824945874 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 6 Feb 2021 12:35:26 -0800 Subject: [PATCH 15/29] Debugger: Track slabs by end, not size. This is simpler, we're always comparing the end anyway. --- Core/Debugger/MemBlockInfo.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 1122ee58593f..26e2fa249921 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -36,7 +36,7 @@ class MemSlabMap { private: struct Slab { uint32_t start = 0; - uint32_t size = 0; + uint32_t end = 0; uint64_t ticks = 0; uint32_t pc = 0; bool allocated = false; @@ -96,7 +96,7 @@ bool MemSlabMap::Mark(uint32_t addr, uint32_t size, uint64_t ticks, uint32_t pc, if (slab->start < addr) slab = Split(slab, addr - slab->start); // Don't replace slab, the return is the after part. - if (slab->start + slab->size > end) { + if (slab->end > end) { Split(slab, end - slab->start); } @@ -127,7 +127,7 @@ bool MemSlabMap::Find(MemBlockFlags flags, uint32_t addr, uint32_t size, std::ve Slab *slab = FindSlab(addr); bool found = false; while (slab != nullptr && slab->start < end) { - results.push_back({ flags, slab->start, slab->size, slab->pc, slab->tag, slab->allocated }); + results.push_back({ flags, slab->start, slab->end - slab->start, slab->pc, slab->tag, slab->allocated }); found = true; slab = slab->next; } @@ -138,7 +138,7 @@ void MemSlabMap::Reset() { Clear(); first_ = new Slab(); - first_->size = MAX_SIZE; + first_->end = MAX_SIZE; heads_.resize(SLICES, first_); } @@ -192,7 +192,7 @@ void MemSlabMap::Slab::DoState(PointerWrap &p) { return; Do(p, start); - Do(p, size); + Do(p, end); Do(p, ticks); Do(p, pc); Do(p, allocated); @@ -214,7 +214,7 @@ MemSlabMap::Slab *MemSlabMap::FindSlab(uint32_t addr) { // Jump ahead using our index. Slab *slab = heads_[addr / SLICE_SIZE]; while (slab != nullptr && slab->start <= addr) { - if (slab->start + slab->size > addr) + if (slab->end > addr) return slab; slab = slab->next; } @@ -224,7 +224,7 @@ MemSlabMap::Slab *MemSlabMap::FindSlab(uint32_t addr) { MemSlabMap::Slab *MemSlabMap::Split(Slab *slab, uint32_t size) { Slab *next = new Slab(); next->start = slab->start + size; - next->size = slab->size - size; + next->end = slab->end; next->ticks = slab->ticks; next->pc = slab->pc; next->allocated = slab->allocated; @@ -239,7 +239,7 @@ MemSlabMap::Slab *MemSlabMap::Split(Slab *slab, uint32_t size) { // If the split is big, we might have to update our index. FillHeads(next); - slab->size = size; + slab->end = slab->start + size; return next; } @@ -264,13 +264,14 @@ bool MemSlabMap::Same(const Slab *a, const Slab *b) const { void MemSlabMap::Merge(Slab *a, Slab *b) { if (a->next == b) { - _assert_(a->start + a->size == b->start); + _assert_(a->end == b->start); + a->end = b->end; a->next = b->next; if (a->next) a->next->prev = a; } else if (a->prev == b) { - _assert_(b->start + b->size == a->start); + _assert_(b->end == a->start); a->start = b->start; a->prev = b->prev; @@ -281,7 +282,6 @@ void MemSlabMap::Merge(Slab *a, Slab *b) { } else { _assert_(false); } - a->size += b->size; // Take over index entries b had. FillHeads(a); delete b; @@ -289,7 +289,7 @@ void MemSlabMap::Merge(Slab *a, Slab *b) { void MemSlabMap::FillHeads(Slab *slab) { uint32_t slice = slab->start / SLICE_SIZE; - uint32_t endSlice = (slab->start + slab->size - 1) / SLICE_SIZE; + uint32_t endSlice = (slab->end - 1) / SLICE_SIZE; // For the first slice, only replace if it's the one we're removing. if (slab->start == slice * SLICE_SIZE) { From f95fdf3dfdf1e8d577a65ee4b4f617f43296a5e2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 6 Feb 2021 12:41:17 -0800 Subject: [PATCH 16/29] Debugger: Optimize linear marking. This is a very common case, so helps skip ahead. --- Core/Debugger/MemBlockInfo.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 26e2fa249921..16998a7cd56f 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -61,6 +61,7 @@ class MemSlabMap { void FillHeads(Slab *slab); Slab *first_ = nullptr; + Slab *lastFind_ = nullptr; std::vector heads_; }; @@ -139,6 +140,7 @@ void MemSlabMap::Reset() { first_ = new Slab(); first_->end = MAX_SIZE; + lastFind_ = first_; heads_.resize(SLICES, first_); } @@ -155,6 +157,7 @@ void MemSlabMap::DoState(PointerWrap &p) { first_ = new Slab(); first_->DoState(p); + lastFind_ = first_; --count; heads_.resize(SLICES, nullptr); @@ -207,15 +210,22 @@ void MemSlabMap::Clear() { s = next; } first_ = nullptr; + lastFind_ = nullptr; heads_.clear(); } MemSlabMap::Slab *MemSlabMap::FindSlab(uint32_t addr) { // Jump ahead using our index. Slab *slab = heads_[addr / SLICE_SIZE]; + // We often move forward, so check the last find. + if (lastFind_->start > slab->start && lastFind_->start <= addr) + slab = lastFind_; + while (slab != nullptr && slab->start <= addr) { - if (slab->end > addr) + if (slab->end > addr) { + lastFind_ = slab; return slab; + } slab = slab->next; } return nullptr; @@ -284,6 +294,8 @@ void MemSlabMap::Merge(Slab *a, Slab *b) { } // Take over index entries b had. FillHeads(a); + if (lastFind_ == b) + lastFind_ = a; delete b; } From 616f5ddc5a716b59c8f38c97704292df985c11d0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Feb 2021 10:18:14 -0800 Subject: [PATCH 17/29] Debugger: Correct search by empty string. --- Windows/Debugger/CtrlMemView.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Windows/Debugger/CtrlMemView.cpp b/Windows/Debugger/CtrlMemView.cpp index 7ae71ef33157..4868f43dab46 100644 --- a/Windows/Debugger/CtrlMemView.cpp +++ b/Windows/Debugger/CtrlMemView.cpp @@ -642,6 +642,10 @@ std::vector CtrlMemView::searchString(std::string searchQuery) return searchResAddrs; size_t queryLength = searchQuery.length(); + if (queryLength == 0) + return searchResAddrs; + + // TODO: Scratchpad, VRAM? u32 segmentStart = PSP_GetKernelMemoryBase(); //RAM start const u32 segmentEnd = PSP_GetUserMemoryEnd() - (u32)queryLength; //RAM end u8* ptr; From 616850663ce53fe5e12ecc99c4a65cba6c9549d5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Feb 2021 10:49:22 -0800 Subject: [PATCH 18/29] Debugger: Add initial UI for mem info type. Does not visualize yet, just implements the selection interface. --- Windows/Debugger/CtrlMemView.cpp | 7 ++ Windows/Debugger/CtrlMemView.h | 7 +- Windows/Debugger/Debugger_MemoryDlg.cpp | 103 +++++++++++------------- Windows/Debugger/Debugger_MemoryDlg.h | 1 + Windows/ppsspp.rc | 6 +- 5 files changed, 66 insertions(+), 58 deletions(-) diff --git a/Windows/Debugger/CtrlMemView.cpp b/Windows/Debugger/CtrlMemView.cpp index 4868f43dab46..417ee0dbac65 100644 --- a/Windows/Debugger/CtrlMemView.cpp +++ b/Windows/Debugger/CtrlMemView.cpp @@ -797,3 +797,10 @@ void CtrlMemView::toggleOffsetScale(CommonToggles toggle) updateStatusBarText(); redraw(); } + +void CtrlMemView::setHighlightType(MemBlockFlags flags) { + if (highlightFlags_ != flags) { + highlightFlags_ = flags; + redraw(); + } +} diff --git a/Windows/Debugger/CtrlMemView.h b/Windows/Debugger/CtrlMemView.h index 44ab3bcdf02b..0a3bb2a583a2 100644 --- a/Windows/Debugger/CtrlMemView.h +++ b/Windows/Debugger/CtrlMemView.h @@ -17,7 +17,8 @@ // //To get a class instance to be able to access it, just use getFrom(HWND wnd). -#include "../../Core/Debugger/DebugInterface.h" +#include "Core/Debugger/DebugInterface.h" +#include "Core/Debugger/MemBlockInfo.h" enum OffsetSpacing { offsetSpace = 3, // the number of blank lines that should be left to make space for the offsets @@ -63,6 +64,9 @@ class CtrlMemView bool hasFocus; static wchar_t szClassName[]; DebugInterface *debugger; + + MemBlockFlags highlightFlags_ = MemBlockFlags::ALLOC; + void updateStatusBarText(); void search(bool continueSearch); public: @@ -99,4 +103,5 @@ class CtrlMemView void drawOffsetScale(HDC hdc); void toggleOffsetScale(CommonToggles toggle); void toggleStringSearch(CommonToggles toggle); + void setHighlightType(MemBlockFlags flags); }; diff --git a/Windows/Debugger/Debugger_MemoryDlg.cpp b/Windows/Debugger/Debugger_MemoryDlg.cpp index 33027861604f..9214a3467366 100644 --- a/Windows/Debugger/Debugger_MemoryDlg.cpp +++ b/Windows/Debugger/Debugger_MemoryDlg.cpp @@ -4,11 +4,12 @@ #include #include "..\resource.h" -#include "Common/System/Display.h" #include "Common/Data/Encoding/Utf8.h" +#include "Common/System/Display.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/Debugger/SymbolMap.h" -#include "Core/MIPS/MIPSDebugInterface.h" // BAD +#include "Core/MIPS/MIPSDebugInterface.h" #include "Debugger_MemoryDlg.h" #include "CtrlMemView.h" @@ -68,6 +69,18 @@ CMemoryDlg::CMemoryDlg(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu searchBoxHdl = GetDlgItem(m_hDlg, IDC_SEARCH_BOX); srcListHdl = GetDlgItem(m_hDlg, IDC_SEARCH_RESULTS); + layerDropdown_ = GetDlgItem(m_hDlg, IDC_REGIONS); + ComboBox_ResetContent(layerDropdown_); + ComboBox_AddString(layerDropdown_, L"Show allocations"); + ComboBox_SetItemData(layerDropdown_, 0, MemBlockFlags::ALLOC); + ComboBox_AddString(layerDropdown_, L"Show sub allocations"); + ComboBox_SetItemData(layerDropdown_, 1, MemBlockFlags::SUB_ALLOC); + ComboBox_AddString(layerDropdown_, L"Show writes"); + ComboBox_SetItemData(layerDropdown_, 2, MemBlockFlags::WRITE); + ComboBox_AddString(layerDropdown_, L"Show textures"); + ComboBox_SetItemData(layerDropdown_, 3, MemBlockFlags::TEXTURE); + ComboBox_SetCurSel(layerDropdown_, 0); + memView = CtrlMemView::getFrom(memViewHdl); memView->setDebugger(_cpu); @@ -118,66 +131,53 @@ void CMemoryDlg::searchBoxRedraw(std::vector results) { void CMemoryDlg::NotifyMapLoaded() { if (m_hDlg) - { - g_symbolMap->FillSymbolListBox(symListHdl,ST_DATA); - int sel = ComboBox_GetCurSel(memViewHdl); - ComboBox_ResetContent(memViewHdl); - /* - for (int i = 0; i < cpu->getMemMap()->numRegions; i++) - { - // TODO: wchar_t - int n = ComboBox_AddString(lb,cpu->getMemMap()->regions[i].name); - ComboBox_SetItemData(lb,n,cpu->getMemMap()->regions[i].start); - }*/ - ComboBox_SetCurSel(memViewHdl,sel>=0?sel:0); - } + g_symbolMap->FillSymbolListBox(symListHdl, ST_DATA); Update(); } -BOOL CMemoryDlg::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) -{ - switch(message){ - case WM_COMMAND:{ +BOOL CMemoryDlg::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { + wchar_t temp[256]{}; + int n; + + switch (message) { + case WM_COMMAND: { HWND lb = GetDlgItem(m_hDlg, LOWORD(wParam)); - switch (LOWORD(wParam)){ + switch (LOWORD(wParam)) { case IDC_REGIONS: switch (HIWORD(wParam)) { - case LBN_DBLCLK:{ - int n = ComboBox_GetCurSel(lb); - if (n != -1) { - unsigned int addr = (unsigned int)ComboBox_GetItemData(lb,n); - memView->gotoAddr(addr); - } + case CBN_SELENDOK: + n = ComboBox_GetCurSel(lb); + if (n != CB_ERR) { + MemBlockFlags flags = (MemBlockFlags)ComboBox_GetItemData(lb, n); + memView->setHighlightType(MemBlockFlags(flags)); } break; - }; - break; + } + break; case IDC_SYMBOLS: switch (HIWORD(wParam)) { - case LBN_DBLCLK:{ - int n = ListBox_GetCurSel(lb); - if (n != -1) { - unsigned int addr = (unsigned int)ListBox_GetItemData(lb,n); - memView->gotoAddr(addr); - } + case LBN_DBLCLK: + n = ListBox_GetCurSel(lb); + if (n != -1) { + unsigned int addr = (unsigned int)ListBox_GetItemData(lb,n); + memView->gotoAddr(addr); + } + break; } break; - }; case IDC_SEARCH_RESULTS: switch (HIWORD(wParam)) { - case LBN_DBLCLK: { - int n = ListBox_GetCurSel(lb); - if (n != -1) { - unsigned int addr = (unsigned int)ListBox_GetItemData(lb, n); - memView->gotoAddr(addr); - } + case LBN_DBLCLK: + n = ListBox_GetCurSel(lb); + if (n != -1) { + unsigned int addr = (unsigned int)ListBox_GetItemData(lb, n); + memView->gotoAddr(addr); + } + break; } break; - }; - break; case IDC_SHOWOFFSETS: - switch (HIWORD(wParam)) - { + switch (HIWORD(wParam)) { case BN_CLICKED: if (SendDlgItemMessage(m_hDlg, IDC_SHOWOFFSETS, BM_GETCHECK, 0, 0)) memView->toggleOffsetScale(On); @@ -187,10 +187,8 @@ BOOL CMemoryDlg::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) } break; case IDC_BUTTON_SEARCH: - switch (HIWORD(wParam)) - { + switch (HIWORD(wParam)) { case BN_CLICKED: - wchar_t temp[256]; GetWindowText(searchBoxHdl, temp, 255); std::vector results = memView->searchString(ConvertWStringToUTF8(temp).c_str()); if (results.size() > 0){ @@ -198,14 +196,14 @@ BOOL CMemoryDlg::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) } break; } + break; } } break; case WM_DEB_MAPLOADED: NotifyMapLoaded(); break; - case WM_DEB_GOTOADDRESSEDIT:{ - wchar_t temp[256]; + case WM_DEB_GOTOADDRESSEDIT: { u32 addr; GetWindowText(editWnd,temp,255); @@ -223,10 +221,7 @@ BOOL CMemoryDlg::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) return TRUE; case WM_INITDIALOG: - { - return TRUE; - } - break; + return TRUE; case WM_SIZE: Size(); diff --git a/Windows/Debugger/Debugger_MemoryDlg.h b/Windows/Debugger/Debugger_MemoryDlg.h index 91bf07e9864c..f8a9d20b5086 100644 --- a/Windows/Debugger/Debugger_MemoryDlg.h +++ b/Windows/Debugger/Debugger_MemoryDlg.h @@ -17,6 +17,7 @@ class CMemoryDlg : public Dialog RECT winRect, srRect; CtrlMemView *memView; HWND memViewHdl, symListHdl, editWnd, searchBoxHdl, srcListHdl; + HWND layerDropdown_; BOOL DlgProc(UINT message, WPARAM wParam, LPARAM lParam); public: diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 4a29a62ea0ce..24bf02b4df0b 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -321,14 +321,14 @@ BEGIN CONTROL "Normal",IDC_MODENORMAL,"Button",BS_AUTORADIOBUTTON | WS_GROUP,198,9,40,9 CONTROL "Symbols",IDC_MODESYMBOLS,"Button",BS_AUTORADIOBUTTON,241,9,43,8 GROUPBOX "Mode",IDC_STATIC,191,0,104,22 - AUTOCHECKBOX "Show Offsets",IDC_SHOWOFFSETS,300,9,55,8 - COMBOBOX IDC_REGIONS,87,5,88,139,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + AUTOCHECKBOX "Show Offsets",IDC_SHOWOFFSETS,300,9,55,8 + COMBOBOX IDC_REGIONS,95,5,88,139,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LISTBOX IDC_SEARCH_RESULTS,557,14,140,272,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP EDITTEXT IDC_SEARCH_BOX,397,6,100,13,ES_AUTOHSCROLL PUSHBUTTON "Search",IDC_BUTTON_SEARCH,504,5,50,14 - LTEXT "Search:",IDC_STATIC,369,6,27,8 + LTEXT "Search:",IDC_STATIC,369,8,27,8 END IDD_INPUTBOX DIALOGEX 0, 0, 163, 55 From 595a17e9bc8527d56adcc4ab14daacd2069833ea Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Feb 2021 11:00:13 -0800 Subject: [PATCH 19/29] Debugger: Ignore unmarked mem block info in find. We start with a large unmarked region which we break up. Ignore this. --- Core/Debugger/MemBlockInfo.cpp | 21 +++++++++++++++++++-- Core/Debugger/MemBlockInfo.h | 1 + 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 16998a7cd56f..cb63e83f5093 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -128,8 +128,10 @@ bool MemSlabMap::Find(MemBlockFlags flags, uint32_t addr, uint32_t size, std::ve Slab *slab = FindSlab(addr); bool found = false; while (slab != nullptr && slab->start < end) { - results.push_back({ flags, slab->start, slab->end - slab->start, slab->pc, slab->tag, slab->allocated }); - found = true; + if (slab->pc != 0 || !slab->tag.empty()) { + results.push_back({ flags, slab->start, slab->end - slab->start, slab->pc, slab->tag, slab->allocated }); + found = true; + } slab = slab->next; } return found; @@ -378,6 +380,21 @@ std::vector FindMemInfo(uint32_t start, uint32_t size) { return results; } +std::vector FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, uint32_t size) { + FlushPendingMemInfo(); + + std::vector results; + if (flags & MemBlockFlags::ALLOC) + allocMap.Find(MemBlockFlags::ALLOC, start, size, results); + if (flags & MemBlockFlags::SUB_ALLOC) + suballocMap.Find(MemBlockFlags::SUB_ALLOC, start, size, results); + if (flags & MemBlockFlags::WRITE) + writeMap.Find(MemBlockFlags::WRITE, start, size, results); + if (flags & MemBlockFlags::TEXTURE) + textureMap.Find(MemBlockFlags::TEXTURE, start, size, results); + return results; +} + void MemBlockInfoInit() { pendingNotifies.reserve(MAX_PENDING_NOTIFIES); } diff --git a/Core/Debugger/MemBlockInfo.h b/Core/Debugger/MemBlockInfo.h index 91e0a6f643ed..b32601585c2a 100644 --- a/Core/Debugger/MemBlockInfo.h +++ b/Core/Debugger/MemBlockInfo.h @@ -49,6 +49,7 @@ void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const std void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_t pc, const std::string &tag); std::vector FindMemInfo(uint32_t start, uint32_t size); +std::vector FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, uint32_t size); void MemBlockInfoInit(); void MemBlockInfoShutdown(); From d80655287ba06412e28939c82434680d4295f525 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Feb 2021 11:39:51 -0800 Subject: [PATCH 20/29] Debugger: Reorganize memory view painting. This also grabs tag info, but doesn't display it yet. --- Windows/Debugger/CtrlMemView.cpp | 160 ++++++++++++++++++------------- Windows/Debugger/CtrlMemView.h | 2 + 2 files changed, 96 insertions(+), 66 deletions(-) diff --git a/Windows/Debugger/CtrlMemView.cpp b/Windows/Debugger/CtrlMemView.cpp index 417ee0dbac65..6351f18412fd 100644 --- a/Windows/Debugger/CtrlMemView.cpp +++ b/Windows/Debugger/CtrlMemView.cpp @@ -173,8 +173,7 @@ CtrlMemView *CtrlMemView::getFrom(HWND hwnd) } -void CtrlMemView::onPaint(WPARAM wParam, LPARAM lParam) -{ +void CtrlMemView::onPaint(WPARAM wParam, LPARAM lParam) { auto memLock = Memory::Lock(); // draw to a bitmap for double buffering @@ -187,6 +186,7 @@ void CtrlMemView::onPaint(WPARAM wParam, LPARAM lParam) SetBkMode(hdc,OPAQUE); HPEN standardPen = CreatePen(0,0,0xFFFFFF); HBRUSH standardBrush = CreateSolidBrush(0xFFFFFF); + COLORREF standardBG = GetBkColor(hdc); HPEN oldPen = (HPEN) SelectObject(hdc,standardPen); HBRUSH oldBrush = (HBRUSH) SelectObject(hdc,standardBrush); @@ -199,88 +199,112 @@ void CtrlMemView::onPaint(WPARAM wParam, LPARAM lParam) if (displayOffsetScale) drawOffsetScale(hdc); - - // draw one extra row that may be partially visible - for (int i = 0; i < visibleRows+1; i++) - { - char temp[32]; + std::vector memRangeInfo = FindMemInfoByFlag(highlightFlags_, windowStart, (visibleRows + 1) * rowSize); - unsigned int address=windowStart + i*rowSize; - int rowY = rowHeight*i; + COLORREF lastTextCol = 0x000000; + COLORREF lastBGCol = standardBG; + auto setTextColors = [&](COLORREF fg, COLORREF bg) { + if (lastTextCol != fg) { + SetTextColor(hdc, fg); + lastTextCol = fg; + } + if (lastBGCol != bg) { + SetBkColor(hdc, bg); + lastBGCol = bg; + } + }; + // draw one extra row that may be partially visible + for (int i = 0; i < visibleRows + 1; i++) { + int rowY = rowHeight * i; + // Skip the first X rows to make space for the offsets. if (displayOffsetScale) - rowY += rowHeight * offsetSpace; // skip the first X rows to make space for the offsets - - - sprintf(temp,"%08X",address); - SetTextColor(hdc,0x600000); - TextOutA(hdc,addressStart,rowY,temp,(int)strlen(temp)); - - SetTextColor(hdc,0x000000); + rowY += rowHeight * offsetSpace; - u32 memory[4]; - bool valid = debugger != NULL && debugger->isAlive() && Memory::IsValidAddress(address); - if (valid) - { - memory[0] = debugger->readMemory(address); - memory[1] = debugger->readMemory(address+4); - memory[2] = debugger->readMemory(address+8); - memory[3] = debugger->readMemory(address+12); + char temp[32]; + uint32_t address = windowStart + i * rowSize; + sprintf(temp, "%08X", address); + + setTextColors(0x600000, standardBG); + TextOutA(hdc, addressStart, rowY, temp, (int)strlen(temp)); + + union { + uint32_t words[4]; + uint8_t bytes[16]; + } memory; + bool valid = debugger != nullptr && debugger->isAlive() && Memory::IsValidAddress(address); + for (int i = 0; valid && i < 4; ++i) { + memory.words[i] = debugger->readMemory(address + i * 4); } - u8* m = (u8*) memory; - for (int j = 0; j < rowSize; j++) - { - if (valid) sprintf(temp,"%02X",m[j]); - else strcpy(temp,"??"); - - unsigned char c = m[j]; - if (c < 32 || c >= 128 || valid == false) c = '.'; + for (int j = 0; j < rowSize; j++) { + uint32_t byteAddress = address + j; + std::string tag; + for (auto info : memRangeInfo) { + if (info.start <= byteAddress && info.start + info.size > byteAddress) + tag = info.tag; + } - if (address+j == curAddress && searching == false) - { - COLORREF oldBkColor = GetBkColor(hdc); - COLORREF oldTextColor = GetTextColor(hdc); + int hexX = hexStart + j * 3 * charWidth; + int asciiX = asciiStart + j * (charWidth + 2); - if (hasFocus && !asciiSelected) - { - SetTextColor(hdc,0xFFFFFF); - SetBkColor(hdc,0xFF9933); - if (selectedNibble == 0) SelectObject(hdc,(HGDIOBJ)underlineFont); - } else { - SetTextColor(hdc,0); - SetBkColor(hdc,0xC0C0C0); - } - TextOutA(hdc,hexStart+j*3*charWidth,rowY,&temp[0],1); - - if (hasFocus && !asciiSelected) - { - if (selectedNibble == 1) SelectObject(hdc,(HGDIOBJ)underlineFont); - else SelectObject(hdc,(HGDIOBJ)font); - } - TextOutA(hdc,hexStart+j*3*charWidth+charWidth,rowY,&temp[1],1); + char c; + if (valid) { + sprintf(temp, "%02X", memory.bytes[j]); + c = (char)memory.bytes[j]; + if (memory.bytes[j] < 32 || memory.bytes[j] >= 128) + c = '.'; + } else { + strcpy(temp, "??"); + c = '.'; + } - if (hasFocus && asciiSelected) - { - SetTextColor(hdc,0xFFFFFF); - SetBkColor(hdc,0xFF9933); + COLORREF hexBGCol = standardBG; + COLORREF hexTextCol = 0x000000; + COLORREF asciiBGCol = standardBG; + COLORREF asciiTextCol = 0x000000; + int underline = -1; + + if (byteAddress == curAddress && searching == false) { + if (asciiSelected) { + hexBGCol = 0xC0C0C0; + hexTextCol = 0x000000; + asciiBGCol = hasFocus ? 0xFF9933 : 0xC0C0C0; + asciiTextCol = hasFocus ? 0xFFFFFF : 0x000000; } else { - SetTextColor(hdc,0); - SetBkColor(hdc,0xC0C0C0); - SelectObject(hdc,(HGDIOBJ)font); + hexBGCol = hasFocus ? 0xFF9933 : 0xC0C0C0; + hexTextCol = hasFocus ? 0xFFFFFF : 0x000000; + asciiBGCol = 0xC0C0C0; + asciiTextCol = 0x000000; + underline = selectedNibble; } - TextOutA(hdc,asciiStart+j*(charWidth+2),rowY,(char*)&c,1); + } else if (!tag.empty()) { + hexBGCol = pickTagColor(tag); + asciiBGCol = pickTagColor(tag); + } - SetTextColor(hdc,oldTextColor); - SetBkColor(hdc,oldBkColor); + setTextColors(hexTextCol, hexBGCol); + if (underline == 0) { + SelectObject(hdc, (HGDIOBJ)underlineFont); + TextOutA(hdc, hexX, rowY, &temp[0], 1); + SelectObject(hdc, (HGDIOBJ)font); + TextOutA(hdc, hexX + charWidth, rowY, &temp[1], 1); + } else if (underline == 1) { + TextOutA(hdc, hexX, rowY, &temp[0], 1); + SelectObject(hdc, (HGDIOBJ)underlineFont); + TextOutA(hdc, hexX + charWidth, rowY, &temp[1], 1); + SelectObject(hdc, (HGDIOBJ)font); } else { - TextOutA(hdc,hexStart+j*3*charWidth,rowY,temp,2); - TextOutA(hdc,asciiStart+j*(charWidth+2),rowY,(char*)&c,1); + TextOutA(hdc, hexX, rowY, temp, 2); } + + setTextColors(asciiTextCol, asciiBGCol); + TextOutA(hdc, asciiX, rowY, &c, 1); } } + setTextColors(0x000000, standardBG); SelectObject(hdc,oldFont); SelectObject(hdc,oldPen); SelectObject(hdc,oldBrush); @@ -804,3 +828,7 @@ void CtrlMemView::setHighlightType(MemBlockFlags flags) { redraw(); } } + +uint32_t CtrlMemView::pickTagColor(const std::string &tag) { + return 0xFFFFFF; +} diff --git a/Windows/Debugger/CtrlMemView.h b/Windows/Debugger/CtrlMemView.h index 0a3bb2a583a2..563f589be26c 100644 --- a/Windows/Debugger/CtrlMemView.h +++ b/Windows/Debugger/CtrlMemView.h @@ -17,6 +17,7 @@ // //To get a class instance to be able to access it, just use getFrom(HWND wnd). +#include #include "Core/Debugger/DebugInterface.h" #include "Core/Debugger/MemBlockInfo.h" @@ -69,6 +70,7 @@ class CtrlMemView void updateStatusBarText(); void search(bool continueSearch); + uint32_t pickTagColor(const std::string &tag); public: CtrlMemView(HWND _wnd); ~CtrlMemView(); From c044e6f7e421442480c285a9f6612db8818e3ee0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Feb 2021 12:02:47 -0800 Subject: [PATCH 21/29] Debugger: Highlight memory ranges in memory view. --- Windows/Debugger/CtrlMemView.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Windows/Debugger/CtrlMemView.cpp b/Windows/Debugger/CtrlMemView.cpp index 6351f18412fd..d664702fc1cc 100644 --- a/Windows/Debugger/CtrlMemView.cpp +++ b/Windows/Debugger/CtrlMemView.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "ext/xxhash.h" #include "Core/Config.h" #include "Windows/resource.h" #include "Core/MemMap.h" @@ -241,17 +242,21 @@ void CtrlMemView::onPaint(WPARAM wParam, LPARAM lParam) { for (int j = 0; j < rowSize; j++) { uint32_t byteAddress = address + j; std::string tag; + bool tagContinues = false; for (auto info : memRangeInfo) { - if (info.start <= byteAddress && info.start + info.size > byteAddress) + if (info.start <= byteAddress && info.start + info.size > byteAddress) { tag = info.tag; + tagContinues = byteAddress + 1 < info.start + info.size; + } } int hexX = hexStart + j * 3 * charWidth; + int hexLen = 2; int asciiX = asciiStart + j * (charWidth + 2); char c; if (valid) { - sprintf(temp, "%02X", memory.bytes[j]); + sprintf(temp, "%02X ", memory.bytes[j]); c = (char)memory.bytes[j]; if (memory.bytes[j] < 32 || memory.bytes[j] >= 128) c = '.'; @@ -282,6 +287,7 @@ void CtrlMemView::onPaint(WPARAM wParam, LPARAM lParam) { } else if (!tag.empty()) { hexBGCol = pickTagColor(tag); asciiBGCol = pickTagColor(tag); + hexLen = tagContinues ? 3 : 2; } setTextColors(hexTextCol, hexBGCol); @@ -296,7 +302,7 @@ void CtrlMemView::onPaint(WPARAM wParam, LPARAM lParam) { TextOutA(hdc, hexX + charWidth, rowY, &temp[1], 1); SelectObject(hdc, (HGDIOBJ)font); } else { - TextOutA(hdc, hexX, rowY, temp, 2); + TextOutA(hdc, hexX, rowY, temp, hexLen); } setTextColors(asciiTextCol, asciiBGCol); @@ -830,5 +836,7 @@ void CtrlMemView::setHighlightType(MemBlockFlags flags) { } uint32_t CtrlMemView::pickTagColor(const std::string &tag) { - return 0xFFFFFF; + int colors[6] = { 0xe0FFFF, 0xFFE0E0, 0xE8E8FF, 0xFFE0FF, 0xE0FFE0, 0xFFFFE0 }; + int which = XXH3_64bits(tag.c_str(), tag.length()) % ARRAY_SIZE(colors); + return colors[which]; } From b1a2090e67abfe4648808d16928a9387fc51602c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Feb 2021 12:18:59 -0800 Subject: [PATCH 22/29] Debugger: Extend tag background on select too. --- Windows/Debugger/CtrlMemView.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Windows/Debugger/CtrlMemView.cpp b/Windows/Debugger/CtrlMemView.cpp index d664702fc1cc..d06f1d9dd113 100644 --- a/Windows/Debugger/CtrlMemView.cpp +++ b/Windows/Debugger/CtrlMemView.cpp @@ -267,6 +267,7 @@ void CtrlMemView::onPaint(WPARAM wParam, LPARAM lParam) { COLORREF hexBGCol = standardBG; COLORREF hexTextCol = 0x000000; + COLORREF continueBGCol = standardBG; COLORREF asciiBGCol = standardBG; COLORREF asciiTextCol = 0x000000; int underline = -1; @@ -284,23 +285,29 @@ void CtrlMemView::onPaint(WPARAM wParam, LPARAM lParam) { asciiTextCol = 0x000000; underline = selectedNibble; } + if (!tag.empty() && tagContinues) { + continueBGCol = pickTagColor(tag); + } } else if (!tag.empty()) { hexBGCol = pickTagColor(tag); + continueBGCol = hexBGCol; asciiBGCol = pickTagColor(tag); hexLen = tagContinues ? 3 : 2; } setTextColors(hexTextCol, hexBGCol); - if (underline == 0) { - SelectObject(hdc, (HGDIOBJ)underlineFont); - TextOutA(hdc, hexX, rowY, &temp[0], 1); - SelectObject(hdc, (HGDIOBJ)font); - TextOutA(hdc, hexX + charWidth, rowY, &temp[1], 1); - } else if (underline == 1) { + if (underline >= 0) { + SelectObject(hdc, underline == 0 ? (HGDIOBJ)underlineFont : (HGDIOBJ)font); TextOutA(hdc, hexX, rowY, &temp[0], 1); - SelectObject(hdc, (HGDIOBJ)underlineFont); + SelectObject(hdc, underline == 0 ? (HGDIOBJ)font : (HGDIOBJ)underlineFont); TextOutA(hdc, hexX + charWidth, rowY, &temp[1], 1); SelectObject(hdc, (HGDIOBJ)font); + + // If the tag keeps going, draw the BG too. + if (continueBGCol != standardBG) { + setTextColors(0x000000, continueBGCol); + TextOutA(hdc, hexX + charWidth * 2, rowY, &temp[2], 1); + } } else { TextOutA(hdc, hexX, rowY, temp, hexLen); } From d48bb7e105d77d11964dd0d0d1ed311857c086bf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Feb 2021 14:07:13 -0800 Subject: [PATCH 23/29] Debugger: Show memory tag info in status bar. --- Core/Debugger/MemBlockInfo.cpp | 2 +- Core/Debugger/MemBlockInfo.h | 1 + Windows/Debugger/CtrlMemView.cpp | 16 +++++++++++----- Windows/Debugger/Debugger_MemoryDlg.cpp | 13 ++++++++++--- Windows/Debugger/Debugger_MemoryDlg.h | 1 + Windows/ppsspp.rc | 4 +++- Windows/resource.h | 3 ++- 7 files changed, 29 insertions(+), 11 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index cb63e83f5093..1ff7d16d504d 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -129,7 +129,7 @@ bool MemSlabMap::Find(MemBlockFlags flags, uint32_t addr, uint32_t size, std::ve bool found = false; while (slab != nullptr && slab->start < end) { if (slab->pc != 0 || !slab->tag.empty()) { - results.push_back({ flags, slab->start, slab->end - slab->start, slab->pc, slab->tag, slab->allocated }); + results.push_back({ flags, slab->start, slab->end - slab->start, slab->ticks, slab->pc, slab->tag, slab->allocated }); found = true; } slab = slab->next; diff --git a/Core/Debugger/MemBlockInfo.h b/Core/Debugger/MemBlockInfo.h index b32601585c2a..fa851ffdfe33 100644 --- a/Core/Debugger/MemBlockInfo.h +++ b/Core/Debugger/MemBlockInfo.h @@ -40,6 +40,7 @@ struct MemBlockInfo { MemBlockFlags flags; uint32_t start; uint32_t size; + uint64_t ticks; uint32_t pc; std::string tag; bool allocated; diff --git a/Windows/Debugger/CtrlMemView.cpp b/Windows/Debugger/CtrlMemView.cpp index d06f1d9dd113..326fa1bdf813 100644 --- a/Windows/Debugger/CtrlMemView.cpp +++ b/Windows/Debugger/CtrlMemView.cpp @@ -555,11 +555,17 @@ void CtrlMemView::onMouseMove(WPARAM wParam, LPARAM lParam, int button) } -void CtrlMemView::updateStatusBarText() -{ - char text[64]; - sprintf(text,"%08X",curAddress); - SendMessage(GetParent(wnd),WM_DEB_SETSTATUSBARTEXT,0,(LPARAM)text); +void CtrlMemView::updateStatusBarText() { + std::vector memRangeInfo = FindMemInfoByFlag(highlightFlags_, curAddress, 1); + + char text[512]; + snprintf(text, sizeof(text), "%08X", curAddress); + // There should only be one. + for (MemBlockInfo info : memRangeInfo) { + snprintf(text, sizeof(text), "%08X - %s (at PC %08X / %lld ticks)", curAddress, info.tag.c_str(), info.pc, info.ticks); + } + + SendMessage(GetParent(wnd), WM_DEB_SETSTATUSBARTEXT, 0, (LPARAM)text); } void CtrlMemView::gotoPoint(int x, int y) diff --git a/Windows/Debugger/Debugger_MemoryDlg.cpp b/Windows/Debugger/Debugger_MemoryDlg.cpp index 9214a3467366..6532c6a6f16f 100644 --- a/Windows/Debugger/Debugger_MemoryDlg.cpp +++ b/Windows/Debugger/Debugger_MemoryDlg.cpp @@ -2,6 +2,7 @@ #include "Windows/stdafx.h" #include +#include #include "..\resource.h" #include "Common/Data/Encoding/Utf8.h" @@ -81,6 +82,8 @@ CMemoryDlg::CMemoryDlg(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu ComboBox_SetItemData(layerDropdown_, 3, MemBlockFlags::TEXTURE); ComboBox_SetCurSel(layerDropdown_, 0); + status_ = GetDlgItem(m_hDlg, IDC_MEMVIEW_STATUS); + memView = CtrlMemView::getFrom(memViewHdl); memView->setDebugger(_cpu); @@ -220,6 +223,10 @@ BOOL CMemoryDlg::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { Update(); return TRUE; + case WM_DEB_SETSTATUSBARTEXT: + SendMessage(status_, SB_SETTEXT, 0, (LPARAM)ConvertUTF8ToWString((const char *)lParam).c_str()); + break; + case WM_INITDIALOG: return TRUE; @@ -250,11 +257,11 @@ void CMemoryDlg::Size() int dlg_w = winRect.right - winRect.left; int dlg_h = winRect.bottom - winRect.top; - int wf = slRect.right-slRect.left; int w = dlg_w - 3 * fontScale - wf*2; - int top = 48 * fontScale; - int height = dlg_h - top; + int top = 40 * fontScale; + int bottom = 24 * fontScale; + int height = dlg_h - top - bottom; //HWND, X, Y, width, height, repaint MoveWindow(symListHdl, 0 ,top, wf, height, TRUE); MoveWindow(memViewHdl, wf+4 ,top, w, height, TRUE); diff --git a/Windows/Debugger/Debugger_MemoryDlg.h b/Windows/Debugger/Debugger_MemoryDlg.h index f8a9d20b5086..cf771c641511 100644 --- a/Windows/Debugger/Debugger_MemoryDlg.h +++ b/Windows/Debugger/Debugger_MemoryDlg.h @@ -18,6 +18,7 @@ class CMemoryDlg : public Dialog CtrlMemView *memView; HWND memViewHdl, symListHdl, editWnd, searchBoxHdl, srcListHdl; HWND layerDropdown_; + HWND status_; BOOL DlgProc(UINT message, WPARAM wParam, LPARAM lParam); public: diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 24bf02b4df0b..bc7e30e06425 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -307,7 +307,7 @@ END #include "aboutbox.rc" #endif -IDD_MEMORY DIALOGEX 0, 0, 700, 287 +IDD_MEMORY DIALOGEX 0, 0, 700, 310 STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME EXSTYLE WS_EX_TOOLWINDOW CAPTION "Memory View" @@ -329,6 +329,8 @@ BEGIN EDITTEXT IDC_SEARCH_BOX,397,6,100,13,ES_AUTOHSCROLL PUSHBUTTON "Search",IDC_BUTTON_SEARCH,504,5,50,14 LTEXT "Search:",IDC_STATIC,369,8,27,8 + + CONTROL "",IDC_MEMVIEW_STATUS,"msctls_statusbar32",WS_CHILD | WS_VISIBLE,0,286,700,24 END IDD_INPUTBOX DIALOGEX 0, 0, 163, 55 diff --git a/Windows/resource.h b/Windows/resource.h index a13d9b3846be..96a4fcab50ed 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -375,6 +375,7 @@ #define IDC_GEDBG_STEPCOUNT_COMBO 40203 #define ID_FILE_DUMP_VIDEO_OUTPUT 40204 #define ID_EMULATION_CHAT 40205 +#define IDC_MEMVIEW_STATUS 40206 // Dummy option to let the buffered rendering hotkey cycle through all the options. #define ID_OPTIONS_BUFFEREDRENDERINGDUMMY 40500 @@ -387,7 +388,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 256 -#define _APS_NEXT_COMMAND_VALUE 40200 +#define _APS_NEXT_COMMAND_VALUE 40207 #define _APS_NEXT_CONTROL_VALUE 1202 #define _APS_NEXT_SYMED_VALUE 101 #endif From a4ed6eb167628a18403641557de6812b1ec077a9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Feb 2021 17:06:14 -0800 Subject: [PATCH 24/29] Debugger: Fix memory lookup in mirrors/uncached. Oops, was crashing before since it's outside the index. --- Core/Debugger/MemBlockInfo.cpp | 2 ++ Windows/Debugger/CtrlMemView.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 1ff7d16d504d..68cbcefe3500 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -371,6 +371,7 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_ std::vector FindMemInfo(uint32_t start, uint32_t size) { FlushPendingMemInfo(); + start &= ~0xC0000000; std::vector results; allocMap.Find(MemBlockFlags::ALLOC, start, size, results); @@ -382,6 +383,7 @@ std::vector FindMemInfo(uint32_t start, uint32_t size) { std::vector FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, uint32_t size) { FlushPendingMemInfo(); + start &= ~0xC0000000; std::vector results; if (flags & MemBlockFlags::ALLOC) diff --git a/Windows/Debugger/CtrlMemView.cpp b/Windows/Debugger/CtrlMemView.cpp index 326fa1bdf813..fbb1478edea9 100644 --- a/Windows/Debugger/CtrlMemView.cpp +++ b/Windows/Debugger/CtrlMemView.cpp @@ -240,7 +240,7 @@ void CtrlMemView::onPaint(WPARAM wParam, LPARAM lParam) { } for (int j = 0; j < rowSize; j++) { - uint32_t byteAddress = address + j; + const uint32_t byteAddress = (address + j) & ~0xC0000000; std::string tag; bool tagContinues = false; for (auto info : memRangeInfo) { @@ -272,7 +272,7 @@ void CtrlMemView::onPaint(WPARAM wParam, LPARAM lParam) { COLORREF asciiTextCol = 0x000000; int underline = -1; - if (byteAddress == curAddress && searching == false) { + if (address + j == curAddress && searching == false) { if (asciiSelected) { hexBGCol = 0xC0C0C0; hexTextCol = 0x000000; From de72190344f9dcb4d8c2e8a0e65a790e90c8fcee Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Feb 2021 17:06:52 -0800 Subject: [PATCH 25/29] Debugger: Update status on scroll down. And include the start and end of the range. --- Windows/Debugger/CtrlMemView.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Windows/Debugger/CtrlMemView.cpp b/Windows/Debugger/CtrlMemView.cpp index fbb1478edea9..5b0e4400b8e7 100644 --- a/Windows/Debugger/CtrlMemView.cpp +++ b/Windows/Debugger/CtrlMemView.cpp @@ -562,7 +562,7 @@ void CtrlMemView::updateStatusBarText() { snprintf(text, sizeof(text), "%08X", curAddress); // There should only be one. for (MemBlockInfo info : memRangeInfo) { - snprintf(text, sizeof(text), "%08X - %s (at PC %08X / %lld ticks)", curAddress, info.tag.c_str(), info.pc, info.ticks); + snprintf(text, sizeof(text), "%08X - %s %08X-%08X (at PC %08X / %lld ticks)", curAddress, info.tag.c_str(), info.start, info.start + info.size, info.pc, info.ticks); } SendMessage(GetParent(wnd), WM_DEB_SETSTATUSBARTEXT, 0, (LPARAM)text); @@ -634,6 +634,7 @@ void CtrlMemView::scrollWindow(int lines) { windowStart += lines*rowSize; curAddress += lines*rowSize; + updateStatusBarText(); redraw(); } From 8d58bbb6342f130e2c498b70172c2ddaef619799 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Feb 2021 17:24:55 -0800 Subject: [PATCH 26/29] Debugger: Correct merging fragmented blocks. Oops, wasn't clearing them so was eventually maxing out fragmentation. --- Core/Debugger/MemBlockInfo.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 68cbcefe3500..8ce39e0f9e75 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -110,7 +110,7 @@ bool MemSlabMap::Mark(uint32_t addr, uint32_t size, uint64_t ticks, uint32_t pc, slab->tag = tag; // Move on to the next one. - if (firstMatch != nullptr) + if (firstMatch == nullptr) firstMatch = slab; slab = slab->next; } @@ -296,6 +296,11 @@ void MemSlabMap::Merge(Slab *a, Slab *b) { } // Take over index entries b had. FillHeads(a); + if (b->ticks > a->ticks) { + a->ticks = b->ticks; + // In case we ignore PC for same. + a->pc = b->pc; + } if (lastFind_ == b) lastFind_ = a; delete b; From cc1b4e695d7b18a38a30055b5fdffd7b5c5ac313 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Feb 2021 19:10:08 -0800 Subject: [PATCH 27/29] Debugger: Correct crash with no alloc tag. --- Core/Util/BlockAllocator.cpp | 2 +- GPU/Debugger/Playback.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/Util/BlockAllocator.cpp b/Core/Util/BlockAllocator.cpp index 76ac5b03d18d..696a43513ddf 100644 --- a/Core/Util/BlockAllocator.cpp +++ b/Core/Util/BlockAllocator.cpp @@ -489,7 +489,7 @@ BlockAllocator::Block::Block(u32 _start, u32 _size, bool _taken, Block *_prev, B } void BlockAllocator::Block::SetAllocated(const char *_tag, bool suballoc) { - NotifyMemInfo(suballoc ? MemBlockFlags::SUB_ALLOC : MemBlockFlags::ALLOC, start, size, _tag); + NotifyMemInfo(suballoc ? MemBlockFlags::SUB_ALLOC : MemBlockFlags::ALLOC, start, size, _tag ? _tag : ""); if (_tag) truncate_cpy(tag, _tag); else diff --git a/GPU/Debugger/Playback.cpp b/GPU/Debugger/Playback.cpp index 4a7fb9ca0052..9009632b336d 100644 --- a/GPU/Debugger/Playback.cpp +++ b/GPU/Debugger/Playback.cpp @@ -330,7 +330,7 @@ void DumpExecute::SyncStall() { bool DumpExecute::SubmitCmds(const void *p, u32 sz) { if (execListBuf == 0) { u32 allocSize = LIST_BUF_SIZE; - execListBuf = userMemory.Alloc(allocSize, "List buf"); + execListBuf = userMemory.Alloc(allocSize, true, "List buf"); if (execListBuf == -1) { execListBuf = 0; } From 07de2e54012f0e6e7d69e14fd10b2eb6d0dcf217 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Feb 2021 22:46:15 -0800 Subject: [PATCH 28/29] Debugger: Prevent thread errors on mem alloc info. --- Core/Debugger/MemBlockInfo.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 8ce39e0f9e75..3997a553fd23 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include #include "Common/Log.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" @@ -80,6 +81,7 @@ static MemSlabMap suballocMap; static MemSlabMap writeMap; static MemSlabMap textureMap; static std::vector pendingNotifies; +static std::mutex pendingMutex; MemSlabMap::MemSlabMap() { Reset(); @@ -322,6 +324,7 @@ void MemSlabMap::FillHeads(Slab *slab) { } void FlushPendingMemInfo() { + std::lock_guard guard(pendingMutex); for (auto info : pendingNotifies) { if (info.flags & MemBlockFlags::ALLOC) { allocMap.Mark(info.start, info.size, info.ticks, info.pc, true, info.tag); @@ -361,9 +364,15 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_ info.ticks = CoreTiming::GetTicks(); info.pc = pc; info.tag = tag; - pendingNotifies.push_back(info); - if (pendingNotifies.size() > MAX_PENDING_NOTIFIES) { + bool needFlush = false; + { + std::lock_guard guard(pendingMutex); + pendingNotifies.push_back(info); + needFlush = pendingNotifies.size() > MAX_PENDING_NOTIFIES; + } + + if (needFlush) { FlushPendingMemInfo(); } @@ -403,10 +412,12 @@ std::vector FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, } void MemBlockInfoInit() { + std::lock_guard guard(pendingMutex); pendingNotifies.reserve(MAX_PENDING_NOTIFIES); } void MemBlockInfoShutdown() { + std::lock_guard guard(pendingMutex); allocMap.Reset(); suballocMap.Reset(); writeMap.Reset(); From ee71ef961f5403cd197acea0ece77a3da72adf12 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Feb 2021 16:16:43 -0800 Subject: [PATCH 29/29] Debugger: Keep char *s for memchecks. --- Core/Debugger/Breakpoints.cpp | 10 +++++----- Core/Debugger/Breakpoints.h | 6 +++--- Core/Debugger/MemBlockInfo.cpp | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Core/Debugger/Breakpoints.cpp b/Core/Debugger/Breakpoints.cpp index 6ee1ac8ee6b3..ddb2d2baf650 100644 --- a/Core/Debugger/Breakpoints.cpp +++ b/Core/Debugger/Breakpoints.cpp @@ -40,15 +40,15 @@ static std::mutex memCheckMutex_; std::vector CBreakPoints::memChecks_; std::vector CBreakPoints::cleanupMemChecks_; -void MemCheck::Log(u32 addr, bool write, int size, u32 pc, const std::string &reason) { +void MemCheck::Log(u32 addr, bool write, int size, u32 pc, const char *reason) { if (result & BREAK_ACTION_LOG) { const char *type = write ? "Write" : "Read"; if (logFormat.empty()) { - NOTICE_LOG(MEMMAP, "CHK %s%i(%s) at %08x (%s), PC=%08x (%s)", type, size * 8, reason.c_str(), addr, g_symbolMap->GetDescription(addr).c_str(), pc, g_symbolMap->GetDescription(pc).c_str()); + NOTICE_LOG(MEMMAP, "CHK %s%i(%s) at %08x (%s), PC=%08x (%s)", type, size * 8, reason, addr, g_symbolMap->GetDescription(addr).c_str(), pc, g_symbolMap->GetDescription(pc).c_str()); } else { std::string formatted; CBreakPoints::EvaluateLogFormat(currentDebugMIPS, logFormat, formatted); - NOTICE_LOG(MEMMAP, "CHK %s%i(%s) at %08x: %s", type, size * 8, reason.c_str(), addr, formatted.c_str()); + NOTICE_LOG(MEMMAP, "CHK %s%i(%s) at %08x: %s", type, size * 8, reason, addr, formatted.c_str()); } } } @@ -63,7 +63,7 @@ BreakAction MemCheck::Apply(u32 addr, bool write, int size, u32 pc) { return BREAK_ACTION_IGNORE; } -BreakAction MemCheck::Action(u32 addr, bool write, int size, u32 pc, const std::string &reason) { +BreakAction MemCheck::Action(u32 addr, bool write, int size, u32 pc, const char *reason) { int mask = write ? MEMCHECK_WRITE : MEMCHECK_READ; if (cond & mask) { Log(addr, write, size, pc, reason); @@ -505,7 +505,7 @@ MemCheck *CBreakPoints::GetMemCheckLocked(u32 address, int size) { return 0; } -BreakAction CBreakPoints::ExecMemCheck(u32 address, bool write, int size, u32 pc, const std::string &reason) +BreakAction CBreakPoints::ExecMemCheck(u32 address, bool write, int size, u32 pc, const char *reason) { if (!anyMemChecks_) return BREAK_ACTION_IGNORE; diff --git a/Core/Debugger/Breakpoints.h b/Core/Debugger/Breakpoints.h index ffb9118cb52e..c2a7d81b6a46 100644 --- a/Core/Debugger/Breakpoints.h +++ b/Core/Debugger/Breakpoints.h @@ -96,13 +96,13 @@ struct MemCheck { // Called on the stored memcheck (affects numHits, etc.) BreakAction Apply(u32 addr, bool write, int size, u32 pc); // Called on a copy. - BreakAction Action(u32 addr, bool write, int size, u32 pc, const std::string &reason); + BreakAction Action(u32 addr, bool write, int size, u32 pc, const char *reason); void JitBeforeApply(u32 addr, bool write, int size, u32 pc); void JitBeforeAction(u32 addr, bool write, int size, u32 pc); bool JitApplyChanged(); void JitCleanup(bool changed); - void Log(u32 addr, bool write, int size, u32 pc, const std::string &reason); + void Log(u32 addr, bool write, int size, u32 pc, const char *reason); bool IsEnabled() const { return (result & BREAK_ACTION_PAUSE) != 0; @@ -151,7 +151,7 @@ class CBreakPoints static bool GetMemCheck(u32 start, u32 end, MemCheck *check); static bool GetMemCheckInRange(u32 address, int size, MemCheck *check); - static BreakAction ExecMemCheck(u32 address, bool write, int size, u32 pc, const std::string &reason); + static BreakAction ExecMemCheck(u32 address, bool write, int size, u32 pc, const char *reason); static BreakAction ExecOpMemCheck(u32 address, u32 pc); // Executes memchecks but used by the jit. Cleanup finalizes after jit is done. diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 3997a553fd23..ef3f1ec2390c 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -75,7 +75,7 @@ struct PendingNotifyMem { std::string tag; }; -static constexpr size_t MAX_PENDING_NOTIFIES = 4096; +static constexpr size_t MAX_PENDING_NOTIFIES = 512; static MemSlabMap allocMap; static MemSlabMap suballocMap; static MemSlabMap writeMap; @@ -377,9 +377,9 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_ } if (flags & MemBlockFlags::WRITE) { - CBreakPoints::ExecMemCheck(start, true, size, pc, tag); + CBreakPoints::ExecMemCheck(start, true, size, pc, tag.c_str()); } else if (flags & MemBlockFlags::READ) { - CBreakPoints::ExecMemCheck(start, false, size, pc, tag); + CBreakPoints::ExecMemCheck(start, false, size, pc, tag.c_str()); } }