mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #9780 from unknownbrackets/ge-record
GE recorder and replay
This commit is contained in:
commit
c5ebeb4273
53 changed files with 1663 additions and 243 deletions
|
@ -1268,6 +1268,8 @@ set(GPU_SOURCES
|
|||
GPU/Common/SplineCommon.h
|
||||
GPU/Debugger/Breakpoints.cpp
|
||||
GPU/Debugger/Breakpoints.h
|
||||
GPU/Debugger/Record.cpp
|
||||
GPU/Debugger/Record.h
|
||||
GPU/Debugger/Stepping.cpp
|
||||
GPU/Debugger/Stepping.h
|
||||
GPU/GPUInterface.h
|
||||
|
@ -1350,6 +1352,8 @@ add_library(${CoreLibName} ${CoreLinkType}
|
|||
Core/ELF/ParamSFO.cpp
|
||||
Core/ELF/ParamSFO.h
|
||||
Core/FileSystems/tlzrc.cpp
|
||||
Core/FileSystems/BlobFileSystem.cpp
|
||||
Core/FileSystems/BlobFileSystem.h
|
||||
Core/FileSystems/BlockDevices.cpp
|
||||
Core/FileSystems/BlockDevices.h
|
||||
Core/FileSystems/DirectoryFileSystem.cpp
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{533F1D30-D04D-47CC-AD71-20F658907E36}</ProjectGuid>
|
||||
<RootNamespace>Core</RootNamespace>
|
||||
<WindowsTargetPlatformVersion></WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>
|
||||
</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
|
@ -183,6 +184,7 @@
|
|||
<ClCompile Include="..\ext\udis86\syn.c" />
|
||||
<ClCompile Include="..\ext\udis86\udis86.c" />
|
||||
<ClCompile Include="AVIDump.cpp" />
|
||||
<ClCompile Include="FileSystems\BlobFileSystem.cpp" />
|
||||
<ClCompile Include="HLE\KUBridge.cpp" />
|
||||
<ClCompile Include="MIPS\IR\IRAsm.cpp" />
|
||||
<ClCompile Include="MIPS\IR\IRCompALU.cpp" />
|
||||
|
@ -524,6 +526,7 @@
|
|||
<ClInclude Include="..\ext\udis86\udint.h" />
|
||||
<ClInclude Include="..\ext\udis86\udis86.h" />
|
||||
<ClInclude Include="AVIDump.h" />
|
||||
<ClInclude Include="FileSystems\BlobFileSystem.h" />
|
||||
<ClInclude Include="HLE\KUBridge.h" />
|
||||
<ClInclude Include="MIPS\IR\IRFrontend.h" />
|
||||
<ClInclude Include="MIPS\IR\IRInst.h" />
|
||||
|
|
|
@ -680,6 +680,9 @@
|
|||
<ClCompile Include="HLE\KUBridge.cpp">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FileSystems\BlobFileSystem.cpp">
|
||||
<Filter>FileSystems</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ELF\ElfReader.h">
|
||||
|
@ -1250,10 +1253,13 @@
|
|||
<ClInclude Include="HLE\KUBridge.h">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FileSystems\BlobFileSystem.h">
|
||||
<Filter>FileSystems</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
<None Include="..\LICENSE.TXT" />
|
||||
<None Include="..\android\jni\Android.mk" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -573,6 +573,10 @@ void ForceCheck()
|
|||
currentMIPS->downcount = -1;
|
||||
// But let's not eat a bunch more time in Advance() because of this.
|
||||
slicelength = -1;
|
||||
|
||||
#ifdef _DEBUG
|
||||
_dbg_assert_msg_(CPU, cyclesExecuted >= 0, "Shouldn't have a negative cyclesExecuted");
|
||||
#endif
|
||||
}
|
||||
|
||||
void Advance()
|
||||
|
@ -613,7 +617,7 @@ void LogPendingEvents()
|
|||
Event *ptr = first;
|
||||
while (ptr)
|
||||
{
|
||||
//INFO_LOG(TIMER, "PENDING: Now: %lld Pending: %lld Type: %d", globalTimer, ptr->time, ptr->type);
|
||||
//INFO_LOG(CPU, "PENDING: Now: %lld Pending: %lld Type: %d", globalTimer, ptr->time, ptr->type);
|
||||
ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,14 @@ public:
|
|||
std::vector<std::string> GetKeys();
|
||||
std::string GenerateFakeID(std::string filename = "");
|
||||
|
||||
std::string GetDiscID() {
|
||||
const std::string discID = GetValueString("DISC_ID");
|
||||
if (discID.empty()) {
|
||||
return GenerateFakeID();
|
||||
}
|
||||
return discID;
|
||||
}
|
||||
|
||||
bool ReadSFO(const u8 *paramsfo, size_t size);
|
||||
bool WriteSFO(u8 **paramsfo, size_t *size);
|
||||
|
||||
|
|
137
Core/FileSystems/BlobFileSystem.cpp
Normal file
137
Core/FileSystems/BlobFileSystem.cpp
Normal file
|
@ -0,0 +1,137 @@
|
|||
// Copyright (c) 2017- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "Core/FileSystems/BlobFileSystem.h"
|
||||
|
||||
BlobFileSystem::BlobFileSystem(IHandleAllocator *hAlloc, FileLoader *fileLoader, std::string alias)
|
||||
: alloc_(hAlloc), fileLoader_(fileLoader), alias_(alias) {
|
||||
}
|
||||
|
||||
BlobFileSystem::~BlobFileSystem() {
|
||||
// TODO: Who deletes fileLoader?
|
||||
}
|
||||
|
||||
void BlobFileSystem::DoState(PointerWrap &p) {
|
||||
// Not used in real emulation.
|
||||
}
|
||||
|
||||
std::vector<PSPFileInfo> BlobFileSystem::GetDirListing(std::string path) {
|
||||
std::vector<PSPFileInfo> listing;
|
||||
listing.push_back(GetFileInfo(alias_));
|
||||
return listing;
|
||||
}
|
||||
|
||||
u32 BlobFileSystem::OpenFile(std::string filename, FileAccess access, const char *devicename) {
|
||||
u32 newHandle = alloc_->GetNewHandle();
|
||||
entries_[newHandle] = 0;
|
||||
return newHandle;
|
||||
}
|
||||
|
||||
void BlobFileSystem::CloseFile(u32 handle) {
|
||||
alloc_->FreeHandle(handle);
|
||||
entries_.erase(handle);
|
||||
}
|
||||
|
||||
size_t BlobFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) {
|
||||
auto entry = entries_.find(handle);
|
||||
if (entry != entries_.end()) {
|
||||
size_t readSize = fileLoader_->ReadAt(entry->second, size, pointer);
|
||||
entry->second += readSize;
|
||||
return readSize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t BlobFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size, int &usec) {
|
||||
usec = 0;
|
||||
return ReadFile(handle, pointer, size);
|
||||
}
|
||||
|
||||
size_t BlobFileSystem::WriteFile(u32 handle, const u8 *pointer, s64 size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t BlobFileSystem::WriteFile(u32 handle, const u8 *pointer, s64 size, int &usec) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t BlobFileSystem::SeekFile(u32 handle, s32 position, FileMove type) {
|
||||
auto entry = entries_.find(handle);
|
||||
if (entry != entries_.end()) {
|
||||
switch (type) {
|
||||
case FILEMOVE_BEGIN:
|
||||
entry->second = position;
|
||||
break;
|
||||
case FILEMOVE_CURRENT:
|
||||
entry->second += position;
|
||||
break;
|
||||
case FILEMOVE_END:
|
||||
entry->second = fileLoader_->FileSize() + position;
|
||||
break;
|
||||
}
|
||||
return (size_t)entry->second;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PSPFileInfo BlobFileSystem::GetFileInfo(std::string filename) {
|
||||
PSPFileInfo info{};
|
||||
info.name = alias_;
|
||||
info.size = fileLoader_->FileSize();
|
||||
info.access = 0666;
|
||||
info.exists = true;
|
||||
info.type = FILETYPE_NORMAL;
|
||||
return info;
|
||||
}
|
||||
|
||||
bool BlobFileSystem::OwnsHandle(u32 handle) {
|
||||
auto entry = entries_.find(handle);
|
||||
return entry != entries_.end();
|
||||
}
|
||||
|
||||
int BlobFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BlobFileSystem::DevType(u32 handle) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool BlobFileSystem::MkDir(const std::string &dirname) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BlobFileSystem::RmDir(const std::string &dirname) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int BlobFileSystem::RenameFile(const std::string &from, const std::string &to) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool BlobFileSystem::RemoveFile(const std::string &filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BlobFileSystem::GetHostPath(const std::string &inpath, std::string &outpath) {
|
||||
outpath = fileLoader_->Path();
|
||||
return true;
|
||||
}
|
||||
|
||||
u64 BlobFileSystem::FreeSpace(const std::string &path) {
|
||||
return 0;
|
||||
}
|
63
Core/FileSystems/BlobFileSystem.h
Normal file
63
Core/FileSystems/BlobFileSystem.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) 2017- 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
|
||||
|
||||
// This is used for opening a debug file as a blob, and mounting it.
|
||||
// Importantly, uses a fileLoader for all access, so http:// URLs are supported.
|
||||
// As of writing, only used by GE dump replay.
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "Core/Loaders.h"
|
||||
#include "Core/FileSystems/FileSystem.h"
|
||||
|
||||
class BlobFileSystem : public IFileSystem {
|
||||
public:
|
||||
BlobFileSystem(IHandleAllocator *hAlloc, FileLoader *fileLoader, std::string alias);
|
||||
~BlobFileSystem();
|
||||
|
||||
void DoState(PointerWrap &p) override;
|
||||
std::vector<PSPFileInfo> GetDirListing(std::string path) override;
|
||||
u32 OpenFile(std::string filename, FileAccess access, const char *devicename = nullptr) override;
|
||||
void CloseFile(u32 handle) override;
|
||||
size_t ReadFile(u32 handle, u8 *pointer, s64 size) override;
|
||||
size_t ReadFile(u32 handle, u8 *pointer, s64 size, int &usec) override;
|
||||
size_t WriteFile(u32 handle, const u8 *pointer, s64 size) override;
|
||||
size_t WriteFile(u32 handle, const u8 *pointer, s64 size, int &usec) override;
|
||||
size_t SeekFile(u32 handle, s32 position, FileMove type) override;
|
||||
PSPFileInfo GetFileInfo(std::string filename) override;
|
||||
bool OwnsHandle(u32 handle) override;
|
||||
int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override;
|
||||
int DevType(u32 handle) override;
|
||||
int Flags() override { return 0; }
|
||||
|
||||
bool MkDir(const std::string &dirname) override;
|
||||
bool RmDir(const std::string &dirname) override;
|
||||
int RenameFile(const std::string &from, const std::string &to) override;
|
||||
bool RemoveFile(const std::string &filename) override;
|
||||
bool GetHostPath(const std::string &inpath, std::string &outpath) override;
|
||||
u64 FreeSpace(const std::string &path) override;
|
||||
|
||||
private:
|
||||
// File positions.
|
||||
std::map<u32, s64> entries_;
|
||||
|
||||
IHandleAllocator *alloc_;
|
||||
FileLoader *fileLoader_;
|
||||
std::string alias_;
|
||||
};
|
|
@ -92,6 +92,7 @@ const HLEFunction FakeSysCalls[] = {
|
|||
{NID_EXTENDRETURN, __KernelReturnFromExtendStack, "__KernelReturnFromExtendStack"},
|
||||
{NID_MODULERETURN, __KernelReturnFromModuleFunc, "__KernelReturnFromModuleFunc"},
|
||||
{NID_IDLE, __KernelIdle, "_sceKernelIdle"},
|
||||
{NID_GPUREPLAY, __KernelGPUReplay, "__KernelGPUReplay"},
|
||||
};
|
||||
|
||||
const HLEFunction UtilsForUser[] =
|
||||
|
|
|
@ -23,5 +23,6 @@
|
|||
#define NID_EXTENDRETURN 0xbad0b0c9
|
||||
#define NID_MODULERETURN 0xbad0d318
|
||||
#define NID_IDLE 0x1d7e1d7e
|
||||
#define NID_GPUREPLAY 0x9e45bd95
|
||||
|
||||
void RegisterAllModules();
|
||||
|
|
|
@ -825,13 +825,29 @@ static u32 sceDisplaySetMode(int displayMode, int displayWidth, int displayHeigh
|
|||
return DisplayWaitForVblanks("display mode", 1);
|
||||
}
|
||||
|
||||
// Some games (GTA) never call this during gameplay, so bad place to put a framerate counter.
|
||||
static u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync) {
|
||||
void __DisplaySetFramebuf(u32 topaddr, int linesize, int pixelFormat, int sync) {
|
||||
FrameBufferState fbstate = {0};
|
||||
fbstate.topaddr = topaddr;
|
||||
fbstate.fmt = (GEBufferFormat)pixelformat;
|
||||
fbstate.fmt = (GEBufferFormat)pixelFormat;
|
||||
fbstate.stride = linesize;
|
||||
|
||||
if (sync == PSP_DISPLAY_SETBUF_IMMEDIATE) {
|
||||
// Write immediately to the current framebuffer parameters
|
||||
framebuf = fbstate;
|
||||
gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.stride, framebuf.fmt);
|
||||
} else {
|
||||
// Delay the write until vblank
|
||||
latchedFramebuf = fbstate;
|
||||
framebufIsLatched = true;
|
||||
|
||||
// If we update the format or stride, this affects the current framebuf immediately.
|
||||
framebuf.fmt = latchedFramebuf.fmt;
|
||||
framebuf.stride = latchedFramebuf.stride;
|
||||
}
|
||||
}
|
||||
|
||||
// Some games (GTA) never call this during gameplay, so bad place to put a framerate counter.
|
||||
u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync) {
|
||||
if (sync != PSP_DISPLAY_SETBUF_IMMEDIATE && sync != PSP_DISPLAY_SETBUF_NEXTFRAME) {
|
||||
return hleLogError(SCEDISPLAY, SCE_KERNEL_ERROR_INVALID_MODE, "invalid sync mode");
|
||||
}
|
||||
|
@ -849,7 +865,7 @@ static u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int
|
|||
}
|
||||
|
||||
if (sync == PSP_DISPLAY_SETBUF_IMMEDIATE) {
|
||||
if (fbstate.fmt != latchedFramebuf.fmt || fbstate.stride != latchedFramebuf.stride) {
|
||||
if ((GEBufferFormat)pixelformat != latchedFramebuf.fmt || linesize != latchedFramebuf.stride) {
|
||||
return hleReportError(SCEDISPLAY, SCE_KERNEL_ERROR_INVALID_MODE, "must change latched framebuf first");
|
||||
}
|
||||
}
|
||||
|
@ -882,19 +898,7 @@ static u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int
|
|||
lastFlipCycles = CoreTiming::GetTicks();
|
||||
}
|
||||
|
||||
if (sync == PSP_DISPLAY_SETBUF_IMMEDIATE) {
|
||||
// Write immediately to the current framebuffer parameters
|
||||
framebuf = fbstate;
|
||||
gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.stride, framebuf.fmt);
|
||||
} else {
|
||||
// Delay the write until vblank
|
||||
latchedFramebuf = fbstate;
|
||||
framebufIsLatched = true;
|
||||
|
||||
// If we update the format or stride, this affects the current framebuf immediately.
|
||||
framebuf.fmt = latchedFramebuf.fmt;
|
||||
framebuf.stride = latchedFramebuf.stride;
|
||||
}
|
||||
__DisplaySetFramebuf(topaddr, linesize, pixelformat, sync);
|
||||
|
||||
if (delayCycles > 0) {
|
||||
// Okay, the game is going at too high a frame rate. God of War and Fat Princess both do this.
|
||||
|
@ -910,10 +914,10 @@ static u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int
|
|||
}
|
||||
}
|
||||
|
||||
bool __DisplayGetFramebuf(u8 **topaddr, u32 *linesize, u32 *pixelFormat, int latchedMode) {
|
||||
bool __DisplayGetFramebuf(PSPPointer<u8> *topaddr, u32 *linesize, u32 *pixelFormat, int latchedMode) {
|
||||
const FrameBufferState &fbState = latchedMode == PSP_DISPLAY_SETBUF_NEXTFRAME ? latchedFramebuf : framebuf;
|
||||
if (topaddr != nullptr)
|
||||
*topaddr = Memory::GetPointer(fbState.topaddr);
|
||||
(*topaddr).ptr = fbState.topaddr;
|
||||
if (linesize != nullptr)
|
||||
*linesize = fbState.stride;
|
||||
if (pixelFormat != nullptr)
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Core/MemMap.h"
|
||||
|
||||
void __DisplayInit();
|
||||
void __DisplayDoState(PointerWrap &p);
|
||||
void __DisplayShutdown();
|
||||
|
@ -27,7 +29,8 @@ void Register_sceDisplay();
|
|||
bool __DisplayFrameDone();
|
||||
|
||||
// Get information about the current framebuffer.
|
||||
bool __DisplayGetFramebuf(u8 **topaddr, u32 *linesize, u32 *pixelFormat, int mode);
|
||||
bool __DisplayGetFramebuf(PSPPointer<u8> *topaddr, u32 *linesize, u32 *pixelFormat, int mode);
|
||||
void __DisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync);
|
||||
|
||||
typedef void (*VblankCallback)();
|
||||
// Listen for vblank events. Only register during init.
|
||||
|
@ -44,4 +47,4 @@ int __DisplayGetFlipCount();
|
|||
// Call this when resuming to avoid a small speedup burst
|
||||
void __DisplaySetWasPaused();
|
||||
|
||||
void Register_sceDisplay_driver();
|
||||
void Register_sceDisplay_driver();
|
||||
|
|
|
@ -1825,7 +1825,8 @@ static u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 o
|
|||
return 0;
|
||||
|
||||
case 0x20: // EMULATOR_DEVCTL__EMIT_SCREENSHOT
|
||||
u8 *topaddr;
|
||||
{
|
||||
PSPPointer<u8> topaddr;
|
||||
u32 linesize, pixelFormat;
|
||||
|
||||
__DisplayGetFramebuf(&topaddr, &linesize, &pixelFormat, 0);
|
||||
|
@ -1833,6 +1834,7 @@ static u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 o
|
|||
host->SendDebugScreenshot(topaddr, linesize, 272);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ERROR_LOG(SCEIO, "sceIoDevCtl: UNKNOWN PARAMETERS");
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "Common/FileUtil.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HLE/FunctionWrappers.h"
|
||||
#include "Core/HLE/HLETables.h"
|
||||
|
@ -57,6 +58,7 @@
|
|||
#include "Core/HLE/KernelWaitHelpers.h"
|
||||
#include "Core/ELF/ParamSFO.h"
|
||||
|
||||
#include "GPU/Debugger/Record.h"
|
||||
#include "GPU/GPU.h"
|
||||
#include "GPU/GPUInterface.h"
|
||||
#include "GPU/GPUState.h"
|
||||
|
@ -1513,8 +1515,36 @@ u32 __KernelGetModuleGP(SceUID uid)
|
|||
}
|
||||
}
|
||||
|
||||
bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_string)
|
||||
{
|
||||
void __KernelLoadReset() {
|
||||
// Wipe kernel here, loadexec should reset the entire system
|
||||
if (__KernelIsRunning()) {
|
||||
u32 error;
|
||||
while (!loadedModules.empty()) {
|
||||
SceUID moduleID = *loadedModules.begin();
|
||||
Module *module = kernelObjects.Get<Module>(moduleID, error);
|
||||
if (module) {
|
||||
module->Cleanup();
|
||||
} else {
|
||||
// An invalid module. We need to remove it or we'll loop forever.
|
||||
WARN_LOG(LOADER, "Invalid module still marked as loaded on loadexec");
|
||||
loadedModules.erase(moduleID);
|
||||
}
|
||||
}
|
||||
|
||||
Replacement_Shutdown();
|
||||
__KernelShutdown();
|
||||
// HLE needs to be reset here
|
||||
HLEShutdown();
|
||||
Replacement_Init();
|
||||
HLEInit();
|
||||
gpu->Reinitialize();
|
||||
}
|
||||
|
||||
__KernelModuleInit();
|
||||
__KernelInit();
|
||||
}
|
||||
|
||||
bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_string) {
|
||||
SceKernelLoadExecParam param;
|
||||
|
||||
if (paramPtr)
|
||||
|
@ -1536,33 +1566,7 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str
|
|||
Memory::Memcpy(param_key, keyAddr, (u32)keylen);
|
||||
}
|
||||
|
||||
// Wipe kernel here, loadexec should reset the entire system
|
||||
if (__KernelIsRunning())
|
||||
{
|
||||
u32 error;
|
||||
while (!loadedModules.empty()) {
|
||||
SceUID moduleID = *loadedModules.begin();
|
||||
Module *module = kernelObjects.Get<Module>(moduleID, error);
|
||||
if (module) {
|
||||
module->Cleanup();
|
||||
} else {
|
||||
// An invalid module. We need to remove it or we'll loop forever.
|
||||
WARN_LOG(LOADER, "Invalid module still marked as loaded on loadexec");
|
||||
loadedModules.erase(moduleID);
|
||||
}
|
||||
}
|
||||
|
||||
Replacement_Shutdown();
|
||||
__KernelShutdown();
|
||||
//HLE needs to be reset here
|
||||
HLEShutdown();
|
||||
Replacement_Init();
|
||||
HLEInit();
|
||||
gpu->Reinitialize();
|
||||
}
|
||||
|
||||
__KernelModuleInit();
|
||||
__KernelInit();
|
||||
__KernelLoadReset();
|
||||
|
||||
PSPFileInfo info = pspFileSystem.GetFileInfo(filename);
|
||||
if (!info.exists) {
|
||||
|
@ -1635,6 +1639,64 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str
|
|||
return true;
|
||||
}
|
||||
|
||||
bool __KernelLoadGEDump(const std::string &base_filename, std::string *error_string) {
|
||||
__KernelLoadReset();
|
||||
|
||||
mipsr4k.pc = PSP_GetUserMemoryBase();
|
||||
|
||||
const static u32_le runDumpCode[] = {
|
||||
// Save the filename.
|
||||
MIPS_MAKE_ORI(MIPS_REG_S0, MIPS_REG_A0, 0),
|
||||
MIPS_MAKE_ORI(MIPS_REG_S1, MIPS_REG_A1, 0),
|
||||
// Call the actual render.
|
||||
MIPS_MAKE_SYSCALL("FakeSysCalls", "__KernelGPUReplay"),
|
||||
// Make sure we don't get out of sync.
|
||||
MIPS_MAKE_LUI(MIPS_REG_A0, 0),
|
||||
MIPS_MAKE_SYSCALL("sceGe_user", "sceGeDrawSync"),
|
||||
// Set the return address after the entry which saved the filename.
|
||||
MIPS_MAKE_LUI(MIPS_REG_RA, mipsr4k.pc >> 16),
|
||||
MIPS_MAKE_ADDIU(MIPS_REG_RA, MIPS_REG_RA, 8),
|
||||
// Wait for the next vblank to render again.
|
||||
MIPS_MAKE_JR_RA(),
|
||||
MIPS_MAKE_SYSCALL("sceDisplay", "sceDisplayWaitVblankStart"),
|
||||
// This never gets reached, just here to be safe.
|
||||
MIPS_MAKE_BREAK(0),
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(runDumpCode); ++i) {
|
||||
Memory::WriteUnchecked_U32(runDumpCode[i], mipsr4k.pc + (int)i * sizeof(u32_le));
|
||||
}
|
||||
|
||||
Module *module = new Module;
|
||||
kernelObjects.Create(module);
|
||||
loadedModules.insert(module->GetUID());
|
||||
memset(&module->nm, 0, sizeof(module->nm));
|
||||
module->isFake = true;
|
||||
module->nm.entry_addr = mipsr4k.pc;
|
||||
module->nm.gp_value = -1;
|
||||
|
||||
SceUID threadID = __KernelSetupRootThread(module->GetUID(), (int)base_filename.size(), base_filename.data(), 0x20, 0x1000, 0);
|
||||
__KernelSetThreadRA(threadID, NID_MODULERETURN);
|
||||
|
||||
__KernelStartIdleThreads(module->GetUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
void __KernelGPUReplay() {
|
||||
// Special ABI: s0 and s1 are the "args". Not null terminated.
|
||||
const char *filenamep = Memory::GetCharPointer(currentMIPS->r[MIPS_REG_S1]);
|
||||
if (!filenamep) {
|
||||
ERROR_LOG(SYSTEM, "Failed to load dump filename");
|
||||
Core_Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string filename(filenamep, currentMIPS->r[MIPS_REG_S0]);
|
||||
if (!GPURecord::RunMountedReplay(filename)) {
|
||||
Core_Stop();
|
||||
}
|
||||
}
|
||||
|
||||
int sceKernelLoadExec(const char *filename, u32 paramPtr)
|
||||
{
|
||||
std::string exec_filename = filename;
|
||||
|
|
|
@ -39,7 +39,9 @@ void __KernelModuleDoState(PointerWrap &p);
|
|||
void __KernelModuleShutdown();
|
||||
|
||||
u32 __KernelGetModuleGP(SceUID module);
|
||||
bool __KernelLoadGEDump(const std::string &base_filename, std::string *error_string);
|
||||
bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_string);
|
||||
void __KernelGPUReplay();
|
||||
void __KernelReturnFromModuleFunc();
|
||||
u32 hleKernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr, bool WithStatus);
|
||||
|
||||
|
|
|
@ -69,31 +69,30 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader) {
|
|||
}
|
||||
|
||||
std::string extension = fileLoader->Extension();
|
||||
if (!strcasecmp(extension.c_str(), ".iso"))
|
||||
{
|
||||
if (!strcasecmp(extension.c_str(), ".iso")) {
|
||||
// may be a psx iso, they have 2352 byte sectors. You never know what some people try to open
|
||||
if ((fileLoader->FileSize() % 2352) == 0)
|
||||
{
|
||||
if ((fileLoader->FileSize() % 2352) == 0) {
|
||||
unsigned char sync[12];
|
||||
fileLoader->ReadAt(0, 12, sync);
|
||||
|
||||
// each sector in a mode2 image starts with these 12 bytes
|
||||
if (memcmp(sync,"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00",12) == 0)
|
||||
{
|
||||
if (memcmp(sync,"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00", 12) == 0) {
|
||||
return IdentifiedFileType::ISO_MODE2;
|
||||
}
|
||||
|
||||
// maybe it also just happened to have that size,
|
||||
}
|
||||
return IdentifiedFileType::PSP_ISO;
|
||||
}
|
||||
else if (!strcasecmp(extension.c_str(),".cso"))
|
||||
{
|
||||
} else if (!strcasecmp(extension.c_str(), ".cso")) {
|
||||
return IdentifiedFileType::PSP_ISO;
|
||||
}
|
||||
else if (!strcasecmp(extension.c_str(),".ppst"))
|
||||
{
|
||||
} else if (!strcasecmp(extension.c_str(), ".ppst")) {
|
||||
return IdentifiedFileType::PPSSPP_SAVESTATE;
|
||||
} else if (!strcasecmp(extension.c_str(), ".ppdmp")) {
|
||||
char data[8]{};
|
||||
fileLoader->ReadAt(0, 8, data);
|
||||
if (memcmp(data, "PPSSPPGE", 8) == 0) {
|
||||
return IdentifiedFileType::PPSSPP_GE_DUMP;
|
||||
}
|
||||
}
|
||||
|
||||
// First, check if it's a directory with an EBOOT.PBP in it.
|
||||
|
@ -337,6 +336,9 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) {
|
|||
*error_string = "This is save data, not a game."; // Actually, we could make it load it...
|
||||
break;
|
||||
|
||||
case IdentifiedFileType::PPSSPP_GE_DUMP:
|
||||
return Load_PSP_GE_Dump(fileLoader, error_string);
|
||||
|
||||
case IdentifiedFileType::UNKNOWN_BIN:
|
||||
case IdentifiedFileType::UNKNOWN_ELF:
|
||||
case IdentifiedFileType::UNKNOWN:
|
||||
|
|
|
@ -49,6 +49,8 @@ enum class IdentifiedFileType {
|
|||
PSP_SAVEDATA_DIRECTORY,
|
||||
PPSSPP_SAVESTATE,
|
||||
|
||||
PPSSPP_GE_DUMP,
|
||||
|
||||
UNKNOWN,
|
||||
};
|
||||
|
||||
|
|
|
@ -612,6 +612,11 @@ void ArmJit::Comp_Syscall(MIPSOpcode op)
|
|||
RestoreRoundingMode();
|
||||
js.downcountAmount = -offset;
|
||||
|
||||
if (!js.inDelaySlot) {
|
||||
gpr.SetRegImm(SCRATCHREG1, GetCompilerPC() + 4);
|
||||
MovToPC(SCRATCHREG1);
|
||||
}
|
||||
|
||||
FlushAll();
|
||||
|
||||
SaveDowncount();
|
||||
|
|
|
@ -594,6 +594,11 @@ void Arm64Jit::Comp_Syscall(MIPSOpcode op)
|
|||
RestoreRoundingMode();
|
||||
js.downcountAmount = -offset;
|
||||
|
||||
if (!js.inDelaySlot) {
|
||||
gpr.SetRegImm(SCRATCH1, GetCompilerPC() + 4);
|
||||
MovToPC(SCRATCH1);
|
||||
}
|
||||
|
||||
FlushAll();
|
||||
|
||||
SaveStaticRegisters();
|
||||
|
|
|
@ -380,6 +380,11 @@ void IRFrontend::Comp_Syscall(MIPSOpcode op) {
|
|||
ir.Write(IROp::Downcount, 0, dcAmount & 0xFF, dcAmount >> 8);
|
||||
js.downcountAmount = 0;
|
||||
|
||||
// If not in a delay slot, we need to update PC.
|
||||
if (!js.inDelaySlot) {
|
||||
ir.Write(IROp::SetPCConst, 0, ir.AddConstant(GetCompilerPC() + 4));
|
||||
}
|
||||
|
||||
FlushAll();
|
||||
|
||||
RestoreRoundingMode();
|
||||
|
|
|
@ -787,6 +787,10 @@ void Jit::Comp_Syscall(MIPSOpcode op)
|
|||
RestoreRoundingMode();
|
||||
js.downcountAmount = -offset;
|
||||
|
||||
if (!js.inDelaySlot) {
|
||||
MOV(32, M(&mips_->pc), Imm32(GetCompilerPC() + 4));
|
||||
}
|
||||
|
||||
#ifdef USE_PROFILER
|
||||
// When profiling, we can't skip CallSyscall, since it times syscalls.
|
||||
ABI_CallFunctionC(&CallSyscall, op.encoding);
|
||||
|
|
|
@ -27,11 +27,12 @@
|
|||
#include "Core/ELF/ElfReader.h"
|
||||
#include "Core/ELF/ParamSFO.h"
|
||||
|
||||
#include "FileSystems/BlockDevices.h"
|
||||
#include "FileSystems/DirectoryFileSystem.h"
|
||||
#include "FileSystems/ISOFileSystem.h"
|
||||
#include "FileSystems/MetaFileSystem.h"
|
||||
#include "FileSystems/VirtualDiscFileSystem.h"
|
||||
#include "Core/FileSystems/BlockDevices.h"
|
||||
#include "Core/FileSystems/BlobFileSystem.h"
|
||||
#include "Core/FileSystems/DirectoryFileSystem.h"
|
||||
#include "Core/FileSystems/ISOFileSystem.h"
|
||||
#include "Core/FileSystems/MetaFileSystem.h"
|
||||
#include "Core/FileSystems/VirtualDiscFileSystem.h"
|
||||
|
||||
#include "Core/Loaders.h"
|
||||
#include "Core/MemMap.h"
|
||||
|
@ -355,3 +356,11 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) {
|
|||
|
||||
return __KernelLoadExec(finalName.c_str(), 0, error_string);
|
||||
}
|
||||
|
||||
bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string) {
|
||||
BlobFileSystem *umd = new BlobFileSystem(&pspFileSystem, fileLoader, "data.ppdmp");
|
||||
pspFileSystem.Mount("disc0:", umd);
|
||||
|
||||
__KernelLoadGEDump("disc0:/data.ppdmp", error_string);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -23,5 +23,6 @@ class FileLoader;
|
|||
|
||||
bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string);
|
||||
bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string);
|
||||
bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string);
|
||||
void InitMemoryForGameISO(FileLoader *fileLoader);
|
||||
void InitMemoryForGamePBP(FileLoader *fileLoader);
|
||||
|
|
|
@ -242,10 +242,7 @@ void CPU_Init() {
|
|||
// Here we have read the PARAM.SFO, let's see if we need any compatibility overrides.
|
||||
// Homebrew usually has an empty discID, and even if they do have a disc id, it's not
|
||||
// likely to collide with any commercial ones.
|
||||
std::string discID = g_paramSFO.GetValueString("DISC_ID");
|
||||
if (discID.empty()) {
|
||||
discID = g_paramSFO.GenerateFakeID();
|
||||
}
|
||||
std::string discID = g_paramSFO.GetDiscID();
|
||||
coreParameter.compat.Load(discID);
|
||||
|
||||
Memory::Init();
|
||||
|
|
|
@ -47,10 +47,7 @@ void TextureReplacer::Init() {
|
|||
}
|
||||
|
||||
void TextureReplacer::NotifyConfigChanged() {
|
||||
gameID_ = g_paramSFO.GetValueString("DISC_ID");
|
||||
if (gameID_.empty()) {
|
||||
gameID_ = g_paramSFO.GenerateFakeID();
|
||||
}
|
||||
gameID_ = g_paramSFO.GetDiscID();
|
||||
|
||||
enabled_ = g_Config.bReplaceTextures || g_Config.bSaveNewTextures;
|
||||
if (enabled_) {
|
||||
|
|
|
@ -119,10 +119,6 @@ FramebufferManagerCommon::~FramebufferManagerCommon() {
|
|||
}
|
||||
|
||||
void FramebufferManagerCommon::Init() {
|
||||
std::string gameId = g_paramSFO.GetValueString("DISC_ID");
|
||||
if (gameId.empty()) {
|
||||
gameId = g_paramSFO.GenerateFakeID();
|
||||
}
|
||||
BeginFrame();
|
||||
}
|
||||
|
||||
|
|
|
@ -480,8 +480,8 @@ class VertexDecoder {
|
|||
public:
|
||||
VertexDecoder();
|
||||
|
||||
// A jit cache is not mandatory, we don't use it in the sw renderer
|
||||
void SetVertexType(u32 vtype, const VertexDecoderOptions &options, VertexDecoderJitCache *jitCache = 0);
|
||||
// A jit cache is not mandatory.
|
||||
void SetVertexType(u32 vtype, const VertexDecoderOptions &options, VertexDecoderJitCache *jitCache = nullptr);
|
||||
|
||||
u32 VertexType() const { return fmt_; }
|
||||
|
||||
|
|
|
@ -293,10 +293,6 @@ void GPU_D3D11::InitClearInternal() {
|
|||
}
|
||||
}
|
||||
|
||||
void GPU_D3D11::DumpNextFrame() {
|
||||
dumpNextFrame_ = true;
|
||||
}
|
||||
|
||||
void GPU_D3D11::BeginHostFrame() {
|
||||
GPUCommon::BeginHostFrame();
|
||||
UpdateCmdInfo();
|
||||
|
@ -309,11 +305,6 @@ void GPU_D3D11::BeginHostFrame() {
|
|||
}
|
||||
}
|
||||
|
||||
void GPU_D3D11::BeginFrame() {
|
||||
ScheduleEvent(GPU_EVENT_BEGIN_FRAME);
|
||||
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
|
||||
}
|
||||
|
||||
void GPU_D3D11::ReapplyGfxStateInternal() {
|
||||
GPUCommon::ReapplyGfxStateInternal();
|
||||
|
||||
|
@ -331,16 +322,11 @@ void GPU_D3D11::BeginFrameInternal() {
|
|||
depalShaderCache_->Decimate();
|
||||
// fragmentTestCache_.Decimate();
|
||||
|
||||
if (dumpNextFrame_) {
|
||||
NOTICE_LOG(G3D, "DUMPING THIS FRAME");
|
||||
dumpThisFrame_ = true;
|
||||
dumpNextFrame_ = false;
|
||||
} else if (dumpThisFrame_) {
|
||||
dumpThisFrame_ = false;
|
||||
}
|
||||
GPUCommon::BeginFrameInternal();
|
||||
shaderManagerD3D11_->DirtyLastShader();
|
||||
|
||||
framebufferManagerD3D11_->BeginFrame();
|
||||
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
|
||||
}
|
||||
|
||||
void GPU_D3D11::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) {
|
||||
|
|
|
@ -42,13 +42,11 @@ public:
|
|||
|
||||
void ReapplyGfxStateInternal() override;
|
||||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
|
||||
void BeginFrame() override;
|
||||
void GetStats(char *buffer, size_t bufsize) override;
|
||||
void ClearCacheNextFrame() override;
|
||||
void DeviceLost() override; // Only happens on Android. Drop all textures and shaders.
|
||||
void DeviceRestore() override;
|
||||
|
||||
void DumpNextFrame() override;
|
||||
void DoState(PointerWrap &p) override;
|
||||
|
||||
void ClearShaderCache() override;
|
||||
|
@ -122,4 +120,4 @@ private:
|
|||
|
||||
std::string reportingPrimaryInfo_;
|
||||
std::string reportingFullInfo_;
|
||||
};
|
||||
};
|
||||
|
|
1037
GPU/Debugger/Record.cpp
Normal file
1037
GPU/Debugger/Record.cpp
Normal file
File diff suppressed because it is too large
Load diff
36
GPU/Debugger/Record.h
Normal file
36
GPU/Debugger/Record.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) 2017- 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 <string>
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
namespace GPURecord {
|
||||
|
||||
bool IsActive();
|
||||
void Activate();
|
||||
|
||||
void NotifyCommand(u32 pc);
|
||||
void NotifyMemcpy(u32 dest, u32 src, u32 sz);
|
||||
void NotifyMemset(u32 dest, int v, u32 sz);
|
||||
void NotifyUpload(u32 dest, u32 sz);
|
||||
void NotifyFrame();
|
||||
|
||||
bool RunMountedReplay(const std::string &filename);
|
||||
|
||||
};
|
|
@ -260,10 +260,6 @@ void GPU_DX9::InitClearInternal() {
|
|||
}
|
||||
}
|
||||
|
||||
void GPU_DX9::DumpNextFrame() {
|
||||
dumpNextFrame_ = true;
|
||||
}
|
||||
|
||||
void GPU_DX9::BeginHostFrame() {
|
||||
GPUCommon::BeginHostFrame();
|
||||
UpdateCmdInfo();
|
||||
|
@ -276,10 +272,6 @@ void GPU_DX9::BeginHostFrame() {
|
|||
}
|
||||
}
|
||||
|
||||
void GPU_DX9::BeginFrame() {
|
||||
ScheduleEvent(GPU_EVENT_BEGIN_FRAME);
|
||||
}
|
||||
|
||||
void GPU_DX9::ReapplyGfxStateInternal() {
|
||||
dxstate.Restore();
|
||||
GPUCommon::ReapplyGfxStateInternal();
|
||||
|
@ -300,13 +292,7 @@ void GPU_DX9::BeginFrameInternal() {
|
|||
depalShaderCache_.Decimate();
|
||||
// fragmentTestCache_.Decimate();
|
||||
|
||||
if (dumpNextFrame_) {
|
||||
NOTICE_LOG(G3D, "DUMPING THIS FRAME");
|
||||
dumpThisFrame_ = true;
|
||||
dumpNextFrame_ = false;
|
||||
} else if (dumpThisFrame_) {
|
||||
dumpThisFrame_ = false;
|
||||
}
|
||||
GPUCommon::BeginFrameInternal();
|
||||
shaderManagerDX9_->DirtyShader();
|
||||
|
||||
framebufferManagerDX9_->BeginFrame();
|
||||
|
|
|
@ -43,13 +43,11 @@ public:
|
|||
|
||||
void ReapplyGfxStateInternal() override;
|
||||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
|
||||
void BeginFrame() override;
|
||||
void GetStats(char *buffer, size_t bufsize) override;
|
||||
void ClearCacheNextFrame() override;
|
||||
void DeviceLost() override; // Only happens on Android. Drop all textures and shaders.
|
||||
void DeviceRestore() override;
|
||||
|
||||
void DumpNextFrame() override;
|
||||
void DoState(PointerWrap &p) override;
|
||||
|
||||
void ClearShaderCache() override;
|
||||
|
|
|
@ -168,10 +168,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
|||
textureCacheGL_->NotifyConfigChanged();
|
||||
|
||||
// Load shader cache.
|
||||
std::string discID = g_paramSFO.GetValueString("DISC_ID");
|
||||
if (discID.empty()) {
|
||||
discID = g_paramSFO.GenerateFakeID();
|
||||
}
|
||||
std::string discID = g_paramSFO.GetDiscID();
|
||||
if (discID.size()) {
|
||||
File::CreateFullPath(GetSysDirectory(DIRECTORY_APP_CACHE));
|
||||
shaderCachePath_ = GetSysDirectory(DIRECTORY_APP_CACHE) + "/" + discID + ".glshadercache";
|
||||
|
@ -422,10 +419,6 @@ void GPU_GLES::InitClearInternal() {
|
|||
glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
|
||||
}
|
||||
|
||||
void GPU_GLES::DumpNextFrame() {
|
||||
dumpNextFrame_ = true;
|
||||
}
|
||||
|
||||
void GPU_GLES::BeginHostFrame() {
|
||||
GPUCommon::BeginHostFrame();
|
||||
UpdateCmdInfo();
|
||||
|
@ -438,10 +431,6 @@ void GPU_GLES::BeginHostFrame() {
|
|||
}
|
||||
}
|
||||
|
||||
void GPU_GLES::BeginFrame() {
|
||||
ScheduleEvent(GPU_EVENT_BEGIN_FRAME);
|
||||
}
|
||||
|
||||
inline void GPU_GLES::UpdateVsyncInterval(bool force) {
|
||||
#ifdef _WIN32
|
||||
int desiredVSyncInterval = g_Config.bVSync ? 1 : 0;
|
||||
|
@ -495,13 +484,7 @@ void GPU_GLES::BeginFrameInternal() {
|
|||
depalShaderCache_.Decimate();
|
||||
fragmentTestCache_.Decimate();
|
||||
|
||||
if (dumpNextFrame_) {
|
||||
NOTICE_LOG(G3D, "DUMPING THIS FRAME");
|
||||
dumpThisFrame_ = true;
|
||||
dumpNextFrame_ = false;
|
||||
} else if (dumpThisFrame_) {
|
||||
dumpThisFrame_ = false;
|
||||
}
|
||||
GPUCommon::BeginFrameInternal();
|
||||
|
||||
// Save the cache from time to time. TODO: How often?
|
||||
if (!shaderCachePath_.empty() && (gpuStats.numFlips & 1023) == 0) {
|
||||
|
|
|
@ -43,14 +43,12 @@ public:
|
|||
|
||||
void ReapplyGfxStateInternal() override;
|
||||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
|
||||
void BeginFrame() override;
|
||||
void GetStats(char *buffer, size_t bufsize) override;
|
||||
|
||||
void ClearCacheNextFrame() override;
|
||||
void DeviceLost() override; // Only happens on Android. Drop all textures and shaders.
|
||||
void DeviceRestore() override;
|
||||
|
||||
void DumpNextFrame() override;
|
||||
void DoState(PointerWrap &p) override;
|
||||
|
||||
void ClearShaderCache() override;
|
||||
|
|
|
@ -218,6 +218,7 @@
|
|||
<ClInclude Include="D3D11\TextureScalerD3D11.h" />
|
||||
<ClInclude Include="D3D11\VertexShaderGeneratorD3D11.h" />
|
||||
<ClInclude Include="Debugger\Breakpoints.h" />
|
||||
<ClInclude Include="Debugger\Record.h" />
|
||||
<ClInclude Include="Debugger\Stepping.h" />
|
||||
<ClInclude Include="Directx9\DepalettizeShaderDX9.h" />
|
||||
<ClInclude Include="Directx9\GPU_DX9.h" />
|
||||
|
@ -318,6 +319,7 @@
|
|||
<ClCompile Include="D3D11\TextureScalerD3D11.cpp" />
|
||||
<ClCompile Include="D3D11\VertexShaderGeneratorD3D11.cpp" />
|
||||
<ClCompile Include="Debugger\Breakpoints.cpp" />
|
||||
<ClCompile Include="Debugger\Record.cpp" />
|
||||
<ClCompile Include="Debugger\Stepping.cpp" />
|
||||
<ClCompile Include="Directx9\DepalettizeShaderDX9.cpp" />
|
||||
<ClCompile Include="Directx9\GPU_DX9.cpp" />
|
||||
|
|
|
@ -262,6 +262,9 @@
|
|||
<ClInclude Include="Software\Sampler.h">
|
||||
<Filter>Software</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Debugger\Record.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Math3D.cpp">
|
||||
|
@ -519,5 +522,8 @@
|
|||
<ClCompile Include="Software\SamplerX86.cpp">
|
||||
<Filter>Software</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Debugger\Record.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -25,6 +25,7 @@
|
|||
#include "GPU/Common/FramebufferCommon.h"
|
||||
#include "GPU/Common/TextureCacheCommon.h"
|
||||
#include "GPU/Common/DrawEngineCommon.h"
|
||||
#include "GPU/Debugger/Record.h"
|
||||
|
||||
const CommonCommandTableEntry commonCommandTable[] = {
|
||||
// From Common. No flushing but definitely need execute.
|
||||
|
@ -461,6 +462,10 @@ void GPUCommon::Resized() {
|
|||
resized_ = true;
|
||||
}
|
||||
|
||||
void GPUCommon::DumpNextFrame() {
|
||||
dumpNextFrame_ = true;
|
||||
}
|
||||
|
||||
u32 GPUCommon::DrawSync(int mode) {
|
||||
if (ThreadEnabled()) {
|
||||
// Sync first, because the CPU is usually faster than the emulated GPU.
|
||||
|
@ -898,7 +903,8 @@ bool GPUCommon::InterpretList(DisplayList &list) {
|
|||
gpuState = list.pc == list.stall ? GPUSTATE_STALL : GPUSTATE_RUNNING;
|
||||
guard.unlock();
|
||||
|
||||
const bool useDebugger = host->GPUDebuggingActive();
|
||||
debugRecording_ = GPURecord::IsActive();
|
||||
const bool useDebugger = host->GPUDebuggingActive() || debugRecording_;
|
||||
const bool useFastRunLoop = !dumpThisFrame_ && !useDebugger;
|
||||
while (gpuState == GPUSTATE_RUNNING) {
|
||||
{
|
||||
|
@ -945,12 +951,28 @@ bool GPUCommon::InterpretList(DisplayList &list) {
|
|||
return gpuState == GPUSTATE_DONE || gpuState == GPUSTATE_ERROR;
|
||||
}
|
||||
|
||||
void GPUCommon::BeginFrame() {
|
||||
ScheduleEvent(GPU_EVENT_BEGIN_FRAME);
|
||||
}
|
||||
|
||||
void GPUCommon::BeginFrameInternal() {
|
||||
if (dumpNextFrame_) {
|
||||
NOTICE_LOG(G3D, "DUMPING THIS FRAME");
|
||||
dumpThisFrame_ = true;
|
||||
dumpNextFrame_ = false;
|
||||
} else if (dumpThisFrame_) {
|
||||
dumpThisFrame_ = false;
|
||||
}
|
||||
GPURecord::NotifyFrame();
|
||||
}
|
||||
|
||||
void GPUCommon::SlowRunLoop(DisplayList &list)
|
||||
{
|
||||
const bool dumpThisFrame = dumpThisFrame_;
|
||||
while (downcount > 0)
|
||||
{
|
||||
host->GPUNotifyCommand(list.pc);
|
||||
GPURecord::NotifyCommand(list.pc);
|
||||
u32 op = Memory::ReadUnchecked_U32(list.pc);
|
||||
u32 cmd = op >> 24;
|
||||
|
||||
|
@ -1197,13 +1219,16 @@ void GPUCommon::Execute_Call(u32 op, u32 diff) {
|
|||
#endif
|
||||
|
||||
// Bone matrix optimization - many games will CALL a bone matrix (!).
|
||||
if ((Memory::ReadUnchecked_U32(target) >> 24) == GE_CMD_BONEMATRIXDATA) {
|
||||
// We don't optimize during recording - so the matrix data gets recorded.
|
||||
if (!debugRecording_ && (Memory::ReadUnchecked_U32(target) >> 24) == GE_CMD_BONEMATRIXDATA) {
|
||||
// Check for the end
|
||||
if ((Memory::ReadUnchecked_U32(target + 11 * 4) >> 24) == GE_CMD_BONEMATRIXDATA &&
|
||||
(Memory::ReadUnchecked_U32(target + 12 * 4) >> 24) == GE_CMD_RET) {
|
||||
// Yep, pretty sure this is a bone matrix call.
|
||||
FastLoadBoneMatrix(target);
|
||||
return;
|
||||
// Yep, pretty sure this is a bone matrix call. Double check stall first.
|
||||
if (target > currentList->stall || target + 12 * 4 < currentList->stall) {
|
||||
FastLoadBoneMatrix(target);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1553,15 +1578,23 @@ void GPUCommon::Execute_WorldMtxNum(u32 op, u32 diff) {
|
|||
const int end = 12 - (op & 0xF);
|
||||
int i = 0;
|
||||
|
||||
while ((src[i] >> 24) == GE_CMD_WORLDMATRIXDATA) {
|
||||
const u32 newVal = src[i] << 8;
|
||||
if (dst[i] != newVal) {
|
||||
Flush();
|
||||
dst[i] = newVal;
|
||||
gstate_c.Dirty(DIRTY_WORLDMATRIX);
|
||||
}
|
||||
if (++i >= end) {
|
||||
break;
|
||||
// We must record the individual data commands while debugRecording_.
|
||||
bool fastLoad = !debugRecording_;
|
||||
if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) {
|
||||
fastLoad = false;
|
||||
}
|
||||
|
||||
if (fastLoad) {
|
||||
while ((src[i] >> 24) == GE_CMD_WORLDMATRIXDATA) {
|
||||
const u32 newVal = src[i] << 8;
|
||||
if (dst[i] != newVal) {
|
||||
Flush();
|
||||
dst[i] = newVal;
|
||||
gstate_c.Dirty(DIRTY_WORLDMATRIX);
|
||||
}
|
||||
if (++i >= end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1594,15 +1627,22 @@ void GPUCommon::Execute_ViewMtxNum(u32 op, u32 diff) {
|
|||
const int end = 12 - (op & 0xF);
|
||||
int i = 0;
|
||||
|
||||
while ((src[i] >> 24) == GE_CMD_VIEWMATRIXDATA) {
|
||||
const u32 newVal = src[i] << 8;
|
||||
if (dst[i] != newVal) {
|
||||
Flush();
|
||||
dst[i] = newVal;
|
||||
gstate_c.Dirty(DIRTY_VIEWMATRIX);
|
||||
}
|
||||
if (++i >= end) {
|
||||
break;
|
||||
bool fastLoad = !debugRecording_;
|
||||
if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) {
|
||||
fastLoad = false;
|
||||
}
|
||||
|
||||
if (fastLoad) {
|
||||
while ((src[i] >> 24) == GE_CMD_VIEWMATRIXDATA) {
|
||||
const u32 newVal = src[i] << 8;
|
||||
if (dst[i] != newVal) {
|
||||
Flush();
|
||||
dst[i] = newVal;
|
||||
gstate_c.Dirty(DIRTY_VIEWMATRIX);
|
||||
}
|
||||
if (++i >= end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1635,15 +1675,22 @@ void GPUCommon::Execute_ProjMtxNum(u32 op, u32 diff) {
|
|||
const int end = 16 - (op & 0xF);
|
||||
int i = 0;
|
||||
|
||||
while ((src[i] >> 24) == GE_CMD_PROJMATRIXDATA) {
|
||||
const u32 newVal = src[i] << 8;
|
||||
if (dst[i] != newVal) {
|
||||
Flush();
|
||||
dst[i] = newVal;
|
||||
gstate_c.Dirty(DIRTY_PROJMATRIX);
|
||||
}
|
||||
if (++i >= end) {
|
||||
break;
|
||||
bool fastLoad = !debugRecording_;
|
||||
if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) {
|
||||
fastLoad = false;
|
||||
}
|
||||
|
||||
if (fastLoad) {
|
||||
while ((src[i] >> 24) == GE_CMD_PROJMATRIXDATA) {
|
||||
const u32 newVal = src[i] << 8;
|
||||
if (dst[i] != newVal) {
|
||||
Flush();
|
||||
dst[i] = newVal;
|
||||
gstate_c.Dirty(DIRTY_PROJMATRIX);
|
||||
}
|
||||
if (++i >= end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1677,15 +1724,22 @@ void GPUCommon::Execute_TgenMtxNum(u32 op, u32 diff) {
|
|||
const int end = 12 - (op & 0xF);
|
||||
int i = 0;
|
||||
|
||||
while ((src[i] >> 24) == GE_CMD_TGENMATRIXDATA) {
|
||||
const u32 newVal = src[i] << 8;
|
||||
if (dst[i] != newVal) {
|
||||
Flush();
|
||||
dst[i] = newVal;
|
||||
gstate_c.Dirty(DIRTY_TEXMATRIX);
|
||||
}
|
||||
if (++i >= end) {
|
||||
break;
|
||||
bool fastLoad = !debugRecording_;
|
||||
if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) {
|
||||
fastLoad = false;
|
||||
}
|
||||
|
||||
if (fastLoad) {
|
||||
while ((src[i] >> 24) == GE_CMD_TGENMATRIXDATA) {
|
||||
const u32 newVal = src[i] << 8;
|
||||
if (dst[i] != newVal) {
|
||||
Flush();
|
||||
dst[i] = newVal;
|
||||
gstate_c.Dirty(DIRTY_TEXMATRIX);
|
||||
}
|
||||
if (++i >= end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1718,34 +1772,41 @@ void GPUCommon::Execute_BoneMtxNum(u32 op, u32 diff) {
|
|||
const int end = 12 * 8 - (op & 0x7F);
|
||||
int i = 0;
|
||||
|
||||
// If we can't use software skinning, we have to flush and dirty.
|
||||
if (!g_Config.bSoftwareSkinning || (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) != 0) {
|
||||
while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) {
|
||||
const u32 newVal = src[i] << 8;
|
||||
if (dst[i] != newVal) {
|
||||
Flush();
|
||||
dst[i] = newVal;
|
||||
}
|
||||
if (++i >= end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool fastLoad = !debugRecording_;
|
||||
if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) {
|
||||
fastLoad = false;
|
||||
}
|
||||
|
||||
const int numPlusCount = (op & 0x7F) + i;
|
||||
for (int num = op & 0x7F; num < numPlusCount; num += 12) {
|
||||
gstate_c.Dirty(DIRTY_BONEMATRIX0 << (num / 12));
|
||||
}
|
||||
} else {
|
||||
while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) {
|
||||
dst[i] = src[i] << 8;
|
||||
if (++i >= end) {
|
||||
break;
|
||||
if (fastLoad) {
|
||||
// If we can't use software skinning, we have to flush and dirty.
|
||||
if (!g_Config.bSoftwareSkinning || (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) != 0) {
|
||||
while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) {
|
||||
const u32 newVal = src[i] << 8;
|
||||
if (dst[i] != newVal) {
|
||||
Flush();
|
||||
dst[i] = newVal;
|
||||
}
|
||||
if (++i >= end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int numPlusCount = (op & 0x7F) + i;
|
||||
for (int num = op & 0x7F; num < numPlusCount; num += 12) {
|
||||
gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12);
|
||||
const int numPlusCount = (op & 0x7F) + i;
|
||||
for (int num = op & 0x7F; num < numPlusCount; num += 12) {
|
||||
gstate_c.Dirty(DIRTY_BONEMATRIX0 << (num / 12));
|
||||
}
|
||||
} else {
|
||||
while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) {
|
||||
dst[i] = src[i] << 8;
|
||||
if (++i >= end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const int numPlusCount = (op & 0x7F) + i;
|
||||
for (int num = op & 0x7F; num < numPlusCount; num += 12) {
|
||||
gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2330,6 +2391,7 @@ bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) {
|
|||
}
|
||||
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
GPURecord::NotifyMemcpy(dest, src, size);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2354,6 +2416,7 @@ bool GPUCommon::PerformMemorySet(u32 dest, u8 v, int size) {
|
|||
|
||||
// Or perhaps a texture, let's invalidate.
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
GPURecord::NotifyMemset(dest, v, size);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2370,6 +2433,7 @@ bool GPUCommon::PerformMemoryUpload(u32 dest, int size) {
|
|||
// Cheat a bit to force an upload of the framebuffer.
|
||||
// VRAM + 0x00400000 is simply a VRAM mirror.
|
||||
if (Memory::IsVRAMAddress(dest)) {
|
||||
GPURecord::NotifyUpload(dest, size);
|
||||
return PerformMemoryCopy(dest, dest ^ 0x00400000, size);
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -61,6 +61,7 @@ public:
|
|||
}
|
||||
|
||||
void Resized() override;
|
||||
void DumpNextFrame() override;
|
||||
|
||||
void ExecuteOp(u32 op, u32 diff) override;
|
||||
void PreExecuteOp(u32 op, u32 diff) override;
|
||||
|
@ -202,7 +203,7 @@ public:
|
|||
const std::list<int>& GetDisplayLists() override {
|
||||
return dlQueue;
|
||||
}
|
||||
virtual bool DecodeTexture(u8* dest, const GPUgstate &state) override {
|
||||
bool DecodeTexture(u8* dest, const GPUgstate &state) override {
|
||||
return false;
|
||||
}
|
||||
std::vector<FramebufferInfo> GetFramebufferList() override {
|
||||
|
@ -211,6 +212,13 @@ public:
|
|||
void ClearShaderCache() override {}
|
||||
void CleanupBeforeUI() override {}
|
||||
|
||||
s64 GetListTicks(int listid) override {
|
||||
if (listid >= 0 && listid < DisplayListMaxCount) {
|
||||
return dls[listid].waitTicks;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<std::string> DebugGetShaderIDs(DebugShaderType shader) override { return std::vector<std::string>(); };
|
||||
std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override {
|
||||
return "N/A";
|
||||
|
@ -227,7 +235,8 @@ protected:
|
|||
}
|
||||
|
||||
virtual void InitClearInternal() {}
|
||||
virtual void BeginFrameInternal() {}
|
||||
void BeginFrame() override;
|
||||
virtual void BeginFrameInternal();
|
||||
virtual void CopyDisplayToOutputInternal() {}
|
||||
virtual void ReinitializeInternal() {}
|
||||
|
||||
|
@ -329,6 +338,7 @@ protected:
|
|||
|
||||
bool dumpNextFrame_;
|
||||
bool dumpThisFrame_;
|
||||
bool debugRecording_;
|
||||
bool interruptsEnabled_;
|
||||
bool resized_;
|
||||
DrawType lastDraw_;
|
||||
|
|
|
@ -299,6 +299,7 @@ public:
|
|||
virtual const std::list<int>& GetDisplayLists() = 0;
|
||||
virtual bool DecodeTexture(u8* dest, const GPUgstate &state) = 0;
|
||||
virtual std::vector<FramebufferInfo> GetFramebufferList() = 0;
|
||||
virtual s64 GetListTicks(int listid) = 0;
|
||||
|
||||
// For debugging. The IDs returned are opaque, do not poke in them or display them in any way.
|
||||
virtual std::vector<std::string> DebugGetShaderIDs(DebugShaderType type) = 0;
|
||||
|
|
|
@ -29,7 +29,6 @@ public:
|
|||
void InitClear() override {}
|
||||
void ExecuteOp(u32 op, u32 diff) override;
|
||||
|
||||
void BeginFrame() override {}
|
||||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override {}
|
||||
void CopyDisplayToOutput() override {}
|
||||
void GetStats(char *buffer, size_t bufsize) override;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "GPU/Software/TransformUnit.h"
|
||||
#include "GPU/Common/DrawEngineCommon.h"
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
#include "GPU/Debugger/Record.h"
|
||||
|
||||
const int FB_WIDTH = 480;
|
||||
const int FB_HEIGHT = 272;
|
||||
|
@ -876,6 +877,7 @@ bool SoftGPU::PerformMemoryCopy(u32 dest, u32 src, int size)
|
|||
{
|
||||
// Nothing to update.
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
GPURecord::NotifyMemcpy(dest, src, size);
|
||||
// Let's just be safe.
|
||||
framebufferDirty_ = true;
|
||||
return false;
|
||||
|
@ -885,6 +887,7 @@ bool SoftGPU::PerformMemorySet(u32 dest, u8 v, int size)
|
|||
{
|
||||
// Nothing to update.
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
GPURecord::NotifyMemset(dest, v, size);
|
||||
// Let's just be safe.
|
||||
framebufferDirty_ = true;
|
||||
return false;
|
||||
|
@ -901,6 +904,7 @@ bool SoftGPU::PerformMemoryUpload(u32 dest, int size)
|
|||
{
|
||||
// Nothing to update.
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
GPURecord::NotifyUpload(dest, size);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@ public:
|
|||
void InitClear() override {}
|
||||
void ExecuteOp(u32 op, u32 diff) override;
|
||||
|
||||
void BeginFrame() override {}
|
||||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
|
||||
void CopyDisplayToOutput() override;
|
||||
void GetStats(char *buffer, size_t bufsize) override;
|
||||
|
@ -70,7 +69,6 @@ public:
|
|||
|
||||
void DeviceLost() override;
|
||||
void DeviceRestore() override;
|
||||
void DumpNextFrame() override {}
|
||||
|
||||
void Resized() override {}
|
||||
void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) override {
|
||||
|
|
|
@ -329,14 +329,6 @@ void GPU_Vulkan::InitClearInternal() {
|
|||
}
|
||||
}
|
||||
|
||||
void GPU_Vulkan::DumpNextFrame() {
|
||||
dumpNextFrame_ = true;
|
||||
}
|
||||
|
||||
void GPU_Vulkan::BeginFrame() {
|
||||
ScheduleEvent(GPU_EVENT_BEGIN_FRAME);
|
||||
}
|
||||
|
||||
void GPU_Vulkan::UpdateVsyncInterval(bool force) {
|
||||
// TODO
|
||||
}
|
||||
|
@ -351,9 +343,6 @@ void GPU_Vulkan::UpdateCmdInfo() {
|
|||
}
|
||||
}
|
||||
|
||||
void GPU_Vulkan::BeginFrameInternal() {
|
||||
}
|
||||
|
||||
void GPU_Vulkan::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) {
|
||||
host->GPUNotifyDisplay(framebuf, stride, format);
|
||||
framebufferManager_->SetDisplayFramebuffer(framebuf, stride, format);
|
||||
|
|
|
@ -46,13 +46,11 @@ public:
|
|||
void ExecuteOp(u32 op, u32 diff) override;
|
||||
|
||||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
|
||||
void BeginFrame() override;
|
||||
void GetStats(char *buffer, size_t bufsize) override;
|
||||
void ClearCacheNextFrame() override;
|
||||
void DeviceLost() override; // Only happens on Android. Drop all textures and shaders.
|
||||
void DeviceRestore() override;
|
||||
|
||||
void DumpNextFrame() override;
|
||||
void DoState(PointerWrap &p) override;
|
||||
|
||||
void ClearShaderCache() override;
|
||||
|
@ -102,7 +100,6 @@ private:
|
|||
void CheckFlushOp(int cmd, u32 diff);
|
||||
void BuildReportingInfo();
|
||||
void InitClearInternal() override;
|
||||
void BeginFrameInternal() override;
|
||||
void CopyDisplayToOutputInternal() override;
|
||||
void ReinitializeInternal() override;
|
||||
inline void UpdateVsyncInterval(bool force);
|
||||
|
|
|
@ -1336,10 +1336,7 @@ UI::EventReturn DeveloperToolsScreen::OnLoadLanguageIni(UI::EventParams &e) {
|
|||
}
|
||||
|
||||
UI::EventReturn DeveloperToolsScreen::OnOpenTexturesIniFile(UI::EventParams &e) {
|
||||
std::string gameID = g_paramSFO.GetValueString("DISC_ID");
|
||||
if (gameID.empty()) {
|
||||
gameID = g_paramSFO.GenerateFakeID();
|
||||
}
|
||||
std::string gameID = g_paramSFO.GetDiscID();
|
||||
std::string texturesDirectory = GetSysDirectory(DIRECTORY_TEXTURES) + gameID + "/";
|
||||
bool enabled_ = !gameID.empty();
|
||||
if (enabled_) {
|
||||
|
|
|
@ -713,10 +713,7 @@ void TakeScreenshot() {
|
|||
// First, find a free filename.
|
||||
int i = 0;
|
||||
|
||||
std::string gameId = g_paramSFO.GetValueString("DISC_ID");
|
||||
if (gameId.empty()) {
|
||||
gameId = g_paramSFO.GenerateFakeID();
|
||||
}
|
||||
std::string gameId = g_paramSFO.GetDiscID();
|
||||
|
||||
char filename[2048];
|
||||
while (i < 10000){
|
||||
|
|
|
@ -320,10 +320,7 @@ void GamePauseScreen::CreateViews() {
|
|||
root_->SetDefaultFocusView(continueChoice);
|
||||
continueChoice->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
|
||||
|
||||
std::string gameId = g_paramSFO.GetValueString("DISC_ID");
|
||||
if (gameId.empty()) {
|
||||
gameId = g_paramSFO.GenerateFakeID();
|
||||
}
|
||||
std::string gameId = g_paramSFO.GetDiscID();
|
||||
if (g_Config.hasGameConfig(gameId)) {
|
||||
rightColumnItems->Add(new Choice(pa->T("Game Settings")))->OnClick.Handle(this, &GamePauseScreen::OnGameSettings);
|
||||
rightColumnItems->Add(new Choice(pa->T("Delete Game Config")))->OnClick.Handle(this, &GamePauseScreen::OnDeleteConfig);
|
||||
|
@ -424,10 +421,7 @@ void GamePauseScreen::CallbackDeleteConfig(bool yes)
|
|||
|
||||
UI::EventReturn GamePauseScreen::OnCreateConfig(UI::EventParams &e)
|
||||
{
|
||||
std::string gameId = g_paramSFO.GetValueString("DISC_ID");
|
||||
if (gameId.empty()) {
|
||||
gameId = g_paramSFO.GenerateFakeID();
|
||||
}
|
||||
std::string gameId = g_paramSFO.GetDiscID();
|
||||
g_Config.createGameConfig(gameId);
|
||||
g_Config.changeGameSpecific(gameId);
|
||||
g_Config.saveGameConfig(gameId);
|
||||
|
|
|
@ -330,6 +330,7 @@
|
|||
<ClInclude Include="..\..\Core\FileLoaders\LocalFileLoader.h" />
|
||||
<ClInclude Include="..\..\Core\FileLoaders\RamCachingFileLoader.h" />
|
||||
<ClInclude Include="..\..\Core\FileLoaders\RetryingFileLoader.h" />
|
||||
<ClInclude Include="..\..\Core\FileSystems\BlobFileSystem.h" />
|
||||
<ClInclude Include="..\..\Core\FileSystems\BlockDevices.h" />
|
||||
<ClInclude Include="..\..\Core\FileSystems\DirectoryFileSystem.h" />
|
||||
<ClInclude Include="..\..\Core\FileSystems\FileSystem.h" />
|
||||
|
@ -521,6 +522,7 @@
|
|||
<ClCompile Include="..\..\Core\FileLoaders\LocalFileLoader.cpp" />
|
||||
<ClCompile Include="..\..\Core\FileLoaders\RamCachingFileLoader.cpp" />
|
||||
<ClCompile Include="..\..\Core\FileLoaders\RetryingFileLoader.cpp" />
|
||||
<ClCompile Include="..\..\Core\FileSystems\BlobFileSystem.cpp" />
|
||||
<ClCompile Include="..\..\Core\FileSystems\BlockDevices.cpp" />
|
||||
<ClCompile Include="..\..\Core\FileSystems\DirectoryFileSystem.cpp" />
|
||||
<ClCompile Include="..\..\Core\FileSystems\FileSystem.cpp" />
|
||||
|
|
|
@ -166,6 +166,9 @@
|
|||
<ClCompile Include="..\..\Core\MIPS\x86\RegCacheFPU.cpp">
|
||||
<Filter>MIPS\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Core\FileSystems\BlobFileSystem.cpp">
|
||||
<Filter>FileSystems</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Core\FileSystems\BlockDevices.cpp">
|
||||
<Filter>FileSystems</Filter>
|
||||
</ClCompile>
|
||||
|
@ -674,6 +677,9 @@
|
|||
<ClInclude Include="..\..\Core\MIPS\x86\RegCacheFPU.h">
|
||||
<Filter>MIPS\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\Core\FileSystems\BlobFileSystem.h">
|
||||
<Filter>FileSystems</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\Core\FileSystems\BlockDevices.h">
|
||||
<Filter>FileSystems</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "GPU/Common/GPUStateUtils.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/Debugger/Breakpoints.h"
|
||||
#include "GPU/Debugger/Record.h"
|
||||
#include "GPU/Debugger/Stepping.h"
|
||||
#include "Core/Config.h"
|
||||
#include <windowsx.h>
|
||||
|
@ -706,6 +707,10 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
|||
breakNext = BREAK_NONE;
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_RECORD:
|
||||
GPURecord::Activate();
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_FORCEOPAQUE:
|
||||
if (attached && gpuDebug != nullptr) {
|
||||
forceOpaque_ = SendMessage(GetDlgItem(m_hDlg, IDC_GEDBG_FORCEOPAQUE), BM_GETCHECK, 0, 0) != 0;
|
||||
|
|
|
@ -176,6 +176,7 @@ BEGIN
|
|||
PUSHBUTTON "Step &Prim",IDC_GEDBG_STEPPRIM,166,2,48,14
|
||||
PUSHBUTTON "Step &Into",IDC_GEDBG_STEP,218,2,48,14
|
||||
PUSHBUTTON "&Resume",IDC_GEDBG_RESUME,270,2,48,14
|
||||
PUSHBUTTON "Rec&ord",IDC_GEDBG_RECORD,440,2,48,14
|
||||
CONTROL "",IDC_GEDBG_TEX,"SimpleGLWindow",WS_CHILD | WS_VISIBLE,10,20,128,128
|
||||
CONTROL "",IDC_GEDBG_FRAME,"SimpleGLWindow",WS_CHILD | WS_VISIBLE,148,20,256,136
|
||||
CONTROL "",IDC_GEDBG_MAINTAB,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER,10,216,480,180
|
||||
|
|
|
@ -333,6 +333,7 @@
|
|||
#define ID_FILE_USEFFV1 40166
|
||||
#define ID_FILE_DUMPAUDIO 40167
|
||||
#define ID_HELP_GITHUB 40168
|
||||
#define IDC_GEDBG_RECORD 40169
|
||||
|
||||
// Dummy option to let the buffered rendering hotkey cycle through all the options.
|
||||
#define ID_OPTIONS_BUFFEREDRENDERINGDUMMY 40500
|
||||
|
|
|
@ -229,6 +229,7 @@ EXEC_AND_LIB_FILES := \
|
|||
$(SRC)/GPU/Common/PostShader.cpp \
|
||||
$(SRC)/GPU/Common/ShaderUniforms.cpp \
|
||||
$(SRC)/GPU/Debugger/Breakpoints.cpp \
|
||||
$(SRC)/GPU/Debugger/Record.cpp \
|
||||
$(SRC)/GPU/Debugger/Stepping.cpp \
|
||||
$(SRC)/GPU/GLES/FramebufferManagerGLES.cpp \
|
||||
$(SRC)/GPU/GLES/DepalettizeShaderGLES.cpp \
|
||||
|
@ -363,6 +364,7 @@ EXEC_AND_LIB_FILES := \
|
|||
$(SRC)/Core/HLE/sceGameUpdate.cpp \
|
||||
$(SRC)/Core/HLE/sceNp.cpp \
|
||||
$(SRC)/Core/HLE/scePauth.cpp \
|
||||
$(SRC)/Core/FileSystems/BlobFileSystem.cpp \
|
||||
$(SRC)/Core/FileSystems/BlockDevices.cpp \
|
||||
$(SRC)/Core/FileSystems/ISOFileSystem.cpp \
|
||||
$(SRC)/Core/FileSystems/FileSystem.cpp \
|
||||
|
|
Loading…
Add table
Reference in a new issue