mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #14056 from unknownbrackets/debugger-mem
Track memory allocations and writes for debug info
This commit is contained in:
commit
2f3bc2d373
55 changed files with 1052 additions and 368 deletions
|
@ -1485,6 +1485,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
|
||||
|
|
|
@ -429,6 +429,7 @@
|
|||
<ClCompile Include="..\ext\udis86\syn.c" />
|
||||
<ClCompile Include="..\ext\udis86\udis86.c" />
|
||||
<ClCompile Include="AVIDump.cpp" />
|
||||
<ClCompile Include="Debugger\MemBlockInfo.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\BreakpointSubscriber.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\CPUCoreSubscriber.cpp" />
|
||||
|
@ -977,6 +978,7 @@
|
|||
<ClInclude Include="..\ext\udis86\udis86.h" />
|
||||
<ClInclude Include="AVIDump.h" />
|
||||
<ClInclude Include="ConfigValues.h" />
|
||||
<ClInclude Include="Debugger\MemBlockInfo.h" />
|
||||
<ClInclude Include="Debugger\WebSocket.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\BreakpointSubscriber.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\GameSubscriber.h" />
|
||||
|
|
|
@ -977,6 +977,9 @@
|
|||
<ClCompile Include="MIPS\fake\FakeJit.cpp">
|
||||
<Filter>MIPS\fake</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Debugger\MemBlockInfo.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ELF\ElfReader.h">
|
||||
|
@ -1670,6 +1673,9 @@
|
|||
<ClInclude Include="MIPS\fake\FakeJit.h">
|
||||
<Filter>MIPS\fake</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Debugger\MemBlockInfo.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -40,14 +40,15 @@ static std::mutex memCheckMutex_;
|
|||
std::vector<MemCheck> CBreakPoints::memChecks_;
|
||||
std::vector<MemCheck *> 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 char *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, 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, 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 char *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 char *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;
|
||||
|
|
|
@ -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 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);
|
||||
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 @@ public:
|
|||
|
||||
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 char *reason);
|
||||
static BreakAction ExecOpMemCheck(u32 address, u32 pc);
|
||||
|
||||
// Executes memchecks but used by the jit. Cleanup finalizes after jit is done.
|
||||
|
|
438
Core/Debugger/MemBlockInfo.cpp
Normal file
438
Core/Debugger/MemBlockInfo.cpp
Normal file
|
@ -0,0 +1,438 @@
|
|||
// 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 <mutex>
|
||||
#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"
|
||||
|
||||
class MemSlabMap {
|
||||
public:
|
||||
MemSlabMap();
|
||||
~MemSlabMap();
|
||||
|
||||
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<MemBlockInfo> &results);
|
||||
void Reset();
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
private:
|
||||
struct Slab {
|
||||
uint32_t start = 0;
|
||||
uint32_t end = 0;
|
||||
uint64_t ticks = 0;
|
||||
uint32_t pc = 0;
|
||||
bool allocated = false;
|
||||
std::string tag;
|
||||
Slab *prev = nullptr;
|
||||
Slab *next = nullptr;
|
||||
|
||||
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.
|
||||
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);
|
||||
void FillHeads(Slab *slab);
|
||||
|
||||
Slab *first_ = nullptr;
|
||||
Slab *lastFind_ = nullptr;
|
||||
std::vector<Slab *> 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 = 512;
|
||||
static MemSlabMap allocMap;
|
||||
static MemSlabMap suballocMap;
|
||||
static MemSlabMap writeMap;
|
||||
static MemSlabMap textureMap;
|
||||
static std::vector<PendingNotifyMem> pendingNotifies;
|
||||
static std::mutex pendingMutex;
|
||||
|
||||
MemSlabMap::MemSlabMap() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
MemSlabMap::~MemSlabMap() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
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;
|
||||
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->end > end) {
|
||||
Split(slab, end - slab->start);
|
||||
}
|
||||
|
||||
slab->allocated = allocated;
|
||||
if (pc != 0) {
|
||||
slab->ticks = ticks;
|
||||
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<MemBlockInfo> &results) {
|
||||
uint32_t end = addr + size;
|
||||
Slab *slab = FindSlab(addr);
|
||||
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->ticks, slab->pc, slab->tag, slab->allocated });
|
||||
found = true;
|
||||
}
|
||||
slab = slab->next;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
void MemSlabMap::Reset() {
|
||||
Clear();
|
||||
|
||||
first_ = new Slab();
|
||||
first_->end = MAX_SIZE;
|
||||
lastFind_ = first_;
|
||||
|
||||
heads_.resize(SLICES, first_);
|
||||
}
|
||||
|
||||
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);
|
||||
lastFind_ = first_;
|
||||
--count;
|
||||
|
||||
heads_.resize(SLICES, nullptr);
|
||||
FillHeads(first_);
|
||||
|
||||
Slab *slab = first_;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
slab->next = new Slab();
|
||||
slab->next->DoState(p);
|
||||
|
||||
slab->next->prev = slab;
|
||||
slab = slab->next;
|
||||
|
||||
FillHeads(slab);
|
||||
}
|
||||
} 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, end);
|
||||
Do(p, ticks);
|
||||
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;
|
||||
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) {
|
||||
lastFind_ = slab;
|
||||
return slab;
|
||||
}
|
||||
slab = slab->next;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MemSlabMap::Slab *MemSlabMap::Split(Slab *slab, uint32_t size) {
|
||||
Slab *next = new Slab();
|
||||
next->start = slab->start + size;
|
||||
next->end = slab->end;
|
||||
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;
|
||||
|
||||
// If the split is big, we might have to update our index.
|
||||
FillHeads(next);
|
||||
|
||||
slab->end = slab->start + 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->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->end == 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);
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
void MemSlabMap::FillHeads(Slab *slab) {
|
||||
uint32_t slice = slab->start / 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) {
|
||||
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 FlushPendingMemInfo() {
|
||||
std::lock_guard<std::mutex> guard(pendingMutex);
|
||||
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);
|
||||
}
|
||||
|
||||
void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_t pc, const std::string &tag) {
|
||||
if (size == 0) {
|
||||
return;
|
||||
}
|
||||
// Clear the uncached and kernel bits.
|
||||
start &= ~0xC0000000;
|
||||
|
||||
PendingNotifyMem info{ flags, start, size };
|
||||
info.ticks = CoreTiming::GetTicks();
|
||||
info.pc = pc;
|
||||
info.tag = tag;
|
||||
|
||||
bool needFlush = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(pendingMutex);
|
||||
pendingNotifies.push_back(info);
|
||||
needFlush = pendingNotifies.size() > MAX_PENDING_NOTIFIES;
|
||||
}
|
||||
|
||||
if (needFlush) {
|
||||
FlushPendingMemInfo();
|
||||
}
|
||||
|
||||
if (flags & MemBlockFlags::WRITE) {
|
||||
CBreakPoints::ExecMemCheck(start, true, size, pc, tag.c_str());
|
||||
} else if (flags & MemBlockFlags::READ) {
|
||||
CBreakPoints::ExecMemCheck(start, false, size, pc, tag.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<MemBlockInfo> FindMemInfo(uint32_t start, uint32_t size) {
|
||||
FlushPendingMemInfo();
|
||||
start &= ~0xC0000000;
|
||||
|
||||
std::vector<MemBlockInfo> results;
|
||||
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;
|
||||
}
|
||||
|
||||
std::vector<MemBlockInfo> FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, uint32_t size) {
|
||||
FlushPendingMemInfo();
|
||||
start &= ~0xC0000000;
|
||||
|
||||
std::vector<MemBlockInfo> 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() {
|
||||
std::lock_guard<std::mutex> guard(pendingMutex);
|
||||
pendingNotifies.reserve(MAX_PENDING_NOTIFIES);
|
||||
}
|
||||
|
||||
void MemBlockInfoShutdown() {
|
||||
std::lock_guard<std::mutex> guard(pendingMutex);
|
||||
allocMap.Reset();
|
||||
suballocMap.Reset();
|
||||
writeMap.Reset();
|
||||
textureMap.Reset();
|
||||
pendingNotifies.clear();
|
||||
}
|
||||
|
||||
void MemBlockInfoDoState(PointerWrap &p) {
|
||||
auto s = p.Section("MemBlockInfo", 0, 1);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
FlushPendingMemInfo();
|
||||
allocMap.DoState(p);
|
||||
suballocMap.DoState(p);
|
||||
writeMap.DoState(p);
|
||||
textureMap.DoState(p);
|
||||
}
|
57
Core/Debugger/MemBlockInfo.h
Normal file
57
Core/Debugger/MemBlockInfo.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
// 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 <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Common/Common.h"
|
||||
|
||||
class PointerWrap;
|
||||
|
||||
enum class MemBlockFlags {
|
||||
ALLOC = 0x0001,
|
||||
SUB_ALLOC = 0x0002,
|
||||
WRITE = 0x0004,
|
||||
TEXTURE = 0x0008,
|
||||
// Not actually logged.
|
||||
READ = 0x0800,
|
||||
FREE = 0x1000,
|
||||
SUB_FREE = 0x2000,
|
||||
};
|
||||
ENUM_CLASS_BITOPS(MemBlockFlags);
|
||||
|
||||
struct MemBlockInfo {
|
||||
MemBlockFlags flags;
|
||||
uint32_t start;
|
||||
uint32_t size;
|
||||
uint64_t ticks;
|
||||
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<MemBlockInfo> FindMemInfo(uint32_t start, uint32_t size);
|
||||
std::vector<MemBlockInfo> FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, uint32_t size);
|
||||
|
||||
void MemBlockInfoInit();
|
||||
void MemBlockInfoShutdown();
|
||||
void MemBlockInfoDoState(PointerWrap &p);
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -475,10 +473,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);
|
||||
CBreakPoints::ExecMemCheck(writeAddr, true, dstSize, currentMIPS->pc);
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, writeAddr, srcSize, "ELFLoad");
|
||||
DEBUG_LOG(LOADER,"Loadable Segment Copied to %08x, size %08x", writeAddr, (u32)p->p_memsz);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "Common/Swap.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"
|
||||
|
@ -154,8 +155,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
|
||||
}
|
||||
|
@ -196,8 +197,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..
|
||||
}
|
||||
|
@ -224,8 +225,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
|
||||
}
|
||||
|
@ -262,8 +263,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
|
||||
}
|
||||
|
@ -290,8 +291,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
|
||||
}
|
||||
|
@ -312,7 +313,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
|
||||
}
|
||||
|
@ -343,7 +344,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..)
|
||||
}
|
||||
|
@ -603,9 +604,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]);
|
||||
|
@ -653,7 +654,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;
|
||||
}
|
||||
|
@ -667,7 +668,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;
|
||||
}
|
||||
|
@ -684,7 +685,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;
|
||||
}
|
||||
|
@ -693,7 +694,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;
|
||||
}
|
||||
|
@ -703,7 +704,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;
|
||||
}
|
||||
|
@ -724,7 +725,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;
|
||||
}
|
||||
|
@ -735,7 +736,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;
|
||||
}
|
||||
|
@ -746,7 +747,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;
|
||||
}
|
||||
|
@ -755,7 +756,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;
|
||||
}
|
||||
|
@ -764,7 +765,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;
|
||||
}
|
||||
|
@ -773,7 +774,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;
|
||||
}
|
||||
|
@ -782,7 +783,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;
|
||||
}
|
||||
|
@ -791,7 +792,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;
|
||||
}
|
||||
|
@ -800,7 +801,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;
|
||||
}
|
||||
|
@ -811,7 +812,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;
|
||||
}
|
||||
|
@ -820,7 +821,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;
|
||||
}
|
||||
|
@ -829,7 +830,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;
|
||||
}
|
||||
|
@ -850,7 +851,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;
|
||||
}
|
||||
|
@ -859,7 +860,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;
|
||||
}
|
||||
|
@ -871,7 +872,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;
|
||||
}
|
||||
|
@ -883,7 +884,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;
|
||||
}
|
||||
|
@ -895,7 +896,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;
|
||||
}
|
||||
|
@ -909,7 +910,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;
|
||||
}
|
||||
|
@ -918,7 +919,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;
|
||||
}
|
||||
|
@ -927,7 +928,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;
|
||||
}
|
||||
|
@ -936,7 +937,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;
|
||||
}
|
||||
|
@ -945,7 +946,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;
|
||||
}
|
||||
|
@ -954,7 +955,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;
|
||||
}
|
||||
|
@ -963,7 +964,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;
|
||||
}
|
||||
|
@ -972,7 +973,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;
|
||||
}
|
||||
|
@ -981,7 +982,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;
|
||||
}
|
||||
|
@ -990,7 +991,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;
|
||||
}
|
||||
|
@ -999,7 +1000,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;
|
||||
}
|
||||
|
@ -1008,7 +1009,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;
|
||||
}
|
||||
|
@ -1017,7 +1018,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;
|
||||
}
|
||||
|
@ -1026,7 +1027,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;
|
||||
}
|
||||
|
@ -1035,7 +1036,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;
|
||||
}
|
||||
|
@ -1044,7 +1045,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;
|
||||
}
|
||||
|
@ -1053,7 +1054,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;
|
||||
}
|
||||
|
@ -1062,7 +1063,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;
|
||||
}
|
||||
|
@ -1093,7 +1094,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;
|
||||
}
|
||||
|
@ -1103,7 +1104,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;
|
||||
}
|
||||
|
@ -1113,7 +1114,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;
|
||||
}
|
||||
|
@ -1122,7 +1123,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;
|
||||
}
|
||||
|
@ -1131,7 +1132,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;
|
||||
}
|
||||
|
@ -1141,7 +1142,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;
|
||||
}
|
||||
|
@ -1150,7 +1151,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;
|
||||
}
|
||||
|
@ -1159,7 +1160,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;
|
||||
}
|
||||
|
@ -1179,7 +1180,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;
|
||||
}
|
||||
|
@ -1188,7 +1189,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;
|
||||
}
|
||||
|
@ -1211,7 +1212,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;
|
||||
}
|
||||
|
@ -1222,14 +1223,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;
|
||||
}
|
||||
|
@ -1262,7 +1263,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;
|
||||
}
|
||||
|
||||
|
@ -1272,7 +1273,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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
@ -1226,7 +1226,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);
|
||||
|
@ -1248,7 +1248,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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2314,7 +2314,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);
|
||||
}
|
||||
|
@ -2451,7 +2451,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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,16 +20,17 @@
|
|||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#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,10 +427,11 @@ void __KernelFplEndCallback(SceUID threadID, SceUID prevCallbackId);
|
|||
|
||||
void __KernelMemoryInit()
|
||||
{
|
||||
kernelMemory.Init(PSP_GetKernelMemoryBase(), PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase());
|
||||
userMemory.Init(PSP_GetUserMemoryBase(), PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase());
|
||||
Memory::Memset(PSP_GetKernelMemoryBase(), 0, PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase());
|
||||
Memory::Memset(PSP_GetUserMemoryBase(), 0, PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase());
|
||||
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(), "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);
|
||||
|
@ -471,6 +473,8 @@ void __KernelMemoryDoState(PointerWrap &p)
|
|||
if (s >= 2) {
|
||||
Do(p, tlsplThreadEndChecks);
|
||||
}
|
||||
|
||||
MemBlockInfoDoState(p);
|
||||
}
|
||||
|
||||
void __KernelMemoryShutdown()
|
||||
|
@ -486,6 +490,7 @@ void __KernelMemoryShutdown()
|
|||
#endif
|
||||
kernelMemory.Shutdown();
|
||||
tlsplThreadEndChecks.clear();
|
||||
MemBlockInfoShutdown();
|
||||
}
|
||||
|
||||
enum SceKernelFplAttr
|
||||
|
@ -510,6 +515,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 +728,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 +760,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 +792,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 +821,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 +1515,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<SceKernelVplHeader>::Create(memBlockPtr);
|
||||
vpl->header->Init(memBlockPtr, vplSize);
|
||||
|
@ -1572,7 +1584,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,9 +1965,10 @@ 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);
|
||||
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);
|
||||
|
@ -2227,10 +2240,12 @@ 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)
|
||||
Memory::Memset(allocAddress, 0, tls->ntls.blockSize);
|
||||
if (needsClear) {
|
||||
Memory::Memset(allocAddress, 0, tls->ntls.blockSize, "TlsAddr");
|
||||
}
|
||||
|
||||
return allocAddress;
|
||||
}
|
||||
|
|
|
@ -861,7 +861,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);
|
||||
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);
|
||||
|
@ -1743,13 +1743,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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -426,7 +426,7 @@ public:
|
|||
bool FillStack() {
|
||||
// Fill the stack.
|
||||
if ((nt.attr & PSP_THREAD_ATTR_NO_FILLSTACK) == 0) {
|
||||
Memory::Memset(currentStack.start, 0xFF, nt.stackSize);
|
||||
Memory::Memset(currentStack.start, 0xFF, nt.stackSize, "ThreadFillStack");
|
||||
}
|
||||
context.r[MIPS_REG_SP] = currentStack.start + nt.stackSize;
|
||||
currentStack.end = context.r[MIPS_REG_SP];
|
||||
|
@ -434,7 +434,7 @@ public:
|
|||
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);
|
||||
|
@ -450,7 +450,7 @@ public:
|
|||
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);
|
||||
Memory::Memset(nt.initialStack, 0, nt.stackSize, "ThreadFreeStack");
|
||||
}
|
||||
|
||||
if (nt.attr & PSP_THREAD_ATTR_KERNEL) {
|
||||
|
@ -475,7 +475,7 @@ public:
|
|||
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);
|
||||
return true;
|
||||
}
|
||||
|
@ -934,7 +934,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) {
|
||||
|
@ -1282,15 +1282,15 @@ 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));
|
||||
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);
|
||||
if (sz != 0)
|
||||
Memory::Memcpy(statusPtr, &t->nt, sz);
|
||||
Memory::Memcpy(statusPtr, &t->nt, sz, "ThreadStatus");
|
||||
}
|
||||
|
||||
hleEatCycles(1400);
|
||||
|
@ -1933,7 +1933,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;
|
||||
|
||||
|
@ -2037,8 +2037,9 @@ int __KernelStartThread(SceUID threadToStartID, int argSize, u32 argBlockPtr, bo
|
|||
}
|
||||
|
||||
// Now copy argument to stack.
|
||||
if (!forceArgs && Memory::IsValidAddress(argBlockPtr))
|
||||
Memory::Memcpy(sp, argBlockPtr, argSize);
|
||||
if (!forceArgs && Memory::IsValidAddress(argBlockPtr)) {
|
||||
Memory::Memcpy(sp, 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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -18,17 +18,18 @@
|
|||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#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);
|
||||
|
|
|
@ -528,8 +528,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);
|
||||
|
@ -1985,7 +1985,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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
@ -862,7 +862,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
|
||||
|
@ -917,7 +917,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;
|
||||
|
||||
|
@ -927,7 +926,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;
|
||||
|
||||
|
@ -937,7 +935,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;
|
||||
|
||||
|
@ -947,7 +944,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;
|
||||
|
||||
|
@ -967,9 +963,9 @@ 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");
|
||||
|
||||
// Account for the y offset as well.
|
||||
return videoImageSize + videoLineSize * ypos;
|
||||
return videoImageSize;
|
||||
#endif // USE_FFMPEG
|
||||
return 0;
|
||||
}
|
||||
|
@ -1042,7 +1038,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;
|
||||
|
|
|
@ -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"
|
||||
|
@ -397,6 +398,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;
|
||||
|
|
|
@ -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"
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
CBreakPoints::ExecMemCheck(_Address, true, _iLength, currentMIPS->pc);
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, _Address, _iLength, tag);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
@ -28,33 +28,31 @@ 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);
|
||||
CBreakPoints::ExecMemCheck(to_address, true, len, currentMIPS->pc);
|
||||
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);
|
||||
CBreakPoints::ExecMemCheck(from_address, false, len, currentMIPS->pc);
|
||||
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);
|
||||
CBreakPoints::ExecMemCheck(to_address, true, len, currentMIPS->pc);
|
||||
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);
|
||||
void Memset(const u32 _Address, const u8 _Data, const u32 _iLength, const std::string &tag = "Memset");
|
||||
|
||||
template<class T>
|
||||
void ReadStruct(u32 address, T *ptr)
|
||||
|
|
|
@ -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 ? _tag : "");
|
||||
if (_tag)
|
||||
truncate_cpy(tag, _tag);
|
||||
else
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
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 @@ private:
|
|||
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 @@ private:
|
|||
u32 rangeSize_;
|
||||
|
||||
u32 grain_;
|
||||
bool suballoc_;
|
||||
|
||||
void MergeFreeBlocks(Block *fromBlock);
|
||||
Block *GetBlockFromAddress(u32 addr);
|
||||
|
|
|
@ -1264,8 +1264,8 @@ bool PPGeImage::Load() {
|
|||
return false;
|
||||
}
|
||||
|
||||
Memory::Memcpy(texture_, textureData, dataSize);
|
||||
Memory::Memset(texture_ + dataSize, 0, texSize - dataSize);
|
||||
Memory::Memcpy(texture_, textureData, dataSize, "PPGeTex");
|
||||
Memory::Memset(texture_ + dataSize, 0, texSize - dataSize, "PPGeTexClear");
|
||||
free(textureData);
|
||||
|
||||
lastFrame_ = gpuStats.numFlips;
|
||||
|
|
|
@ -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"
|
||||
|
@ -1290,8 +1290,14 @@ 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);
|
||||
}
|
||||
if (old.fbo) {
|
||||
INFO_LOG(FRAMEBUF, "Resizing FBO for %08x : %dx%dx%s", vfb->fb_address, w, h, GeBufferFormatToString(vfb->format));
|
||||
if (vfb->fbo) {
|
||||
|
@ -1680,10 +1686,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);
|
||||
|
@ -2162,7 +2172,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);
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
@ -1121,6 +1123,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.
|
||||
|
@ -1305,6 +1309,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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,8 +2720,8 @@ 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;
|
||||
|
@ -2731,9 +2731,7 @@ 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);
|
||||
|
@ -2743,6 +2741,8 @@ 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;
|
||||
|
@ -2751,13 +2751,14 @@ bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) {
|
|||
bool GPUCommon::PerformMemorySet(u32 dest, u8 v, int size) {
|
||||
// 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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -389,6 +389,7 @@
|
|||
<ClInclude Include="..\..\Core\Debugger\Breakpoints.h" />
|
||||
<ClInclude Include="..\..\Core\Debugger\DebugInterface.h" />
|
||||
<ClInclude Include="..\..\Core\Debugger\DisassemblyManager.h" />
|
||||
<ClInclude Include="..\..\Core\Debugger\MemBlockInfo.h" />
|
||||
<ClInclude Include="..\..\Core\Debugger\SymbolMap.h" />
|
||||
<ClInclude Include="..\..\Core\Debugger\WebSocket.h" />
|
||||
<ClInclude Include="..\..\Core\Debugger\WebSocket\BreakpointSubscriber.h" />
|
||||
|
@ -621,6 +622,7 @@
|
|||
<ClCompile Include="..\..\Core\CwCheat.cpp" />
|
||||
<ClCompile Include="..\..\Core\Debugger\Breakpoints.cpp" />
|
||||
<ClCompile Include="..\..\Core\Debugger\DisassemblyManager.cpp" />
|
||||
<ClCompile Include="..\..\Core\Debugger\MemBlockInfo.cpp" />
|
||||
<ClCompile Include="..\..\Core\Debugger\SymbolMap.cpp" />
|
||||
<ClCompile Include="..\..\Core\Debugger\WebSocket.cpp" />
|
||||
<ClCompile Include="..\..\Core\Debugger\WebSocket\BreakpointSubscriber.cpp" />
|
||||
|
|
|
@ -563,6 +563,9 @@
|
|||
<ClCompile Include="..\..\Core\Debugger\DisassemblyManager.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Core\Debugger\MemBlockInfo.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Core\Debugger\SymbolMap.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1372,6 +1375,9 @@
|
|||
<ClInclude Include="..\..\Core\Debugger\DisassemblyManager.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\Core\Debugger\MemBlockInfo.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\Core\Debugger\SymbolMap.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <tchar.h>
|
||||
#include <math.h>
|
||||
#include <iomanip>
|
||||
#include "ext/xxhash.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Windows/resource.h"
|
||||
#include "Core/MemMap.h"
|
||||
|
@ -173,8 +174,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 +187,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 +200,124 @@ void CtrlMemView::onPaint(WPARAM wParam, LPARAM lParam)
|
|||
|
||||
if (displayOffsetScale)
|
||||
drawOffsetScale(hdc);
|
||||
|
||||
|
||||
std::vector<MemBlockInfo> memRangeInfo = FindMemInfoByFlag(highlightFlags_, windowStart, (visibleRows + 1) * rowSize);
|
||||
|
||||
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++)
|
||||
{
|
||||
char temp[32];
|
||||
|
||||
unsigned int address=windowStart + i*rowSize;
|
||||
int rowY = rowHeight*i;
|
||||
|
||||
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));
|
||||
rowY += rowHeight * offsetSpace;
|
||||
|
||||
SetTextColor(hdc,0x000000);
|
||||
char temp[32];
|
||||
uint32_t address = windowStart + i * rowSize;
|
||||
sprintf(temp, "%08X", address);
|
||||
|
||||
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);
|
||||
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 = '.';
|
||||
|
||||
if (address+j == curAddress && searching == false)
|
||||
{
|
||||
COLORREF oldBkColor = GetBkColor(hdc);
|
||||
COLORREF oldTextColor = GetTextColor(hdc);
|
||||
|
||||
if (hasFocus && !asciiSelected)
|
||||
{
|
||||
SetTextColor(hdc,0xFFFFFF);
|
||||
SetBkColor(hdc,0xFF9933);
|
||||
if (selectedNibble == 0) SelectObject(hdc,(HGDIOBJ)underlineFont);
|
||||
} else {
|
||||
SetTextColor(hdc,0);
|
||||
SetBkColor(hdc,0xC0C0C0);
|
||||
for (int j = 0; j < rowSize; j++) {
|
||||
const uint32_t byteAddress = (address + j) & ~0xC0000000;
|
||||
std::string tag;
|
||||
bool tagContinues = false;
|
||||
for (auto info : memRangeInfo) {
|
||||
if (info.start <= byteAddress && info.start + info.size > byteAddress) {
|
||||
tag = info.tag;
|
||||
tagContinues = byteAddress + 1 < info.start + info.size;
|
||||
}
|
||||
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);
|
||||
|
||||
if (hasFocus && asciiSelected)
|
||||
{
|
||||
SetTextColor(hdc,0xFFFFFF);
|
||||
SetBkColor(hdc,0xFF9933);
|
||||
} else {
|
||||
SetTextColor(hdc,0);
|
||||
SetBkColor(hdc,0xC0C0C0);
|
||||
SelectObject(hdc,(HGDIOBJ)font);
|
||||
}
|
||||
TextOutA(hdc,asciiStart+j*(charWidth+2),rowY,(char*)&c,1);
|
||||
|
||||
SetTextColor(hdc,oldTextColor);
|
||||
SetBkColor(hdc,oldBkColor);
|
||||
} else {
|
||||
TextOutA(hdc,hexStart+j*3*charWidth,rowY,temp,2);
|
||||
TextOutA(hdc,asciiStart+j*(charWidth+2),rowY,(char*)&c,1);
|
||||
}
|
||||
|
||||
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]);
|
||||
c = (char)memory.bytes[j];
|
||||
if (memory.bytes[j] < 32 || memory.bytes[j] >= 128)
|
||||
c = '.';
|
||||
} else {
|
||||
strcpy(temp, "??");
|
||||
c = '.';
|
||||
}
|
||||
|
||||
COLORREF hexBGCol = standardBG;
|
||||
COLORREF hexTextCol = 0x000000;
|
||||
COLORREF continueBGCol = standardBG;
|
||||
COLORREF asciiBGCol = standardBG;
|
||||
COLORREF asciiTextCol = 0x000000;
|
||||
int underline = -1;
|
||||
|
||||
if (address + j == curAddress && searching == false) {
|
||||
if (asciiSelected) {
|
||||
hexBGCol = 0xC0C0C0;
|
||||
hexTextCol = 0x000000;
|
||||
asciiBGCol = hasFocus ? 0xFF9933 : 0xC0C0C0;
|
||||
asciiTextCol = hasFocus ? 0xFFFFFF : 0x000000;
|
||||
} else {
|
||||
hexBGCol = hasFocus ? 0xFF9933 : 0xC0C0C0;
|
||||
hexTextCol = hasFocus ? 0xFFFFFF : 0x000000;
|
||||
asciiBGCol = 0xC0C0C0;
|
||||
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, underline == 0 ? (HGDIOBJ)underlineFont : (HGDIOBJ)font);
|
||||
TextOutA(hdc, hexX, rowY, &temp[0], 1);
|
||||
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);
|
||||
}
|
||||
|
||||
setTextColors(asciiTextCol, asciiBGCol);
|
||||
TextOutA(hdc, asciiX, rowY, &c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
setTextColors(0x000000, standardBG);
|
||||
SelectObject(hdc,oldFont);
|
||||
SelectObject(hdc,oldPen);
|
||||
SelectObject(hdc,oldBrush);
|
||||
|
@ -518,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<MemBlockInfo> 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 %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);
|
||||
}
|
||||
|
||||
void CtrlMemView::gotoPoint(int x, int y)
|
||||
|
@ -591,6 +634,7 @@ void CtrlMemView::scrollWindow(int lines)
|
|||
{
|
||||
windowStart += lines*rowSize;
|
||||
curAddress += lines*rowSize;
|
||||
updateStatusBarText();
|
||||
redraw();
|
||||
}
|
||||
|
||||
|
@ -642,6 +686,10 @@ std::vector<u32> 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;
|
||||
|
@ -793,3 +841,16 @@ void CtrlMemView::toggleOffsetScale(CommonToggles toggle)
|
|||
updateStatusBarText();
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CtrlMemView::setHighlightType(MemBlockFlags flags) {
|
||||
if (highlightFlags_ != flags) {
|
||||
highlightFlags_ = flags;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t CtrlMemView::pickTagColor(const std::string &tag) {
|
||||
int colors[6] = { 0xe0FFFF, 0xFFE0E0, 0xE8E8FF, 0xFFE0FF, 0xE0FFE0, 0xFFFFE0 };
|
||||
int which = XXH3_64bits(tag.c_str(), tag.length()) % ARRAY_SIZE(colors);
|
||||
return colors[which];
|
||||
}
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
//
|
||||
//To get a class instance to be able to access it, just use getFrom(HWND wnd).
|
||||
|
||||
#include "../../Core/Debugger/DebugInterface.h"
|
||||
#include <cstdint>
|
||||
#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,8 +65,12 @@ class CtrlMemView
|
|||
bool hasFocus;
|
||||
static wchar_t szClassName[];
|
||||
DebugInterface *debugger;
|
||||
|
||||
MemBlockFlags highlightFlags_ = MemBlockFlags::ALLOC;
|
||||
|
||||
void updateStatusBarText();
|
||||
void search(bool continueSearch);
|
||||
uint32_t pickTagColor(const std::string &tag);
|
||||
public:
|
||||
CtrlMemView(HWND _wnd);
|
||||
~CtrlMemView();
|
||||
|
@ -99,4 +105,5 @@ public:
|
|||
void drawOffsetScale(HDC hdc);
|
||||
void toggleOffsetScale(CommonToggles toggle);
|
||||
void toggleStringSearch(CommonToggles toggle);
|
||||
void setHighlightType(MemBlockFlags flags);
|
||||
};
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
|
||||
#include "Windows/stdafx.h"
|
||||
#include <windowsx.h>
|
||||
#include <commctrl.h>
|
||||
#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 +70,20 @@ 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);
|
||||
|
||||
status_ = GetDlgItem(m_hDlg, IDC_MEMVIEW_STATUS);
|
||||
|
||||
memView = CtrlMemView::getFrom(memViewHdl);
|
||||
memView->setDebugger(_cpu);
|
||||
|
||||
|
@ -118,66 +134,53 @@ void CMemoryDlg::searchBoxRedraw(std::vector<u32> 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 +190,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<u32> results = memView->searchString(ConvertWStringToUTF8(temp).c_str());
|
||||
if (results.size() > 0){
|
||||
|
@ -198,14 +199,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);
|
||||
|
||||
|
@ -222,12 +223,13 @@ BOOL CMemoryDlg::DlgProc(UINT message, WPARAM wParam, LPARAM lParam)
|
|||
Update();
|
||||
return TRUE;
|
||||
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
case WM_DEB_SETSTATUSBARTEXT:
|
||||
SendMessage(status_, SB_SETTEXT, 0, (LPARAM)ConvertUTF8ToWString((const char *)lParam).c_str());
|
||||
break;
|
||||
|
||||
case WM_INITDIALOG:
|
||||
return TRUE;
|
||||
|
||||
case WM_SIZE:
|
||||
Size();
|
||||
break;
|
||||
|
@ -255,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);
|
||||
|
|
|
@ -17,6 +17,8 @@ private:
|
|||
RECT winRect, srRect;
|
||||
CtrlMemView *memView;
|
||||
HWND memViewHdl, symListHdl, editWnd, searchBoxHdl, srcListHdl;
|
||||
HWND layerDropdown_;
|
||||
HWND status_;
|
||||
BOOL DlgProc(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
public:
|
||||
|
|
|
@ -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"
|
||||
|
@ -321,14 +321,16 @@ 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
|
||||
|
||||
CONTROL "",IDC_MEMVIEW_STATUS,"msctls_statusbar32",WS_CHILD | WS_VISIBLE,0,286,700,24
|
||||
END
|
||||
|
||||
IDD_INPUTBOX DIALOGEX 0, 0, 163, 55
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
Loading…
Add table
Reference in a new issue