mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 09:39:33 +01:00
Merge pull request #20114 from hrydgard/more-atrac-prep
Fix sceUtilityLoadModuleAv, allow browsing memory tags in the memory viewer
This commit is contained in:
6 files changed
+121
-62
No files matched your search
+11
-2
@@ -95,7 +95,11 @@ const AtracBase *__AtracGetCtx(int i, u32 *type) {
|
||||
void __AtracInit() {
|
||||
_assert_(sizeof(SceAtracContext) == 256);
|
||||
|
||||
atracInited = true;
|
||||
atracLibVersion = 0;
|
||||
atracLibCrc = 0;
|
||||
|
||||
atracInited = true; // TODO: This should probably only happen in __AtracNotifyLoadModule.
|
||||
|
||||
memset(atracContexts, 0, sizeof(atracContexts));
|
||||
|
||||
// Start with 2 of each in this order.
|
||||
@@ -114,13 +118,18 @@ void __AtracShutdown() {
|
||||
}
|
||||
}
|
||||
|
||||
void __AtracLoadModule(int version, u32 crc, u32 bssAddr, int bssSize) {
|
||||
void __AtracNotifyLoadModule(int version, u32 crc, u32 bssAddr, int bssSize) {
|
||||
atracLibVersion = version;
|
||||
atracLibCrc = crc;
|
||||
INFO_LOG(Log::ME, "Atrac module loaded: atracLibVersion 0x%0x, atracLibcrc %x, bss: %x (%x bytes)", atracLibVersion, atracLibCrc, bssAddr, bssSize);
|
||||
// Later, save bssAddr/bssSize and use them to return context addresses.
|
||||
}
|
||||
|
||||
void __AtracNotifyUnloadModule() {
|
||||
atracLibVersion = 0;
|
||||
atracLibCrc = 0;
|
||||
}
|
||||
|
||||
void __AtracDoState(PointerWrap &p) {
|
||||
auto s = p.Section("sceAtrac", 1, 2);
|
||||
if (!s)
|
||||
|
||||
+3
-1
@@ -25,7 +25,9 @@ void Register_sceAtrac3plus();
|
||||
void __AtracInit();
|
||||
void __AtracDoState(PointerWrap &p);
|
||||
void __AtracShutdown();
|
||||
void __AtracLoadModule(int version, u32 crc, u32 bssAddr, int bssSize);
|
||||
|
||||
void __AtracNotifyLoadModule(int version, u32 crc, u32 bssAddr, int bssSize);
|
||||
void __AtracNotifyUnloadModule();
|
||||
|
||||
enum AtracStatus : u8 {
|
||||
ATRAC_STATUS_NO_DATA = 1,
|
||||
|
||||
@@ -277,8 +277,9 @@ public:
|
||||
const char *GetTypeName() override { return GetStaticTypeName(); }
|
||||
static const char *GetStaticTypeName() { return "Module"; }
|
||||
void GetQuickInfo(char *ptr, int size) override {
|
||||
snprintf(ptr, size, "%sname=%s gp=%08x entry=%08x",
|
||||
isFake ? "faked " : "",
|
||||
snprintf(ptr, size, "%d.%d %sname=%s gp=%08x entry=%08x",
|
||||
nm.version[1], nm.version[0],
|
||||
isFake ? "(faked) " : "",
|
||||
nm.name,
|
||||
nm.gp_value,
|
||||
nm.entry_addr);
|
||||
@@ -480,7 +481,8 @@ public:
|
||||
|
||||
void PSPModule::GetLongInfo(char *ptr, int bufSize) const {
|
||||
StringWriter w(ptr, bufSize);
|
||||
w.F("%s: Version %d.%d. %d segments", nm.name, nm.version[0], nm.version[1], nm.nsegment).endl();
|
||||
w.F("%s: Version %d.%d. %d segments", nm.name, nm.version[1], nm.version[0], nm.nsegment).endl();
|
||||
w.F("Memory block: %08x (%08x/%d bytes)", memoryBlockAddr, memoryBlockSize, memoryBlockSize).endl();
|
||||
for (int i = 0; i < nm.nsegment; i++) {
|
||||
w.F(" %08x (%08x bytes)\n", nm.segmentaddr[i], nm.segmentsize[i]);
|
||||
}
|
||||
@@ -1340,7 +1342,6 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
|
||||
strncpy(module->nm.name, head->modname, ARRAY_SIZE(module->nm.name));
|
||||
module->nm.entry_addr = -1;
|
||||
module->nm.gp_value = -1;
|
||||
module->nm.bss_size = head->bss_size;
|
||||
|
||||
// Let's still try to allocate it. It may use user memory.
|
||||
u32 totalSize = 0;
|
||||
@@ -1367,6 +1368,8 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
|
||||
module->memoryBlockAddr = addr;
|
||||
module->memoryBlockSize = totalSize;
|
||||
module->nm.text_addr = addr;
|
||||
module->nm.bss_size = head->bss_size;
|
||||
module->nm.nsegment = head->nsegments;
|
||||
module->nm.version[0] = head->module_ver_hi;
|
||||
module->nm.version[1] = head->module_ver_lo;
|
||||
|
||||
@@ -1389,7 +1392,7 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
|
||||
__PsmfPlayerLoadModule(devkitVersion, module->crc);
|
||||
}
|
||||
if (!strcmp(head->modname, "sceATRAC3plus_Library")) {
|
||||
__AtracLoadModule(ver, module->crc, module->GetBSSAddr(), head->bss_size);
|
||||
__AtracNotifyLoadModule(ver, module->crc, module->GetBSSAddr(), head->bss_size);
|
||||
}
|
||||
|
||||
return module;
|
||||
@@ -1775,7 +1778,7 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
|
||||
__PsmfPlayerLoadModule(devkitVersion, module->crc);
|
||||
}
|
||||
if (!strcmp(modinfo->name, "sceATRAC3plus_Library")) {
|
||||
__AtracLoadModule(modinfo->moduleVersion, module->crc, module->GetBSSAddr(), module->nm.bss_size);
|
||||
__AtracNotifyLoadModule(modinfo->moduleVersion, module->crc, module->GetBSSAddr(), module->nm.bss_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+59
-37
@@ -87,7 +87,10 @@ static void NotifyLoadStatusAtrac(int state, u32 loadAddr, u32 totalSize) {
|
||||
constexpr int version = 0x103;
|
||||
constexpr int bssSize = 0x67C;
|
||||
_dbg_assert_(bssSize <= totalSize);
|
||||
__AtracLoadModule(version, 0, loadAddr, bssSize);
|
||||
__AtracNotifyLoadModule(version, 0, loadAddr, bssSize);
|
||||
} else if (state == -1) {
|
||||
// Unload.
|
||||
__AtracNotifyUnloadModule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,31 +108,31 @@ static const ModuleLoadInfo moduleLoadInfo[] = {
|
||||
ModuleLoadInfo(0x104, 0x00002000, "net_parse_http"),
|
||||
ModuleLoadInfo(0x105, 0x00028000, "net_http", httpModuleDeps),
|
||||
ModuleLoadInfo(0x106, 0x00044000, "net_ssl", sslModuleDeps),
|
||||
ModuleLoadInfo(0x107, 0x00010000, "0x107"),
|
||||
ModuleLoadInfo(0x107, 0x00010000, "unk_0x107"),
|
||||
ModuleLoadInfo(0x108, 0x00008000, "usb_pspcm", httpStorageModuleDeps),
|
||||
ModuleLoadInfo(0x200, 0x00000000, "usb_mic"),
|
||||
ModuleLoadInfo(0x201, 0x00000000, "usb_cam"),
|
||||
ModuleLoadInfo(0x202, 0x00000000, "usb_gps"),
|
||||
ModuleLoadInfo(0x203, 0x00000000, "0x203"),
|
||||
ModuleLoadInfo(0x2ff, 0x00000000, "0x2ff"),
|
||||
ModuleLoadInfo(0x203, 0x00000000, "usb_unk_0x203"),
|
||||
ModuleLoadInfo(0x2ff, 0x00000000, "unk_0x2ff"),
|
||||
ModuleLoadInfo(0x300, 0x00000000, "av_avcodec", &NotifyLoadStatusAvcodec),
|
||||
ModuleLoadInfo(0x301, 0x00000000, "av_sascore"),
|
||||
ModuleLoadInfo(0x302, 0x00008000, "av_atrac3plus", atrac3PlusModuleDeps, &NotifyLoadStatusAtrac), // TODO: 0x8000 is likely too large.
|
||||
ModuleLoadInfo(0x302, 0x00004000, "av_atrac3plus", atrac3PlusModuleDeps, &NotifyLoadStatusAtrac), // TODO: 0x8000 is likely too large.
|
||||
ModuleLoadInfo(0x303, 0x0000c000, "av_mpegbase", mpegBaseModuleDeps),
|
||||
ModuleLoadInfo(0x304, 0x00004000, "av_mp3"),
|
||||
ModuleLoadInfo(0x305, 0x0000a300, "av_vaudio"),
|
||||
ModuleLoadInfo(0x306, 0x00004000, "av_aac"),
|
||||
ModuleLoadInfo(0x307, 0x00000000, "av_g729"),
|
||||
ModuleLoadInfo(0x308, 0x0003c000, "av_", mp4ModuleDeps),
|
||||
ModuleLoadInfo(0x308, 0x0003c000, "av_mp4", mp4ModuleDeps),
|
||||
ModuleLoadInfo(0x3fe, 0x00000000, "me_stuff"),
|
||||
ModuleLoadInfo(0x3ff, 0x00000000, "me_core"), // ME Core?
|
||||
ModuleLoadInfo(0x400, 0x0000c000, "np_common"),
|
||||
ModuleLoadInfo(0x401, 0x00018000, "np_service"),
|
||||
ModuleLoadInfo(0x402, 0x00048000, "np_matching2"),
|
||||
ModuleLoadInfo(0x403, 0x0000e000, "0x403"),
|
||||
ModuleLoadInfo(0x403, 0x0000e000, "np_unk_0x403"),
|
||||
ModuleLoadInfo(0x500, 0x00000000, "np_drm"),
|
||||
ModuleLoadInfo(0x600, 0x00000000, "irda"),
|
||||
ModuleLoadInfo(0x601, 0x00000000, "0x601"),
|
||||
ModuleLoadInfo(0x601, 0x00000000, "unk_0x601"),
|
||||
};
|
||||
|
||||
// Only a single dialog is allowed at a time.
|
||||
@@ -508,6 +511,9 @@ bool __UtilityModuleGetMemoryRange(int moduleID, u32 *startPtr, u32 *sizePtr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int LoadModuleInternal(u32 module);
|
||||
static int UnloadModuleInternal(u32 module);
|
||||
|
||||
// Same as sceUtilityLoadModule, just limited in categories.
|
||||
// It seems this just loads module 0x300 + module & 0xFF..
|
||||
static u32 sceUtilityLoadAvModule(u32 module) {
|
||||
@@ -516,37 +522,61 @@ static u32 sceUtilityLoadAvModule(u32 module) {
|
||||
return hleLogError(Log::sceUtility, SCE_ERROR_AV_MODULE_BAD_ID);
|
||||
}
|
||||
|
||||
if (module == 0)
|
||||
JpegNotifyLoadStatus(1);
|
||||
return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility av module loaded", 25000);
|
||||
int result = LoadModuleInternal(0x300 | module);
|
||||
return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility av module loaded", 25000);
|
||||
}
|
||||
|
||||
static u32 sceUtilityUnloadAvModule(u32 module) {
|
||||
if (module == 0)
|
||||
JpegNotifyLoadStatus(-1);
|
||||
return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility av module unloaded", 800);
|
||||
if (module > 7) {
|
||||
ERROR_LOG_REPORT(Log::sceUtility, "sceUtilityLoadAvModule(%i): invalid module id", module);
|
||||
return hleLogError(Log::sceUtility, SCE_ERROR_AV_MODULE_BAD_ID);
|
||||
}
|
||||
|
||||
int result = UnloadModuleInternal(0x300 | module);
|
||||
return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility av module unloaded", 800);
|
||||
}
|
||||
|
||||
static u32 sceUtilityLoadModule(u32 module) {
|
||||
int result = LoadModuleInternal(module);
|
||||
// TODO: Each module has its own timing, technically, but this is a low-end.
|
||||
if (module == 0x3FF) {
|
||||
return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility module loaded", 130);
|
||||
} else {
|
||||
return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility module loaded", 25000);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 sceUtilityUnloadModule(u32 module) {
|
||||
int result = UnloadModuleInternal(module);
|
||||
// TODO: Each module has its own timing, technically, but this is a low-end.
|
||||
if (module == 0x3FF) {
|
||||
return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility module unloaded", 110);
|
||||
} else {
|
||||
return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility module unloaded", 400);
|
||||
}
|
||||
}
|
||||
|
||||
static int LoadModuleInternal(u32 module) {
|
||||
const ModuleLoadInfo *info = __UtilityModuleInfo(module);
|
||||
if (!info) {
|
||||
return hleReportError(Log::sceUtility, SCE_ERROR_MODULE_BAD_ID, "invalid module id");
|
||||
return SCE_ERROR_MODULE_BAD_ID;
|
||||
}
|
||||
|
||||
if (currentlyLoadedModules.find(module) != currentlyLoadedModules.end()) {
|
||||
return hleLogError(Log::sceUtility, SCE_ERROR_MODULE_ALREADY_LOADED, "already loaded");
|
||||
return SCE_ERROR_MODULE_ALREADY_LOADED;
|
||||
}
|
||||
|
||||
// Some games, like Kamen Rider Climax Heroes OOO, require an error if dependencies aren't loaded yet.
|
||||
for (const int *dep = info->dependencies; *dep != 0; ++dep) {
|
||||
if (currentlyLoadedModules.find(*dep) == currentlyLoadedModules.end()) {
|
||||
return hleDelayResult(hleLogError(Log::sceUtility, SCE_KERNEL_ERROR_LIBRARY_NOTFOUND, "dependent module %04x not loaded", *dep), "utility module load attempt", 25000);
|
||||
return SCE_KERNEL_ERROR_LIBRARY_NOTFOUND;
|
||||
}
|
||||
}
|
||||
|
||||
u32 allocSize = info->size;
|
||||
u32 address = 0;
|
||||
char name[128];
|
||||
snprintf(name, sizeof(name), "UtilityModule/%x", module);
|
||||
snprintf(name, sizeof(name), "UtilityModule/%3x_%s", module, info->name);
|
||||
if (allocSize != 0) {
|
||||
address = userMemory.Alloc(allocSize, false, name);
|
||||
}
|
||||
@@ -554,36 +584,28 @@ static u32 sceUtilityLoadModule(u32 module) {
|
||||
if (info->notify) {
|
||||
info->notify(1, address, allocSize);
|
||||
}
|
||||
|
||||
// TODO: Each module has its own timing, technically, but this is a low-end.
|
||||
if (module == 0x3FF)
|
||||
return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility module loaded", 130);
|
||||
else
|
||||
return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility module loaded", 25000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 sceUtilityUnloadModule(u32 module) {
|
||||
static int UnloadModuleInternal(u32 module) {
|
||||
const ModuleLoadInfo *info = __UtilityModuleInfo(module);
|
||||
if (!info) {
|
||||
return hleReportError(Log::sceUtility, SCE_ERROR_MODULE_BAD_ID, "invalid module id");
|
||||
return SCE_ERROR_MODULE_BAD_ID;
|
||||
}
|
||||
|
||||
if (currentlyLoadedModules.find(module) == currentlyLoadedModules.end()) {
|
||||
return hleLogWarning(Log::sceUtility, SCE_ERROR_MODULE_NOT_LOADED, "not yet loaded");
|
||||
auto iter = currentlyLoadedModules.find(module);
|
||||
if (iter == currentlyLoadedModules.end()) {
|
||||
return SCE_ERROR_MODULE_NOT_LOADED;
|
||||
}
|
||||
if (currentlyLoadedModules[module] != 0) {
|
||||
userMemory.Free(currentlyLoadedModules[module]);
|
||||
if (iter->second != 0) {
|
||||
userMemory.Free(iter->second);
|
||||
}
|
||||
currentlyLoadedModules.erase(module);
|
||||
|
||||
if (info->notify)
|
||||
if (info->notify) {
|
||||
info->notify(-1, 0, 0);
|
||||
|
||||
// TODO: Each module has its own timing, technically, but this is a low-end.
|
||||
if (module == 0x3FF)
|
||||
return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility module unloaded", 110);
|
||||
else
|
||||
return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility module unloaded", 400);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sceUtilityMsgDialogInitStart(u32 paramAddr) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Common/Log/LogManager.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/Debugger/MemBlockInfo.h"
|
||||
#include "Core/RetroAchievements.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/Debugger/DebugInterface.h"
|
||||
@@ -21,7 +22,6 @@
|
||||
#include "Core/FileSystems/MetaFileSystem.h"
|
||||
#include "Core/Debugger/SymbolMap.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HLE/SocketManager.h"
|
||||
#include "Core/HLE/NetInetConstants.h"
|
||||
@@ -1575,6 +1575,10 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Core")) {
|
||||
ImGui::MenuItem("Scheduler", nullptr, &cfg_.schedulerOpen);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("CPU")) {
|
||||
ImGui::MenuItem("CPU debugger", nullptr, &cfg_.disasmOpen);
|
||||
ImGui::MenuItem("GPR regs", nullptr, &cfg_.gprOpen);
|
||||
@@ -1582,8 +1586,9 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu
|
||||
ImGui::MenuItem("VFPU regs", nullptr, &cfg_.vfpuOpen);
|
||||
ImGui::MenuItem("Callstacks", nullptr, &cfg_.callstackOpen);
|
||||
ImGui::MenuItem("Breakpoints", nullptr, &cfg_.breakpointsOpen);
|
||||
ImGui::MenuItem("Scheduler", nullptr, &cfg_.schedulerOpen);
|
||||
ImGui::Separator();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Memory")) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
char title[64];
|
||||
snprintf(title, sizeof(title), "Memory %d", i + 1);
|
||||
@@ -1592,7 +1597,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu
|
||||
ImGui::MenuItem("Memory Dumper", nullptr, &cfg_.memDumpOpen);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("HLE")) {
|
||||
if (ImGui::BeginMenu("OS HLE")) {
|
||||
ImGui::MenuItem("File System Browser", nullptr, &cfg_.filesystemBrowserOpen);
|
||||
ImGui::MenuItem("Kernel Objects", nullptr, &cfg_.kernelObjectsOpen);
|
||||
ImGui::MenuItem("Threads", nullptr, &cfg_.threadsOpen);
|
||||
@@ -1852,21 +1857,38 @@ void ImMemWindow::Draw(MIPSDebugInterface *mipsDebug, ImConfig &cfg, ImControl &
|
||||
|
||||
ImVec2 size(0, -ImGui::GetFrameHeightWithSpacing());
|
||||
|
||||
auto node = [&](const char *title, uint32_t start, uint32_t len) {
|
||||
if (ImGui::TreeNode(title)) {
|
||||
if (ImGui::Selectable("(start)", cfg.selectedMemoryBlock == start)) {
|
||||
cfg.selectedMemoryBlock = start;
|
||||
GotoAddr(start);
|
||||
}
|
||||
const std::vector<MemBlockInfo> info = FindMemInfo(start, len);
|
||||
for (auto &iter : info) {
|
||||
ImGui::PushID(iter.start);
|
||||
if (ImGui::Selectable(iter.tag.c_str(), cfg.selectedMemoryBlock == iter.start)) {
|
||||
cfg.selectedMemoryBlock = iter.start;
|
||||
GotoAddr(iter.start);
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
const u32 end = start + len;
|
||||
if (ImGui::Selectable("(end)", cfg.selectedMemoryBlock == end)) {
|
||||
cfg.selectedMemoryBlock = end;
|
||||
GotoAddr(end);
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
};
|
||||
|
||||
// Main views - list of interesting addresses to the left, memory view to the right.
|
||||
if (ImGui::BeginChild("addr_list", ImVec2(200.0f, size.y), ImGuiChildFlags_ResizeX)) {
|
||||
if (ImGui::Selectable("Scratch")) {
|
||||
GotoAddr(0x00010000);
|
||||
}
|
||||
if (ImGui::Selectable("Kernel RAM")) {
|
||||
GotoAddr(0x08000000);
|
||||
}
|
||||
if (ImGui::Selectable("User RAM")) {
|
||||
GotoAddr(0x08800000);
|
||||
}
|
||||
if (ImGui::Selectable("VRAM")) {
|
||||
GotoAddr(0x04000000);
|
||||
}
|
||||
node("Scratch", 0x00010000, 0x00004000);
|
||||
node("Kernel RAM", 0x08000000, 0x00800000);
|
||||
node("User RAM" , 0x08800000, 0x01800000);
|
||||
node("VRAM", 0x04000000, 0x00200000);
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -164,6 +164,7 @@ struct ImConfig {
|
||||
int selectedBreakpoint = -1;
|
||||
int selectedMemCheck = -1;
|
||||
int selectedAtracCtx = 0;
|
||||
u32 selectedMemoryBlock = 0;
|
||||
uint64_t selectedTexAddr = 0;
|
||||
|
||||
bool realtimePixelPreview = false;
|
||||
|
||||
Reference in new issue
Block a user