mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge branch 'master' into armjit-fpu
Conflicts: Core/MIPS/MIPSVFPUUtils.cpp Core/MIPS/x86/CompVFPU.cpp GPU/GLES/VertexDecoder.cpp
This commit is contained in:
commit
e32721c72a
101 changed files with 4642 additions and 999 deletions
|
@ -9,9 +9,7 @@ if(ANDROID)
|
|||
endif()
|
||||
|
||||
if (IOS)
|
||||
if (${IOS_PLATFORM} STREQUAL "OS")
|
||||
set(ARM ON)
|
||||
endif()
|
||||
set(ARM ON)
|
||||
endif()
|
||||
|
||||
if(BLACKBERRY)
|
||||
|
@ -410,6 +408,16 @@ if(ANDROID)
|
|||
native/android/native-audio-so.h)
|
||||
target_link_libraries(native_audio OpenSLES)
|
||||
# No target
|
||||
elseif(IOS)
|
||||
set(nativeExtra ${nativeExtra}
|
||||
ios/main.m
|
||||
ios/AppDelegate.m
|
||||
ios/AppDelegate.h
|
||||
ios/ViewController.mm
|
||||
ios/ViewController.h)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-framework Foundation -framework CoreGraphics -framework QuartzCore -framework OpenGLES -framework UIKit")
|
||||
# No target
|
||||
# set(TargetBin PPSSPP)
|
||||
elseif(USING_QT_UI)
|
||||
# Currently unused
|
||||
find_package(Qt4 COMPONENTS QtMultimedia QtOpenGL QtGui QtCore)
|
||||
|
@ -433,9 +441,7 @@ elseif(SDL_FOUND)
|
|||
elseif(PANDORA)
|
||||
set(nativeExtraLibs ${nativeExtraLibs} pthread EGL X11)
|
||||
endif()
|
||||
if(NOT IOS) # No target
|
||||
set(TargetBin PPSSPPSDL)
|
||||
endif()
|
||||
set(TargetBin PPSSPPSDL)
|
||||
else()
|
||||
message(FATAL_ERROR "Could not find SDL. Failing.")
|
||||
endif()
|
||||
|
@ -950,4 +956,9 @@ endif()
|
|||
|
||||
file(INSTALL ${NativeAssets} DESTINATION assets)
|
||||
|
||||
# code signing
|
||||
if (IOS)
|
||||
set_target_properties(${NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST PPSSPP-Info.plist XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer: My Name")
|
||||
endif()
|
||||
|
||||
#include(CPack)
|
||||
|
|
|
@ -625,7 +625,7 @@ public:
|
|||
u8 *uncomp_buffer = new u8[header.UncompressedSize];
|
||||
size_t uncomp_size = header.UncompressedSize;
|
||||
snappy_uncompress((const char *)buffer, sz, (char *)uncomp_buffer, &uncomp_size);
|
||||
if (uncomp_size != header.UncompressedSize) {
|
||||
if ((int)uncomp_size != header.UncompressedSize) {
|
||||
ERROR_LOG(COMMON,"Size mismatch: file: %i calc: %i", (int)header.UncompressedSize, (int)uncomp_size);
|
||||
}
|
||||
ptr = uncomp_buffer;
|
||||
|
|
|
@ -131,8 +131,6 @@ void MemArena::GrabLowMemSpace(size_t size)
|
|||
ERROR_LOG(MEMMAP, "Failed to grab ashmem space of size: %08x errno: %d", (int)size, (int)(errno));
|
||||
return;
|
||||
}
|
||||
#elif defined(UNUSABLE_MMAP)
|
||||
// Do nothing as we are using malloc()
|
||||
#else
|
||||
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
fd = open(ram_temp_file.c_str(), O_RDWR | O_CREAT, mode);
|
||||
|
@ -157,8 +155,9 @@ void MemArena::ReleaseSpace()
|
|||
#ifdef _WIN32
|
||||
CloseHandle(hMemoryMapping);
|
||||
hMemoryMapping = 0;
|
||||
#elif defined(UNUSABLE_MMAP)
|
||||
// Do nothing as we are using malloc()
|
||||
#elif defined(__SYMBIAN32__)
|
||||
memmap->Close();
|
||||
delete memmap;
|
||||
#else
|
||||
close(fd);
|
||||
#endif
|
||||
|
@ -170,20 +169,7 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base)
|
|||
#ifdef _WIN32
|
||||
size = roundup(size);
|
||||
void *ptr = MapViewOfFileEx(hMemoryMapping, FILE_MAP_ALL_ACCESS, 0, (DWORD)((u64)offset), size, base);
|
||||
if (!ptr) {
|
||||
//ERROR_LOG(MEMMAP, "Failed to map memory: %08x %08x %08x : %s", (u32)offset, (u32)size, (u32)base, GetLastErrorMsg());
|
||||
} else {
|
||||
//ERROR_LOG(MEMMAP, "Mapped memory: %08x %08x %08x : %s", (u32)offset, (u32)size, (u32)base, GetLastErrorMsg());
|
||||
}
|
||||
return ptr;
|
||||
#elif defined(UNUSABLE_MMAP)
|
||||
void *retval = malloc(size);
|
||||
if (!retval)
|
||||
{
|
||||
NOTICE_LOG(MEMMAP, "malloc failed: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
return retval;
|
||||
#else
|
||||
void *retval = mmap(base, size, PROT_READ | PROT_WRITE, MAP_SHARED |
|
||||
((base == 0) ? 0 : MAP_FIXED), fd, offset);
|
||||
|
@ -202,14 +188,14 @@ void MemArena::ReleaseView(void* view, size_t size)
|
|||
{
|
||||
#ifdef _WIN32
|
||||
UnmapViewOfFile(view);
|
||||
#elif defined(UNUSABLE_MMAP)
|
||||
free(view);
|
||||
#elif defined(__SYMBIAN32__)
|
||||
memmap->Decommit(((int)view - (int)memmap->Base()) & 0x3FFFFFFF, size);
|
||||
#else
|
||||
munmap(view, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef __SYMBIAN32__
|
||||
u8* MemArena::Find4GBBase()
|
||||
{
|
||||
#ifdef _M_X64
|
||||
|
@ -224,8 +210,8 @@ u8* MemArena::Find4GBBase()
|
|||
return reinterpret_cast<u8*>(0x2300000000ULL);
|
||||
#endif
|
||||
|
||||
#else
|
||||
// 32 bit
|
||||
#else // 32 bit
|
||||
|
||||
#ifdef _WIN32
|
||||
// The highest thing in any 1GB section of memory space is the locked cache. We only need to fit it.
|
||||
u8* base = (u8*)VirtualAlloc(0, 0x10000000, MEM_RESERVE, PAGE_READWRITE);
|
||||
|
@ -233,9 +219,6 @@ u8* MemArena::Find4GBBase()
|
|||
VirtualFree(base, 0, MEM_RELEASE);
|
||||
}
|
||||
return base;
|
||||
#elif defined(UNUSABLE_MMAP)
|
||||
// We are unable to use relative addresses due to lack of mmap()
|
||||
return NULL;
|
||||
#else
|
||||
void* base = mmap(0, 0x10000000, PROT_READ | PROT_WRITE,
|
||||
MAP_ANON | MAP_SHARED, -1, 0);
|
||||
|
@ -248,6 +231,7 @@ u8* MemArena::Find4GBBase()
|
|||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// yeah, this could also be done in like two bitwise ops...
|
||||
|
@ -282,6 +266,12 @@ static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32
|
|||
if (view.flags & MV_MIRROR_PREVIOUS) {
|
||||
position = last_position;
|
||||
} else {
|
||||
#ifdef __SYMBIAN32__
|
||||
*(view.out_ptr_low) = (u8*)((int)arena->memmap->Base() + view.virtual_address);
|
||||
arena->memmap->Commit(view.virtual_address & 0x3FFFFFFF, view.size);
|
||||
}
|
||||
*(view.out_ptr) = (u8*)((int)arena->memmap->Base() + view.virtual_address & 0x3FFFFFFF);
|
||||
#else
|
||||
*(view.out_ptr_low) = (u8*)arena->CreateView(position, view.size);
|
||||
if (!*view.out_ptr_low)
|
||||
goto bail;
|
||||
|
@ -299,6 +289,8 @@ static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32
|
|||
if (!*view.out_ptr)
|
||||
goto bail;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
last_position = position;
|
||||
position += roundup(view.size);
|
||||
|
@ -344,7 +336,9 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena
|
|||
total_mem += roundup(views[i].size);
|
||||
}
|
||||
// Grab some pagefile backed memory out of the void ...
|
||||
#ifndef __SYMBIAN32__
|
||||
arena->GrabLowMemSpace(total_mem);
|
||||
#endif
|
||||
|
||||
// Now, create views in high memory where there's plenty of space.
|
||||
#ifdef _M_X64
|
||||
|
@ -374,6 +368,16 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena
|
|||
break;
|
||||
}
|
||||
}
|
||||
#elif defined(__SYMBIAN32__)
|
||||
arena->memmap = new RChunk();
|
||||
arena->memmap->CreateDisconnectedLocal(0 , 0, 0x10000000);
|
||||
if (!Memory_TryBase(arena->memmap->Base(), views, num_views, flags, arena))
|
||||
{
|
||||
PanicAlert("MemoryMap_Setup: Failed finding a memory base.");
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
u8* base = arena->memmap->Base();
|
||||
#else
|
||||
// Linux32 is fine with the x64 method, although limited to 32-bit with no automirrors.
|
||||
u8 *base = MemArena::Find4GBBase();
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef __SYMBIAN32__
|
||||
#include <e32std.h>
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// This class lets you create a block of anonymous RAM, and then arbitrarily map views into it.
|
||||
|
@ -36,8 +40,12 @@ public:
|
|||
void *CreateView(s64 offset, size_t size, void *base = 0);
|
||||
void ReleaseView(void *view, size_t size);
|
||||
|
||||
#ifdef __SYMBIAN32__
|
||||
RChunk* memmap;
|
||||
#else
|
||||
// This only finds 1 GB in 32-bit
|
||||
static u8 *Find4GBBase();
|
||||
#endif
|
||||
private:
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -23,11 +23,6 @@
|
|||
#endif
|
||||
#include <string>
|
||||
|
||||
#if defined(__SYMBIAN32__)
|
||||
// Also Xbox 360
|
||||
#define UNUSABLE_MMAP 1
|
||||
#endif
|
||||
|
||||
void* AllocateExecutableMemory(size_t size, bool low = true);
|
||||
void* AllocateMemoryPages(size_t size);
|
||||
void FreeMemoryPages(void* ptr, size_t size);
|
||||
|
|
|
@ -49,14 +49,15 @@ void CConfig::Load(const char *iniFileName)
|
|||
general->Get("FirstRun", &bFirstRun, true);
|
||||
general->Get("AutoLoadLast", &bAutoLoadLast, false);
|
||||
general->Get("AutoRun", &bAutoRun, true);
|
||||
general->Get("Browse", &bBrowse, false);
|
||||
general->Get("ConfirmOnQuit", &bConfirmOnQuit, false);
|
||||
general->Get("IgnoreBadMemAccess", &bIgnoreBadMemAccess, true);
|
||||
general->Get("CurrentDirectory", ¤tDirectory, "");
|
||||
general->Get("ShowDebuggerOnLoad", &bShowDebuggerOnLoad, false);
|
||||
|
||||
IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU");
|
||||
cpu->Get("Core", &iCpuCore, 2);
|
||||
cpu->Get("FastMemory", &bFastMemory, false);
|
||||
cpu->Get("Jit", &bJit, true);
|
||||
cpu->Get("FastMemory", &bFastMemory, true);
|
||||
|
||||
IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics");
|
||||
graphics->Get("ShowFPSCounter", &bShowFPSCounter, false);
|
||||
|
@ -67,6 +68,7 @@ void CConfig::Load(const char *iniFileName)
|
|||
graphics->Get("LinearFiltering", &bLinearFiltering, false);
|
||||
graphics->Get("SSAA", &SSAntiAliasing, 0);
|
||||
graphics->Get("VBO", &bUseVBO, false);
|
||||
graphics->Get("FrameSkip", &iFrameSkip, 0);
|
||||
#ifdef USING_GLES2
|
||||
graphics->Get("AnisotropyLevel", &iAnisotropyLevel, 0);
|
||||
#else
|
||||
|
@ -112,12 +114,13 @@ void CConfig::Save()
|
|||
general->Set("FirstRun", bFirstRun);
|
||||
general->Set("AutoLoadLast", bAutoLoadLast);
|
||||
general->Set("AutoRun", bAutoRun);
|
||||
general->Set("Browse", bBrowse);
|
||||
general->Set("ConfirmOnQuit", bConfirmOnQuit);
|
||||
general->Set("IgnoreBadMemAccess", bIgnoreBadMemAccess);
|
||||
general->Set("CurrentDirectory", currentDirectory);
|
||||
general->Set("ShowDebuggerOnLoad", bShowDebuggerOnLoad);
|
||||
IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU");
|
||||
cpu->Set("Core", iCpuCore);
|
||||
cpu->Set("Jit", bJit);
|
||||
cpu->Set("FastMemory", bFastMemory);
|
||||
|
||||
IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics");
|
||||
|
@ -129,6 +132,7 @@ void CConfig::Save()
|
|||
graphics->Set("LinearFiltering", bLinearFiltering);
|
||||
graphics->Set("SSAA", SSAntiAliasing);
|
||||
graphics->Set("VBO", bUseVBO);
|
||||
graphics->Set("FrameSkip", iFrameSkip);
|
||||
graphics->Set("AnisotropyLevel", iAnisotropyLevel);
|
||||
graphics->Set("DisableG3DLog", bDisableG3DLog);
|
||||
graphics->Set("VertexCache", bVertexCache);
|
||||
|
|
|
@ -44,11 +44,12 @@ public:
|
|||
bool bSpeedLimit;
|
||||
bool bConfirmOnQuit;
|
||||
bool bAutoRun; // start immediately
|
||||
bool bBrowse;
|
||||
|
||||
// Core
|
||||
bool bIgnoreBadMemAccess;
|
||||
bool bFastMemory;
|
||||
int iCpuCore;
|
||||
bool bJit;
|
||||
|
||||
// GFX
|
||||
bool bDisplayFramebuffer;
|
||||
|
@ -58,6 +59,7 @@ public:
|
|||
bool bLinearFiltering;
|
||||
bool bUseVBO;
|
||||
bool bStretchToDisplay;
|
||||
int iFrameSkip; // 0 = off; 1 = auto; (future: 2 = skip every 2nd frame; 3 = skip every 3rd frame etc).
|
||||
|
||||
int iWindowZoom; // for Windows
|
||||
bool SSAntiAliasing; //for Windows, too
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
#include "Core.h"
|
||||
#include "MemMap.h"
|
||||
#include "MIPS/MIPS.h"
|
||||
#ifdef _WIN32
|
||||
#include "Windows/OpenGLBase.h"
|
||||
#endif
|
||||
|
||||
#include "Host.h"
|
||||
|
||||
|
@ -64,7 +67,16 @@ bool Core_IsStepping()
|
|||
|
||||
void Core_RunLoop()
|
||||
{
|
||||
currentMIPS->RunLoopUntil(0xFFFFFFFFFFFFFFFULL);
|
||||
while (!coreState) {
|
||||
currentMIPS->RunLoopUntil(0xFFFFFFFFFFFFFFFULL);
|
||||
if (coreState == CORE_NEXTFRAME)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
GL_SwapBuffers();
|
||||
#endif
|
||||
coreState = CORE_RUNNING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core_DoSingleStep()
|
||||
|
@ -100,6 +112,8 @@ reswitch:
|
|||
case CORE_STEPPING:
|
||||
//1: wait for step command..
|
||||
#if defined(USING_QT_UI) || defined(_DEBUG)
|
||||
host->UpdateDisassembly();
|
||||
host->UpdateMemView();
|
||||
host->SendCoreWait(true);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -68,6 +68,8 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>../common;..;../native;../native/ext/glew;../ext/zlib</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
@ -79,6 +81,8 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>../common;..;../native;../native/ext/glew;../ext/zlib</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
@ -108,6 +112,8 @@
|
|||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>../common;..;../native;../native/ext/glew;../ext/zlib</AdditionalIncludeDirectories>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
enum CPUCore {
|
||||
CPU_INTERPRETER,
|
||||
CPU_FASTINTERPRETER, // unsafe, a bit faster than INTERPRETER
|
||||
CPU_JIT,
|
||||
};
|
||||
|
||||
|
|
|
@ -1080,7 +1080,7 @@ bool SavedataParam::CreatePNGIcon(u8* pngData, int pngSize, SaveFileInfo& info)
|
|||
u32 atlasPtr;
|
||||
if (success)
|
||||
atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon");
|
||||
if (success && atlasPtr != -1)
|
||||
if (success && atlasPtr != (u32)-1)
|
||||
{
|
||||
info.textureData = atlasPtr;
|
||||
Memory::Memcpy(atlasPtr, textureData, texSize);
|
||||
|
|
|
@ -217,7 +217,7 @@ bool ElfReader::LoadInto(u32 loadAddress)
|
|||
vaddr = userMemory.Alloc(totalSize, false, "ELF");
|
||||
}
|
||||
|
||||
if (vaddr == -1) {
|
||||
if (vaddr == (u32)-1) {
|
||||
ERROR_LOG(LOADER, "Failed to allocate memory for ELF!");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -297,7 +297,7 @@ bool hleExecuteDebugBreak(const HLEFunction &func)
|
|||
|
||||
// Never break on these, they're noise.
|
||||
u32 blacklistedNIDs[] = {NID_SUSPEND_INTR, NID_RESUME_INTR, NID_IDLE};
|
||||
for (int i = 0; i < ARRAY_SIZE(blacklistedNIDs); ++i)
|
||||
for (size_t i = 0; i < ARRAY_SIZE(blacklistedNIDs); ++i)
|
||||
{
|
||||
if (func.ID == blacklistedNIDs[i])
|
||||
return false;
|
||||
|
|
|
@ -187,7 +187,7 @@ u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishF
|
|||
ret = ATRAC_ERROR_ALL_DATA_DECODED;
|
||||
} else {
|
||||
// TODO: This isn't at all right, but at least it makes the music "last" some time.
|
||||
int numSamples = (atrac->decodeEnd - atrac->decodePos) / (sizeof(s16) * 2);
|
||||
u32 numSamples = (atrac->decodeEnd - atrac->decodePos) / (sizeof(s16) * 2);
|
||||
if (atrac->decodePos >= atrac->decodeEnd) {
|
||||
numSamples = 0;
|
||||
} else if (numSamples > ATRAC_MAX_SAMPLES) {
|
||||
|
@ -554,7 +554,7 @@ int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr)
|
|||
|
||||
int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesConsumedAddr, u32 samplesAddr, u32 sampleBytesAddr)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL sceAtracLowLevelDecode(%i, %i, %08x, %08x, %08x, %08x)", atracID, sourceAddr, sourceBytesConsumedAddr, samplesAddr, sampleBytesAddr);
|
||||
ERROR_LOG(HLE, "UNIMPL sceAtracLowLevelDecode(%i, %08x, %08x, %08x, %08x)", atracID, sourceAddr, sourceBytesConsumedAddr, samplesAddr, sampleBytesAddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
const int PSP_CTRL_ERROR_INVALID_MODE = 0x80000107;
|
||||
const int PSP_CTRL_ERROR_INVALID_IDLE_PTR = 0x80000023;
|
||||
|
||||
const int NUM_CTRL_BUFFERS = 64;
|
||||
const u32 NUM_CTRL_BUFFERS = 64;
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -68,8 +68,8 @@ static u32 ctrlOldButtons = 0;
|
|||
|
||||
static _ctrl_data ctrlBufs[NUM_CTRL_BUFFERS];
|
||||
static _ctrl_data ctrlCurrent;
|
||||
static int ctrlBuf = 0;
|
||||
static int ctrlBufRead = 0;
|
||||
static u32 ctrlBuf = 0;
|
||||
static u32 ctrlBufRead = 0;
|
||||
static CtrlLatch latch;
|
||||
|
||||
static int ctrlIdleReset = -1;
|
||||
|
@ -189,7 +189,7 @@ int __CtrlReadBuffer(u32 ctrlDataPtr, u32 nBufs, bool negative, bool peek)
|
|||
if (nBufs > NUM_CTRL_BUFFERS)
|
||||
return SCE_KERNEL_ERROR_INVALID_SIZE;
|
||||
|
||||
int resetRead = ctrlBufRead;
|
||||
u32 resetRead = ctrlBufRead;
|
||||
|
||||
u32 availBufs;
|
||||
// Peeks always work, they just go go from now X buffers.
|
||||
|
|
|
@ -80,14 +80,17 @@ static bool framebufIsLatched;
|
|||
|
||||
static int enterVblankEvent = -1;
|
||||
static int leaveVblankEvent = -1;
|
||||
static int afterFlipEvent = -1;
|
||||
|
||||
static int hCount;
|
||||
static int hCountTotal; //unused
|
||||
static int vCount;
|
||||
static int isVblank;
|
||||
static int numSkippedFrames;
|
||||
static bool hasSetMode;
|
||||
// Don't include this in the state, time increases regardless of state.
|
||||
static double lastFrameTime;
|
||||
static double curFrameTime;
|
||||
static double nextFrameTime;
|
||||
|
||||
std::vector<WaitVBlankInfo> vblankWaitingThreads;
|
||||
|
||||
|
@ -107,10 +110,12 @@ enum {
|
|||
|
||||
void hleEnterVblank(u64 userdata, int cyclesLate);
|
||||
void hleLeaveVblank(u64 userdata, int cyclesLate);
|
||||
void hleAfterFlip(u64 userdata, int cyclesLate);
|
||||
|
||||
void __DisplayInit() {
|
||||
gpuStats.reset();
|
||||
hasSetMode = false;
|
||||
numSkippedFrames = 0;
|
||||
framebufIsLatched = false;
|
||||
framebuf.topaddr = 0x04000000;
|
||||
framebuf.pspFramebufFormat = PSP_DISPLAY_PIXEL_FORMAT_8888;
|
||||
|
@ -118,13 +123,15 @@ void __DisplayInit() {
|
|||
|
||||
enterVblankEvent = CoreTiming::RegisterEvent("EnterVBlank", &hleEnterVblank);
|
||||
leaveVblankEvent = CoreTiming::RegisterEvent("LeaveVBlank", &hleLeaveVblank);
|
||||
afterFlipEvent = CoreTiming::RegisterEvent("AfterFlip", &hleAfterFlip);
|
||||
|
||||
CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs), enterVblankEvent, 0);
|
||||
isVblank = 0;
|
||||
vCount = 0;
|
||||
hCount = 0;
|
||||
hCountTotal = 0;
|
||||
lastFrameTime = 0;
|
||||
curFrameTime = 0.0;
|
||||
nextFrameTime = 0.0;
|
||||
|
||||
InitGfxState();
|
||||
}
|
||||
|
@ -186,7 +193,7 @@ float calculateFPS()
|
|||
static int lastFpsFrame = 0;
|
||||
static double lastFpsTime = 0.0;
|
||||
static double fps = 0.0;
|
||||
|
||||
|
||||
time_update();
|
||||
double now = time_now_d();
|
||||
|
||||
|
@ -202,6 +209,127 @@ float calculateFPS()
|
|||
return fps;
|
||||
}
|
||||
|
||||
void DebugStats()
|
||||
{
|
||||
gpu->UpdateStats();
|
||||
char stats[2048];
|
||||
|
||||
sprintf(stats,
|
||||
"Frames: %i\n"
|
||||
"DL processing time: %0.2f ms\n"
|
||||
"Kernel processing time: %0.2f ms\n"
|
||||
"Slowest syscall: %s : %0.2f ms\n"
|
||||
"Most active syscall: %s : %0.2f ms\n"
|
||||
"Draw calls: %i, flushes %i\n"
|
||||
"Cached Draw calls: %i\n"
|
||||
"Num Tracked Vertex Arrays: %i\n"
|
||||
"Vertices Submitted: %i\n"
|
||||
"Cached Vertices Drawn: %i\n"
|
||||
"Uncached Vertices Drawn: %i\n"
|
||||
"FBOs active: %i\n"
|
||||
"Textures active: %i, decoded: %i\n"
|
||||
"Texture invalidations: %i\n"
|
||||
"Vertex shaders loaded: %i\n"
|
||||
"Fragment shaders loaded: %i\n"
|
||||
"Combined shaders loaded: %i\n",
|
||||
gpuStats.numFrames,
|
||||
gpuStats.msProcessingDisplayLists * 1000.0f,
|
||||
kernelStats.msInSyscalls * 1000.0f,
|
||||
kernelStats.slowestSyscallName ? kernelStats.slowestSyscallName : "(none)",
|
||||
kernelStats.slowestSyscallTime * 1000.0f,
|
||||
kernelStats.summedSlowestSyscallName ? kernelStats.summedSlowestSyscallName : "(none)",
|
||||
kernelStats.summedSlowestSyscallTime * 1000.0f,
|
||||
gpuStats.numDrawCalls,
|
||||
gpuStats.numFlushes,
|
||||
gpuStats.numCachedDrawCalls,
|
||||
gpuStats.numTrackedVertexArrays,
|
||||
gpuStats.numVertsSubmitted,
|
||||
gpuStats.numCachedVertsDrawn,
|
||||
gpuStats.numUncachedVertsDrawn,
|
||||
gpuStats.numFBOs,
|
||||
gpuStats.numTextures,
|
||||
gpuStats.numTexturesDecoded,
|
||||
gpuStats.numTextureInvalidations,
|
||||
gpuStats.numVertexShaders,
|
||||
gpuStats.numFragmentShaders,
|
||||
gpuStats.numShaders
|
||||
);
|
||||
|
||||
float zoom = 0.3f; /// g_Config.iWindowZoom;
|
||||
float soff = 0.3f;
|
||||
PPGeBegin();
|
||||
PPGeDrawText(stats, soff, soff, 0, zoom, 0xCC000000);
|
||||
PPGeDrawText(stats, -soff, -soff, 0, zoom, 0xCC000000);
|
||||
PPGeDrawText(stats, 0, 0, 0, zoom, 0xFFFFFFFF);
|
||||
PPGeEnd();
|
||||
|
||||
gpuStats.resetFrame();
|
||||
kernelStats.ResetFrame();
|
||||
}
|
||||
|
||||
// Let's collect all the throttling and frameskipping logic here.
|
||||
void DoFrameTiming(bool &throttle, bool &skipFrame, bool &skipFlip) {
|
||||
#ifdef _WIN32
|
||||
throttle = !GetAsyncKeyState(VK_TAB);
|
||||
#else
|
||||
throttle = false;
|
||||
#endif
|
||||
skipFlip = false;
|
||||
skipFrame = false;
|
||||
if (PSP_CoreParameter().headLess)
|
||||
throttle = false;
|
||||
|
||||
// Check if the frameskipping code should be enabled. If neither throttling or frameskipping is on,
|
||||
// we have nothing to do here.
|
||||
bool doFrameSkip = g_Config.iFrameSkip == 1;
|
||||
if (!throttle && !doFrameSkip)
|
||||
return;
|
||||
|
||||
time_update();
|
||||
|
||||
curFrameTime = time_now_d();
|
||||
if (nextFrameTime == 0.0)
|
||||
nextFrameTime = time_now_d() + 1.0 / 60.0;
|
||||
|
||||
if (curFrameTime > nextFrameTime && doFrameSkip) {
|
||||
// Argh, we are falling behind! Let's skip a frame and see if we catch up.
|
||||
skipFrame = true;
|
||||
skipFlip = true;
|
||||
INFO_LOG(HLE,"FRAMESKIP %i", numSkippedFrames);
|
||||
}
|
||||
|
||||
if (curFrameTime < nextFrameTime && throttle)
|
||||
{
|
||||
// If time gap is huge just jump (somebody unthrottled)
|
||||
if (nextFrameTime - curFrameTime > 1.0 / 30.0) {
|
||||
nextFrameTime = curFrameTime + 1.0 / 60.0;
|
||||
} else {
|
||||
// Wait until we've catched up.
|
||||
while (time_now_d() < nextFrameTime) {
|
||||
Common::SleepCurrentThread(1);
|
||||
time_update();
|
||||
}
|
||||
}
|
||||
curFrameTime = time_now_d();
|
||||
}
|
||||
// Advance lastFrameTime by a constant amount each frame,
|
||||
// but don't let it get too far behind as things can get very jumpy.
|
||||
const double maxFallBehindFrames = 5.5;
|
||||
|
||||
if (throttle || doFrameSkip) {
|
||||
nextFrameTime = std::max(nextFrameTime + 1.0 / 60.0, time_now_d() - maxFallBehindFrames / 60.0);
|
||||
} else {
|
||||
nextFrameTime = nextFrameTime + 1.0 / 60.0;
|
||||
}
|
||||
|
||||
// Max 6 skipped frames in a row - 10 fps is really the bare minimum for playability.
|
||||
if (numSkippedFrames >= 4) {
|
||||
skipFrame = false;
|
||||
skipFlip = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void hleEnterVblank(u64 userdata, int cyclesLate) {
|
||||
int vbCount = userdata;
|
||||
|
||||
|
@ -223,7 +351,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) {
|
|||
// Trigger VBlank interrupt handlers.
|
||||
__TriggerInterrupt(PSP_INTR_IMMEDIATE | PSP_INTR_ONLY_IF_ENABLED | PSP_INTR_ALWAYS_RESCHED, PSP_VBLANK_INTR, PSP_INTR_SUB_ALL);
|
||||
|
||||
CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount+1);
|
||||
CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount + 1);
|
||||
|
||||
// TODO: Should this be done here or in hleLeaveVblank?
|
||||
if (framebufIsLatched) {
|
||||
|
@ -233,65 +361,11 @@ void hleEnterVblank(u64 userdata, int cyclesLate) {
|
|||
gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.pspFramebufLinesize, framebuf.pspFramebufFormat);
|
||||
}
|
||||
|
||||
// Draw screen overlays before blitting. Saves and restores the Ge context.
|
||||
gpuStats.numFrames++;
|
||||
|
||||
// Now we can subvert the Ge engine in order to draw custom overlays like stat counters etc.
|
||||
if (g_Config.bShowDebugStats && gpuStats.numDrawCalls) {
|
||||
gpu->UpdateStats();
|
||||
char stats[2048];
|
||||
|
||||
sprintf(stats,
|
||||
"Frames: %i\n"
|
||||
"DL processing time: %0.2f ms\n"
|
||||
"Kernel processing time: %0.2f ms\n"
|
||||
"Slowest syscall: %s : %0.2f ms\n"
|
||||
"Most active syscall: %s : %0.2f ms\n"
|
||||
"Draw calls: %i, flushes %i\n"
|
||||
"Cached Draw calls: %i\n"
|
||||
"Num Tracked Vertex Arrays: %i\n"
|
||||
"Vertices Submitted: %i\n"
|
||||
"Cached Vertices Drawn: %i\n"
|
||||
"Uncached Vertices Drawn: %i\n"
|
||||
"FBOs active: %i\n"
|
||||
"Textures active: %i, decoded: %i\n"
|
||||
"Texture invalidations: %i\n"
|
||||
"Vertex shaders loaded: %i\n"
|
||||
"Fragment shaders loaded: %i\n"
|
||||
"Combined shaders loaded: %i\n",
|
||||
gpuStats.numFrames,
|
||||
gpuStats.msProcessingDisplayLists * 1000.0f,
|
||||
kernelStats.msInSyscalls * 1000.0f,
|
||||
kernelStats.slowestSyscallName ? kernelStats.slowestSyscallName : "(none)",
|
||||
kernelStats.slowestSyscallTime * 1000.0f,
|
||||
kernelStats.summedSlowestSyscallName ? kernelStats.summedSlowestSyscallName : "(none)",
|
||||
kernelStats.summedSlowestSyscallTime * 1000.0f,
|
||||
gpuStats.numDrawCalls,
|
||||
gpuStats.numFlushes,
|
||||
gpuStats.numCachedDrawCalls,
|
||||
gpuStats.numTrackedVertexArrays,
|
||||
gpuStats.numVertsSubmitted,
|
||||
gpuStats.numCachedVertsDrawn,
|
||||
gpuStats.numUncachedVertsDrawn,
|
||||
gpuStats.numFBOs,
|
||||
gpuStats.numTextures,
|
||||
gpuStats.numTexturesDecoded,
|
||||
gpuStats.numTextureInvalidations,
|
||||
gpuStats.numVertexShaders,
|
||||
gpuStats.numFragmentShaders,
|
||||
gpuStats.numShaders
|
||||
);
|
||||
|
||||
float zoom = 0.3f; /// g_Config.iWindowZoom;
|
||||
float soff = 0.3f;
|
||||
PPGeBegin();
|
||||
PPGeDrawText(stats, soff, soff, 0, zoom, 0xCC000000);
|
||||
PPGeDrawText(stats, -soff, -soff, 0, zoom, 0xCC000000);
|
||||
PPGeDrawText(stats, 0, 0, 0, zoom, 0xFFFFFFFF);
|
||||
PPGeEnd();
|
||||
|
||||
gpuStats.resetFrame();
|
||||
kernelStats.ResetFrame();
|
||||
DebugStats();
|
||||
}
|
||||
|
||||
if (g_Config.bShowFPSCounter) {
|
||||
|
@ -313,41 +387,42 @@ void hleEnterVblank(u64 userdata, int cyclesLate) {
|
|||
PPGeEnd();
|
||||
}
|
||||
|
||||
// Draw screen overlays before blitting. Saves and restores the Ge context.
|
||||
// Yeah, this has to be the right moment to end the frame. Give the graphics backend opportunity
|
||||
// to blit the framebuffer, in order to support half-framerate games that otherwise wouldn't have
|
||||
// anything to draw here.
|
||||
gpu->CopyDisplayToOutput();
|
||||
gstate_c.skipDrawReason &= ~SKIPDRAW_SKIPFRAME;
|
||||
|
||||
host->EndFrame();
|
||||
bool throttle, skipFrame, skipFlip;
|
||||
|
||||
DoFrameTiming(throttle, skipFrame, skipFlip);
|
||||
|
||||
#ifdef _WIN32
|
||||
// Best place to throttle the frame rate on non vsynced platforms is probably here. Let's try it.
|
||||
time_update();
|
||||
if (lastFrameTime == 0.0)
|
||||
lastFrameTime = time_now_d();
|
||||
if (!GetAsyncKeyState(VK_TAB) && !PSP_CoreParameter().headLess) {
|
||||
while (time_now_d() < lastFrameTime + 1.0 / 60.0) {
|
||||
Common::SleepCurrentThread(1);
|
||||
time_update();
|
||||
}
|
||||
// Advance lastFrameTime by a constant amount each frame,
|
||||
// but don't let it get too far behind.
|
||||
lastFrameTime = std::max(lastFrameTime + 1.0 / 60.0, time_now_d() - 1.5 / 60.0);
|
||||
// Setting CORE_NEXTFRAME causes a swap.
|
||||
if (skipFrame) {
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_SKIPFRAME;
|
||||
numSkippedFrames++;
|
||||
} else {
|
||||
numSkippedFrames = 0;
|
||||
}
|
||||
|
||||
// We are going to have to do something about audio timing for platforms that
|
||||
// are vsynced to something that's not exactly 60fps..
|
||||
if (!skipFlip) {
|
||||
coreState = CORE_NEXTFRAME;
|
||||
CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0);
|
||||
|
||||
#endif
|
||||
gpu->CopyDisplayToOutput();
|
||||
}
|
||||
|
||||
// Returning here with coreState == CORE_NEXTFRAME causes a buffer flip to happen (next frame).
|
||||
// Right after, we regain control for a little bit in hleAfterFlip. I think that's a great
|
||||
// place to do housekeeping.
|
||||
}
|
||||
|
||||
void hleAfterFlip(u64 userdata, int cyclesLate)
|
||||
{
|
||||
// This checks input on PC. Fine to do even if not calling BeginFrame.
|
||||
host->BeginFrame();
|
||||
gpu->BeginFrame();
|
||||
|
||||
// Tell the emu core that it's time to stop emulating
|
||||
// Win32 doesn't need this.
|
||||
#ifndef _WIN32
|
||||
coreState = CORE_NEXTFRAME;
|
||||
#endif
|
||||
gpu->BeginFrame(); // doesn't really matter if begin or end of frame.
|
||||
}
|
||||
|
||||
void hleLeaveVblank(u64 userdata, int cyclesLate) {
|
||||
|
|
|
@ -237,10 +237,10 @@ u32 sceGeSetCallback(u32 structAddr)
|
|||
DEBUG_LOG(HLE, "sceGeSetCallback(struct=%08x)", structAddr);
|
||||
|
||||
int cbID = -1;
|
||||
for (int i = 0; i < ARRAY_SIZE(ge_used_callbacks); ++i)
|
||||
for (size_t i = 0; i < ARRAY_SIZE(ge_used_callbacks); ++i)
|
||||
if (!ge_used_callbacks[i])
|
||||
{
|
||||
cbID = i;
|
||||
cbID = (int) i;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ void __InterruptsInit()
|
|||
{
|
||||
interruptsEnabled = 1;
|
||||
inInterrupt = false;
|
||||
for(int i = 0; i < ARRAY_SIZE(intrHandlers); ++i)
|
||||
for (size_t i = 0; i < ARRAY_SIZE(intrHandlers); ++i)
|
||||
intrHandlers[i] = new IntrHandler(i);
|
||||
intState.clear();
|
||||
}
|
||||
|
@ -246,11 +246,11 @@ void __InterruptsDoStateLate(PointerWrap &p)
|
|||
|
||||
void __InterruptsShutdown()
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(intrHandlers); ++i)
|
||||
for (size_t i = 0; i < ARRAY_SIZE(intrHandlers); ++i)
|
||||
intrHandlers[i]->clear();
|
||||
for(int i = 0; i < ARRAY_SIZE(intrHandlers); ++i)
|
||||
for (size_t i = 0; i < ARRAY_SIZE(intrHandlers); ++i)
|
||||
{
|
||||
if(intrHandlers[i])
|
||||
if (intrHandlers[i])
|
||||
{
|
||||
delete intrHandlers[i];
|
||||
intrHandlers[i] = 0;
|
||||
|
|
|
@ -2805,7 +2805,10 @@ std::vector<DebugThreadInfo> GetThreadsInfo()
|
|||
info.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0;
|
||||
info.status = t->nt.status;
|
||||
info.entrypoint = t->nt.entrypoint;
|
||||
info.curPC = t->context.pc;
|
||||
if(*iter == currentThread)
|
||||
info.curPC = currentMIPS->pc;
|
||||
else
|
||||
info.curPC = t->context.pc;
|
||||
info.isCurrent = (*iter == currentThread);
|
||||
threadList.push_back(info);
|
||||
}
|
||||
|
|
|
@ -61,55 +61,57 @@ void __SasShutdown() {
|
|||
}
|
||||
|
||||
|
||||
u32 sceSasInit(u32 core, u32 grainSize, u32 maxVoices, u32 outputMode, u32 sampleRate)
|
||||
{
|
||||
u32 sceSasInit(u32 core, u32 grainSize, u32 maxVoices, u32 outputMode, u32 sampleRate) {
|
||||
INFO_LOG(HLE,"sceSasInit(%08x, %i, %i, %i, %i)", core, grainSize, maxVoices, outputMode, sampleRate);
|
||||
|
||||
sas->SetGrainSize(grainSize);
|
||||
sas->maxVoices = maxVoices;
|
||||
sas->outputMode = outputMode;
|
||||
for (int i = 0; i < sas->maxVoices; i++) {
|
||||
sas->voices[i].sampleRate = sampleRate;
|
||||
sas->voices[i].playing = false;
|
||||
sas->voices[i].loop = true; // inverted flag
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasGetEndFlag(u32 core)
|
||||
{
|
||||
u32 sceSasGetEndFlag(u32 core) {
|
||||
u32 endFlag = 0;
|
||||
for (int i = 0; i < sas->maxVoices; i++) {
|
||||
if (!sas->voices[i].playing)
|
||||
endFlag |= (1 << i);
|
||||
}
|
||||
|
||||
DEBUG_LOG(HLE,"sceSasGetEndFlag(%08x)", endFlag);
|
||||
return endFlag;
|
||||
}
|
||||
|
||||
// Runs the mixer
|
||||
u32 _sceSasCore(u32 core, u32 outAddr)
|
||||
{
|
||||
u32 _sceSasCore(u32 core, u32 outAddr) {
|
||||
DEBUG_LOG(HLE,"sceSasCore(%08x, %08x)", core, outAddr);
|
||||
|
||||
if (!Memory::IsValidAddress(outAddr)) {
|
||||
return ERROR_SAS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Memory::Memset(outAddr, 0, sas->GetGrainSize() * 2 * 2);
|
||||
sas->Mix(outAddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Another way of running the mixer, what was the difference again?
|
||||
u32 _sceSasCoreWithMix(u32 core, u32 outAddr, int leftVolume, int rightVolume)
|
||||
{
|
||||
u32 _sceSasCoreWithMix(u32 core, u32 outAddr, int leftVolume, int rightVolume) {
|
||||
DEBUG_LOG(HLE,"sceSasCoreWithMix(%08x, %08x, %i, %i)", core , outAddr, leftVolume, rightVolume);
|
||||
|
||||
if (!Memory::IsValidAddress(outAddr)) {
|
||||
return ERROR_SAS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
sas->Mix(outAddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loop)
|
||||
{
|
||||
u32 sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loop) {
|
||||
DEBUG_LOG(HLE,"sceSasSetVoice(%08x, %i, %08x, %i, %i)", core, voiceNum, vagAddr, size, loop);
|
||||
|
||||
if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) {
|
||||
|
@ -167,8 +169,7 @@ u32 sceSasSetVoicePCM(u32 core, int voiceNum, u32 pcmAddr, int size, int loop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasGetPauseFlag(u32 core)
|
||||
{
|
||||
u32 sceSasGetPauseFlag(u32 core) {
|
||||
u32 pauseFlag = 0;
|
||||
for (int i = 0; i < sas->maxVoices; i++) {
|
||||
if (sas->voices[i].paused)
|
||||
|
@ -179,24 +180,21 @@ u32 sceSasGetPauseFlag(u32 core)
|
|||
return pauseFlag;
|
||||
}
|
||||
|
||||
u32 sceSasSetPause(u32 core, int voicebit, int pause)
|
||||
{
|
||||
u32 sceSasSetPause(u32 core, int voicebit, int pause) {
|
||||
DEBUG_LOG(HLE,"sceSasSetPause(%08x, %08x, %i)", core, voicebit, pause);
|
||||
|
||||
for (int i = 0; voicebit != 0; i++, voicebit >>= 1) {
|
||||
if (i < PSP_SAS_VOICES_MAX && i >= 0) {
|
||||
if ((voicebit & 1) != 0)
|
||||
sas->voices[i].paused = pause ? true : false;
|
||||
}
|
||||
// TODO: Correct error code? Mimana crashes otherwise.
|
||||
else
|
||||
} else // TODO: Correct error code? Mimana crashes otherwise.
|
||||
return ERROR_SAS_INVALID_VOICE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasSetVolume(u32 core, int voiceNum, int leftVol, int rightVol, int effectLeftVol, int effectRightVol)
|
||||
{
|
||||
u32 sceSasSetVolume(u32 core, int voiceNum, int leftVol, int rightVol, int effectLeftVol, int effectRightVol) {
|
||||
DEBUG_LOG(HLE,"sceSasSetVolume(%08x, %i, %i, %i, %i, %i)", core, voiceNum, leftVol, rightVol, effectLeftVol, effectRightVol);
|
||||
|
||||
if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) {
|
||||
|
@ -212,8 +210,7 @@ u32 sceSasSetVolume(u32 core, int voiceNum, int leftVol, int rightVol, int effec
|
|||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasSetPitch(u32 core, int voiceNum, int pitch)
|
||||
{
|
||||
u32 sceSasSetPitch(u32 core, int voiceNum, int pitch) {
|
||||
DEBUG_LOG(HLE,"sceSasSetPitch(%08x, %i, %i)", core, voiceNum, pitch);
|
||||
|
||||
if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) {
|
||||
|
@ -227,8 +224,7 @@ u32 sceSasSetPitch(u32 core, int voiceNum, int pitch)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasSetKeyOn(u32 core, int voiceNum)
|
||||
{
|
||||
u32 sceSasSetKeyOn(u32 core, int voiceNum) {
|
||||
DEBUG_LOG(HLE,"sceSasSetKeyOn(%08x, %i)", core, voiceNum);
|
||||
|
||||
if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) {
|
||||
|
@ -236,39 +232,38 @@ u32 sceSasSetKeyOn(u32 core, int voiceNum)
|
|||
return ERROR_SAS_INVALID_VOICE;
|
||||
}
|
||||
|
||||
SasVoice &v = sas->voices[voiceNum];
|
||||
if (sas->voices[voiceNum].paused) {
|
||||
return ERROR_SAS_VOICE_PAUSED;
|
||||
}
|
||||
|
||||
SasVoice &v = sas->voices[voiceNum];
|
||||
v.KeyOn();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// sceSasSetKeyOff can be used to start sounds, that just sound during the Release phase!
|
||||
u32 sceSasSetKeyOff(u32 core, int voiceNum)
|
||||
{
|
||||
u32 sceSasSetKeyOff(u32 core, int voiceNum) {
|
||||
if (voiceNum == -1) {
|
||||
// TODO: Some games (like Every Extend Extra) deliberately pass voiceNum = -1. Does that mean all voices? for now let's ignore.
|
||||
DEBUG_LOG(HLE,"sceSasSetKeyOff(%08x, %i) - voiceNum = -1???", core, voiceNum);
|
||||
return 0;
|
||||
} else if (voiceNum < 0 || voiceNum >= PSP_SAS_VOICES_MAX) {
|
||||
} else if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) {
|
||||
WARN_LOG(HLE, "%s: invalid voicenum %d", __FUNCTION__, voiceNum);
|
||||
return ERROR_SAS_INVALID_VOICE;
|
||||
} else {
|
||||
DEBUG_LOG(HLE,"sceSasSetKeyOff(%08x, %i)", core, voiceNum);
|
||||
SasVoice &v = sas->voices[voiceNum];
|
||||
|
||||
if (sas->voices[voiceNum].paused) {
|
||||
return ERROR_SAS_VOICE_PAUSED;
|
||||
}
|
||||
|
||||
SasVoice &v = sas->voices[voiceNum];
|
||||
v.KeyOff();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 sceSasSetNoise(u32 core, int voiceNum, int freq)
|
||||
{
|
||||
u32 sceSasSetNoise(u32 core, int voiceNum, int freq) {
|
||||
DEBUG_LOG(HLE,"sceSasSetNoise(%08x, %i, %i)", core, voiceNum, freq);
|
||||
|
||||
if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) {
|
||||
|
@ -283,8 +278,7 @@ u32 sceSasSetNoise(u32 core, int voiceNum, int freq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasSetSL(u32 core, int voiceNum, int level)
|
||||
{
|
||||
u32 sceSasSetSL(u32 core, int voiceNum, int level) {
|
||||
DEBUG_LOG(HLE,"sceSasSetSL(%08x, %i, %i)", core, voiceNum, level);
|
||||
|
||||
if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) {
|
||||
|
@ -297,8 +291,7 @@ u32 sceSasSetSL(u32 core, int voiceNum, int level)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasSetADSR(u32 core, int voiceNum, int flag , int a, int d, int s, int r)
|
||||
{
|
||||
u32 sceSasSetADSR(u32 core, int voiceNum, int flag , int a, int d, int s, int r) {
|
||||
DEBUG_LOG(HLE,"0=sceSasSetADSR(%08x, %i, %i, %08x, %08x, %08x, %08x)",core, voiceNum, flag, a, d, s, r)
|
||||
|
||||
if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) {
|
||||
|
@ -314,8 +307,7 @@ u32 sceSasSetADSR(u32 core, int voiceNum, int flag , int a, int d, int s, int r)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasSetADSRMode(u32 core, int voiceNum,int flag ,int a, int d, int s, int r)
|
||||
{
|
||||
u32 sceSasSetADSRMode(u32 core, int voiceNum,int flag ,int a, int d, int s, int r) {
|
||||
DEBUG_LOG(HLE,"sceSasSetADSRMode(%08x, %i, %i, %08x, %08x, %08x, %08x)",core, voiceNum, flag, a,d,s,r)
|
||||
|
||||
if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) {
|
||||
|
@ -332,21 +324,23 @@ u32 sceSasSetADSRMode(u32 core, int voiceNum,int flag ,int a, int d, int s, int
|
|||
}
|
||||
|
||||
|
||||
u32 sceSasSetSimpleADSR(u32 core, u32 voiceNum, u32 ADSREnv1, u32 ADSREnv2)
|
||||
{
|
||||
u32 sceSasSetSimpleADSR(u32 core, int voiceNum, u32 ADSREnv1, u32 ADSREnv2) {
|
||||
DEBUG_LOG(HLE,"sasSetSimpleADSR(%08x, %i, %08x, %08x)", core, voiceNum, ADSREnv1, ADSREnv2);
|
||||
|
||||
if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) {
|
||||
WARN_LOG(HLE, "%s: invalid voicenum %d", __FUNCTION__, voiceNum);
|
||||
return ERROR_SAS_INVALID_VOICE;
|
||||
}
|
||||
|
||||
SasVoice &v = sas->voices[voiceNum];
|
||||
v.envelope.SetSimpleEnvelope(ADSREnv1 & 0xFFFF, ADSREnv2 & 0xFFFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasGetEnvelopeHeight(u32 core, u32 voiceNum)
|
||||
{
|
||||
// Spam reduction
|
||||
if (voiceNum == 17) {
|
||||
DEBUG_LOG(HLE,"sceSasGetEnvelopeHeight(%08x, %i)", core, voiceNum);
|
||||
}
|
||||
if (voiceNum >= PSP_SAS_VOICES_MAX) {
|
||||
u32 sceSasGetEnvelopeHeight(u32 core, int voiceNum) {
|
||||
DEBUG_LOG(HLE,"sceSasGetEnvelopeHeight(%08x, %i)", core, voiceNum);
|
||||
|
||||
if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) {
|
||||
WARN_LOG(HLE, "%s: invalid voicenum %d", __FUNCTION__, voiceNum);
|
||||
return ERROR_SAS_INVALID_VOICE;
|
||||
}
|
||||
|
@ -355,105 +349,96 @@ u32 sceSasGetEnvelopeHeight(u32 core, u32 voiceNum)
|
|||
return v.envelope.GetHeight();
|
||||
}
|
||||
|
||||
u32 sceSasRevType(u32 core, int type)
|
||||
{
|
||||
u32 sceSasRevType(u32 core, int type) {
|
||||
DEBUG_LOG(HLE,"sceSasRevType(%08x, %i)", core, type);
|
||||
sas->waveformEffect.type = type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasRevParam(u32 core, int delay, int feedback)
|
||||
{
|
||||
u32 sceSasRevParam(u32 core, int delay, int feedback) {
|
||||
DEBUG_LOG(HLE,"sceSasRevParam(%08x, %i, %i)", core, delay, feedback);
|
||||
sas->waveformEffect.delay = delay;
|
||||
sas->waveformEffect.feedback = feedback;
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasRevEVOL(u32 core, int lv, int rv)
|
||||
{
|
||||
u32 sceSasRevEVOL(u32 core, int lv, int rv) {
|
||||
DEBUG_LOG(HLE,"sceSasRevEVOL(%08x, %i, %i)", core, lv, rv);
|
||||
sas->waveformEffect.leftVol = lv;
|
||||
sas->waveformEffect.rightVol = rv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasRevVON(u32 core, int dry, int wet)
|
||||
{
|
||||
u32 sceSasRevVON(u32 core, int dry, int wet) {
|
||||
DEBUG_LOG(HLE,"sceSasRevVON(%08x, %i, %i)", core, dry, wet);
|
||||
sas->waveformEffect.isDryOn = (dry > 0);
|
||||
sas->waveformEffect.isWetOn = (wet > 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasGetGrain(u32 core)
|
||||
{
|
||||
u32 sceSasGetGrain(u32 core) {
|
||||
DEBUG_LOG(HLE,"sceSasGetGrain(%08x)", core);
|
||||
return sas->GetGrainSize();
|
||||
}
|
||||
|
||||
u32 sceSasSetGrain(u32 core, int grain)
|
||||
{
|
||||
u32 sceSasSetGrain(u32 core, int grain) {
|
||||
INFO_LOG(HLE,"sceSasSetGrain(%08x, %i)", core, grain);
|
||||
sas->SetGrainSize(grain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasGetOutputMode(u32 core)
|
||||
{
|
||||
u32 sceSasGetOutputMode(u32 core) {
|
||||
DEBUG_LOG(HLE,"sceSasGetOutputMode(%08x)", core);
|
||||
return sas->outputMode;
|
||||
}
|
||||
|
||||
u32 sceSasSetOutputMode(u32 core, u32 outputMode)
|
||||
{
|
||||
u32 sceSasSetOutputMode(u32 core, u32 outputMode) {
|
||||
DEBUG_LOG(HLE,"sceSasSetOutputMode(%08x, %i)", core, outputMode);
|
||||
sas->outputMode = outputMode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
u32 sceSasGetAllEnvelopeHeights(u32 core, u32 heightsAddr)
|
||||
{
|
||||
u32 sceSasGetAllEnvelopeHeights(u32 core, u32 heightsAddr) {
|
||||
DEBUG_LOG(HLE,"sceSasGetAllEnvelopeHeights(%08x, %i)", core, heightsAddr);
|
||||
if (Memory::IsValidAddress(heightsAddr)) {
|
||||
for (int i = 0; i < PSP_SAS_VOICES_MAX; i++) {
|
||||
|
||||
if (!Memory::IsValidAddress(heightsAddr)) {
|
||||
return ERROR_SAS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
for (int i = 0; i < PSP_SAS_VOICES_MAX; i++) {
|
||||
int voiceHeight = sas->voices[i].envelope.GetHeight();
|
||||
Memory::Write_U32(voiceHeight, heightsAddr + i * 4);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasSetTriangularWave(u32 sasCore, int voice, int unknown)
|
||||
{
|
||||
u32 sceSasSetTriangularWave(u32 sasCore, int voice, int unknown) {
|
||||
ERROR_LOG(HLE,"UNIMPL sceSasSetTriangularWave(%08x, %i, %i)", sasCore, voice, unknown);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceSasSetSteepWave(u32 sasCore, int voice, int unknown)
|
||||
{
|
||||
u32 sceSasSetSteepWave(u32 sasCore, int voice, int unknown) {
|
||||
ERROR_LOG(HLE,"UNIMPL sceSasSetSteepWave(%08x, %i, %i)", sasCore, voice, unknown);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 __sceSasSetVoiceATRAC3(u32 core, int voice, int atrac3Context)
|
||||
{
|
||||
u32 __sceSasSetVoiceATRAC3(u32 core, int voice, int atrac3Context) {
|
||||
ERROR_LOG(HLE,"UNIMPL __sceSasSetVoiceATRAC3(%08x, %i, %i)", core, voice, atrac3Context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 __sceSasConcatenateATRAC3(u32 core, int voice, u32 atrac3DataAddr, int atrac3DataLength)
|
||||
{
|
||||
ERROR_LOG(HLE,"UNIMPL __sceSasConcatenateATRAC3(%08x, %i, %i)", core, voice, atrac3DataAddr, atrac3DataLength);
|
||||
u32 __sceSasConcatenateATRAC3(u32 core, int voice, u32 atrac3DataAddr, int atrac3DataLength) {
|
||||
ERROR_LOG(HLE,"UNIMPL __sceSasConcatenateATRAC3(%08x, %i, %08x, %i)", core, voice, atrac3DataAddr, atrac3DataLength);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 __sceSasUnsetATRAC3(u32 core, int voice)
|
||||
{
|
||||
u32 __sceSasUnsetATRAC3(u32 core, int voice) {
|
||||
ERROR_LOG(HLE, "UNIMPL __sceSasUnsetATRAC3(%08x, %i)", core, voice);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const HLEFunction sceSasCore[] =
|
||||
{
|
||||
{0x42778a9f, WrapU_UUUUU<sceSasInit>, "__sceSasInit"},
|
||||
|
@ -467,8 +452,8 @@ const HLEFunction sceSasCore[] =
|
|||
{0x019b25eb, WrapU_UIIIIII<sceSasSetADSR>, "__sceSasSetADSR"},
|
||||
{0x9ec3676a, WrapU_UIIIIII<sceSasSetADSRMode>, "__sceSasSetADSRmode"},
|
||||
{0x5f9529f6, WrapU_UII<sceSasSetSL>, "__sceSasSetSL"},
|
||||
{0x74ae582a, WrapU_UU<sceSasGetEnvelopeHeight>, "__sceSasGetEnvelopeHeight"},
|
||||
{0xcbcd4f79, WrapU_UUUU<sceSasSetSimpleADSR>, "__sceSasSetSimpleADSR"},
|
||||
{0x74ae582a, WrapU_UI<sceSasGetEnvelopeHeight>, "__sceSasGetEnvelopeHeight"},
|
||||
{0xcbcd4f79, WrapU_UIUU<sceSasSetSimpleADSR>, "__sceSasSetSimpleADSR"},
|
||||
{0xa0cf2fa4, WrapU_UI<sceSasSetKeyOff>, "__sceSasSetKeyOff"},
|
||||
{0x76f01aca, WrapU_UI<sceSasSetKeyOn>, "__sceSasSetKeyOn"},
|
||||
{0xf983b186, WrapU_UII<sceSasRevVON>, "__sceSasRevVON"},
|
||||
|
|
|
@ -548,9 +548,10 @@ static int getExpCurveAt(int index, int duration) {
|
|||
}
|
||||
|
||||
ADSREnvelope::ADSREnvelope()
|
||||
: steps_(0),
|
||||
state_(STATE_OFF),
|
||||
: state_(STATE_OFF),
|
||||
steps_(0),
|
||||
height_(0) {
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
|
||||
void ADSREnvelope::WalkCurve(int rate, int type) {
|
||||
|
|
|
@ -157,7 +157,9 @@ private:
|
|||
struct SasVoice
|
||||
{
|
||||
SasVoice()
|
||||
: playing(false), paused(false), on(false),
|
||||
: playing(false),
|
||||
paused(false),
|
||||
on(false),
|
||||
type(VOICETYPE_OFF),
|
||||
vagAddr(0),
|
||||
vagSize(0),
|
||||
|
@ -171,7 +173,10 @@ struct SasVoice
|
|||
volumeLeft(0),
|
||||
volumeRight(0),
|
||||
volumeLeftSend(0),
|
||||
volumeRightSend(0) {
|
||||
volumeRightSend(0),
|
||||
effectLeft(0),
|
||||
effectRight(0) {
|
||||
memset(resampleHist, 0, sizeof(resampleHist));
|
||||
}
|
||||
|
||||
void Reset();
|
||||
|
|
|
@ -46,7 +46,6 @@ public:
|
|||
|
||||
virtual void InitGL() = 0;
|
||||
virtual void BeginFrame() {}
|
||||
virtual void EndFrame() {}
|
||||
virtual void ShutdownGL() = 0;
|
||||
|
||||
virtual void InitSound(PMixer *mixer) = 0;
|
||||
|
@ -64,8 +63,9 @@ public:
|
|||
virtual void SendCoreWait(bool) {}
|
||||
|
||||
virtual bool GpuStep() { return false; }
|
||||
virtual void SendGPUWait() {}
|
||||
virtual void SetGPUStep(bool value) {}
|
||||
virtual void SendGPUStart() {}
|
||||
virtual void SendGPUWait(u32 cmd, u32 addr, void* data) {}
|
||||
virtual void SetGPUStep(bool value, int flag = 0, int data = 0) {}
|
||||
virtual void NextGPUStep() {}
|
||||
|
||||
// Used for headless.
|
||||
|
|
|
@ -113,11 +113,7 @@ void Jit::GenerateFixedCode()
|
|||
// * downcount
|
||||
// * R2-R4
|
||||
// Really starting to run low on registers already though...
|
||||
#ifdef UNUSABLE_MMAP
|
||||
MOVI2R(R11, (u32)Memory::m_pRAM - 0x08000000);
|
||||
#else
|
||||
MOVI2R(R11, (u32)Memory::base);
|
||||
#endif
|
||||
MOVI2R(R10, (u32)mips_);
|
||||
MOVI2R(R9, (u32)GetBlockCache()->GetCodePointers());
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "../../Core.h"
|
||||
#include "../../CoreTiming.h"
|
||||
#include "../MIPS.h"
|
||||
|
@ -63,6 +64,11 @@ Jit::Jit(MIPSState *mips) : blocks(mips), gpr(mips), fpr(mips), mips_(mips)
|
|||
GenerateFixedCode();
|
||||
}
|
||||
|
||||
void Jit::DoState(PointerWrap &p)
|
||||
{
|
||||
p.DoMarker("Jit");
|
||||
}
|
||||
|
||||
void Jit::FlushAll()
|
||||
{
|
||||
gpr.FlushAll();
|
||||
|
|
|
@ -113,6 +113,7 @@ class Jit : public ArmGen::ARMXCodeBlock
|
|||
{
|
||||
public:
|
||||
Jit(MIPSState *mips);
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
// Compiled ops should ignore delay slots
|
||||
// the compiler will take care of them by itself
|
||||
|
@ -168,6 +169,9 @@ public:
|
|||
void ClearCache();
|
||||
void ClearCacheAt(u32 em_address);
|
||||
|
||||
// TODO: Eat VFPU prefixes here.
|
||||
void EatPrefix() { }
|
||||
|
||||
private:
|
||||
void GenerateFixedCode();
|
||||
void FlushAll();
|
||||
|
|
|
@ -45,8 +45,11 @@ MIPSState::MIPSState()
|
|||
|
||||
MIPSState::~MIPSState()
|
||||
{
|
||||
delete MIPSComp::jit;
|
||||
MIPSComp::jit = 0;
|
||||
if (MIPSComp::jit)
|
||||
{
|
||||
delete MIPSComp::jit;
|
||||
MIPSComp::jit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MIPSState::Reset()
|
||||
|
@ -107,6 +110,8 @@ void MIPSState::DoState(PointerWrap &p)
|
|||
// Reset the jit if we're loading.
|
||||
if (p.mode == p.MODE_READ)
|
||||
Reset();
|
||||
if (MIPSComp::jit)
|
||||
MIPSComp::jit->DoState(p);
|
||||
|
||||
p.DoArray(r, sizeof(r) / sizeof(r[0]));
|
||||
p.DoArray(f, sizeof(f) / sizeof(f[0]));
|
||||
|
@ -143,11 +148,7 @@ int MIPSState::RunLoopUntil(u64 globalTicks)
|
|||
MIPSComp::jit->RunLoopUntil(globalTicks);
|
||||
break;
|
||||
|
||||
case CPU_FASTINTERPRETER: // For jit-less platforms. Crashier than INTERPRETER.
|
||||
return MIPSInterpret_RunFastUntil(globalTicks);
|
||||
|
||||
case CPU_INTERPRETER:
|
||||
// INFO_LOG(CPU, "Entering run loop for %i ticks, pc=%08x", (int)globalTicks, mipsr4k.pc);
|
||||
return MIPSInterpret_RunUntil(globalTicks);
|
||||
}
|
||||
return 1;
|
||||
|
|
|
@ -98,7 +98,7 @@ namespace MIPSAnalyst
|
|||
"slt", "sltu",
|
||||
};
|
||||
const char *opName = MIPSGetName(op);
|
||||
for (int i = 0; i < ARRAY_SIZE(safeOps); ++i)
|
||||
for (size_t i = 0; i < ARRAY_SIZE(safeOps); ++i)
|
||||
{
|
||||
if (!strcmp(safeOps[i], opName))
|
||||
return true;
|
||||
|
|
|
@ -110,6 +110,14 @@ void ApplyPrefixST(float *v, u32 data, VectorSize size)
|
|||
|
||||
if (!constants)
|
||||
{
|
||||
// Prefix may say "z, z, z, z" but if this is a pair, we force to x.
|
||||
// TODO: But some ops seem to use const 0 instead?
|
||||
if (regnum >= n)
|
||||
{
|
||||
ERROR_LOG(CPU, "Invalid VFPU swizzle: %08x / %d", data, size);
|
||||
regnum = 0;
|
||||
}
|
||||
|
||||
v[i] = origV[regnum];
|
||||
if (abs)
|
||||
v[i] = fabs(v[i]);
|
||||
|
@ -137,26 +145,22 @@ inline void ApplySwizzleT(float *v, VectorSize size)
|
|||
void ApplyPrefixD(float *v, VectorSize size, bool onlyWriteMask = false)
|
||||
{
|
||||
u32 data = currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX];
|
||||
if (!data)
|
||||
if (!data || onlyWriteMask)
|
||||
return;
|
||||
int n = GetNumVectorElements(size);
|
||||
bool writeMask[4];
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
int mask = (data >> (8 + i)) & 1;
|
||||
writeMask[i] = mask ? true : false;
|
||||
if (!onlyWriteMask) {
|
||||
int sat = (data >> (i * 2)) & 3;
|
||||
if (sat == 1)
|
||||
{
|
||||
if (v[i] > 1.0f) v[i] = 1.0f;
|
||||
if (v[i] < 0.0f) v[i] = 0.0f;
|
||||
}
|
||||
else if (sat == 3)
|
||||
{
|
||||
if (v[i] > 1.0f) v[i] = 1.0f;
|
||||
if (v[i] < -1.0f) v[i] = -1.0f;
|
||||
}
|
||||
int sat = (data >> (i * 2)) & 3;
|
||||
if (sat == 1)
|
||||
{
|
||||
if (v[i] > 1.0f) v[i] = 1.0f;
|
||||
// This includes -0.0f -> +0.0f.
|
||||
if (v[i] <= 0.0f) v[i] = 0.0f;
|
||||
}
|
||||
else if (sat == 3)
|
||||
{
|
||||
if (v[i] > 1.0f) v[i] = 1.0f;
|
||||
if (v[i] < -1.0f) v[i] = -1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -718,7 +722,7 @@ namespace MIPSInt
|
|||
void Int_Vx2i(u32 op)
|
||||
{
|
||||
int s[4];
|
||||
u32 d[4] = {0};
|
||||
u32 d[4] = {0};
|
||||
int vd = _VD;
|
||||
int vs = _VS;
|
||||
VectorSize sz = GetVecSize(op);
|
||||
|
@ -852,7 +856,7 @@ namespace MIPSInt
|
|||
_dbg_assert_msg_(CPU,0,"Trying to interpret instruction that can't be interpreted");
|
||||
break;
|
||||
}
|
||||
ApplyPrefixD((float*)d,oz,true);
|
||||
ApplyPrefixD((float*)d,oz);
|
||||
WriteVector((float*)d,oz,vd);
|
||||
PC += 4;
|
||||
EatPrefixes();
|
||||
|
@ -927,7 +931,7 @@ namespace MIPSInt
|
|||
}
|
||||
d = sum;
|
||||
ApplyPrefixD(&d,V_Single);
|
||||
V(vd) = d;
|
||||
WriteVector(&d, V_Single, vd);
|
||||
PC += 4;
|
||||
EatPrefixes();
|
||||
}
|
||||
|
@ -1179,6 +1183,11 @@ namespace MIPSInt
|
|||
ReadVector(s, sz, vs);
|
||||
ApplySwizzleS(s, sz);
|
||||
float scale = V(vt);
|
||||
if (currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX] != 0xE4)
|
||||
{
|
||||
// WARN_LOG(CPU, "Broken T prefix used with VScl: %08x / %08x", currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX], op);
|
||||
ApplySwizzleT(&scale, V_Single);
|
||||
}
|
||||
int n = GetNumVectorElements(sz);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
|
@ -1196,6 +1205,7 @@ namespace MIPSInt
|
|||
int seed = VI(vd);
|
||||
currentMIPS->rng.Init(seed);
|
||||
PC += 4;
|
||||
EatPrefixes();
|
||||
}
|
||||
|
||||
void Int_VrndX(u32 op)
|
||||
|
|
|
@ -147,22 +147,22 @@ const MIPSInstruction tableImmediate[64] = //xxxxxx .....
|
|||
//48
|
||||
INSTR("ll", &Jit::Comp_Generic, Dis_Generic, Int_StoreSync, 0),
|
||||
INSTR("lwc1", &Jit::Comp_FPULS, Dis_FPULS, Int_FPULS, IN_RT|IN_RS_ADDR),
|
||||
INSTR("lv.s", &Jit::Comp_SV, Dis_SV, Int_SV, IS_VFPU),
|
||||
INSTR("lv.s", &Jit::Comp_SV, Dis_SV, Int_SV, IS_VFPU|VFPU_NO_PREFIX),
|
||||
{-2}, // HIT THIS IN WIPEOUT
|
||||
{VFPU4Jump},
|
||||
INSTR("lv", &Jit::Comp_SVQ, Dis_SVLRQ, Int_SVQ, IS_VFPU),
|
||||
INSTR("lv.q", &Jit::Comp_SVQ, Dis_SVQ, Int_SVQ, IS_VFPU), //copU
|
||||
INSTR("lv", &Jit::Comp_SVQ, Dis_SVLRQ, Int_SVQ, IS_VFPU|VFPU_NO_PREFIX),
|
||||
INSTR("lv.q", &Jit::Comp_SVQ, Dis_SVQ, Int_SVQ, IS_VFPU|VFPU_NO_PREFIX), //copU
|
||||
{VFPU5},
|
||||
//56
|
||||
INSTR("sc", &Jit::Comp_Generic, Dis_Generic, Int_StoreSync, 0),
|
||||
INSTR("swc1", &Jit::Comp_FPULS, Dis_FPULS, Int_FPULS, 0), //copU
|
||||
INSTR("sv.s", &Jit::Comp_SV, Dis_SV, Int_SV,IS_VFPU),
|
||||
INSTR("sv.s", &Jit::Comp_SV, Dis_SV, Int_SV,IS_VFPU|VFPU_NO_PREFIX),
|
||||
{-2},
|
||||
//60
|
||||
{VFPU6},
|
||||
INSTR("sv", &Jit::Comp_SVQ, Dis_SVLRQ, Int_SVQ, IS_VFPU), //copU
|
||||
INSTR("sv.q", &Jit::Comp_SVQ, Dis_SVQ, Int_SVQ, IS_VFPU),
|
||||
INSTR("vflush", &Jit::Comp_Generic, Dis_Vflush, Int_Vflush, IS_VFPU),
|
||||
INSTR("sv", &Jit::Comp_SVQ, Dis_SVLRQ, Int_SVQ, IS_VFPU|VFPU_NO_PREFIX), //copU
|
||||
INSTR("sv.q", &Jit::Comp_SVQ, Dis_SVQ, Int_SVQ, IS_VFPU|VFPU_NO_PREFIX),
|
||||
INSTR("vflush", &Jit::Comp_Generic, Dis_Vflush, Int_Vflush, IS_VFPU|VFPU_NO_PREFIX),
|
||||
};
|
||||
|
||||
const MIPSInstruction tableSpecial[64] = /// 000000 ...... ...... .......... xxxxxx
|
||||
|
@ -478,19 +478,19 @@ const MIPSInstruction tableCop1BC[32] =
|
|||
|
||||
const MIPSInstruction tableVFPU0[8] =
|
||||
{
|
||||
INSTR("vadd",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU),
|
||||
INSTR("vsub",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU),
|
||||
INSTR("vadd",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsub",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsbn",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vsbn, IS_VFPU),
|
||||
{-2}, {-2}, {-2}, {-2},
|
||||
|
||||
INSTR("vdiv",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU),
|
||||
INSTR("vdiv",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU|OUT_EAT_PREFIX),
|
||||
};
|
||||
|
||||
const MIPSInstruction tableVFPU1[8] =
|
||||
{
|
||||
INSTR("vmul",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU),
|
||||
INSTR("vdot",&Jit::Comp_VDot, Dis_VectorDot, Int_VDot, IS_VFPU),
|
||||
INSTR("vscl",&Jit::Comp_Generic, Dis_VScl, Int_VScl, IS_VFPU),
|
||||
INSTR("vmul",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vdot",&Jit::Comp_VDot, Dis_VectorDot, Int_VDot, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vscl",&Jit::Comp_Generic, Dis_VScl, Int_VScl, IS_VFPU|OUT_EAT_PREFIX),
|
||||
{-2},
|
||||
INSTR("vhdp",&Jit::Comp_Generic, Dis_Generic, Int_VHdp, IS_VFPU),
|
||||
INSTR("vcrs",&Jit::Comp_Generic, Dis_Vcrs, Int_Vcrs, IS_VFPU),
|
||||
|
@ -500,14 +500,14 @@ const MIPSInstruction tableVFPU1[8] =
|
|||
|
||||
const MIPSInstruction tableVFPU3[8] = //011011 xxx
|
||||
{
|
||||
INSTR("vcmp",&Jit::Comp_Generic, Dis_Vcmp, Int_Vcmp, IS_VFPU),
|
||||
INSTR("vcmp",&Jit::Comp_Generic, Dis_Vcmp, Int_Vcmp, IS_VFPU|OUT_EAT_PREFIX),
|
||||
{-2},
|
||||
INSTR("vmin",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU),
|
||||
INSTR("vmax",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU),
|
||||
INSTR("vmin",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vmax",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU|OUT_EAT_PREFIX),
|
||||
{-2},
|
||||
INSTR("vscmp",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vscmp, IS_VFPU),
|
||||
INSTR("vsge",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vsge, IS_VFPU),
|
||||
INSTR("vslt",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vslt, IS_VFPU),
|
||||
INSTR("vscmp",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vscmp, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsge",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vsge, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vslt",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vslt, IS_VFPU|OUT_EAT_PREFIX),
|
||||
};
|
||||
|
||||
|
||||
|
@ -516,7 +516,7 @@ const MIPSInstruction tableVFPU4Jump[32] = //110100 xxxxx
|
|||
{VFPU4},
|
||||
{VFPU7},
|
||||
{VFPU9},
|
||||
INSTR("vcst", &Jit::Comp_Generic, Dis_Vcst, Int_Vcst, IS_VFPU),
|
||||
INSTR("vcst", &Jit::Comp_Generic, Dis_Vcst, Int_Vcst, IS_VFPU|OUT_EAT_PREFIX),
|
||||
{-2},{-2},{-2},{-2},
|
||||
|
||||
//8
|
||||
|
@ -524,13 +524,13 @@ const MIPSInstruction tableVFPU4Jump[32] = //110100 xxxxx
|
|||
{-2},{-2},{-2},{-2},
|
||||
|
||||
//16
|
||||
INSTR("vf2in", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU),
|
||||
INSTR("vf2iz", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU),
|
||||
INSTR("vf2iu", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU),
|
||||
INSTR("vf2id", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU),
|
||||
INSTR("vf2in", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vf2iz", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vf2iu", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vf2id", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU|OUT_EAT_PREFIX),
|
||||
//20
|
||||
INSTR("vi2f", &Jit::Comp_Generic, Dis_Vf2i, Int_Vi2f, IS_VFPU),
|
||||
INSTR("vcmov", &Jit::Comp_Generic, Dis_Vcmov,Int_Vcmov,IS_VFPU),
|
||||
INSTR("vi2f", &Jit::Comp_Generic, Dis_Vf2i, Int_Vi2f, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vcmov", &Jit::Comp_Generic, Dis_Vcmov,Int_Vcmov,IS_VFPU|OUT_EAT_PREFIX),
|
||||
{-2},
|
||||
{-2},
|
||||
|
||||
|
@ -546,10 +546,10 @@ const MIPSInstruction tableVFPU4Jump[32] = //110100 xxxxx
|
|||
|
||||
const MIPSInstruction tableVFPU7[32] =
|
||||
{
|
||||
INSTR("vrnds", &Jit::Comp_Generic, Dis_Generic, Int_Vrnds, IS_VFPU),
|
||||
INSTR("vrndi", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU),
|
||||
INSTR("vrndf1", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU),
|
||||
INSTR("vrndf2", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU),
|
||||
INSTR("vrnds", &Jit::Comp_Generic, Dis_Generic, Int_Vrnds, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vrndi", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vrndf1", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vrndf2", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU|OUT_EAT_PREFIX),
|
||||
|
||||
{-2},{-2},{-2},{-2},
|
||||
//8
|
||||
|
@ -559,8 +559,8 @@ const MIPSInstruction tableVFPU7[32] =
|
|||
//16
|
||||
{-2},
|
||||
{-2},
|
||||
INSTR("vf2h", &Jit::Comp_Generic, Dis_Generic, Int_Vf2h, IS_VFPU),
|
||||
INSTR("vh2f", &Jit::Comp_Generic, Dis_Generic, Int_Vh2f, IS_VFPU),
|
||||
INSTR("vf2h", &Jit::Comp_Generic, Dis_Generic, Int_Vf2h, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vh2f", &Jit::Comp_Generic, Dis_Generic, Int_Vh2f, IS_VFPU|OUT_EAT_PREFIX),
|
||||
|
||||
{-2},
|
||||
{-2},
|
||||
|
@ -572,41 +572,41 @@ const MIPSInstruction tableVFPU7[32] =
|
|||
INSTR("vus2i", &Jit::Comp_Generic, Dis_Vs2i, Int_Vx2i, IS_VFPU),
|
||||
INSTR("vs2i", &Jit::Comp_Generic, Dis_Vs2i, Int_Vx2i, IS_VFPU),
|
||||
|
||||
INSTR("vi2uc", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU),
|
||||
INSTR("vi2c", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU),
|
||||
INSTR("vi2us", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU),
|
||||
INSTR("vi2s", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU),
|
||||
INSTR("vi2uc", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vi2c", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vi2us", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vi2s", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU|OUT_EAT_PREFIX),
|
||||
};
|
||||
|
||||
// 110100 00000 10100 0000000000000000
|
||||
// 110100 00000 10111 0000000000000000
|
||||
const MIPSInstruction tableVFPU4[32] = //110100 00000 xxxxx
|
||||
{
|
||||
INSTR("vmov", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU),
|
||||
INSTR("vabs", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU),
|
||||
INSTR("vneg", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU),
|
||||
INSTR("vidt", &Jit::Comp_Generic, Dis_VectorSet1, Int_Vidt,IS_VFPU),
|
||||
INSTR("vsat0", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
|
||||
INSTR("vsat1", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
|
||||
INSTR("vzero", &Jit::Comp_Generic, Dis_VectorSet1, Int_VVectorInit, IS_VFPU),
|
||||
INSTR("vone", &Jit::Comp_Generic, Dis_VectorSet1, Int_VVectorInit, IS_VFPU),
|
||||
INSTR("vmov", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vabs", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vneg", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vidt", &Jit::Comp_Generic, Dis_VectorSet1, Int_Vidt,IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsat0", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsat1", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vzero", &Jit::Comp_Generic, Dis_VectorSet1, Int_VVectorInit, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vone", &Jit::Comp_Generic, Dis_VectorSet1, Int_VVectorInit, IS_VFPU|OUT_EAT_PREFIX),
|
||||
//8
|
||||
{-2},{-2},{-2},{-2},{-2},{-2},{-2},{-2},
|
||||
//16
|
||||
INSTR("vrcp", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
|
||||
INSTR("vrsq", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
|
||||
INSTR("vsin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
|
||||
INSTR("vcos", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
|
||||
INSTR("vexp2", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
|
||||
INSTR("vlog2", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
|
||||
INSTR("vsqrt", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
|
||||
INSTR("vasin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
|
||||
INSTR("vrcp", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vrsq", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vcos", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vexp2", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vlog2", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsqrt", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vasin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX),
|
||||
//24
|
||||
INSTR("vnrcp", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU),
|
||||
INSTR("vnrcp", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX),
|
||||
{-2},
|
||||
INSTR("vnsin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU),
|
||||
INSTR("vnsin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX),
|
||||
{-2},
|
||||
INSTR("vrexp2",&Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
|
||||
INSTR("vrexp2",&Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX),
|
||||
{-2},{-2},{-2},
|
||||
//32
|
||||
};
|
||||
|
@ -626,35 +626,35 @@ MIPSInstruction tableVFPU5[8] = //110111 xxx
|
|||
const MIPSInstruction tableVFPU6[32] = //111100 xxx
|
||||
{
|
||||
//0
|
||||
INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU),
|
||||
INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU),
|
||||
INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU),
|
||||
INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU),
|
||||
INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU|OUT_EAT_PREFIX),
|
||||
|
||||
INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
|
||||
INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
|
||||
INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
|
||||
INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
|
||||
INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX),
|
||||
//8
|
||||
INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
|
||||
INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
|
||||
INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
|
||||
INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
|
||||
INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX),
|
||||
|
||||
INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
|
||||
INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
|
||||
INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
|
||||
INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
|
||||
INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX),
|
||||
//16
|
||||
INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU),
|
||||
INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU),
|
||||
INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU),
|
||||
INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU),
|
||||
INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU|OUT_EAT_PREFIX),
|
||||
|
||||
INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU),
|
||||
INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU),
|
||||
INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU),
|
||||
INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU),
|
||||
INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU|OUT_EAT_PREFIX),
|
||||
//24
|
||||
{-2},
|
||||
{-2},
|
||||
|
@ -662,22 +662,22 @@ const MIPSInstruction tableVFPU6[32] = //111100 xxx
|
|||
{-2},
|
||||
|
||||
{VFPUMatrix1},
|
||||
INSTR("vrot",&Jit::Comp_Generic, Dis_VRot, Int_Vrot, IS_VFPU),
|
||||
INSTR("vrot",&Jit::Comp_Generic, Dis_VRot, Int_Vrot, IS_VFPU|OUT_EAT_PREFIX),
|
||||
{-2},
|
||||
{-2},
|
||||
};
|
||||
|
||||
const MIPSInstruction tableVFPUMatrixSet1[16] = //111100 11100 0xxxx (rm x is 16)
|
||||
{
|
||||
INSTR("vmmov",&Jit::Comp_Generic, Dis_MatrixSet2, Int_Vmmov, IS_VFPU),
|
||||
INSTR("vmmov",&Jit::Comp_Generic, Dis_MatrixSet2, Int_Vmmov, IS_VFPU|OUT_EAT_PREFIX),
|
||||
{-2},
|
||||
{-2},
|
||||
INSTR("vmidt",&Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU),
|
||||
INSTR("vmidt",&Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU|OUT_EAT_PREFIX),
|
||||
|
||||
{-2},
|
||||
{-2},
|
||||
INSTR("vmzero", &Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU),
|
||||
INSTR("vmone", &Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU),
|
||||
INSTR("vmzero", &Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vmone", &Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU|OUT_EAT_PREFIX),
|
||||
|
||||
{-2},{-2},{-2},{-2},
|
||||
{-2},{-2},{-2},{-2},
|
||||
|
@ -687,12 +687,12 @@ const MIPSInstruction tableVFPU9[32] = //110100 00010 xxxxx
|
|||
{
|
||||
INSTR("vsrt1", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt1, IS_VFPU),
|
||||
INSTR("vsrt2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt2, IS_VFPU),
|
||||
INSTR("vbfy1", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU),
|
||||
INSTR("vbfy2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU),
|
||||
INSTR("vbfy1", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vbfy2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU|OUT_EAT_PREFIX),
|
||||
//4
|
||||
INSTR("vocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vocp, IS_VFPU), // one's complement
|
||||
INSTR("vsocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsocp, IS_VFPU),
|
||||
INSTR("vfad", &Jit::Comp_Generic, Dis_Vfad, Int_Vfad, IS_VFPU),
|
||||
INSTR("vfad", &Jit::Comp_Generic, Dis_Vfad, Int_Vfad, IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vavg", &Jit::Comp_Generic, Dis_Vfad, Int_Vavg, IS_VFPU),
|
||||
//8
|
||||
INSTR("vsrt3", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt3, IS_VFPU),
|
||||
|
@ -868,6 +868,7 @@ void MIPSCompileOp(u32 op)
|
|||
if (op==0)
|
||||
return;
|
||||
const MIPSInstruction *instr = MIPSGetInstruction(op);
|
||||
const int info = MIPSGetInfo(op);
|
||||
if (instr)
|
||||
{
|
||||
if (instr->compile)
|
||||
|
@ -877,6 +878,9 @@ void MIPSCompileOp(u32 op)
|
|||
ERROR_LOG(CPU,"MIPSCompileOp %08x failed",op);
|
||||
//MessageBox(0,"ARGH2",0,0);//compile an interpreter call
|
||||
}
|
||||
|
||||
if (info & OUT_EAT_PREFIX)
|
||||
MIPSComp::jit->EatPrefix();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1016,124 +1020,6 @@ static inline void DelayBranchTo(MIPSState *curMips, u32 where)
|
|||
curMips->inDelaySlot = true;
|
||||
}
|
||||
|
||||
// Optimized interpreter loop that shortcuts the most common instructions.
|
||||
// For slow platforms without JITs.
|
||||
#define SIMM16 (s32)(s16)(op & 0xFFFF)
|
||||
#define UIMM16 (u32)(u16)(op & 0xFFFF)
|
||||
#define SUIMM16 (u32)(s32)(s16)(op & 0xFFFF)
|
||||
int MIPSInterpret_RunFastUntil(u64 globalTicks)
|
||||
{
|
||||
MIPSState *curMips = currentMIPS;
|
||||
while (coreState == CORE_RUNNING)
|
||||
{
|
||||
CoreTiming::Advance();
|
||||
|
||||
while (curMips->downcount >= 0 && coreState == CORE_RUNNING) // TODO: Try to get rid of the latter check
|
||||
{
|
||||
again:
|
||||
bool wasInDelaySlot = curMips->inDelaySlot;
|
||||
u32 op = Memory::ReadUnchecked_U32(curMips->pc);
|
||||
switch (op >> 29)
|
||||
{
|
||||
case 0x0:
|
||||
{
|
||||
int imm = (s16)(op&0xFFFF) << 2;
|
||||
int rs = _RS;
|
||||
int rt = _RT;
|
||||
u32 addr = curMips->pc + imm + 4;
|
||||
switch (op >> 26)
|
||||
{
|
||||
case 4: if (R(rt) == R(rs)) DelayBranchTo(curMips, addr); else curMips->pc += 4; break; //beq
|
||||
case 5: if (R(rt) != R(rs)) DelayBranchTo(curMips, addr); else curMips->pc += 4; break; //bne
|
||||
case 6: if ((s32)R(rs) <= 0) DelayBranchTo(curMips, addr); else curMips->pc += 4; break; //blez
|
||||
case 7: if ((s32)R(rs) > 0) DelayBranchTo(curMips, addr); else curMips->pc += 4; break; //bgtz
|
||||
default:
|
||||
goto interpret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1:
|
||||
{
|
||||
int rt = _RT;
|
||||
int rs = _RS;
|
||||
switch (op >> 26)
|
||||
{
|
||||
case 8: R(rt) = R(rs) + SIMM16; break; //addi
|
||||
case 9: R(rt) = R(rs) + SIMM16; break; //addiu
|
||||
case 10: R(rt) = (s32)R(rs) < SIMM16; break; //slti
|
||||
case 11: R(rt) = R(rs) < SUIMM16; break; //sltiu
|
||||
case 12: R(rt) = R(rs) & UIMM16; break; //andi
|
||||
case 13: R(rt) = R(rs) | UIMM16; break; //ori
|
||||
case 14: R(rt) = R(rs) ^ UIMM16; break; //xori
|
||||
case 15: R(rt) = UIMM16 << 16; break; //lui
|
||||
default:
|
||||
goto interpret;
|
||||
}
|
||||
currentMIPS->pc += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
{
|
||||
int rt = _RT;
|
||||
int rs = _RS;
|
||||
int imm = (s16)(op & 0xFFFF);
|
||||
u32 addr = R(rs) + imm;
|
||||
switch (op >> 26)
|
||||
{
|
||||
case 32: R(rt) = (u32)(s32)(s8) Memory::ReadUnchecked_U8(addr); break; //lb
|
||||
case 33: R(rt) = (u32)(s32)(s16)Memory::ReadUnchecked_U16(addr); break; //lh
|
||||
case 35: R(rt) = Memory::ReadUnchecked_U32(addr); break; //lw
|
||||
case 36: R(rt) = Memory::ReadUnchecked_U8(addr); break; //lbu
|
||||
case 37: R(rt) = Memory::ReadUnchecked_U16(addr); break; //lhu
|
||||
default:
|
||||
goto interpret;
|
||||
}
|
||||
currentMIPS->pc += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x5:
|
||||
{
|
||||
int rt = _RT;
|
||||
int rs = _RS;
|
||||
int imm = (s16)(op & 0xFFFF);
|
||||
u32 addr = R(rs) + imm;
|
||||
switch (op >> 26)
|
||||
{
|
||||
case 40: Memory::WriteUnchecked_U8(R(rt), addr); break; //sb
|
||||
case 41: Memory::WriteUnchecked_U16(R(rt), addr); break; //sh
|
||||
case 43: Memory::WriteUnchecked_U32(R(rt), addr); break; //sw
|
||||
default:
|
||||
goto interpret;
|
||||
}
|
||||
currentMIPS->pc += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
interpret:
|
||||
MIPSInterpret(op);
|
||||
}
|
||||
|
||||
if (curMips->inDelaySlot)
|
||||
{
|
||||
// The reason we have to check this is the delay slot hack in Int_Syscall.
|
||||
if (wasInDelaySlot)
|
||||
{
|
||||
curMips->pc = curMips->nextPC;
|
||||
curMips->inDelaySlot = false;
|
||||
}
|
||||
curMips->downcount -= 1;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
const char *MIPSGetName(u32 op)
|
||||
{
|
||||
static const char *noname = "unk";
|
||||
|
|
|
@ -19,31 +19,34 @@
|
|||
|
||||
#include "../../Globals.h"
|
||||
|
||||
#define IS_CONDBRANCH 0x100
|
||||
#define IS_JUMP 0x200
|
||||
#define IS_VFPU 0x80000000
|
||||
#define LIKELY 0x80
|
||||
#define UNCONDITIONAL 0x40
|
||||
#define BAD_INSTRUCTION 0x20
|
||||
#define DELAYSLOT 0x10
|
||||
#define DELAYSLOT 0x00000010
|
||||
#define BAD_INSTRUCTION 0x00000020
|
||||
#define UNCONDITIONAL 0x00000040
|
||||
#define LIKELY 0x00000080
|
||||
#define IS_CONDBRANCH 0x00000100
|
||||
#define IS_JUMP 0x00000200
|
||||
|
||||
#define IN_RS_ADDR 0x800
|
||||
#define IN_RS_SHIFT 0x400
|
||||
#define IN_RS 0x1000
|
||||
#define IN_RT 0x2000
|
||||
#define IN_SA 0x4000
|
||||
#define IN_IMM16 0x8000
|
||||
#define IN_IMM26 0x10000
|
||||
#define IN_MEM 0x20000
|
||||
#define IN_OTHER 0x40000
|
||||
#define IN_FPUFLAG 0x80000
|
||||
#define IN_RS_SHIFT 0x00000400
|
||||
#define IN_RS_ADDR 0x00000800
|
||||
#define IN_RS 0x00001000
|
||||
#define IN_RT 0x00002000
|
||||
#define IN_SA 0x00004000
|
||||
#define IN_IMM16 0x00008000
|
||||
#define IN_IMM26 0x00010000
|
||||
#define IN_MEM 0x00020000
|
||||
#define IN_OTHER 0x00040000
|
||||
#define IN_FPUFLAG 0x00080000
|
||||
|
||||
#define OUT_RT 0x100000
|
||||
#define OUT_RD 0x200000
|
||||
#define OUT_RA 0x400000
|
||||
#define OUT_MEM 0x800000
|
||||
#define OUT_OTHER 0x1000000
|
||||
#define OUT_FPUFLAG 0x2000000
|
||||
#define OUT_RT 0x00100000
|
||||
#define OUT_RD 0x00200000
|
||||
#define OUT_RA 0x00400000
|
||||
#define OUT_MEM 0x00800000
|
||||
#define OUT_OTHER 0x01000000
|
||||
#define OUT_FPUFLAG 0x02000000
|
||||
#define OUT_EAT_PREFIX 0x04000000
|
||||
|
||||
#define VFPU_NO_PREFIX 0x08000000
|
||||
#define IS_VFPU 0x80000000
|
||||
|
||||
#ifndef CDECL
|
||||
#define CDECL
|
||||
|
@ -57,7 +60,6 @@ void MIPSCompileOp(u32 op);
|
|||
void MIPSDisAsm(u32 op, u32 pc, char *out, bool tabsToSpaces = false);
|
||||
u32 MIPSGetInfo(u32 op);
|
||||
void MIPSInterpret(u32 op); //only for those rare ones
|
||||
int MIPSInterpret_RunFastUntil(u64 globalTicks);
|
||||
int MIPSInterpret_RunUntil(u64 globalTicks);
|
||||
MIPSInterpretFunc MIPSGetInterpretFunc(u32 op);
|
||||
|
||||
|
|
|
@ -179,19 +179,22 @@ void WriteMatrix(const float *rd, MatrixSize size, int reg) {
|
|||
case M_4x4: row = (reg>>5)&2; side = 4; break;
|
||||
}
|
||||
|
||||
int transpose = (reg>>5)&1;
|
||||
int transpose = (reg>>5)&1;
|
||||
if (currentMIPS->VfpuWriteMask() != 0) {
|
||||
ERROR_LOG(CPU, "Write mask used with vfpu matrix instruction.");
|
||||
}
|
||||
|
||||
for (int i=0; i<side; i++) {
|
||||
for (int j=0; j<side; j++) {
|
||||
// Hm, I wonder if this should affect matrices at all.
|
||||
if (!currentMIPS->VfpuWriteMask(i))
|
||||
if (j != side -1 || !currentMIPS->VfpuWriteMask(i))
|
||||
{
|
||||
int index = mtx * 4;
|
||||
int index = mtx * 4;
|
||||
if (transpose)
|
||||
index += ((row+i)&3) + ((col+j)&3)*32;
|
||||
else
|
||||
index += ((col+j)&3) + ((row+i)&3)*32;
|
||||
V(index) = rd[j*4+i];
|
||||
index += ((row+i)&3) + ((col+j)&3)*32;
|
||||
else
|
||||
index += ((col+j)&3) + ((row+i)&3)*32;
|
||||
V(index) = rd[j*4+i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -278,7 +281,10 @@ const char *GetVectorNotation(int reg, VectorSize size)
|
|||
case V_Quad: c='C'; row=(reg>>5)&2; break;
|
||||
}
|
||||
if (transpose && c == 'C') c='R';
|
||||
sprintf(hej[yo],"%c%i%i%i",c,mtx,col,row);
|
||||
if (transpose)
|
||||
sprintf(hej[yo],"%c%i%i%i",c,mtx,row,col);
|
||||
else
|
||||
sprintf(hej[yo],"%c%i%i%i",c,mtx,col,row);
|
||||
return hej[yo];
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ void Jit::Comp_FPU3op(u32 op)
|
|||
}
|
||||
}
|
||||
|
||||
static u32 GC_ALIGNED16(ssLoadStoreTemp[1]);
|
||||
static u32 GC_ALIGNED16(ssLoadStoreTemp);
|
||||
|
||||
void Jit::Comp_FPULS(u32 op)
|
||||
{
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace MIPSComp
|
|||
|
||||
static const float one = 1.0f;
|
||||
static const float minus_one = -1.0f;
|
||||
static const float zero = -1.0f;
|
||||
static const float zero = 0.0f;
|
||||
|
||||
const u32 GC_ALIGNED16( noSignMask[4] ) = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
|
||||
const u32 GC_ALIGNED16( signBitLower[4] ) = {0x80000000, 0, 0, 0};
|
||||
|
@ -75,9 +75,6 @@ void Jit::Comp_VPFX(u32 op)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: Got register value ownership issues. We need to be sure that if we modify input
|
||||
// like this, it does NOT get written back!
|
||||
void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) {
|
||||
if (prefix == 0xE4) return;
|
||||
|
||||
|
@ -86,9 +83,7 @@ void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) {
|
|||
static const float constantArray[8] = {0.f, 1.f, 2.f, 0.5f, 3.f, 1.f/3.f, 0.25f, 1.f/6.f};
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
origV[i] = vregs[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
|
@ -97,48 +92,104 @@ void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) {
|
|||
int negate = (prefix >> (16+i)) & 1;
|
||||
int constants = (prefix >> (12+i)) & 1;
|
||||
|
||||
// Unchanged, hurray.
|
||||
if (!constants && regnum == i && !abs && !negate)
|
||||
continue;
|
||||
|
||||
// This puts the value into a temp reg, so we won't write the modified value back.
|
||||
vregs[i] = fpr.GetTempV();
|
||||
fpr.MapRegV(vregs[i], MAP_NOINIT | MAP_DIRTY);
|
||||
|
||||
if (!constants) {
|
||||
vregs[i] = origV[regnum];
|
||||
// Prefix may say "z, z, z, z" but if this is a pair, we force to x.
|
||||
// TODO: But some ops seem to use const 0 instead?
|
||||
if (regnum > n) {
|
||||
ERROR_LOG(CPU, "Invalid VFPU swizzle: %08x / %d", prefix, sz);
|
||||
regnum = 0;
|
||||
}
|
||||
MOVSS(fpr.VX(vregs[i]), fpr.V(origV[regnum]));
|
||||
if (abs) {
|
||||
ANDPS(fpr.VX(vregs[i]), M((void *)&noSignMask));
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
MOVSS(fpr.VX(vregs[i]), M((void *)&constantArray[regnum + (abs<<2)]));
|
||||
}
|
||||
|
||||
if (negate)
|
||||
XORPS(fpr.VX(vregs[i]), M((void *)&signBitLower));
|
||||
|
||||
// TODO: This probably means it will swap out soon, inefficiently...
|
||||
fpr.ReleaseSpillLockV(vregs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Jit::ApplyPrefixD(const u8 *vregs, u32 prefix, VectorSize sz, bool onlyWriteMask) {
|
||||
void Jit::GetVectorRegsPrefixD(u8 *regs, VectorSize sz, int vectorReg) {
|
||||
_assert_(js.prefixDFlag & JitState::PREFIX_KNOWN);
|
||||
if (!prefix) return;
|
||||
|
||||
GetVectorRegs(regs, sz, vectorReg);
|
||||
if (js.prefixD == 0)
|
||||
return;
|
||||
|
||||
int n = GetNumVectorElements(sz);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
int mask = (prefix >> (8 + i)) & 1;
|
||||
js.writeMask[i] = mask ? true : false;
|
||||
if (onlyWriteMask)
|
||||
// Hopefully this is rare, we'll just write it into a reg we drop.
|
||||
if (js.VfpuWriteMask(i))
|
||||
regs[i] = fpr.GetTempV();
|
||||
}
|
||||
}
|
||||
|
||||
void Jit::ApplyPrefixD(const u8 *vregs, VectorSize sz) {
|
||||
_assert_(js.prefixDFlag & JitState::PREFIX_KNOWN);
|
||||
if (!js.prefixD) return;
|
||||
|
||||
int n = GetNumVectorElements(sz);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
if (js.VfpuWriteMask(i))
|
||||
continue;
|
||||
if (!mask) {
|
||||
int sat = (prefix >> (i * 2)) & 3;
|
||||
if (sat == 1)
|
||||
{
|
||||
MAXSS(fpr.VX(vregs[i]), M((void *)&zero));
|
||||
MINSS(fpr.VX(vregs[i]), M((void *)&one));
|
||||
}
|
||||
else if (sat == 3)
|
||||
{
|
||||
MAXSS(fpr.VX(vregs[i]), M((void *)&minus_one));
|
||||
MINSS(fpr.VX(vregs[i]), M((void *)&one));
|
||||
}
|
||||
|
||||
int sat = (js.prefixD >> (i * 2)) & 3;
|
||||
if (sat == 1)
|
||||
{
|
||||
fpr.MapRegV(vregs[i], MAP_DIRTY);
|
||||
MAXSS(fpr.VX(vregs[i]), M((void *)&zero));
|
||||
MINSS(fpr.VX(vregs[i]), M((void *)&one));
|
||||
}
|
||||
else if (sat == 3)
|
||||
{
|
||||
fpr.MapRegV(vregs[i], MAP_DIRTY);
|
||||
MAXSS(fpr.VX(vregs[i]), M((void *)&minus_one));
|
||||
MINSS(fpr.VX(vregs[i]), M((void *)&one));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static u32 GC_ALIGNED16(ssLoadStoreTemp[1]);
|
||||
// Vector regs can overlap in all sorts of swizzled ways.
|
||||
// This does allow a single overlap in sregs[i].
|
||||
bool IsOverlapSafeAllowS(int dreg, int di, int sn, u8 sregs[], int tn, u8 tregs[])
|
||||
{
|
||||
for (int i = 0; i < sn; ++i)
|
||||
{
|
||||
if (sregs[i] == dreg && i != di)
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < tn; ++i)
|
||||
{
|
||||
if (tregs[i] == dreg)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hurray, no overlap, we can write directly.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsOverlapSafe(int dreg, int di, int sn, u8 sregs[], int tn, u8 tregs[])
|
||||
{
|
||||
return IsOverlapSafeAllowS(dreg, di, sn, sregs, tn, tregs) && sregs[di] != dreg;
|
||||
}
|
||||
|
||||
static u32 GC_ALIGNED16(ssLoadStoreTemp);
|
||||
|
||||
void Jit::Comp_SV(u32 op) {
|
||||
CONDITIONAL_DISABLE;
|
||||
|
@ -286,12 +337,10 @@ void Jit::Comp_SVQ(u32 op)
|
|||
}
|
||||
|
||||
void Jit::Comp_VDot(u32 op) {
|
||||
DISABLE;
|
||||
CONDITIONAL_DISABLE;
|
||||
|
||||
// WARNING: No prefix support!
|
||||
if (js.MayHavePrefix()) {
|
||||
if (js.HasUnknownPrefix()) {
|
||||
Comp_Generic(op);
|
||||
js.EatPrefix();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -301,45 +350,45 @@ void Jit::Comp_VDot(u32 op) {
|
|||
VectorSize sz = GetVecSize(op);
|
||||
|
||||
// TODO: Force read one of them into regs? probably not.
|
||||
u8 sregs[4], tregs[4], dregs[4];
|
||||
GetVectorRegs(sregs, sz, vs);
|
||||
GetVectorRegs(tregs, sz, vt);
|
||||
GetVectorRegs(dregs, V_Single, vd);
|
||||
|
||||
// TODO: applyprefixST here somehow (shuffle, etc...)
|
||||
|
||||
MOVSS(XMM0, fpr.V(sregs[0]));
|
||||
MULSS(XMM0, fpr.V(tregs[0]));
|
||||
u8 sregs[4], tregs[4], dregs[1];
|
||||
GetVectorRegsPrefixS(sregs, sz, vs);
|
||||
GetVectorRegsPrefixT(tregs, sz, vt);
|
||||
GetVectorRegsPrefixD(dregs, V_Single, vd);
|
||||
|
||||
int n = GetNumVectorElements(sz);
|
||||
for (int i = 1; i < n; i++)
|
||||
X64Reg tempxreg = XMM0;
|
||||
if (IsOverlapSafe(dregs[0], 0, n, sregs, n, tregs))
|
||||
{
|
||||
fpr.MapRegsV(dregs, V_Single, MAP_NOINIT);
|
||||
tempxreg = fpr.VX(dregs[0]);
|
||||
}
|
||||
|
||||
// Need to start with +0.0f so it doesn't result in -0.0f.
|
||||
XORPS(tempxreg, R(tempxreg));
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
// sum += s[i]*t[i];
|
||||
MOVSS(XMM1, fpr.V(sregs[i]));
|
||||
MULSS(XMM1, fpr.V(tregs[i]));
|
||||
ADDSS(XMM0, R(XMM1));
|
||||
ADDSS(tempxreg, R(XMM1));
|
||||
}
|
||||
fpr.ReleaseSpillLocks();
|
||||
|
||||
fpr.MapRegsV(dregs, V_Single, MAP_NOINIT);
|
||||
if (!fpr.V(dregs[0]).IsSimpleReg(tempxreg))
|
||||
{
|
||||
fpr.MapRegsV(dregs, V_Single, MAP_NOINIT);
|
||||
MOVSS(fpr.V(dregs[0]), tempxreg);
|
||||
}
|
||||
|
||||
// TODO: applyprefixD here somehow (write mask etc..)
|
||||
|
||||
MOVSS(fpr.V(vd), XMM0);
|
||||
ApplyPrefixD(dregs, V_Single);
|
||||
|
||||
fpr.ReleaseSpillLocks();
|
||||
|
||||
js.EatPrefix();
|
||||
}
|
||||
|
||||
void Jit::Comp_VecDo3(u32 op) {
|
||||
DISABLE;
|
||||
CONDITIONAL_DISABLE;
|
||||
|
||||
// WARNING: No prefix support!
|
||||
if (js.MayHavePrefix())
|
||||
{
|
||||
if (js.HasUnknownPrefix()) {
|
||||
Comp_Generic(op);
|
||||
js.EatPrefix();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -349,9 +398,9 @@ void Jit::Comp_VecDo3(u32 op) {
|
|||
VectorSize sz = GetVecSize(op);
|
||||
|
||||
u8 sregs[4], tregs[4], dregs[4];
|
||||
GetVectorRegs(sregs, sz, vs);
|
||||
GetVectorRegs(tregs, sz, vt);
|
||||
GetVectorRegs(dregs, sz, vd);
|
||||
GetVectorRegsPrefixS(sregs, sz, vs);
|
||||
GetVectorRegsPrefixT(tregs, sz, vt);
|
||||
GetVectorRegsPrefixD(dregs, sz, vd);
|
||||
|
||||
void (XEmitter::*xmmop)(X64Reg, OpArg) = NULL;
|
||||
switch (op >> 26)
|
||||
|
@ -382,26 +431,53 @@ void Jit::Comp_VecDo3(u32 op) {
|
|||
|
||||
if (xmmop == NULL)
|
||||
{
|
||||
fpr.ReleaseSpillLocks();
|
||||
Comp_Generic(op);
|
||||
js.EatPrefix();
|
||||
return;
|
||||
}
|
||||
|
||||
int n = GetNumVectorElements(sz);
|
||||
// We need at least n temporaries...
|
||||
if (n > 2)
|
||||
fpr.Flush();
|
||||
|
||||
X64Reg tempxregs[4];
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
if (!IsOverlapSafeAllowS(dregs[i], i, n, sregs, n, tregs))
|
||||
{
|
||||
// On 32-bit we only have 6 xregs for mips regs, use XMM0/XMM1 if possible.
|
||||
if (i < 2)
|
||||
tempxregs[i] = (X64Reg) (XMM0 + i);
|
||||
else
|
||||
{
|
||||
int reg = fpr.GetTempV();
|
||||
fpr.MapRegV(reg, MAP_NOINIT | MAP_DIRTY);
|
||||
fpr.SpillLockV(reg);
|
||||
tempxregs[i] = fpr.VX(reg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fpr.MapRegV(dregs[i], (dregs[i] == sregs[i] ? 0 : MAP_NOINIT) | MAP_DIRTY);
|
||||
fpr.SpillLockV(dregs[i]);
|
||||
tempxregs[i] = fpr.VX(dregs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; ++i)
|
||||
MOVSS((X64Reg) (XMM0 + i), fpr.V(sregs[i]));
|
||||
{
|
||||
if (!fpr.V(sregs[i]).IsSimpleReg(tempxregs[i]))
|
||||
MOVSS(tempxregs[i], fpr.V(sregs[i]));
|
||||
}
|
||||
for (int i = 0; i < n; ++i)
|
||||
(this->*xmmop)((X64Reg) (XMM0 + i), fpr.V(tregs[i]));
|
||||
(this->*xmmop)(tempxregs[i], fpr.V(tregs[i]));
|
||||
for (int i = 0; i < n; ++i)
|
||||
MOVSS(fpr.V(dregs[i]), (X64Reg) (XMM0 + i));
|
||||
{
|
||||
if (!fpr.V(dregs[i]).IsSimpleReg(tempxregs[i]))
|
||||
MOVSS(fpr.V(dregs[i]), tempxregs[i]);
|
||||
}
|
||||
|
||||
ApplyPrefixD(dregs, sz);
|
||||
|
||||
fpr.ReleaseSpillLocks();
|
||||
|
||||
js.EatPrefix();
|
||||
}
|
||||
|
||||
void Jit::Comp_Mftv(u32 op) {
|
||||
|
@ -478,4 +554,4 @@ void Jit::Comp_Vmtvc(u32 op) {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "../../Core.h"
|
||||
#include "../../CoreTiming.h"
|
||||
#include "../../Config.h"
|
||||
|
@ -103,6 +104,15 @@ Jit::Jit(MIPSState *mips) : blocks(mips), mips_(mips)
|
|||
gpr.SetEmitter(this);
|
||||
fpr.SetEmitter(this);
|
||||
AllocCodeSpace(1024 * 1024 * 16);
|
||||
|
||||
// TODO: If it becomes possible to switch from the interpreter, this should be set right.
|
||||
js.startDefaultPrefix = true;
|
||||
}
|
||||
|
||||
void Jit::DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(js.startDefaultPrefix);
|
||||
p.DoMarker("Jit");
|
||||
}
|
||||
|
||||
void Jit::FlushAll()
|
||||
|
@ -202,6 +212,17 @@ void Jit::Compile(u32 em_address)
|
|||
int block_num = blocks.AllocateBlock(em_address);
|
||||
JitBlock *b = blocks.GetBlock(block_num);
|
||||
blocks.FinalizeBlock(block_num, jo.enableBlocklink, DoJit(em_address, b));
|
||||
|
||||
// Drat. The VFPU hit an uneaten prefix at the end of a block.
|
||||
if (js.startDefaultPrefix && js.MayHavePrefix())
|
||||
{
|
||||
js.startDefaultPrefix = false;
|
||||
// Our assumptions are all wrong so it's clean-slate time.
|
||||
ClearCache();
|
||||
|
||||
// Let's try that one more time. We won't get back here because we toggled the value.
|
||||
Compile(em_address);
|
||||
}
|
||||
}
|
||||
|
||||
void Jit::RunLoopUntil(u64 globalticks)
|
||||
|
@ -282,9 +303,13 @@ void Jit::Comp_Generic(u32 op)
|
|||
else
|
||||
_dbg_assert_msg_(JIT, 0, "Trying to compile instruction that can't be interpreted");
|
||||
|
||||
// Might have eaten prefixes, hard to tell...
|
||||
if ((MIPSGetInfo(op) & IS_VFPU) != 0)
|
||||
js.PrefixStart();
|
||||
const int info = MIPSGetInfo(op);
|
||||
if ((info & IS_VFPU) != 0 && (info & VFPU_NO_PREFIX) == 0)
|
||||
{
|
||||
// If it does eat them, it'll happen in MIPSCompileOp().
|
||||
if ((info & OUT_EAT_PREFIX) == 0)
|
||||
js.PrefixUnknown();
|
||||
}
|
||||
}
|
||||
|
||||
void Jit::WriteExit(u32 destination, int exit_num)
|
||||
|
|
|
@ -66,29 +66,42 @@ struct JitState
|
|||
JitBlock *curBlock;
|
||||
|
||||
// VFPU prefix magic
|
||||
bool startDefaultPrefix;
|
||||
u32 prefixS;
|
||||
u32 prefixT;
|
||||
u32 prefixD;
|
||||
bool writeMask[4];
|
||||
PrefixState prefixSFlag;
|
||||
PrefixState prefixTFlag;
|
||||
PrefixState prefixDFlag;
|
||||
void PrefixStart() {
|
||||
if (startDefaultPrefix) {
|
||||
EatPrefix();
|
||||
} else {
|
||||
PrefixUnknown();
|
||||
}
|
||||
}
|
||||
void PrefixUnknown() {
|
||||
prefixSFlag = PREFIX_UNKNOWN;
|
||||
prefixTFlag = PREFIX_UNKNOWN;
|
||||
prefixDFlag = PREFIX_UNKNOWN;
|
||||
}
|
||||
bool MayHavePrefix() const {
|
||||
if (!(prefixSFlag & PREFIX_KNOWN) || !(prefixTFlag & PREFIX_KNOWN) || !(prefixDFlag & PREFIX_KNOWN)) {
|
||||
if (HasUnknownPrefix()) {
|
||||
return true;
|
||||
} else if (prefixS != 0xE4 || prefixT != 0xE4 || prefixD != 0) {
|
||||
return true;
|
||||
} else if (writeMask[0] || writeMask[1] || writeMask[2] || writeMask[3]) {
|
||||
} else if (VfpuWriteMask() != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool HasUnknownPrefix() const {
|
||||
if (!(prefixSFlag & PREFIX_KNOWN) || !(prefixTFlag & PREFIX_KNOWN) || !(prefixDFlag & PREFIX_KNOWN)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void EatPrefix() {
|
||||
if ((prefixSFlag & PREFIX_KNOWN) == 0 || prefixS != 0xE4) {
|
||||
prefixSFlag = PREFIX_KNOWN_DIRTY;
|
||||
|
@ -98,12 +111,19 @@ struct JitState
|
|||
prefixTFlag = PREFIX_KNOWN_DIRTY;
|
||||
prefixT = 0xE4;
|
||||
}
|
||||
if ((prefixDFlag & PREFIX_KNOWN) == 0 || prefixD != 0x0 || writeMask[0] || writeMask[1] || writeMask[2] || writeMask[3]) {
|
||||
if ((prefixDFlag & PREFIX_KNOWN) == 0 || prefixD != 0x0 || VfpuWriteMask() != 0) {
|
||||
prefixDFlag = PREFIX_KNOWN_DIRTY;
|
||||
prefixD = 0x0;
|
||||
writeMask[0] = writeMask[1] = writeMask[2] = writeMask[3] = false;
|
||||
}
|
||||
}
|
||||
u8 VfpuWriteMask() const {
|
||||
_assert_(prefixDFlag & JitState::PREFIX_KNOWN);
|
||||
return (prefixD >> 8) & 0xF;
|
||||
}
|
||||
bool VfpuWriteMask(int i) const {
|
||||
_assert_(prefixDFlag & JitState::PREFIX_KNOWN);
|
||||
return (prefixD >> (8 + i)) & 1;
|
||||
}
|
||||
};
|
||||
|
||||
enum CompileDelaySlotFlags
|
||||
|
@ -122,6 +142,7 @@ class Jit : public Gen::XCodeBlock
|
|||
{
|
||||
public:
|
||||
Jit(MIPSState *mips);
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
// Compiled ops should ignore delay slots
|
||||
// the compiler will take care of them by itself
|
||||
|
@ -172,7 +193,19 @@ public:
|
|||
void Comp_DoNothing(u32 op);
|
||||
|
||||
void ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz);
|
||||
void ApplyPrefixD(const u8 *vregs, u32 prefix, VectorSize sz, bool onlyWriteMask = false);
|
||||
void ApplyPrefixD(const u8 *vregs, VectorSize sz);
|
||||
void GetVectorRegsPrefixS(u8 *regs, VectorSize sz, int vectorReg) {
|
||||
_assert_(js.prefixSFlag & JitState::PREFIX_KNOWN);
|
||||
GetVectorRegs(regs, sz, vectorReg);
|
||||
ApplyPrefixST(regs, js.prefixS, sz);
|
||||
}
|
||||
void GetVectorRegsPrefixT(u8 *regs, VectorSize sz, int vectorReg) {
|
||||
_assert_(js.prefixTFlag & JitState::PREFIX_KNOWN);
|
||||
GetVectorRegs(regs, sz, vectorReg);
|
||||
ApplyPrefixST(regs, js.prefixT, sz);
|
||||
}
|
||||
void GetVectorRegsPrefixD(u8 *regs, VectorSize sz, int vectorReg);
|
||||
void EatPrefix() { js.EatPrefix(); }
|
||||
|
||||
JitBlockCache *GetBlockCache() { return &blocks; }
|
||||
AsmRoutineManager &Asm() { return asm_; }
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "Core/MIPS/MIPSAnalyst.h"
|
||||
#include "Core/MIPS/x86/RegCacheFPU.h"
|
||||
|
||||
u32 FPURegCache::tempValues[NUM_TEMPS];
|
||||
|
||||
FPURegCache::FPURegCache() : emit(0), mips(0) {
|
||||
memset(regs, 0, sizeof(regs));
|
||||
memset(xregs, 0, sizeof(xregs));
|
||||
|
@ -37,6 +39,7 @@ void FPURegCache::Start(MIPSState *mips, MIPSAnalyst::AnalysisResults &stats) {
|
|||
regs[i].location = GetDefaultLocation(i);
|
||||
regs[i].away = false;
|
||||
regs[i].locked = false;
|
||||
regs[i].tempLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,6 +90,8 @@ void FPURegCache::ReleaseSpillLock(int mipsreg)
|
|||
void FPURegCache::ReleaseSpillLocks() {
|
||||
for (int i = 0; i < NUM_MIPS_FPRS; i++)
|
||||
regs[i].locked = false;
|
||||
for (int i = TEMP0; i < TEMP0 + NUM_TEMPS; ++i)
|
||||
DiscardR(i);
|
||||
}
|
||||
|
||||
void FPURegCache::BindToRegister(const int i, bool doLoad, bool makeDirty) {
|
||||
|
@ -129,6 +134,39 @@ void FPURegCache::StoreFromRegister(int i) {
|
|||
}
|
||||
}
|
||||
|
||||
void FPURegCache::DiscardR(int i) {
|
||||
_assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "FPU can't handle imm yet.");
|
||||
if (regs[i].away) {
|
||||
X64Reg xr = regs[i].location.GetSimpleReg();
|
||||
_assert_msg_(DYNA_REC, xr < NUM_X_FPREGS, "DiscardR: MipsReg had bad X64Reg");
|
||||
// Note that we DO NOT write it back here. That's the whole point of Discard.
|
||||
xregs[xr].dirty = false;
|
||||
xregs[xr].mipsReg = -1;
|
||||
regs[i].location = GetDefaultLocation(i);
|
||||
regs[i].away = false;
|
||||
regs[i].tempLocked = false;
|
||||
} else {
|
||||
// _assert_msg_(DYNA_REC,0,"already stored");
|
||||
regs[i].tempLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FPURegCache::IsTempX(X64Reg xr) {
|
||||
return xregs[xr].mipsReg >= TEMP0;
|
||||
}
|
||||
|
||||
int FPURegCache::GetTempR() {
|
||||
for (int r = TEMP0; r < TEMP0 + NUM_TEMPS; ++r) {
|
||||
if (!regs[r].away && !regs[r].tempLocked) {
|
||||
regs[r].tempLocked = true;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
_assert_msg_(DYNA_REC, 0, "Regcache ran out of temp regs, might need to DiscardR() some.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void FPURegCache::Flush() {
|
||||
for (int i = 0; i < NUM_MIPS_FPRS; i++) {
|
||||
if (regs[i].locked) {
|
||||
|
@ -151,8 +189,10 @@ void FPURegCache::Flush() {
|
|||
OpArg FPURegCache::GetDefaultLocation(int reg) const {
|
||||
if (reg < 32) {
|
||||
return M(&mips->f[reg]);
|
||||
} else {
|
||||
} else if (reg < 32 + 128) {
|
||||
return M(&mips->v[reg - 32]);
|
||||
} else {
|
||||
return M(&tempValues[reg - 32 - 128]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,7 +248,7 @@ X64Reg FPURegCache::GetFreeXReg() {
|
|||
return (X64Reg) -1;
|
||||
}
|
||||
|
||||
void FPURegCache::FlushR(X64Reg reg) {
|
||||
void FPURegCache::FlushX(X64Reg reg) {
|
||||
if (reg >= NUM_X_FPREGS)
|
||||
PanicAlert("Flushing non existent reg");
|
||||
if (xregs[reg].mipsReg != -1) {
|
||||
|
|
|
@ -26,9 +26,17 @@ using namespace Gen;
|
|||
|
||||
|
||||
// GPRs are numbered 0 to 31
|
||||
// VFPU regs are numbered 32 to 160.
|
||||
// VFPU regs are numbered 32 to 159.
|
||||
// Then we have some temp regs for VFPU handling from 160 to 175.
|
||||
|
||||
#define NUM_MIPS_FPRS (32 + 128)
|
||||
// Temp regs: 4 from S prefix, 4 from T prefix, 4 from D mask, and 4 for work (worst case.)
|
||||
// But most of the time prefixes aren't used that heavily so we won't use all of them.
|
||||
|
||||
enum {
|
||||
NUM_TEMPS = 16,
|
||||
TEMP0 = 32 + 128,
|
||||
NUM_MIPS_FPRS = 32 + 128 + NUM_TEMPS,
|
||||
};
|
||||
|
||||
#ifdef _M_X64
|
||||
#define NUM_X_FPREGS 16
|
||||
|
@ -45,6 +53,8 @@ struct MIPSCachedFPReg {
|
|||
OpArg location;
|
||||
bool away; // value not in source register
|
||||
bool locked;
|
||||
// Only for temp regs.
|
||||
bool tempLocked;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -68,6 +78,15 @@ public:
|
|||
StoreFromRegister(preg + 32);
|
||||
}
|
||||
OpArg GetDefaultLocation(int reg) const;
|
||||
void DiscardR(int freg);
|
||||
void DiscardV(int vreg) {
|
||||
DiscardR(vreg + 32);
|
||||
}
|
||||
bool IsTempX(X64Reg xreg);
|
||||
int GetTempR();
|
||||
int GetTempV() {
|
||||
return GetTempR() - 32;
|
||||
}
|
||||
|
||||
void SetEmitter(XEmitter *emitter) {emit = emitter;}
|
||||
|
||||
|
@ -101,19 +120,28 @@ public:
|
|||
void MapRegV(int vreg, int flags);
|
||||
void MapRegsV(int vec, VectorSize vsz, int flags);
|
||||
void MapRegsV(const u8 *v, VectorSize vsz, int flags);
|
||||
void SpillLockV(int vreg) {
|
||||
SpillLock(vreg + 32);
|
||||
}
|
||||
void SpillLockV(const u8 *v, VectorSize vsz);
|
||||
void SpillLockV(int vec, VectorSize vsz);
|
||||
void ReleaseSpillLockV(int vreg) {
|
||||
ReleaseSpillLock(vreg + 32);
|
||||
}
|
||||
|
||||
MIPSState *mips;
|
||||
|
||||
private:
|
||||
X64Reg GetFreeXReg();
|
||||
void FlushR(X64Reg reg);
|
||||
void FlushX(X64Reg reg);
|
||||
const int *GetAllocationOrder(int &count);
|
||||
|
||||
MIPSCachedFPReg regs[NUM_MIPS_FPRS];
|
||||
X64CachedFPReg xregs[NUM_X_FPREGS];
|
||||
MIPSCachedFPReg *vregs;
|
||||
|
||||
// TEMP0, etc. are swapped in here if necessary (e.g. on x86.)
|
||||
static u32 tempValues[NUM_TEMPS];
|
||||
|
||||
XEmitter *emit;
|
||||
};
|
||||
|
|
|
@ -36,9 +36,9 @@
|
|||
#if defined(_DEBUG)
|
||||
//#define SAFE_MEMORY
|
||||
#endif
|
||||
// Required for UNUSABLE_MMAP. Can define this in cmake instead later
|
||||
|
||||
#ifdef __SYMBIAN32__
|
||||
#define SAFE_MEMORY
|
||||
//#define SAFE_MEMORY
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ inline void ReadFromHardware(T &var, const u32 address)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (g_Config.iCpuCore == CPU_JIT) {
|
||||
if (g_Config.bJit) {
|
||||
WARN_LOG(MEMMAP, "ReadFromHardware: Invalid address %08x", address);
|
||||
} else {
|
||||
WARN_LOG(MEMMAP, "ReadFromHardware: Invalid address %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
|
||||
|
@ -115,7 +115,7 @@ inline void WriteToHardware(u32 address, const T data)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (g_Config.iCpuCore == CPU_JIT) {
|
||||
if (g_Config.bJit) {
|
||||
WARN_LOG(MEMMAP, "WriteToHardware: Invalid address %08x", address);
|
||||
} else {
|
||||
WARN_LOG(MEMMAP, "WriteToHardware: Invalid address %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
extern u32 curTextureWidth;
|
||||
extern u32 curTextureHeight;
|
||||
|
||||
static const int flushOnChangedBeforeCommandList[] = {
|
||||
static const u8 flushOnChangedBeforeCommandList[] = {
|
||||
GE_CMD_VERTEXTYPE,
|
||||
GE_CMD_BLENDMODE,
|
||||
GE_CMD_BLENDFIXEDA,
|
||||
|
@ -137,7 +137,7 @@ static const int flushOnChangedBeforeCommandList[] = {
|
|||
GE_CMD_ZBUFWIDTH,
|
||||
};
|
||||
|
||||
static const int flushBeforeCommandList[] = {
|
||||
static const u8 flushBeforeCommandList[] = {
|
||||
GE_CMD_BEZIER,
|
||||
GE_CMD_SPLINE,
|
||||
GE_CMD_SIGNAL,
|
||||
|
@ -330,6 +330,9 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
|||
|
||||
case GE_CMD_PRIM:
|
||||
{
|
||||
if (gstate_c.skipDrawReason)
|
||||
return;
|
||||
|
||||
framebufferManager_.SetRenderFrameBuffer();
|
||||
|
||||
u32 count = data & 0xFFFF;
|
||||
|
@ -1056,6 +1059,11 @@ void GLES_GPU::Resized() {
|
|||
framebufferManager_.Resized();
|
||||
}
|
||||
|
||||
std::vector<FramebufferInfo> GLES_GPU::GetFramebufferList()
|
||||
{
|
||||
return framebufferManager_.GetFramebufferList();
|
||||
}
|
||||
|
||||
void GLES_GPU::DoState(PointerWrap &p) {
|
||||
GPUCommon::DoState(p);
|
||||
|
||||
|
|
|
@ -59,6 +59,12 @@ public:
|
|||
|
||||
// Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*.
|
||||
virtual void Resized();
|
||||
virtual bool DecodeTexture(u8* dest, GPUgstate state)
|
||||
{
|
||||
return textureCache_.DecodeTexture(dest, state);
|
||||
}
|
||||
|
||||
std::vector<FramebufferInfo> GetFramebufferList();
|
||||
|
||||
private:
|
||||
void DoBlockTransfer();
|
||||
|
|
|
@ -326,12 +326,12 @@ void FramebufferManager::SetRenderFrameBuffer() {
|
|||
vfb->renderHeight = (u16)(drawing_height * renderHeightFactor);
|
||||
vfb->format = fmt;
|
||||
|
||||
vfb->colorDepth = FBO_8888;
|
||||
switch (fmt) {
|
||||
case GE_FORMAT_4444: vfb->colorDepth = FBO_4444;
|
||||
case GE_FORMAT_5551: vfb->colorDepth = FBO_5551;
|
||||
case GE_FORMAT_565: vfb->colorDepth = FBO_565;
|
||||
case GE_FORMAT_8888: vfb->colorDepth = FBO_8888;
|
||||
case GE_FORMAT_4444: vfb->colorDepth = FBO_4444; break;
|
||||
case GE_FORMAT_5551: vfb->colorDepth = FBO_5551; break;
|
||||
case GE_FORMAT_565: vfb->colorDepth = FBO_565; break;
|
||||
case GE_FORMAT_8888: vfb->colorDepth = FBO_8888; break;
|
||||
default: vfb->colorDepth = FBO_8888; break;
|
||||
}
|
||||
//#ifdef ANDROID
|
||||
// vfb->colorDepth = FBO_8888;
|
||||
|
@ -448,6 +448,26 @@ void FramebufferManager::SetDisplayFramebuffer(u32 framebuf, u32 stride, int for
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<FramebufferInfo> FramebufferManager::GetFramebufferList()
|
||||
{
|
||||
std::vector<FramebufferInfo> list;
|
||||
|
||||
for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) {
|
||||
VirtualFramebuffer *vfb = *iter;
|
||||
|
||||
FramebufferInfo info;
|
||||
info.fb_address = vfb->fb_address;
|
||||
info.z_address = vfb->z_address;
|
||||
info.format = vfb->format;
|
||||
info.width = vfb->width;
|
||||
info.height = vfb->height;
|
||||
info.fbo = vfb->fbo;
|
||||
list.push_back(info);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void FramebufferManager::DecimateFBOs() {
|
||||
for (auto iter = vfbs_.begin(); iter != vfbs_.end();) {
|
||||
VirtualFramebuffer *vfb = *iter;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
|
||||
#include "../Globals.h"
|
||||
#include "GPU/GPUCommon.h"
|
||||
|
||||
struct GLSLProgram;
|
||||
class TextureCache;
|
||||
|
@ -80,6 +81,8 @@ public:
|
|||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, int format);
|
||||
size_t NumVFBs() const { return vfbs_.size(); }
|
||||
|
||||
std::vector<FramebufferInfo> GetFramebufferList();
|
||||
|
||||
int GetRenderWidth() const { return currentRenderVfb_ ? currentRenderVfb_->renderWidth : 480; }
|
||||
int GetRenderHeight() const { return currentRenderVfb_ ? currentRenderVfb_->renderHeight : 272; }
|
||||
int GetTargetWidth() const { return currentRenderVfb_ ? currentRenderVfb_->width : 480; }
|
||||
|
|
|
@ -684,6 +684,8 @@ void TextureCache::SetTexture() {
|
|||
clutformat = gstate.clutformat & 3;
|
||||
clutaddr = GetClutAddr(clutformat == GE_CMODE_32BIT_ABGR8888 ? 4 : 2);
|
||||
cachekey |= (u64)clutaddr << 32;
|
||||
} else {
|
||||
clutaddr = 0;
|
||||
}
|
||||
|
||||
int maxLevel = ((gstate.texmode >> 16) & 0x7);
|
||||
|
@ -725,7 +727,7 @@ void TextureCache::SetTexture() {
|
|||
entry->hash != texhash ||
|
||||
entry->format != format ||
|
||||
entry->maxLevel != maxLevel ||
|
||||
((format >= GE_TFMT_CLUT4 && format <= GE_TFMT_CLUT32) &&
|
||||
(hasClut &&
|
||||
(entry->clutformat != clutformat ||
|
||||
entry->clutaddr != clutaddr ||
|
||||
entry->cluthash != Memory::Read_U32(entry->clutaddr))))
|
||||
|
@ -810,9 +812,9 @@ void TextureCache::SetTexture() {
|
|||
entry->lodBias = 0.0f;
|
||||
|
||||
|
||||
if (format >= GE_TFMT_CLUT4 && format <= GE_TFMT_CLUT32) {
|
||||
if (hasClut) {
|
||||
entry->clutformat = clutformat;
|
||||
entry->clutaddr = GetClutAddr(clutformat == GE_CMODE_32BIT_ABGR8888 ? 4 : 2);
|
||||
entry->clutaddr = clutaddr;
|
||||
entry->cluthash = Memory::Read_U32(entry->clutaddr);
|
||||
} else {
|
||||
entry->clutaddr = 0;
|
||||
|
@ -1131,3 +1133,289 @@ void TextureCache::LoadTextureLevel(TexCacheEntry &entry, int level)
|
|||
GLuint components = dstFmt == GL_UNSIGNED_SHORT_5_6_5 ? GL_RGB : GL_RGBA;
|
||||
glTexImage2D(GL_TEXTURE_2D, level, components, w, h, 0, components, dstFmt, finalBuf);
|
||||
}
|
||||
|
||||
bool TextureCache::DecodeTexture(u8* output, GPUgstate state)
|
||||
{
|
||||
GPUgstate oldState = gstate;
|
||||
gstate = state;
|
||||
|
||||
u32 texaddr = (gstate.texaddr[0] & 0xFFFFF0) | ((gstate.texbufwidth[0]<<8) & 0x0F000000);
|
||||
|
||||
if (!Memory::IsValidAddress(texaddr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
u8 level = 0;
|
||||
u32 format = gstate.texformat & 0xF;
|
||||
if (format >= 11) {
|
||||
ERROR_LOG(G3D, "Unknown texture format %i", format);
|
||||
format = 0;
|
||||
}
|
||||
|
||||
u32 clutformat = gstate.clutformat & 3;
|
||||
u32 clutaddr = GetClutAddr(clutformat == GE_CMODE_32BIT_ABGR8888 ? 4 : 2);
|
||||
|
||||
const u8 *texptr = Memory::GetPointer(texaddr);
|
||||
u32 texhash = texptr ? MiniHash((const u32*)texptr) : 0;
|
||||
|
||||
u64 cachekey = texaddr ^ texhash;
|
||||
if (formatUsesClut[format])
|
||||
cachekey |= (u64) clutaddr << 32;
|
||||
|
||||
int bufw = gstate.texbufwidth[0] & 0x3ff;
|
||||
|
||||
int w = 1 << (gstate.texsize[0] & 0xf);
|
||||
int h = 1 << ((gstate.texsize[0]>>8) & 0xf);
|
||||
|
||||
|
||||
GLenum dstFmt = 0;
|
||||
u32 texByteAlign = 1;
|
||||
|
||||
void *finalBuf = NULL;
|
||||
|
||||
// TODO: Look into using BGRA for 32-bit textures when the GL_EXT_texture_format_BGRA8888 extension is available, as it's faster than RGBA on some chips.
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case GE_TFMT_CLUT4:
|
||||
dstFmt = getClutDestFormat((GEPaletteFormat)(gstate.clutformat & 3));
|
||||
|
||||
switch (clutformat) {
|
||||
case GE_CMODE_16BIT_BGR5650:
|
||||
case GE_CMODE_16BIT_ABGR5551:
|
||||
case GE_CMODE_16BIT_ABGR4444:
|
||||
{
|
||||
ReadClut16(clutBuf16);
|
||||
const u16 *clut = clutBuf16;
|
||||
u32 clutSharingOff = 0;//gstate.mipmapShareClut ? 0 : level * 16;
|
||||
texByteAlign = 2;
|
||||
if (!(gstate.texmode & 1)) {
|
||||
const u8 *addr = Memory::GetPointer(texaddr);
|
||||
for (int i = 0; i < bufw * h; i += 2)
|
||||
{
|
||||
u8 index = *addr++;
|
||||
tmpTexBuf16[i + 0] = clut[GetClutIndex((index >> 0) & 0xf) + clutSharingOff];
|
||||
tmpTexBuf16[i + 1] = clut[GetClutIndex((index >> 4) & 0xf) + clutSharingOff];
|
||||
}
|
||||
} else {
|
||||
UnswizzleFromMem(texaddr, 0, level);
|
||||
for (int i = 0, j = 0; i < bufw * h; i += 8, j++)
|
||||
{
|
||||
u32 n = tmpTexBuf32[j];
|
||||
u32 k, index;
|
||||
for (k = 0; k < 8; k++) {
|
||||
index = (n >> (k * 4)) & 0xf;
|
||||
tmpTexBuf16[i + k] = clut[GetClutIndex(index) + clutSharingOff];
|
||||
}
|
||||
}
|
||||
}
|
||||
finalBuf = tmpTexBuf16;
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_CMODE_32BIT_ABGR8888:
|
||||
{
|
||||
ReadClut32(clutBuf32);
|
||||
const u32 *clut = clutBuf32;
|
||||
u32 clutSharingOff = 0;//gstate.mipmapShareClut ? 0 : level * 16;
|
||||
if (!(gstate.texmode & 1)) {
|
||||
const u8 *addr = Memory::GetPointer(texaddr);
|
||||
for (int i = 0; i < bufw * h; i += 2)
|
||||
{
|
||||
u8 index = *addr++;
|
||||
tmpTexBuf32[i + 0] = clut[GetClutIndex((index >> 0) & 0xf) + clutSharingOff];
|
||||
tmpTexBuf32[i + 1] = clut[GetClutIndex((index >> 4) & 0xf) + clutSharingOff];
|
||||
}
|
||||
} else {
|
||||
u32 pixels = bufw * h;
|
||||
UnswizzleFromMem(texaddr, 0, level);
|
||||
for (int i = pixels - 8, j = (pixels / 8) - 1; i >= 0; i -= 8, j--) {
|
||||
u32 n = tmpTexBuf32[j];
|
||||
for (int k = 0; k < 8; k++) {
|
||||
u32 index = (n >> (k * 4)) & 0xf;
|
||||
tmpTexBuf32[i + k] = clut[GetClutIndex(index) + clutSharingOff];
|
||||
}
|
||||
}
|
||||
}
|
||||
finalBuf = tmpTexBuf32;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG(G3D, "Unknown CLUT4 texture mode %d", (gstate.clutformat & 3));
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_TFMT_CLUT8:
|
||||
finalBuf = readIndexedTex(level, texaddr, 1);
|
||||
dstFmt = getClutDestFormat((GEPaletteFormat)(gstate.clutformat & 3));
|
||||
texByteAlign = texByteAlignMap[(gstate.clutformat & 3)];
|
||||
break;
|
||||
|
||||
case GE_TFMT_CLUT16:
|
||||
finalBuf = readIndexedTex(level, texaddr, 2);
|
||||
dstFmt = getClutDestFormat((GEPaletteFormat)(gstate.clutformat & 3));
|
||||
texByteAlign = texByteAlignMap[(gstate.clutformat & 3)];
|
||||
break;
|
||||
|
||||
case GE_TFMT_CLUT32:
|
||||
finalBuf = readIndexedTex(level, texaddr, 4);
|
||||
dstFmt = getClutDestFormat((GEPaletteFormat)(gstate.clutformat & 3));
|
||||
texByteAlign = texByteAlignMap[(gstate.clutformat & 3)];
|
||||
break;
|
||||
|
||||
case GE_TFMT_4444:
|
||||
case GE_TFMT_5551:
|
||||
case GE_TFMT_5650:
|
||||
if (format == GE_TFMT_4444)
|
||||
dstFmt = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
else if (format == GE_TFMT_5551)
|
||||
dstFmt = GL_UNSIGNED_SHORT_5_5_5_1;
|
||||
else if (format == GE_TFMT_5650)
|
||||
dstFmt = GL_UNSIGNED_SHORT_5_6_5;
|
||||
texByteAlign = 2;
|
||||
|
||||
if (!(gstate.texmode & 1)) {
|
||||
int len = std::max(bufw, w) * h;
|
||||
for (int i = 0; i < len; i++)
|
||||
tmpTexBuf16[i] = Memory::ReadUnchecked_U16(texaddr + i * 2);
|
||||
finalBuf = tmpTexBuf16;
|
||||
}
|
||||
else
|
||||
finalBuf = UnswizzleFromMem(texaddr, 2, level);
|
||||
break;
|
||||
|
||||
case GE_TFMT_8888:
|
||||
dstFmt = GL_UNSIGNED_BYTE;
|
||||
if (!(gstate.texmode & 1)) {
|
||||
int len = bufw * h;
|
||||
for (int i = 0; i < len; i++)
|
||||
tmpTexBuf32[i] = Memory::ReadUnchecked_U32(texaddr + i * 4);
|
||||
finalBuf = tmpTexBuf32;
|
||||
}
|
||||
else
|
||||
finalBuf = UnswizzleFromMem(texaddr, 4, level);
|
||||
break;
|
||||
|
||||
case GE_TFMT_DXT1:
|
||||
dstFmt = GL_UNSIGNED_BYTE;
|
||||
{
|
||||
u32 *dst = tmpTexBuf32;
|
||||
DXT1Block *src = (DXT1Block*)texptr;
|
||||
|
||||
for (int y = 0; y < h; y += 4) {
|
||||
u32 blockIndex = (y / 4) * (bufw / 4);
|
||||
for (int x = 0; x < std::min(bufw, w); x += 4) {
|
||||
decodeDXT1Block(dst + bufw * y + x, src + blockIndex, bufw);
|
||||
blockIndex++;
|
||||
}
|
||||
}
|
||||
finalBuf = tmpTexBuf32;
|
||||
w = (w + 3) & ~3;
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_TFMT_DXT3:
|
||||
dstFmt = GL_UNSIGNED_BYTE;
|
||||
{
|
||||
u32 *dst = tmpTexBuf32;
|
||||
DXT3Block *src = (DXT3Block*)texptr;
|
||||
|
||||
// Alpha is off
|
||||
for (int y = 0; y < h; y += 4) {
|
||||
u32 blockIndex = (y / 4) * (bufw / 4);
|
||||
for (int x = 0; x < std::min(bufw, w); x += 4) {
|
||||
decodeDXT3Block(dst + bufw * y + x, src + blockIndex, bufw);
|
||||
blockIndex++;
|
||||
}
|
||||
}
|
||||
w = (w + 3) & ~3;
|
||||
finalBuf = tmpTexBuf32;
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_TFMT_DXT5:
|
||||
ERROR_LOG(G3D, "Unhandled compressed texture, format %i! swizzle=%i", format, gstate.texmode & 1);
|
||||
dstFmt = GL_UNSIGNED_BYTE;
|
||||
{
|
||||
u32 *dst = tmpTexBuf32;
|
||||
DXT5Block *src = (DXT5Block*)texptr;
|
||||
|
||||
// Alpha is almost right
|
||||
for (int y = 0; y < h; y += 4) {
|
||||
u32 blockIndex = (y / 4) * (bufw / 4);
|
||||
for (int x = 0; x < std::min(bufw, w); x += 4) {
|
||||
decodeDXT5Block(dst + bufw * y + x, src + blockIndex, bufw);
|
||||
blockIndex++;
|
||||
}
|
||||
}
|
||||
w = (w + 3) & ~3;
|
||||
finalBuf = tmpTexBuf32;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG(G3D, "Unknown Texture Format %d!!!", format);
|
||||
finalBuf = tmpTexBuf32;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!finalBuf) {
|
||||
ERROR_LOG(G3D, "NO finalbuf! Will crash!");
|
||||
}
|
||||
|
||||
convertColors((u8*)finalBuf, dstFmt, bufw * h);
|
||||
|
||||
if(dstFmt == GL_UNSIGNED_SHORT_4_4_4_4)
|
||||
{
|
||||
for(int x = 0; x < h; x++)
|
||||
for(int y = 0; y < bufw; y++)
|
||||
{
|
||||
u32 val = ((u16*)finalBuf)[x*bufw + y];
|
||||
u32 a = (val & 0xF) * 255 / 15;
|
||||
u32 r = ((val & 0xF) >> 24) * 255 / 15;
|
||||
u32 g = ((val & 0xF) >> 16) * 255 / 15;
|
||||
u32 b = ((val & 0xF) >> 8) * 255 / 15;
|
||||
((u32*)output)[x*w + y] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
else if(dstFmt == GL_UNSIGNED_SHORT_5_5_5_1)
|
||||
{
|
||||
for(int x = 0; x < h; x++)
|
||||
for(int y = 0; y < bufw; y++)
|
||||
{
|
||||
u32 val = ((u16*)finalBuf)[x*bufw + y];
|
||||
u32 a = (val & 0x1) * 255;
|
||||
u32 r = ((val & 0x1F) >> 11) * 255 / 31;
|
||||
u32 g = ((val & 0x1F) >> 6) * 255 / 31;
|
||||
u32 b = ((val & 0x1F) >> 1) * 255 / 31;
|
||||
((u32*)output)[x*w + y] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
else if(dstFmt == GL_UNSIGNED_SHORT_5_6_5)
|
||||
{
|
||||
for(int x = 0; x < h; x++)
|
||||
for(int y = 0; y < bufw; y++)
|
||||
{
|
||||
u32 val = ((u16*)finalBuf)[x*bufw + y];
|
||||
u32 a = 0xFF;
|
||||
u32 r = ((val & 0x1F) >> 11) * 255 / 31;
|
||||
u32 g = ((val & 0x3F) >> 6) * 255 / 63;
|
||||
u32 b = ((val & 0x1F)) * 255 / 31;
|
||||
((u32*)output)[x*w + y] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int x = 0; x < h; x++)
|
||||
for(int y = 0; y < bufw; y++)
|
||||
{
|
||||
u32 val = ((u32*)finalBuf)[x*bufw + y];
|
||||
((u32*)output)[x*w + y] = ((val & 0xFF000000)) | ((val & 0x00FF0000)>>16) | ((val & 0x0000FF00)) | ((val & 0x000000FF)<<16);
|
||||
}
|
||||
}
|
||||
|
||||
gstate = oldState;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "../Globals.h"
|
||||
#include "gfx_es2/fbo.h"
|
||||
#include "GPU/GPUState.h"
|
||||
|
||||
class TextureCache
|
||||
{
|
||||
|
@ -42,6 +43,7 @@ public:
|
|||
return cache.size();
|
||||
}
|
||||
|
||||
bool DecodeTexture(u8 *output, GPUgstate state);
|
||||
private:
|
||||
|
||||
struct TexCacheEntry {
|
||||
|
@ -64,8 +66,8 @@ private:
|
|||
int numFrames;
|
||||
u32 framesUntilNextFullHash;
|
||||
u8 format;
|
||||
u8 clutformat;
|
||||
u16 dim;
|
||||
u8 clutformat;
|
||||
u32 clutaddr;
|
||||
u32 cluthash;
|
||||
u32 texture; //GLuint
|
||||
|
@ -100,7 +102,7 @@ private:
|
|||
u32 *clutBuf32;
|
||||
u16 *clutBuf16;
|
||||
|
||||
int lastBoundTexture;
|
||||
u32 lastBoundTexture;
|
||||
float maxAnisotropyLevel;
|
||||
};
|
||||
|
||||
|
|
|
@ -53,12 +53,14 @@ enum {
|
|||
};
|
||||
|
||||
TransformDrawEngine::TransformDrawEngine()
|
||||
: numDrawCalls(0),
|
||||
collectedVerts(0),
|
||||
: collectedVerts(0),
|
||||
prevPrim_(-1),
|
||||
lastVType_(-1),
|
||||
curVbo_(0),
|
||||
shaderManager_(0) {
|
||||
shaderManager_(0),
|
||||
textureCache_(0),
|
||||
framebufferManager_(0),
|
||||
numDrawCalls(0) {
|
||||
// Allocate nicely aligned memory. Maybe graphics drivers will
|
||||
// appreciate it.
|
||||
// All this is a LOT of memory, need to see if we can cut down somehow.
|
||||
|
|
|
@ -197,7 +197,7 @@ void VertexDecoder::Step_Color5551() const
|
|||
c[0] = Convert5To8(cdata & 0x1f);
|
||||
c[1] = Convert5To8((cdata>>5) & 0x1f);
|
||||
c[2] = Convert5To8((cdata>>10) & 0x1f);
|
||||
c[3] = (cdata>>15) ? 255 : 0;
|
||||
c[3] = (cdata>>15) ? 255.0f : 0.0f;
|
||||
}
|
||||
|
||||
void VertexDecoder::Step_Color4444() const
|
||||
|
@ -222,15 +222,15 @@ void VertexDecoder::Step_Color565Morph() const
|
|||
{
|
||||
float w = gstate_c.morphWeights[n];
|
||||
u16 cdata = *(u16*)(ptr_ + onesize_*n + coloff);
|
||||
col[0] += w * (cdata & 0x1f) / 31.f;
|
||||
col[1] += w * ((cdata>>5) & 0x3f) / 63.f;
|
||||
col[2] += w * ((cdata>>11) & 0x1f) / 31.f;
|
||||
col[0] += w * (cdata & 0x1f) / 31.0f;
|
||||
col[1] += w * ((cdata>>5) & 0x3f) / 63.0f;
|
||||
col[2] += w * ((cdata>>11) & 0x1f) / 31.0f;
|
||||
}
|
||||
u8 *c = decoded_ + decFmt.c0off;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
c[i] = (u8)(col[i] * 255.0f);
|
||||
}
|
||||
c[3] = 255;
|
||||
c[3] = 255.0f;
|
||||
}
|
||||
|
||||
void VertexDecoder::Step_Color5551Morph() const
|
||||
|
@ -240,9 +240,9 @@ void VertexDecoder::Step_Color5551Morph() const
|
|||
{
|
||||
float w = gstate_c.morphWeights[n];
|
||||
u16 cdata = *(u16*)(ptr_ + onesize_*n + coloff);
|
||||
col[0] += w * (cdata & 0x1f) / 31.f;
|
||||
col[1] += w * ((cdata>>5) & 0x1f) / 31.f;
|
||||
col[2] += w * ((cdata>>10) & 0x1f) / 31.f;
|
||||
col[0] += w * (cdata & 0x1f) / 31.0f;
|
||||
col[1] += w * ((cdata>>5) & 0x1f) / 31.0f;
|
||||
col[2] += w * ((cdata>>10) & 0x1f) / 31.0f;
|
||||
col[3] += w * ((cdata>>15) ? 1.0f : 0.0f);
|
||||
}
|
||||
u8 *c = decoded_ + decFmt.c0off;
|
||||
|
@ -259,7 +259,7 @@ void VertexDecoder::Step_Color4444Morph() const
|
|||
float w = gstate_c.morphWeights[n];
|
||||
u16 cdata = *(u16*)(ptr_ + onesize_*n + coloff);
|
||||
for (int j = 0; j < 4; j++)
|
||||
col[j] += w * ((cdata >> (j * 4)) & 0xF) / 15.f;
|
||||
col[j] += w * ((cdata >> (j * 4)) & 0xF) / 15.0f;
|
||||
}
|
||||
u8 *c = decoded_ + decFmt.c0off;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
@ -346,7 +346,7 @@ void VertexDecoder::Step_NormalS16Morph() const
|
|||
multiplier = -multiplier;
|
||||
}
|
||||
const s16 *sv = (const s16 *)(ptr_ + onesize_*n + nrmoff);
|
||||
multiplier *= (1.0f/32767.f);
|
||||
multiplier *= (1.0f/32767.0f);
|
||||
for (int j = 0; j < 3; j++)
|
||||
normal[j] += sv[j] * multiplier;
|
||||
}
|
||||
|
|
|
@ -239,23 +239,29 @@ public:
|
|||
}
|
||||
|
||||
void ReadUV(float uv[2]) {
|
||||
const u8 *b = (const u8 *)(data_ + decFmt_.uvoff);
|
||||
const u16 *s = (const u16 *)(data_ + decFmt_.uvoff);
|
||||
const float *f = (const float *)(data_ + decFmt_.uvoff);
|
||||
switch (decFmt_.uvfmt) {
|
||||
case DEC_U8_2:
|
||||
uv[0] = b[0] * (1.f / 128.f);
|
||||
uv[1] = b[1] * (1.f / 128.f);
|
||||
{
|
||||
const u8 *b = (const u8 *)(data_ + decFmt_.uvoff);
|
||||
uv[0] = b[0] * (1.f / 128.f);
|
||||
uv[1] = b[1] * (1.f / 128.f);
|
||||
}
|
||||
break;
|
||||
|
||||
case DEC_U16_2:
|
||||
uv[0] = s[0] * (1.f / 32768.f);
|
||||
uv[1] = s[1] * (1.f / 32768.f);
|
||||
{
|
||||
const u16 *s = (const u16 *)(data_ + decFmt_.uvoff);
|
||||
uv[0] = s[0] * (1.f / 32768.f);
|
||||
uv[1] = s[1] * (1.f / 32768.f);
|
||||
}
|
||||
break;
|
||||
|
||||
case DEC_FLOAT_2:
|
||||
uv[0] = f[0] * 2.0f;
|
||||
uv[1] = f[1] * 2.0f;
|
||||
{
|
||||
const float *f = (const float *)(data_ + decFmt_.uvoff);
|
||||
uv[0] = f[0] * 2.0f;
|
||||
uv[1] = f[1] * 2.0f;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEC_U16A_2:
|
||||
|
|
|
@ -76,6 +76,12 @@ bool GPUCommon::InterpretList(DisplayList &list)
|
|||
ERROR_LOG(G3D, "DL PC = %08x WTF!!!!", list.pc);
|
||||
return true;
|
||||
}
|
||||
#if defined(USING_QT_UI)
|
||||
if(host->GpuStep())
|
||||
{
|
||||
host->SendGPUStart();
|
||||
}
|
||||
#endif
|
||||
|
||||
while (!finished)
|
||||
{
|
||||
|
@ -85,14 +91,16 @@ bool GPUCommon::InterpretList(DisplayList &list)
|
|||
list.status = PSP_GE_LIST_STALL_REACHED;
|
||||
return false;
|
||||
}
|
||||
|
||||
op = Memory::ReadUnchecked_U32(list.pc); //read from memory
|
||||
u32 cmd = op >> 24;
|
||||
|
||||
#if defined(USING_QT_UI)
|
||||
if(host->GpuStep())
|
||||
{
|
||||
host->SendGPUWait();
|
||||
host->SendGPUWait(cmd, list.pc, &gstate);
|
||||
}
|
||||
#endif
|
||||
op = Memory::ReadUnchecked_U32(list.pc); //read from memory
|
||||
u32 cmd = op >> 24;
|
||||
u32 diff = op ^ gstate.cmdmem[cmd];
|
||||
PreExecuteOp(op, diff);
|
||||
// TODO: Add a compiler flag to remove stuff like this at very-final build time.
|
||||
|
|
|
@ -62,4 +62,13 @@ public:
|
|||
{
|
||||
return currentList;
|
||||
}
|
||||
virtual bool DecodeTexture(u8* dest, GPUgstate state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
std::vector<FramebufferInfo> GetFramebufferList()
|
||||
{
|
||||
return std::vector<FramebufferInfo>();
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Globals.h"
|
||||
#include "GPUState.h"
|
||||
#include <deque>
|
||||
|
||||
class PointerWrap;
|
||||
|
@ -32,6 +33,18 @@ enum DisplayListStatus
|
|||
PSP_GE_LIST_CANCEL_DONE = 5, // canceled?
|
||||
};
|
||||
|
||||
|
||||
// Used for debug
|
||||
struct FramebufferInfo
|
||||
{
|
||||
u32 fb_address;
|
||||
u32 z_address;
|
||||
int format;
|
||||
u32 width;
|
||||
u32 height;
|
||||
void* fbo;
|
||||
};
|
||||
|
||||
struct DisplayList
|
||||
{
|
||||
int id;
|
||||
|
@ -94,4 +107,6 @@ public:
|
|||
virtual void DumpNextFrame() = 0;
|
||||
virtual const std::deque<DisplayList>& GetDisplayLists() = 0;
|
||||
virtual DisplayList* GetCurrentDisplayList() = 0;
|
||||
virtual bool DecodeTexture(u8* dest, GPUgstate state) = 0;
|
||||
virtual std::vector<FramebufferInfo> GetFramebufferList() = 0;
|
||||
};
|
||||
|
|
|
@ -224,7 +224,11 @@ struct GPUgstate
|
|||
|
||||
// Real data in the context ends here
|
||||
};
|
||||
|
||||
|
||||
enum SkipDrawReasonFlags {
|
||||
SKIPDRAW_SKIPFRAME = 1,
|
||||
};
|
||||
|
||||
// The rest is cached simplified/converted data for fast access.
|
||||
// Does not need to be saved when saving/restoring context.
|
||||
struct GPUStateCache
|
||||
|
@ -236,6 +240,8 @@ struct GPUStateCache
|
|||
|
||||
bool textureChanged;
|
||||
|
||||
int skipDrawReason;
|
||||
|
||||
float uScale,vScale;
|
||||
float uOff,vOff;
|
||||
bool flipTexture;
|
||||
|
|
|
@ -152,7 +152,7 @@ void EmuThread::run()
|
|||
host->UpdateUI();
|
||||
host->InitGL();
|
||||
|
||||
glWindow->makeCurrent();
|
||||
EmuThread_LockDraw(true);
|
||||
|
||||
#ifndef USING_GLES2
|
||||
glewInit();
|
||||
|
@ -163,6 +163,8 @@ void EmuThread::run()
|
|||
|
||||
QElapsedTimer timer;
|
||||
|
||||
EmuThread_LockDraw(false);
|
||||
|
||||
while(running) {
|
||||
//UpdateGamepad(*input_state);
|
||||
timer.start();
|
||||
|
@ -173,10 +175,7 @@ void EmuThread::run()
|
|||
|
||||
if(gRun)
|
||||
{
|
||||
|
||||
gameMutex->lock();
|
||||
|
||||
glWindow->makeCurrent();
|
||||
EmuThread_LockDraw(true);
|
||||
if(needInitGame)
|
||||
{
|
||||
g_State.bEmuThreadStarted = true;
|
||||
|
@ -185,7 +184,7 @@ void EmuThread::run()
|
|||
coreParameter.fileToStart = fileToStart.toStdString();
|
||||
coreParameter.enableSound = true;
|
||||
coreParameter.gpuCore = GPU_GLES;
|
||||
coreParameter.cpuCore = (CPUCore)g_Config.iCpuCore;
|
||||
coreParameter.cpuCore = g_Config.bJit ? CPU_JIT : CPU_INTERPRETER;
|
||||
coreParameter.enableDebugging = true;
|
||||
coreParameter.printfEmuLog = false;
|
||||
coreParameter.headLess = false;
|
||||
|
@ -219,19 +218,6 @@ void EmuThread::run()
|
|||
host->BootDone();
|
||||
needInitGame = false;
|
||||
}
|
||||
UpdateInputState(input_state);
|
||||
|
||||
for (int i = 0; i < controllistCount; i++) {
|
||||
if (input_state->pad_buttons_down & controllist[i].emu_id) {
|
||||
__CtrlButtonDown(controllist[i].psp_id);
|
||||
}
|
||||
if (input_state->pad_buttons_up & controllist[i].emu_id) {
|
||||
__CtrlButtonUp(controllist[i].psp_id);
|
||||
}
|
||||
}
|
||||
__CtrlSetAnalog(input_state->pad_lstick_x, input_state->pad_lstick_y);
|
||||
|
||||
EndInputState(input_state);
|
||||
|
||||
glstate.Restore();
|
||||
glViewport(0, 0, pixel_xres, pixel_yres);
|
||||
|
@ -252,14 +238,12 @@ void EmuThread::run()
|
|||
|
||||
qint64 time = timer.elapsed();
|
||||
const int frameTime = (1.0f/60.0f) * 1000;
|
||||
gameMutex->unlock();
|
||||
if(time < frameTime)
|
||||
{
|
||||
glWindow->doneCurrent();
|
||||
EmuThread_LockDraw(false);
|
||||
msleep(frameTime-time);
|
||||
glWindow->makeCurrent();
|
||||
EmuThread_LockDraw(true);
|
||||
}
|
||||
gameMutex->lock();
|
||||
timer.start();
|
||||
}
|
||||
|
||||
|
@ -289,13 +273,11 @@ void EmuThread::run()
|
|||
}
|
||||
#endif
|
||||
glWindow->swapBuffers();
|
||||
glWindow->doneCurrent();
|
||||
gameMutex->unlock();
|
||||
EmuThread_LockDraw(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
gameMutex->lock();
|
||||
glWindow->makeCurrent();
|
||||
EmuThread_LockDraw(true);
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
|
@ -336,8 +318,7 @@ void EmuThread::run()
|
|||
ui_draw2d.Flush(UIShader_Get());
|
||||
|
||||
glWindow->swapBuffers();
|
||||
glWindow->doneCurrent();
|
||||
gameMutex->unlock();
|
||||
EmuThread_LockDraw(false);
|
||||
qint64 time = timer.elapsed();
|
||||
const int frameTime = (1.0f/60.0f) * 1000;
|
||||
if(time < frameTime)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "android/jni/EmuScreen.h"
|
||||
#include "android/jni/UIShader.h"
|
||||
#include "android/jni/ui_atlas.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "EmuThread.h"
|
||||
|
||||
std::string boot_filename = "";
|
||||
|
@ -27,6 +28,7 @@ recursive_mutex m_hGPUStepMutex;
|
|||
QtHost::QtHost(MainWindow *mainWindow_)
|
||||
: mainWindow(mainWindow_)
|
||||
, m_GPUStep(false)
|
||||
, m_GPUFlag(0)
|
||||
{
|
||||
QObject::connect(this,SIGNAL(BootDoneSignal()),mainWindow,SLOT(Boot()));
|
||||
}
|
||||
|
@ -48,7 +50,6 @@ void QtHost::SetWindowTitle(const char *message)
|
|||
|
||||
void QtHost::UpdateUI()
|
||||
{
|
||||
mainWindow->Update();
|
||||
mainWindow->UpdateMenus();
|
||||
}
|
||||
|
||||
|
@ -66,6 +67,10 @@ void QtHost::UpdateDisassembly()
|
|||
mainWindow->GetDialogDisasm()->GotoPC();
|
||||
mainWindow->GetDialogDisasm()->Update();
|
||||
}
|
||||
if(mainWindow->GetDialogDisplaylist())
|
||||
{
|
||||
mainWindow->GetDialogDisplaylist()->Update();
|
||||
}
|
||||
}
|
||||
|
||||
void QtHost::SetDebugMode(bool mode)
|
||||
|
@ -77,7 +82,9 @@ void QtHost::SetDebugMode(bool mode)
|
|||
|
||||
void QtHost::BeginFrame()
|
||||
{
|
||||
mainWindow->Update();
|
||||
}
|
||||
|
||||
void QtHost::EndFrame()
|
||||
{
|
||||
}
|
||||
|
@ -144,19 +151,59 @@ bool QtHost::GpuStep()
|
|||
return m_GPUStep;
|
||||
}
|
||||
|
||||
void QtHost::SendGPUWait()
|
||||
void QtHost::SendGPUStart()
|
||||
{
|
||||
EmuThread_LockDraw(false);
|
||||
|
||||
mainWindow->GetDialogDisasm()->UpdateDisplayList();
|
||||
m_hGPUStepEvent.wait(m_hGPUStepMutex);
|
||||
if(m_GPUFlag == -1)
|
||||
{
|
||||
m_GPUFlag = 0;
|
||||
}
|
||||
|
||||
EmuThread_LockDraw(true);
|
||||
}
|
||||
|
||||
void QtHost::SetGPUStep(bool value)
|
||||
void QtHost::SendGPUWait(u32 cmd, u32 addr, void *data)
|
||||
{
|
||||
EmuThread_LockDraw(false);
|
||||
|
||||
if((m_GPUFlag == 1 && (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE)))
|
||||
{
|
||||
// Break after the draw
|
||||
m_GPUFlag = 0;
|
||||
}
|
||||
else if(m_GPUFlag == 0)
|
||||
{
|
||||
mainWindow->GetDialogDisasm()->UpdateDisplayList();
|
||||
mainWindow->GetDialogDisplaylist()->Update();
|
||||
m_hGPUStepEvent.wait(m_hGPUStepMutex);
|
||||
}
|
||||
else if(m_GPUFlag == 2 && addr == m_GPUData)
|
||||
{
|
||||
mainWindow->GetDialogDisasm()->UpdateDisplayList();
|
||||
mainWindow->GetDialogDisplaylist()->Update();
|
||||
m_hGPUStepEvent.wait(m_hGPUStepMutex);
|
||||
}
|
||||
else if(m_GPUFlag == 3 && (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE))
|
||||
{
|
||||
GPUgstate *state = (GPUgstate*)data;
|
||||
u32 texAddr = (state->texaddr[0] & 0xFFFFF0) | ((state->texbufwidth[0]<<8) & 0x0F000000);
|
||||
if(texAddr == m_GPUData)
|
||||
{
|
||||
mainWindow->GetDialogDisasm()->UpdateDisplayList();
|
||||
mainWindow->GetDialogDisplaylist()->Update();
|
||||
m_hGPUStepEvent.wait(m_hGPUStepMutex);
|
||||
}
|
||||
}
|
||||
|
||||
EmuThread_LockDraw(true);
|
||||
}
|
||||
|
||||
void QtHost::SetGPUStep(bool value, int flag, int data)
|
||||
{
|
||||
m_GPUStep = value;
|
||||
m_GPUFlag = flag;
|
||||
m_GPUData = data;
|
||||
}
|
||||
|
||||
void QtHost::NextGPUStep()
|
||||
|
|
|
@ -51,8 +51,9 @@ public:
|
|||
|
||||
void SendCoreWait(bool);
|
||||
bool GpuStep();
|
||||
void SendGPUWait();
|
||||
void SetGPUStep(bool value);
|
||||
void SendGPUWait(u32 cmd, u32 addr, void* data);
|
||||
void SendGPUStart();
|
||||
void SetGPUStep(bool value, int flag = 0, int data = 0);
|
||||
void NextGPUStep();
|
||||
|
||||
signals:
|
||||
|
@ -60,6 +61,8 @@ signals:
|
|||
private:
|
||||
MainWindow* mainWindow;
|
||||
bool m_GPUStep;
|
||||
int m_GPUFlag;
|
||||
int m_GPUData;
|
||||
};
|
||||
|
||||
#endif // QTAPP_H
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <QMenu>
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
|
@ -164,9 +163,7 @@ void CtrlDisAsmView::GoToMemoryView()
|
|||
|
||||
void CtrlDisAsmView::CopyAddress()
|
||||
{
|
||||
char temp[16];
|
||||
sprintf(temp,"%08x",selection);
|
||||
QApplication::clipboard()->setText(QString(temp));
|
||||
QApplication::clipboard()->setText(QString("%1").arg(selection,8,16,QChar('0')));
|
||||
}
|
||||
|
||||
void CtrlDisAsmView::CopyInstrDisAsm()
|
||||
|
@ -178,11 +175,9 @@ void CtrlDisAsmView::CopyInstrDisAsm()
|
|||
|
||||
void CtrlDisAsmView::CopyInstrHex()
|
||||
{
|
||||
char temp[24];
|
||||
EmuThread_LockDraw(true);
|
||||
sprintf(temp,"%08x",debugger->readMemory(selection));
|
||||
QApplication::clipboard()->setText(QString("%1").arg(debugger->readMemory(selection),8,16,QChar('0')));
|
||||
EmuThread_LockDraw(false);
|
||||
QApplication::clipboard()->setText(temp);
|
||||
}
|
||||
|
||||
void CtrlDisAsmView::SetNextStatement()
|
||||
|
@ -234,8 +229,7 @@ void CtrlDisAsmView::RenameFunction()
|
|||
int sym = symbolMap.GetSymbolNum(selection);
|
||||
if (sym != -1)
|
||||
{
|
||||
char name[256];
|
||||
strncpy(name, symbolMap.GetSymbolName(sym),256);
|
||||
QString name = symbolMap.GetSymbolName(sym);
|
||||
bool ok;
|
||||
QString newname = QInputDialog::getText(this, tr("New function name"),
|
||||
tr("New function name:"), QLineEdit::Normal,
|
||||
|
@ -300,8 +294,6 @@ void CtrlDisAsmView::paintEvent(QPaintEvent *)
|
|||
|
||||
int rowY1 = rect().bottom()/2 + rowHeight*i - rowHeight/2;
|
||||
int rowY2 = rect().bottom()/2 + rowHeight*i + rowHeight/2 - 1;
|
||||
char temp[256];
|
||||
sprintf(temp,"%08x",address);
|
||||
|
||||
lbr.setColor(marker==address?QColor(0xFFFFEEE0):QColor(debugger->getColor(address)));
|
||||
QColor bg = lbr.color();
|
||||
|
@ -319,7 +311,6 @@ void CtrlDisAsmView::paintEvent(QPaintEvent *)
|
|||
if (address == debugger->getPC())
|
||||
{
|
||||
painter.setBrush(pcBrush);
|
||||
qDebug() << address;
|
||||
}
|
||||
|
||||
painter.drawRect(16,rowY1,width-16-1,rowY2-rowY1);
|
||||
|
@ -327,7 +318,7 @@ void CtrlDisAsmView::paintEvent(QPaintEvent *)
|
|||
QPen textPen = QPen(QColor(halfAndHalf(bg.rgba(),0)));
|
||||
painter.setPen(textPen);
|
||||
painter.setFont(alignedFont);
|
||||
painter.drawText(17,rowY1-3+rowHeight,QString(temp));
|
||||
painter.drawText(17,rowY1-3+rowHeight,QString("%1").arg(address,8,16,QChar('0')));
|
||||
painter.setFont(normalFont);
|
||||
textPen.setColor(QColor(0xFF000000));
|
||||
painter.setPen(textPen);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <QMessageBox>
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QInputDialog>
|
||||
|
||||
#include "EmuThread.h"
|
||||
#include "Core/MemMap.h"
|
||||
|
@ -108,7 +109,6 @@ void CtrlMemView::paintEvent(QPaintEvent *)
|
|||
int rowY2 = rect().bottom()/2 + rowHeight*i + rowHeight/2;
|
||||
|
||||
char temp[256];
|
||||
sprintf(temp,"%08x",address);
|
||||
|
||||
painter.setBrush(currentBrush);
|
||||
|
||||
|
@ -123,7 +123,7 @@ void CtrlMemView::paintEvent(QPaintEvent *)
|
|||
textPen.setColor(0x600000);
|
||||
painter.setPen(textPen);
|
||||
painter.setFont(alignedFont);
|
||||
painter.drawText(17,rowY1-2+rowHeight, temp);
|
||||
painter.drawText(17,rowY1-2+rowHeight, QString("%1").arg(address,8,16,QChar('0')));
|
||||
textPen.setColor(0xFF000000);
|
||||
painter.setPen(textPen);
|
||||
if (debugger->isAlive())
|
||||
|
@ -222,6 +222,10 @@ void CtrlMemView::contextMenu(const QPoint &pos)
|
|||
connect(copyValue, SIGNAL(triggered()), this, SLOT(CopyValue()));
|
||||
menu.addAction(copyValue);
|
||||
|
||||
QAction *changeValue = new QAction(tr("C&hange value"), this);
|
||||
connect(changeValue, SIGNAL(triggered()), this, SLOT(Change()));
|
||||
menu.addAction(changeValue);
|
||||
|
||||
QAction *dump = new QAction(tr("Dump..."), this);
|
||||
connect(dump, SIGNAL(triggered()), this, SLOT(Dump()));
|
||||
menu.addAction(dump);
|
||||
|
@ -231,9 +235,9 @@ void CtrlMemView::contextMenu(const QPoint &pos)
|
|||
|
||||
void CtrlMemView::CopyValue()
|
||||
{
|
||||
char temp[24];
|
||||
sprintf(temp,"%08x",Memory::ReadUnchecked_U32(selection));
|
||||
QApplication::clipboard()->setText(temp);
|
||||
EmuThread_LockDraw(true);
|
||||
QApplication::clipboard()->setText(QString("%1").arg(Memory::ReadUnchecked_U32(selection),8,16,QChar('0')));
|
||||
EmuThread_LockDraw(false);
|
||||
}
|
||||
|
||||
void CtrlMemView::Dump()
|
||||
|
@ -241,6 +245,27 @@ void CtrlMemView::Dump()
|
|||
QMessageBox::information(this,"Sorry","This feature has not been implemented.",QMessageBox::Ok);
|
||||
}
|
||||
|
||||
|
||||
void CtrlMemView::Change()
|
||||
{
|
||||
EmuThread_LockDraw(true);
|
||||
QString curVal = QString("%1").arg(Memory::ReadUnchecked_U32(selection),8,16,QChar('0'));
|
||||
EmuThread_LockDraw(false);
|
||||
|
||||
bool ok;
|
||||
QString text = QInputDialog::getText(this, tr("Set new value"),
|
||||
tr("Set new value:"), QLineEdit::Normal,
|
||||
curVal, &ok);
|
||||
if (ok && !text.isEmpty())
|
||||
{
|
||||
EmuThread_LockDraw(true);
|
||||
Memory::WriteUnchecked_U32(text.toInt(0,16),selection);
|
||||
EmuThread_LockDraw(false);
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CtrlMemView::yToAddress(int y)
|
||||
{
|
||||
int ydiff=y-rect().bottom()/2-rowHeight/2;
|
||||
|
|
|
@ -72,6 +72,7 @@ signals:
|
|||
public slots:
|
||||
void CopyValue();
|
||||
void Dump();
|
||||
void Change();
|
||||
private:
|
||||
int curAddress;
|
||||
int align;
|
||||
|
|
|
@ -236,14 +236,14 @@ void CtrlRegisterList::paintEvent(QPaintEvent *)
|
|||
painter.setBrush(currentBrush);
|
||||
if (i<cpu->GetNumRegsInCategory(category))
|
||||
{
|
||||
char temp[256];
|
||||
sprintf(temp,"%s",cpu->GetRegName(category,i));
|
||||
QString regName = cpu->GetRegName(category,i);
|
||||
textPen.setColor(0x600000);
|
||||
painter.setPen(textPen);
|
||||
painter.drawText(17,rowY1-3+rowHeight,temp);
|
||||
painter.drawText(17,rowY1-3+rowHeight,regName);
|
||||
textPen.setColor(0xFF000000);
|
||||
painter.setPen(textPen);
|
||||
|
||||
char temp[256];
|
||||
cpu->PrintRegValue(category,i,temp);
|
||||
if (category == 0 && changedCat0Regs[i])
|
||||
{
|
||||
|
@ -331,10 +331,7 @@ void CtrlRegisterList::CopyValue()
|
|||
u32 val = cpu->GetRegValue(cat,reg);
|
||||
EmuThread_LockDraw(false);
|
||||
|
||||
char temp[24];
|
||||
sprintf(temp,"%08x",val);
|
||||
|
||||
QApplication::clipboard()->setText(temp);
|
||||
QApplication::clipboard()->setText(QString("%1").arg(val,8,16,QChar('0')));
|
||||
}
|
||||
|
||||
void CtrlRegisterList::Change()
|
||||
|
|
|
@ -45,9 +45,7 @@ void CtrlVfpuView::paintEvent(QPaintEvent *)
|
|||
{
|
||||
int my = (int)(yStart + matrix * rowHeight * 5.5f);
|
||||
painter.drawRect(0, my, xStart-1, rowHeight-1);
|
||||
char temp[256];
|
||||
sprintf(temp, "M%i00", matrix);
|
||||
painter.drawText(3, my+rowHeight-3, temp);
|
||||
painter.drawText(3, my+rowHeight-3, QString("M%1").arg(matrix)+"00");
|
||||
painter.drawRect(xStart, my+rowHeight, columnWidth*4-1, 4*rowHeight-1);
|
||||
|
||||
for (int column = 0; column<4; column++)
|
||||
|
@ -56,13 +54,10 @@ void CtrlVfpuView::paintEvent(QPaintEvent *)
|
|||
int x = column * columnWidth + xStart;
|
||||
|
||||
painter.drawRect(x, y, columnWidth-1, rowHeight - 1);
|
||||
char temp[256];
|
||||
sprintf(temp, "R%i0%i", matrix, column);
|
||||
painter.drawText(x+3, y-3+rowHeight, temp);
|
||||
painter.drawText(x+3, y-3+rowHeight, QString("R%1").arg(matrix)+QString("0%1").arg(column));
|
||||
|
||||
painter.drawRect(0, y+rowHeight*(column+1), xStart - 1, rowHeight - 1);
|
||||
sprintf(temp, "C%i%i0", matrix, column);
|
||||
painter.drawText(3, y+rowHeight*(column+2)-3, temp);
|
||||
painter.drawText(3, y+rowHeight*(column+2)-3, QString("C%1").arg(matrix)+QString("%1").arg(column)+"0");
|
||||
|
||||
y+=rowHeight;
|
||||
|
||||
|
|
|
@ -344,7 +344,7 @@ void Debugger_Disasm::FillFunctions()
|
|||
if(symbolMap.GetSymbolType(i) & ST_FUNCTION)
|
||||
{
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
item->setText(QString(symbolMap.GetSymbolName(i)) + " ("+ QVariant(symbolMap.GetSymbolSize(i)).toString() +")");
|
||||
item->setText(QString(symbolMap.GetSymbolName(i)) + " ("+ QString::number(symbolMap.GetSymbolSize(i)) +")");
|
||||
item->setData(Qt::UserRole, symbolMap.GetAddress(i));
|
||||
ui->FuncList->addItem(item);
|
||||
}
|
||||
|
@ -372,9 +372,7 @@ void Debugger_Disasm::UpdateBreakpointsGUI()
|
|||
if(!CBreakPoints::IsTempBreakPoint(addr_))
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
char temp[24];
|
||||
sprintf(temp,"%08x",addr_);
|
||||
item->setText(0,temp);
|
||||
item->setText(0,QString("%1").arg(addr_,8,16,QChar('0')));
|
||||
item->setData(0,Qt::UserRole,addr_);
|
||||
ui->breakpointsList->addTopLevelItem(item);
|
||||
if(curBpAddr == addr_)
|
||||
|
@ -434,7 +432,7 @@ void Debugger_Disasm::UpdateThreadGUI()
|
|||
for(int i = 0; i < threads.size(); i++)
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
item->setText(0,QVariant(threads[i].id).toString());
|
||||
item->setText(0,QString::number(threads[i].id));
|
||||
item->setData(0,Qt::UserRole,threads[i].id);
|
||||
item->setText(1,threads[i].name);
|
||||
QString status = "";
|
||||
|
@ -445,12 +443,9 @@ void Debugger_Disasm::UpdateThreadGUI()
|
|||
if(threads[i].status & THREADSTATUS_DORMANT) status += "Dormant ";
|
||||
if(threads[i].status & THREADSTATUS_DEAD) status += "Dead ";
|
||||
item->setText(2,status);
|
||||
char temp[24];
|
||||
sprintf(temp,"%08x",threads[i].curPC);
|
||||
item->setText(3,temp);
|
||||
item->setText(3,QString("%1").arg(threads[i].curPC,8,16,QChar('0')));
|
||||
item->setData(3,Qt::UserRole,threads[i].curPC);
|
||||
sprintf(temp,"%08x",threads[i].entrypoint);
|
||||
item->setText(4,temp);
|
||||
item->setText(4,QString("%1").arg(threads[i].entrypoint,8,16,QChar('0')));
|
||||
item->setData(4,Qt::UserRole,threads[i].entrypoint);
|
||||
|
||||
if(threads[i].isCurrent)
|
||||
|
@ -461,6 +456,8 @@ void Debugger_Disasm::UpdateThreadGUI()
|
|||
|
||||
ui->threadList->addTopLevelItem(item);
|
||||
}
|
||||
for(int i = 0; i < ui->threadList->columnCount(); i++)
|
||||
ui->threadList->resizeColumnToContents(i);
|
||||
}
|
||||
|
||||
void Debugger_Disasm::on_threadList_itemClicked(QTreeWidgetItem *item, int column)
|
||||
|
@ -542,7 +539,6 @@ void Debugger_Disasm::UpdateDisplayListGUI()
|
|||
curDlId = ui->displayList->currentItem()->data(0,Qt::UserRole).toInt();
|
||||
|
||||
ui->displayList->clear();
|
||||
ui->displayListData->clear();
|
||||
|
||||
EmuThread_LockDraw(true);
|
||||
const std::deque<DisplayList>& dlQueue = gpu->GetDisplayLists();
|
||||
|
@ -551,7 +547,7 @@ void Debugger_Disasm::UpdateDisplayListGUI()
|
|||
if(dl)
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
item->setText(0,QVariant(dl->id).toString());
|
||||
item->setText(0,QString::number(dl->id));
|
||||
item->setData(0, Qt::UserRole, dl->id);
|
||||
switch(dl->status)
|
||||
{
|
||||
|
@ -563,19 +559,15 @@ void Debugger_Disasm::UpdateDisplayListGUI()
|
|||
case PSP_GE_LIST_CANCEL_DONE: item->setText(1,"Cancel Done"); break;
|
||||
default: break;
|
||||
}
|
||||
char temp[24];
|
||||
sprintf(temp,"%08x",dl->startpc);
|
||||
item->setText(2,temp);
|
||||
item->setText(2,QString("%1").arg(dl->startpc,8,16,QChar('0')));
|
||||
item->setData(2, Qt::UserRole, dl->startpc);
|
||||
sprintf(temp,"%08x",dl->pc);
|
||||
item->setText(3,temp);
|
||||
item->setText(3,QString("%1").arg(dl->pc,8,16,QChar('0')));
|
||||
item->setData(3, Qt::UserRole, dl->pc);
|
||||
ui->displayList->addTopLevelItem(item);
|
||||
if(curDlId == dl->id)
|
||||
{
|
||||
ui->displayList->setCurrentItem(item);
|
||||
displayListRowSelected = item;
|
||||
ShowDLCode();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -584,7 +576,7 @@ void Debugger_Disasm::UpdateDisplayListGUI()
|
|||
if(dl && it->id == dl->id)
|
||||
continue;
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
item->setText(0,QVariant(it->id).toString());
|
||||
item->setText(0,QString::number(it->id));
|
||||
item->setData(0, Qt::UserRole, it->id);
|
||||
switch(it->status)
|
||||
{
|
||||
|
@ -596,21 +588,19 @@ void Debugger_Disasm::UpdateDisplayListGUI()
|
|||
case PSP_GE_LIST_CANCEL_DONE: item->setText(1,"Cancel Done"); break;
|
||||
default: break;
|
||||
}
|
||||
char temp[24];
|
||||
sprintf(temp,"%08x",it->startpc);
|
||||
item->setText(2,temp);
|
||||
item->setText(2,QString("%1").arg(it->startpc,8,16,QChar('0')));
|
||||
item->setData(2, Qt::UserRole, it->startpc);
|
||||
sprintf(temp,"%08x",it->pc);
|
||||
item->setText(3,temp);
|
||||
item->setText(3,QString("%1").arg(it->pc,8,16,QChar('0')));
|
||||
item->setData(3, Qt::UserRole, it->pc);
|
||||
ui->displayList->addTopLevelItem(item);
|
||||
if(curDlId == it->id)
|
||||
{
|
||||
ui->displayList->setCurrentItem(item);
|
||||
displayListRowSelected = item;
|
||||
ShowDLCode();
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < ui->displayList->columnCount(); i++)
|
||||
ui->displayList->resizeColumnToContents(i);
|
||||
EmuThread_LockDraw(false);
|
||||
}
|
||||
|
||||
|
@ -621,96 +611,12 @@ void Debugger_Disasm::on_displayList_customContextMenuRequested(const QPoint &po
|
|||
{
|
||||
displayListRowSelected = item;
|
||||
|
||||
QMenu menu(this);
|
||||
/*QMenu menu(this);
|
||||
|
||||
QAction *showCode = new QAction(tr("Show code"), this);
|
||||
connect(showCode, SIGNAL(triggered()), this, SLOT(ShowDLCode()));
|
||||
menu.addAction(showCode);
|
||||
menu.addAction(showCode);*/
|
||||
|
||||
menu.exec( ui->displayList->mapToGlobal(pos));
|
||||
//menu.exec( ui->displayList->mapToGlobal(pos));
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger_Disasm::ShowDLCode()
|
||||
{
|
||||
ui->displayListData->clear();
|
||||
ui->displayListData->setColumnWidth(0,70);
|
||||
|
||||
u32 startPc = displayListRowSelected->data(2,Qt::UserRole).toInt();
|
||||
u32 curPc = displayListRowSelected->data(3,Qt::UserRole).toInt();
|
||||
|
||||
std::map<int,std::string> data;
|
||||
FillDisplayListCmd(data, startPc,0);
|
||||
|
||||
for(std::map<int,std::string>::iterator it = data.begin(); it != data.end(); it++)
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
char temp[24];
|
||||
sprintf(temp,"%08x",it->first);
|
||||
item->setText(0,temp);
|
||||
item->setText(1,it->second.c_str());
|
||||
if(curPc == it->first)
|
||||
{
|
||||
for(int j = 0; j < 2; j++)
|
||||
item->setTextColor(j, Qt::green);
|
||||
}
|
||||
ui->displayListData->addTopLevelItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger_Disasm::FillDisplayListCmd(std::map<int,std::string>& data, u32 pc, u32 prev)
|
||||
{
|
||||
u32 curPc = pc;
|
||||
int debugLimit = 10000; // Anti crash if this code is bugged
|
||||
while(Memory::IsValidAddress(curPc) && debugLimit > 0)
|
||||
{
|
||||
if(data.find(curPc) != data.end())
|
||||
return;
|
||||
|
||||
u32 op = Memory::ReadUnchecked_U32(curPc); //read from memory
|
||||
u32 cmd = op >> 24;
|
||||
u32 diff = op ^ gstate.cmdmem[cmd];
|
||||
char temp[256];
|
||||
GeDisassembleOp(curPc, op, prev, temp);
|
||||
data[curPc] = temp;
|
||||
prev = op;
|
||||
if(cmd == GE_CMD_JUMP)
|
||||
{
|
||||
u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0x0FFFFFFF;
|
||||
FillDisplayListCmd(data, target, prev);
|
||||
return;
|
||||
}
|
||||
else if(cmd == GE_CMD_CALL)
|
||||
{
|
||||
u32 target = gstate_c.getRelativeAddress(op & 0xFFFFFF);
|
||||
FillDisplayListCmd(data, target, prev);
|
||||
}
|
||||
else if(cmd == GE_CMD_RET)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if(cmd == GE_CMD_FINISH)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if(cmd == GE_CMD_END)
|
||||
{
|
||||
if(prev >> 24 == GE_CMD_FINISH)
|
||||
return;
|
||||
}
|
||||
curPc += 4;
|
||||
debugLimit--;
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger_Disasm::on_nextGPU_clicked()
|
||||
{
|
||||
host->SetGPUStep(true);
|
||||
host->NextGPUStep();
|
||||
}
|
||||
|
||||
void Debugger_Disasm::on_runBtn_clicked()
|
||||
{
|
||||
host->SetGPUStep(false);
|
||||
host->NextGPUStep();
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ public:
|
|||
void UpdateDisplayList();
|
||||
protected:
|
||||
void showEvent(QShowEvent *);
|
||||
void FillDisplayListCmd(std::map<int,std::string>& data, u32 pc, u32 prev);
|
||||
|
||||
signals:
|
||||
void updateDisplayList_();
|
||||
|
@ -52,7 +51,6 @@ public slots:
|
|||
void Goto(u32 addr);
|
||||
void RemoveBreakpoint();
|
||||
void GotoThreadEntryPoint();
|
||||
void ShowDLCode();
|
||||
|
||||
private slots:
|
||||
void UpdateDisplayListGUI();
|
||||
|
@ -103,9 +101,6 @@ private slots:
|
|||
void SetThreadStatusSuspend();
|
||||
void on_displayList_customContextMenuRequested(const QPoint &pos);
|
||||
|
||||
void on_nextGPU_clicked();
|
||||
|
||||
void on_runBtn_clicked();
|
||||
|
||||
private:
|
||||
void SetThreadStatus(ThreadStatus status);
|
||||
|
|
|
@ -313,7 +313,7 @@
|
|||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget_2">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_3">
|
||||
<attribute name="title">
|
||||
|
@ -424,70 +424,6 @@
|
|||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="displayListData">
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">2</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="runBtn">
|
||||
<property name="text">
|
||||
<string>Run</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="nextGPU">
|
||||
<property name="text">
|
||||
<string>Step</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
1850
Qt/debugger_displaylist.cpp
Normal file
1850
Qt/debugger_displaylist.cpp
Normal file
File diff suppressed because it is too large
Load diff
124
Qt/debugger_displaylist.h
Normal file
124
Qt/debugger_displaylist.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
#ifndef DEBUGGER_DISPLAYLIST_H
|
||||
#define DEBUGGER_DISPLAYLIST_H
|
||||
|
||||
#include "Core/Debugger/DebugInterface.h"
|
||||
#include <QDialog>
|
||||
#include <QTreeWidgetItem>
|
||||
#include "GPU/GPUState.h"
|
||||
#include "native/gfx_es2/fbo.h"
|
||||
|
||||
class MainWindow;
|
||||
namespace Ui {
|
||||
class Debugger_DisplayList;
|
||||
}
|
||||
|
||||
|
||||
class DListLine
|
||||
{
|
||||
public:
|
||||
u32 addr;
|
||||
u32 cmd;
|
||||
u32 data;
|
||||
QString comment;
|
||||
bool implementationNotFinished;
|
||||
u32 texAddr;
|
||||
u32 fboAddr;
|
||||
u32 vtxAddr;
|
||||
int vtxStart;
|
||||
int vtxCount;
|
||||
u32 idxAddr;
|
||||
int idxStart;
|
||||
int idxCount;
|
||||
};
|
||||
|
||||
class Debugger_DisplayList : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Debugger_DisplayList(DebugInterface *_cpu, MainWindow *mainWindow_, QWidget *parent = 0);
|
||||
~Debugger_DisplayList();
|
||||
|
||||
void UpdateDisplayList();
|
||||
|
||||
void ShowDLCode();
|
||||
void FillDisplayListCmd(std::map<int,DListLine> &data, u32 pc, u32 prev, GPUgstate &state);
|
||||
void Update();
|
||||
void UpdateRenderBuffer();
|
||||
void UpdateRenderBufferList();
|
||||
void UpdateVertexInfo();
|
||||
void UpdateIndexInfo();
|
||||
protected:
|
||||
void showEvent(QShowEvent *);
|
||||
|
||||
signals:
|
||||
void updateDisplayList_();
|
||||
void updateRenderBufferList_();
|
||||
void updateRenderBuffer_();
|
||||
|
||||
private slots:
|
||||
void UpdateDisplayListGUI();
|
||||
void UpdateRenderBufferListGUI();
|
||||
void UpdateRenderBufferGUI();
|
||||
void releaseLock();
|
||||
|
||||
void on_displayList_itemClicked(QTreeWidgetItem *item, int column);
|
||||
|
||||
void on_stepBtn_clicked();
|
||||
|
||||
void on_runBtn_clicked();
|
||||
|
||||
void on_stopBtn_clicked();
|
||||
|
||||
void on_nextDrawBtn_clicked();
|
||||
|
||||
void on_gotoPCBtn_clicked();
|
||||
|
||||
void on_texturesList_itemDoubleClicked(QTreeWidgetItem *item, int column);
|
||||
|
||||
void on_comboBox_currentIndexChanged(int index);
|
||||
|
||||
void on_fboList_itemClicked(QTreeWidgetItem *item, int column);
|
||||
|
||||
void on_nextDLBtn_clicked();
|
||||
void setCurrentFBO(u32 addr);
|
||||
|
||||
void on_zoommBtn_clicked();
|
||||
|
||||
void on_zoompBtn_clicked();
|
||||
|
||||
void on_vertexList_itemClicked(QTreeWidgetItem *item, int column);
|
||||
|
||||
void on_pushButton_clicked();
|
||||
|
||||
void on_nextIdx_clicked();
|
||||
|
||||
void on_indexList_itemClicked(QTreeWidgetItem *item, int column);
|
||||
|
||||
void on_displayListData_customContextMenuRequested(const QPoint &pos);
|
||||
|
||||
void on_texturesList_customContextMenuRequested(const QPoint &pos);
|
||||
void RunToDLPC();
|
||||
void RunToDrawTex();
|
||||
|
||||
private:
|
||||
QString DisassembleOp(u32 pc, u32 op, u32 prev, const GPUgstate &state);
|
||||
|
||||
Ui::Debugger_DisplayList *ui;
|
||||
DebugInterface* cpu;
|
||||
MainWindow* mainWindow;
|
||||
QTreeWidgetItem* displayListRowSelected;
|
||||
QTreeWidgetItem* displayListDataSelected;
|
||||
QTreeWidgetItem* textureDataSelected;
|
||||
int currentRenderFrameDisplay;
|
||||
FBO* currentTextureDisplay;
|
||||
float fboZoomFactor;
|
||||
int maxVtxDisplay;
|
||||
int maxIdxDisplay;
|
||||
|
||||
std::vector<GPUgstate> drawGPUState;
|
||||
std::map<u32, int> vtxBufferSize;
|
||||
std::map<u32, int> idxBufferSize;
|
||||
};
|
||||
|
||||
#endif // DEBUGGER_DISPLAYLIST_H
|
533
Qt/debugger_displaylist.ui
Normal file
533
Qt/debugger_displaylist.ui
Normal file
|
@ -0,0 +1,533 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Debugger_DisplayList</class>
|
||||
<widget class="QDialog" name="Debugger_DisplayList">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>795</width>
|
||||
<height>506</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QSplitter" name="splitter_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>DisplayList</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="displayList">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>30</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Id</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Status</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Start Address</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Current Address</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="runBtn">
|
||||
<property name="text">
|
||||
<string>Run</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="stopBtn">
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="nextDLBtn">
|
||||
<property name="text">
|
||||
<string>Next DL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QTabWidget" name="displayListInfo">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Commands</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="displayListData">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">2</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="stepBtn">
|
||||
<property name="text">
|
||||
<string>Step</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="nextDrawBtn">
|
||||
<property name="text">
|
||||
<string>Next Draw</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="gotoPCBtn">
|
||||
<property name="text">
|
||||
<string>Goto PC</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Textures</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="texturesList">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Width</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Height</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Format</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3">
|
||||
<attribute name="title">
|
||||
<string>Vertex Buffer</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="vertexList">
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>30</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">Address</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Coord Type</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Number Morph</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Number Weights</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Has Weight</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Has Position</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Has Normal</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Has Color</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Has UV</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="vertexData">
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>30</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">Idx</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Values</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Next 20</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_4">
|
||||
<attribute name="title">
|
||||
<string>Index Buffer</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QTreeWidget" name="indexList">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">Address</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
<widget class="QTreeWidget" name="indexData">
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>30</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Idx</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">Adress</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Value</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QPushButton" name="nextIdx">
|
||||
<property name="text">
|
||||
<string>Next 20</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Framebuffer</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QTreeWidget" name="fboList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>VAddress</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Width</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Height</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Format</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
<widget class="QScrollArea" name="fboScroll">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>375</width>
|
||||
<height>76</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="fboImg">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Display : </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Color</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Depth</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="zoommBtn">
|
||||
<property name="text">
|
||||
<string>Zoom-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="zoompBtn">
|
||||
<property name="text">
|
||||
<string>Zoom+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -51,9 +51,7 @@ void Debugger_Memory::Goto(u32 addr)
|
|||
|
||||
void Debugger_Memory::on_editAddress_textChanged(const QString &arg1)
|
||||
{
|
||||
u32 addr;
|
||||
sscanf(arg1.toStdString().c_str(),"%08x",&addr);
|
||||
ui->memView->gotoAddr(addr & ~3);
|
||||
ui->memView->gotoAddr(arg1.toInt(0,16) & ~3);
|
||||
}
|
||||
|
||||
void Debugger_Memory::on_normalBtn_clicked()
|
||||
|
@ -83,7 +81,7 @@ void Debugger_Memory::NotifyMapLoaded()
|
|||
if(symbolMap.GetSymbolType(i) & ST_DATA)
|
||||
{
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
item->setText(QString(symbolMap.GetSymbolName(i)) + " ("+ QVariant(symbolMap.GetSymbolSize(i)).toString() +")");
|
||||
item->setText(QString(symbolMap.GetSymbolName(i)) + " ("+ QString::number(symbolMap.GetSymbolSize(i)) +")");
|
||||
item->setData(Qt::UserRole, symbolMap.GetAddress(i));
|
||||
ui->symbols->addItem(item);
|
||||
}
|
||||
|
|
95
Qt/debugger_memorytex.cpp
Normal file
95
Qt/debugger_memorytex.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
#include "debugger_memorytex.h"
|
||||
#include "gfx_es2/gl_state.h"
|
||||
#include "gfx/gl_common.h"
|
||||
#include "gfx/gl_lost_manager.h"
|
||||
#include "ui_debugger_memorytex.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include <QImage>
|
||||
#include <QTimer>
|
||||
#include "Core/HLE/sceDisplay.h"
|
||||
#include "GPU/GPUInterface.h"
|
||||
#include "EmuThread.h"
|
||||
#include "base/display.h"
|
||||
|
||||
Debugger_MemoryTex::Debugger_MemoryTex(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::Debugger_MemoryTex)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
Debugger_MemoryTex::~Debugger_MemoryTex()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
void Debugger_MemoryTex::showEvent(QShowEvent *)
|
||||
{
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
// Hack to remove the X11 crash with threaded opengl when opening the first dialog
|
||||
EmuThread_LockDraw(true);
|
||||
QTimer::singleShot(100, this, SLOT(releaseLock()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Debugger_MemoryTex::releaseLock()
|
||||
{
|
||||
EmuThread_LockDraw(false);
|
||||
}
|
||||
|
||||
|
||||
void Debugger_MemoryTex::ShowTex(const GPUgstate &state)
|
||||
{
|
||||
ui->texaddr->setText(QString("%1").arg(state.texaddr[0] & 0xFFFFFF,8,16,QChar('0')));
|
||||
ui->texbufwidth0->setText(QString("%1").arg(state.texbufwidth[0] & 0xFFFFFF,8,16,QChar('0')));
|
||||
ui->texformat->setText(QString("%1").arg(state.texformat & 0xFFFFFF,8,16,QChar('0')));
|
||||
ui->texsize->setText(QString("%1").arg(state.texsize[0] & 0xFFFFFF,8,16,QChar('0')));
|
||||
ui->texmode->setText(QString("%1").arg(state.texmode & 0xFFFFFF,8,16,QChar('0')));
|
||||
ui->clutformat->setText(QString("%1").arg(state.clutformat & 0xFFFFFF,8,16,QChar('0')));
|
||||
ui->clutaddr->setText(QString("%1").arg(state.clutaddr & 0xFFFFFF,8,16,QChar('0')));
|
||||
ui->clutaddrupper->setText(QString("%1").arg(state.clutaddrupper & 0xFFFFFF,8,16,QChar('0')));
|
||||
ui->loadclut->setText(QString("%1").arg(state.loadclut & 0xFFFFFF,8,16,QChar('0')));
|
||||
on_readBtn_clicked();
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
void Debugger_MemoryTex::on_readBtn_clicked()
|
||||
{
|
||||
EmuThread_LockDraw(true);
|
||||
|
||||
GPUgstate state;
|
||||
state.texaddr[0] = ui->texaddr->text().toInt(0,16);
|
||||
state.texbufwidth[0] = ui->texbufwidth0->text().toInt(0,16);
|
||||
state.texformat = ui->texformat->text().toInt(0,16);
|
||||
state.texsize[0] = ui->texsize->text().toInt(0,16);
|
||||
state.texmode = ui->texmode->text().toInt(0,16);
|
||||
state.clutformat = ui->clutformat->text().toInt(0,16);
|
||||
state.clutaddr = ui->clutaddr->text().toInt(0,16);
|
||||
state.clutaddrupper = ui->clutaddrupper->text().toInt(0,16);
|
||||
state.loadclut = ui->loadclut->text().toInt(0,16);
|
||||
int bufW = state.texbufwidth[0] & 0x3ff;
|
||||
int w = 1 << (state.texsize[0] & 0xf);
|
||||
int h = 1 << ((state.texsize[0]>>8) & 0xf);
|
||||
w = std::max(bufW,w);
|
||||
uchar* newData = new uchar[w*h*4];
|
||||
|
||||
if(gpu->DecodeTexture(newData, state))
|
||||
{
|
||||
QImage img = QImage(newData, w, h, w*4, QImage::Format_ARGB32); // EmuThread_GrabBackBuffer();
|
||||
|
||||
QPixmap pixmap = QPixmap::fromImage(img);
|
||||
ui->textureImg->setPixmap(pixmap);
|
||||
ui->textureImg->setMinimumWidth(pixmap.width());
|
||||
ui->textureImg->setMinimumHeight(pixmap.height());
|
||||
ui->textureImg->setMaximumWidth(pixmap.width());
|
||||
ui->textureImg->setMaximumHeight(pixmap.height());
|
||||
}
|
||||
|
||||
delete[] newData;
|
||||
EmuThread_LockDraw(false);
|
||||
|
||||
|
||||
}
|
30
Qt/debugger_memorytex.h
Normal file
30
Qt/debugger_memorytex.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef DEBUGGER_MEMORYTEX_H
|
||||
#define DEBUGGER_MEMORYTEX_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "GPU/GPUState.h"
|
||||
|
||||
namespace Ui {
|
||||
class Debugger_MemoryTex;
|
||||
}
|
||||
|
||||
class Debugger_MemoryTex : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Debugger_MemoryTex(QWidget *parent = 0);
|
||||
~Debugger_MemoryTex();
|
||||
|
||||
void ShowTex(const GPUgstate& state);
|
||||
protected:
|
||||
void showEvent(QShowEvent *);
|
||||
private slots:
|
||||
void releaseLock();
|
||||
void on_readBtn_clicked();
|
||||
|
||||
private:
|
||||
Ui::Debugger_MemoryTex *ui;
|
||||
};
|
||||
|
||||
#endif // DEBUGGER_MEMORYTEX_H
|
177
Qt/debugger_memorytex.ui
Normal file
177
Qt/debugger_memorytex.ui
Normal file
|
@ -0,0 +1,177 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Debugger_MemoryTex</class>
|
||||
<widget class="QDialog" name="Debugger_MemoryTex">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>768</width>
|
||||
<height>546</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>TexAddr</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>TexBufWidth0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>TexFormat</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>TexSize</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>ClutFormat</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>ClutAddr</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>ClutAddrUpper</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>LoadClut</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="texaddr"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="texbufwidth0"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="texformat"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="texsize"/>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="clutformat"/>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLineEdit" name="clutaddr"/>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QLineEdit" name="clutaddrupper"/>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QLineEdit" name="loadclut"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>TexMode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="texmode"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="readBtn">
|
||||
<property name="text">
|
||||
<string>Read</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QScrollArea" name="texture">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>76</width>
|
||||
<height>526</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="textureImg">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -28,7 +28,9 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
ui(new Ui::MainWindow),
|
||||
nextState(CORE_POWERDOWN),
|
||||
dialogDisasm(0),
|
||||
memoryWindow(0)
|
||||
memoryWindow(0),
|
||||
memoryTexWindow(0),
|
||||
displaylistWindow(0)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
qApp->installEventFilter(this);
|
||||
|
@ -109,15 +111,11 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co
|
|||
gfxLog = true;
|
||||
break;
|
||||
case 'j':
|
||||
g_Config.iCpuCore = CPU_JIT;
|
||||
g_Config.bSaveSettings = false;
|
||||
break;
|
||||
case 'f':
|
||||
g_Config.iCpuCore = CPU_FASTINTERPRETER;
|
||||
g_Config.bJit = true;
|
||||
g_Config.bSaveSettings = false;
|
||||
break;
|
||||
case 'i':
|
||||
g_Config.iCpuCore = CPU_INTERPRETER;
|
||||
g_Config.bJit = false;
|
||||
g_Config.bSaveSettings = false;
|
||||
break;
|
||||
case 'l':
|
||||
|
@ -210,6 +208,8 @@ void MainWindow::Boot()
|
|||
on_action_OptionsFullScreen_triggered();
|
||||
|
||||
memoryWindow = new Debugger_Memory(currentDebugMIPS, this, this);
|
||||
memoryTexWindow = new Debugger_MemoryTex(this);
|
||||
displaylistWindow = new Debugger_DisplayList(currentDebugMIPS, this, this);
|
||||
|
||||
if (dialogDisasm)
|
||||
dialogDisasm->NotifyMapLoaded();
|
||||
|
@ -231,9 +231,8 @@ void MainWindow::UpdateMenus()
|
|||
{
|
||||
ui->action_OptionsDisplayRawFramebuffer->setChecked(g_Config.bDisplayFramebuffer);
|
||||
ui->action_OptionsIgnoreIllegalReadsWrites->setChecked(g_Config.bIgnoreBadMemAccess);
|
||||
ui->action_CPUInterpreter->setChecked(g_Config.iCpuCore == CPU_INTERPRETER);
|
||||
ui->action_CPUFastInterpreter->setChecked(g_Config.iCpuCore == CPU_FASTINTERPRETER);
|
||||
ui->action_CPUDynarec->setChecked(g_Config.iCpuCore == CPU_JIT);
|
||||
ui->action_CPUInterpreter->setChecked(!g_Config.bJit);
|
||||
ui->action_CPUDynarec->setChecked(g_Config.bJit);
|
||||
ui->action_OptionsBufferedRendering->setChecked(g_Config.bBufferedRendering);
|
||||
ui->action_OptionsShowDebugStatistics->setChecked(g_Config.bShowDebugStats);
|
||||
ui->action_OptionsWireframe->setChecked(g_Config.bDrawWireframe);
|
||||
|
@ -266,11 +265,12 @@ void MainWindow::UpdateMenus()
|
|||
ui->action_FileQuickSaveState->setEnabled(!enable);
|
||||
ui->action_CPUDynarec->setEnabled(enable);
|
||||
ui->action_CPUInterpreter->setEnabled(enable);
|
||||
ui->action_CPUFastInterpreter->setEnabled(enable);
|
||||
ui->action_EmulationStop->setEnabled(!enable);
|
||||
ui->action_DebugDumpFrame->setEnabled(!enable);
|
||||
ui->action_DebugDisassembly->setEnabled(!enable);
|
||||
ui->action_DebugMemoryView->setEnabled(!enable);
|
||||
ui->action_DebugMemoryViewTexture->setEnabled(!enable);
|
||||
ui->action_DebugDisplayList->setEnabled(!enable);
|
||||
|
||||
ui->action_OptionsScreen1x->setChecked(0 == (g_Config.iWindowZoom - 1));
|
||||
ui->action_OptionsScreen2x->setChecked(1 == (g_Config.iWindowZoom - 1));
|
||||
|
@ -359,6 +359,10 @@ void MainWindow::on_action_EmulationStop_triggered()
|
|||
dialogDisasm->close();
|
||||
if(memoryWindow && memoryWindow->isVisible())
|
||||
memoryWindow->close();
|
||||
if(memoryTexWindow && memoryTexWindow->isVisible())
|
||||
memoryTexWindow->close();
|
||||
if(displaylistWindow && displaylistWindow->isVisible())
|
||||
displaylistWindow->close();
|
||||
|
||||
EmuThread_StopGame();
|
||||
SetGameTitle("");
|
||||
|
@ -518,19 +522,13 @@ void MainWindow::on_action_FileExit_triggered()
|
|||
|
||||
void MainWindow::on_action_CPUDynarec_triggered()
|
||||
{
|
||||
g_Config.iCpuCore = CPU_JIT;
|
||||
g_Config.bJit = true;
|
||||
UpdateMenus();
|
||||
}
|
||||
|
||||
void MainWindow::on_action_CPUInterpreter_triggered()
|
||||
{
|
||||
g_Config.iCpuCore = CPU_INTERPRETER;
|
||||
UpdateMenus();
|
||||
}
|
||||
|
||||
void MainWindow::on_action_CPUFastInterpreter_triggered()
|
||||
{
|
||||
g_Config.iCpuCore = CPU_FASTINTERPRETER;
|
||||
g_Config.bJit = false;
|
||||
UpdateMenus();
|
||||
}
|
||||
|
||||
|
@ -697,22 +695,12 @@ void MainWindow::keyPressEvent(QKeyEvent *e)
|
|||
return;
|
||||
}
|
||||
|
||||
for (int b = 0; b < controllistCount; b++) {
|
||||
if (e->key() == controllist[b].key)
|
||||
{
|
||||
input_state.pad_buttons |= (controllist[b].emu_id);
|
||||
}
|
||||
}
|
||||
pressedKeys.insert(e->key());
|
||||
}
|
||||
|
||||
void MainWindow::keyReleaseEvent(QKeyEvent *e)
|
||||
{
|
||||
for (int b = 0; b < controllistCount; b++) {
|
||||
if (e->key() == controllist[b].key)
|
||||
{
|
||||
input_state.pad_buttons &= ~(controllist[b].emu_id);
|
||||
}
|
||||
}
|
||||
pressedKeys.remove(e->key());
|
||||
}
|
||||
|
||||
void MainWindow::on_MainWindow_destroyed()
|
||||
|
@ -928,7 +916,17 @@ void MainWindow::ShowMemory(u32 addr)
|
|||
|
||||
void MainWindow::Update()
|
||||
{
|
||||
UpdateInputState(&input_state);
|
||||
|
||||
for (int i = 0; i < controllistCount; i++)
|
||||
{
|
||||
if (pressedKeys.contains(controllist[i].key) ||
|
||||
input_state.pad_buttons_down & controllist[i].emu_id)
|
||||
__CtrlButtonDown(controllist[i].psp_id);
|
||||
else
|
||||
__CtrlButtonUp(controllist[i].psp_id);
|
||||
}
|
||||
__CtrlSetAnalog(input_state.pad_lstick_x, input_state.pad_lstick_y);
|
||||
}
|
||||
|
||||
void MainWindow::on_action_EmulationReset_triggered()
|
||||
|
@ -943,6 +941,10 @@ void MainWindow::on_action_EmulationReset_triggered()
|
|||
dialogDisasm->close();
|
||||
if(memoryWindow)
|
||||
memoryWindow->close();
|
||||
if(memoryTexWindow)
|
||||
memoryTexWindow->close();
|
||||
if(displaylistWindow)
|
||||
displaylistWindow->close();
|
||||
|
||||
EmuThread_StopGame();
|
||||
|
||||
|
@ -1027,3 +1029,15 @@ void MainWindow::on_action_Sound_triggered()
|
|||
g_Config.bEnableSound = !g_Config.bEnableSound;
|
||||
UpdateMenus();
|
||||
}
|
||||
|
||||
void MainWindow::on_action_DebugMemoryViewTexture_triggered()
|
||||
{
|
||||
if(memoryTexWindow)
|
||||
memoryTexWindow->show();
|
||||
}
|
||||
|
||||
void MainWindow::on_action_DebugDisplayList_triggered()
|
||||
{
|
||||
if(displaylistWindow)
|
||||
displaylistWindow->show();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "input/input_state.h"
|
||||
#include "debugger_disasm.h"
|
||||
#include "debugger_memory.h"
|
||||
#include "debugger_memorytex.h"
|
||||
#include "debugger_displaylist.h"
|
||||
#include "controls.h"
|
||||
#include "gamepaddialog.h"
|
||||
|
||||
|
@ -33,6 +35,8 @@ public:
|
|||
|
||||
Debugger_Disasm* GetDialogDisasm() { return dialogDisasm; }
|
||||
Debugger_Memory* GetDialogMemory() { return memoryWindow; }
|
||||
Debugger_MemoryTex* GetDialogMemoryTex() { return memoryTexWindow; }
|
||||
Debugger_DisplayList* GetDialogDisplaylist() { return displaylistWindow; }
|
||||
CoreState GetNextState() { return nextState; }
|
||||
void closeEvent(QCloseEvent *event);
|
||||
void keyPressEvent(QKeyEvent *);
|
||||
|
@ -81,8 +85,6 @@ private slots:
|
|||
|
||||
void on_action_CPUInterpreter_triggered();
|
||||
|
||||
void on_action_CPUFastInterpreter_triggered();
|
||||
|
||||
void on_action_DebugLoadMapFile_triggered();
|
||||
|
||||
void on_action_DebugSaveMapFile_triggered();
|
||||
|
@ -171,6 +173,10 @@ private slots:
|
|||
|
||||
void on_action_Sound_triggered();
|
||||
|
||||
void on_action_DebugMemoryViewTexture_triggered();
|
||||
|
||||
void on_action_DebugDisplayList_triggered();
|
||||
|
||||
private:
|
||||
void loadLanguage(const QString &language);
|
||||
void createLanguageMenu();
|
||||
|
@ -190,8 +196,12 @@ private:
|
|||
|
||||
Debugger_Disasm *dialogDisasm;
|
||||
Debugger_Memory *memoryWindow;
|
||||
Debugger_MemoryTex *memoryTexWindow;
|
||||
Debugger_DisplayList *displaylistWindow;
|
||||
Controls* controls;
|
||||
GamePadDialog* gamePadDlg;
|
||||
|
||||
QSet<int> pressedKeys;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>21</height>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
|
@ -83,8 +83,10 @@
|
|||
<addaction name="action_DebugDumpFrame"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_DebugDisassembly"/>
|
||||
<addaction name="action_DebugDisplayList"/>
|
||||
<addaction name="action_DebugLog"/>
|
||||
<addaction name="action_DebugMemoryView"/>
|
||||
<addaction name="action_DebugMemoryViewTexture"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Options">
|
||||
<property name="title">
|
||||
|
@ -180,7 +182,6 @@
|
|||
<string>&Core</string>
|
||||
</property>
|
||||
<addaction name="action_CPUInterpreter"/>
|
||||
<addaction name="action_CPUFastInterpreter"/>
|
||||
<addaction name="action_CPUDynarec"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_OptionsFastMemory"/>
|
||||
|
@ -289,14 +290,6 @@
|
|||
<string>&Interpreter</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_CPUFastInterpreter">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Slightly Faster Interpreter</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_CPUDynarec">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
|
@ -625,6 +618,11 @@
|
|||
<string>Memory View Texture...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_DebugDisplayList">
|
||||
<property name="text">
|
||||
<string>DisplayList...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Simple_2xAA">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
|
|
|
@ -68,7 +68,7 @@ DWORD TheThread(LPVOID x)
|
|||
coreParameter.fileToStart = fileToStart;
|
||||
coreParameter.enableSound = true;
|
||||
coreParameter.gpuCore = GPU_GLES;
|
||||
coreParameter.cpuCore = (CPUCore)g_Config.iCpuCore;
|
||||
coreParameter.cpuCore = g_Config.bJit ? CPU_JIT : CPU_INTERPRETER;
|
||||
coreParameter.enableDebugging = true;
|
||||
coreParameter.printfEmuLog = false;
|
||||
coreParameter.headLess = false;
|
||||
|
|
|
@ -49,14 +49,7 @@ void GL_Resized() // Resize And Initialize The GL Window
|
|||
glstate.viewport.restore();
|
||||
}
|
||||
|
||||
|
||||
void GL_BeginFrame()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GL_EndFrame()
|
||||
void GL_SwapBuffers()
|
||||
{
|
||||
SwapBuffers(hDC);
|
||||
}
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
bool GL_Init(HWND window);
|
||||
void GL_Shutdown();
|
||||
void GL_Resized();
|
||||
void GL_BeginFrame();
|
||||
void GL_EndFrame();
|
||||
void GL_SwapBuffers();
|
||||
|
|
|
@ -209,10 +209,12 @@
|
|||
<None Include="..\android\atlasscript.txt">
|
||||
<Filter>Android</Filter>
|
||||
</None>
|
||||
<None Include="..\CMakeLists.txt" />
|
||||
<None Include="..\android\jni\Application.mk">
|
||||
<Filter>Android</Filter>
|
||||
</None>
|
||||
<None Include="..\CMakeLists.txt">
|
||||
<Filter>Windows</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="ppsspp.rc">
|
||||
|
|
|
@ -117,11 +117,6 @@ void WindowsHost::BeginFrame()
|
|||
for (auto iter = this->input.begin(); iter != this->input.end(); iter++)
|
||||
if ((*iter)->UpdateState() == 0)
|
||||
break; // *iter is std::shared_ptr, **iter is InputDevice
|
||||
GL_BeginFrame();
|
||||
}
|
||||
void WindowsHost::EndFrame()
|
||||
{
|
||||
GL_EndFrame();
|
||||
}
|
||||
|
||||
void WindowsHost::BootDone()
|
||||
|
|
|
@ -21,7 +21,6 @@ public:
|
|||
|
||||
void InitGL();
|
||||
void BeginFrame();
|
||||
void EndFrame();
|
||||
void ShutdownGL();
|
||||
|
||||
void InitSound(PMixer *mixer);
|
||||
|
|
|
@ -73,8 +73,7 @@ namespace MainWindow
|
|||
|
||||
void Init(HINSTANCE hInstance)
|
||||
{
|
||||
#ifdef THEMES
|
||||
WTL::CTheme::IsThemingSupported();
|
||||
#ifdef THEMES WTL::CTheme::IsThemingSupported();
|
||||
#endif
|
||||
//Register classes
|
||||
WNDCLASSEX wcex;
|
||||
|
@ -447,20 +446,21 @@ namespace MainWindow
|
|||
gpu->Resized(); // easy way to force a clear...
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_FRAMESKIP:
|
||||
g_Config.iFrameSkip = !g_Config.iFrameSkip;
|
||||
UpdateMenus();
|
||||
break;
|
||||
|
||||
case ID_FILE_EXIT:
|
||||
DestroyWindow(hWnd);
|
||||
break;
|
||||
|
||||
case ID_CPU_DYNAREC:
|
||||
g_Config.iCpuCore = CPU_JIT;
|
||||
g_Config.bJit = true;
|
||||
UpdateMenus();
|
||||
break;
|
||||
case ID_CPU_INTERPRETER:
|
||||
g_Config.iCpuCore = CPU_INTERPRETER;
|
||||
UpdateMenus();
|
||||
break;
|
||||
case ID_CPU_FASTINTERPRETER:
|
||||
g_Config.iCpuCore = CPU_FASTINTERPRETER;
|
||||
g_Config.bJit = false;
|
||||
UpdateMenus();
|
||||
break;
|
||||
|
||||
|
@ -701,9 +701,8 @@ namespace MainWindow
|
|||
// CHECK(ID_OPTIONS_EMULATESYSCALL,g_bEmulateSyscall);
|
||||
CHECKITEM(ID_OPTIONS_DISPLAYRAWFRAMEBUFFER, g_Config.bDisplayFramebuffer);
|
||||
CHECKITEM(ID_OPTIONS_IGNOREILLEGALREADS,g_Config.bIgnoreBadMemAccess);
|
||||
CHECKITEM(ID_CPU_INTERPRETER,g_Config.iCpuCore == CPU_INTERPRETER);
|
||||
CHECKITEM(ID_CPU_FASTINTERPRETER,g_Config.iCpuCore == CPU_FASTINTERPRETER);
|
||||
CHECKITEM(ID_CPU_DYNAREC,g_Config.iCpuCore == CPU_JIT);
|
||||
CHECKITEM(ID_CPU_INTERPRETER,g_Config.bJit == false);
|
||||
CHECKITEM(ID_CPU_DYNAREC,g_Config.bJit == true);
|
||||
CHECKITEM(ID_OPTIONS_BUFFEREDRENDERING, g_Config.bBufferedRendering);
|
||||
CHECKITEM(ID_OPTIONS_SHOWDEBUGSTATISTICS, g_Config.bShowDebugStats);
|
||||
CHECKITEM(ID_OPTIONS_WIREFRAME, g_Config.bDrawWireframe);
|
||||
|
@ -717,6 +716,7 @@ namespace MainWindow
|
|||
CHECKITEM(ID_OPTIONS_DISABLEG3DLOG, g_Config.bDisableG3DLog);
|
||||
CHECKITEM(ID_OPTIONS_VERTEXCACHE, g_Config.bVertexCache);
|
||||
CHECKITEM(ID_OPTIONS_SHOWFPS, g_Config.bShowFPSCounter);
|
||||
CHECKITEM(ID_OPTIONS_FRAMESKIP, g_Config.iFrameSkip != 0);
|
||||
|
||||
UINT enable = !Core_IsStepping() ? MF_GRAYED : MF_ENABLED;
|
||||
EnableMenuItem(menu,ID_EMULATION_RUN, g_State.bEmuThreadStarted ? enable : MF_GRAYED);
|
||||
|
@ -731,7 +731,6 @@ namespace MainWindow
|
|||
EnableMenuItem(menu,ID_FILE_QUICKLOADSTATE,!enable);
|
||||
EnableMenuItem(menu,ID_CPU_DYNAREC,enable);
|
||||
EnableMenuItem(menu,ID_CPU_INTERPRETER,enable);
|
||||
EnableMenuItem(menu,ID_CPU_FASTINTERPRETER,enable);
|
||||
EnableMenuItem(menu,ID_DVD_INSERTISO,enable);
|
||||
EnableMenuItem(menu,ID_FILE_BOOTBIOS,enable);
|
||||
EnableMenuItem(menu,ID_EMULATION_STOP,!enable);
|
||||
|
|
|
@ -76,15 +76,11 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
|||
switch (__argv[i][1])
|
||||
{
|
||||
case 'j':
|
||||
g_Config.iCpuCore = CPU_JIT;
|
||||
g_Config.bJit = true;
|
||||
g_Config.bSaveSettings = false;
|
||||
break;
|
||||
case 'i':
|
||||
g_Config.iCpuCore = CPU_INTERPRETER;
|
||||
g_Config.bSaveSettings = false;
|
||||
break;
|
||||
case 'f':
|
||||
g_Config.iCpuCore = CPU_FASTINTERPRETER;
|
||||
g_Config.bJit = false;
|
||||
g_Config.bSaveSettings = false;
|
||||
break;
|
||||
case 'l':
|
||||
|
@ -163,9 +159,12 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
|||
|
||||
EmuThread_Start(fileToStart);
|
||||
}
|
||||
else
|
||||
if (g_Config.bBrowse)
|
||||
MainWindow::BrowseAndBoot();
|
||||
|
||||
if (!hideLog)
|
||||
SetForegroundWindow(hwndMain);
|
||||
|
||||
if (fileToStart != NULL && stateToLoad != NULL)
|
||||
SaveState::Load(stateToLoad);
|
||||
|
||||
|
|
Binary file not shown.
|
@ -260,6 +260,7 @@
|
|||
#define ID_OPTIONS_VERTEXCACHE 40136
|
||||
#define ID_OPTIONS_SHOWFPS 40137
|
||||
#define ID_OPTIONS_STRETCHDISPLAY 40138
|
||||
#define ID_OPTIONS_FRAMESKIP 40139
|
||||
#define IDC_STATIC -1
|
||||
|
||||
// Next default values for new objects
|
||||
|
@ -267,7 +268,7 @@
|
|||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 233
|
||||
#define _APS_NEXT_COMMAND_VALUE 40139
|
||||
#define _APS_NEXT_COMMAND_VALUE 40140
|
||||
#define _APS_NEXT_CONTROL_VALUE 1163
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.ppsspp.ppsspp"
|
||||
android:versionCode="61"
|
||||
android:versionName="0.61" >
|
||||
android:versionName="0.61"
|
||||
android:installLocation="auto" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8"/>
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ EmuScreen::EmuScreen(const std::string &filename) : invalid_(true)
|
|||
INFO_LOG(BOOT, "Starting up hardware.");
|
||||
|
||||
CoreParameter coreParam;
|
||||
coreParam.cpuCore = (CPUCore)g_Config.iCpuCore;
|
||||
coreParam.cpuCore = g_Config.bJit ? CPU_JIT : CPU_INTERPRETER;
|
||||
coreParam.gpuCore = GPU_GLES;
|
||||
coreParam.enableSound = g_Config.bEnableSound;
|
||||
coreParam.fileToStart = fileToStart;
|
||||
|
@ -156,7 +156,7 @@ void EmuScreen::render()
|
|||
|
||||
// We just run the CPU until we get to vblank. This will quickly sync up pretty nicely.
|
||||
// The actual number of cycles doesn't matter so much here as we will break due to CORE_NEXTFRAME, most of the time hopefully...
|
||||
int blockTicks = usToCycles(1000000 / 2);
|
||||
int blockTicks = usToCycles(1000000 / 10);
|
||||
|
||||
// Run until CORE_NEXTFRAME
|
||||
while (coreState == CORE_RUNNING) {
|
||||
|
|
|
@ -251,6 +251,9 @@ void InGameMenuScreen::render() {
|
|||
UICheckBox(GEN_ID, x, y += 50, "Stretch to display", ALIGN_TOPLEFT, &g_Config.bStretchToDisplay);
|
||||
|
||||
UICheckBox(GEN_ID, x, y += 50, "Hardware Transform", ALIGN_TOPLEFT, &g_Config.bHardwareTransform);
|
||||
bool fs = g_Config.iFrameSkip == 1;
|
||||
UICheckBox(GEN_ID, x, y += 50, "Frameskip", ALIGN_TOPLEFT, &fs);
|
||||
g_Config.iFrameSkip = fs ? 1 : 0;
|
||||
|
||||
// TODO: Add UI for more than one slot.
|
||||
VLinear vlinear1(x, y + 80, 20);
|
||||
|
@ -314,11 +317,9 @@ void SettingsScreen::render() {
|
|||
UICheckBox(GEN_ID, x, y += stride, "Draw using Stream VBO", ALIGN_TOPLEFT, &g_Config.bUseVBO);
|
||||
UICheckBox(GEN_ID, x, y += stride, "Vertex Cache", ALIGN_TOPLEFT, &g_Config.bVertexCache);
|
||||
|
||||
bool useJit = g_Config.iCpuCore == CPU_JIT;
|
||||
UICheckBox(GEN_ID, x, y += stride, "JIT (Dynarec)", ALIGN_TOPLEFT, &useJit);
|
||||
if (g_Config.iCpuCore == CPU_JIT)
|
||||
UICheckBox(GEN_ID, x + 450, y, "Fastmem (may crash)", ALIGN_TOPLEFT, &g_Config.bFastMemory);
|
||||
g_Config.iCpuCore = useJit ? CPU_JIT : CPU_INTERPRETER;
|
||||
UICheckBox(GEN_ID, x, y += stride, "JIT (Dynarec)", ALIGN_TOPLEFT, &g_Config.bJit);
|
||||
if (g_Config.bJit)
|
||||
UICheckBox(GEN_ID, x + 450, y, "Fastmem (may be unstable)", ALIGN_TOPLEFT, &g_Config.bFastMemory);
|
||||
// ui_draw2d.DrawText(UBUNTU48, "much faster JIT coming later", x, y+=50, 0xcFFFFFFF, ALIGN_LEFT);
|
||||
UICheckBox(GEN_ID, x, y += stride, "On-screen Touch Controls", ALIGN_TOPLEFT, &g_Config.bShowTouchControls);
|
||||
if (g_Config.bShowTouchControls) {
|
||||
|
|
|
@ -101,7 +101,6 @@ public:
|
|||
|
||||
virtual void InitGL() {}
|
||||
virtual void BeginFrame() {}
|
||||
virtual void EndFrame() {}
|
||||
virtual void ShutdownGL() {}
|
||||
|
||||
virtual void InitSound(PMixer *mixer);
|
||||
|
@ -201,15 +200,11 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co
|
|||
gfxLog = true;
|
||||
break;
|
||||
case 'j':
|
||||
g_Config.iCpuCore = CPU_JIT;
|
||||
g_Config.bSaveSettings = false;
|
||||
break;
|
||||
case 'f':
|
||||
g_Config.iCpuCore = CPU_FASTINTERPRETER;
|
||||
g_Config.bJit = true;
|
||||
g_Config.bSaveSettings = false;
|
||||
break;
|
||||
case 'i':
|
||||
g_Config.iCpuCore = CPU_INTERPRETER;
|
||||
g_Config.bJit = false;
|
||||
g_Config.bSaveSettings = false;
|
||||
break;
|
||||
case '-':
|
||||
|
|
|
@ -4,12 +4,13 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../Core/Config.h"
|
||||
#include "../Core/Core.h"
|
||||
#include "../Core/CoreTiming.h"
|
||||
#include "../Core/System.h"
|
||||
#include "../Core/MIPS/MIPS.h"
|
||||
#include "../Core/Host.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Windows/OpenGLBase.h"
|
||||
#include "Log.h"
|
||||
#include "LogManager.h"
|
||||
|
||||
|
@ -46,6 +47,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// Temporary hack around annoying linking error.
|
||||
void GL_SwapBuffers() { }
|
||||
|
||||
void printUsage(const char *progname, const char *reason)
|
||||
{
|
||||
if (reason != NULL)
|
||||
|
@ -66,7 +70,6 @@ void printUsage(const char *progname, const char *reason)
|
|||
}
|
||||
|
||||
fprintf(stderr, " -i use the interpreter\n");
|
||||
fprintf(stderr, " -f use the fast interpreter\n");
|
||||
fprintf(stderr, " -j use jit (default)\n");
|
||||
fprintf(stderr, " -c, --compare compare with output in file.expected\n");
|
||||
fprintf(stderr, "\nSee headless.txt for details.\n");
|
||||
|
@ -76,7 +79,6 @@ int main(int argc, const char* argv[])
|
|||
{
|
||||
bool fullLog = false;
|
||||
bool useJit = false;
|
||||
bool fastInterpreter = false;
|
||||
bool autoCompare = false;
|
||||
bool useGraphics = false;
|
||||
|
||||
|
@ -101,8 +103,6 @@ int main(int argc, const char* argv[])
|
|||
useJit = false;
|
||||
else if (!strcmp(argv[i], "-j"))
|
||||
useJit = true;
|
||||
else if (!strcmp(argv[i], "-f"))
|
||||
fastInterpreter = true;
|
||||
else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--compare"))
|
||||
autoCompare = true;
|
||||
else if (!strcmp(argv[i], "--graphics"))
|
||||
|
@ -156,7 +156,7 @@ int main(int argc, const char* argv[])
|
|||
coreParameter.fileToStart = bootFilename;
|
||||
coreParameter.mountIso = mountIso ? mountIso : "";
|
||||
coreParameter.startPaused = false;
|
||||
coreParameter.cpuCore = fastInterpreter ? CPU_FASTINTERPRETER : (useJit ? CPU_JIT : CPU_INTERPRETER);
|
||||
coreParameter.cpuCore = useJit ? CPU_JIT : CPU_INTERPRETER;
|
||||
coreParameter.gpuCore = headlessHost->isGLWorking() ? GPU_GLES : GPU_NULL;
|
||||
coreParameter.enableSound = false;
|
||||
coreParameter.headLess = true;
|
||||
|
@ -196,8 +196,10 @@ int main(int argc, const char* argv[])
|
|||
mipsr4k.RunLoopUntil(nowTicks + frameTicks);
|
||||
|
||||
// If we were rendering, this might be a nice time to do something about it.
|
||||
if (coreState == CORE_NEXTFRAME)
|
||||
if (coreState == CORE_NEXTFRAME) {
|
||||
headlessHost->SwapBuffers();
|
||||
coreState = CORE_RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
host->ShutdownGL();
|
||||
|
|
|
@ -35,7 +35,6 @@ public:
|
|||
|
||||
virtual void InitGL() {}
|
||||
virtual void BeginFrame() {}
|
||||
virtual void EndFrame() {}
|
||||
virtual void ShutdownGL() {}
|
||||
|
||||
virtual void InitSound(PMixer *mixer) {}
|
||||
|
@ -53,4 +52,9 @@ public:
|
|||
virtual void SetComparisonScreenshot(const std::string &filename) {}
|
||||
|
||||
virtual bool isGLWorking() { return false; }
|
||||
|
||||
|
||||
// Unique for HeadlessHost
|
||||
virtual void SwapBuffers() {}
|
||||
|
||||
};
|
|
@ -218,7 +218,7 @@ void WindowsHeadlessHost::BeginFrame()
|
|||
|
||||
}
|
||||
|
||||
void WindowsHeadlessHost::EndFrame()
|
||||
void WindowsHeadlessHost::SwapBuffers()
|
||||
{
|
||||
SwapBuffers(hDC);
|
||||
::SwapBuffers(hDC);
|
||||
}
|
||||
|
|
|
@ -30,10 +30,11 @@ class WindowsHeadlessHost : public HeadlessHost
|
|||
public:
|
||||
virtual void InitGL();
|
||||
virtual void BeginFrame();
|
||||
virtual void EndFrame();
|
||||
virtual void ShutdownGL();
|
||||
virtual bool isGLWorking() { return glOkay; }
|
||||
|
||||
virtual void SwapBuffers();
|
||||
|
||||
virtual void SendDebugOutput(const std::string &output);
|
||||
virtual void SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h);
|
||||
virtual void SetComparisonScreenshot(const std::string &filename);
|
||||
|
|
13
ios/AppDelegate.h
Normal file
13
ios/AppDelegate.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
// AppDelegate.h boilerplate
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class ViewController;
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
@property (strong, nonatomic) ViewController *viewController;
|
||||
|
||||
@end
|
25
ios/AppDelegate.m
Normal file
25
ios/AppDelegate.m
Normal file
|
@ -0,0 +1,25 @@
|
|||
// AppDelegate.m boilerplate
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "ViewController.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_window release];
|
||||
[_viewController release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
|
||||
self.viewController = [[[ViewController alloc] init] autorelease];
|
||||
self.window.rootViewController = self.viewController;
|
||||
[self.window makeKeyAndVisible];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
46
ios/PPSSPP-Info.plist
Normal file
46
ios/PPSSPP-Info.plist
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.rock88dev.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<true/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
9
ios/PPSSPP-Prefix.pch
Normal file
9
ios/PPSSPP-Prefix.pch
Normal file
|
@ -0,0 +1,9 @@
|
|||
#import <Availability.h>
|
||||
|
||||
#ifndef __IPHONE_4_0
|
||||
#warning "This project uses features only available in iOS SDK 4.0 and later."
|
||||
#endif
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <Foundation/Foundation.h>
|
||||
#endif
|
8
ios/ViewController.h
Normal file
8
ios/ViewController.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
// ViewController.h boilerplate
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <GLKit/GLKit.h>
|
||||
|
||||
@interface ViewController : GLKViewController
|
||||
|
||||
@end
|
241
ios/ViewController.mm
Normal file
241
ios/ViewController.mm
Normal file
|
@ -0,0 +1,241 @@
|
|||
//
|
||||
// ViewController.m
|
||||
//
|
||||
// Created by rock88
|
||||
// Modified by xSacha
|
||||
//
|
||||
|
||||
#import "ViewController.h"
|
||||
#import <GLKit/GLKit.h>
|
||||
|
||||
#include "base/display.h"
|
||||
#include "base/timeutil.h"
|
||||
#include "file/zip_read.h"
|
||||
#include "input/input_state.h"
|
||||
#include "net/resolve.h"
|
||||
#include "ui_atlas.h"
|
||||
#include "ui/screen.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "gfx_es2/fbo.h"
|
||||
|
||||
#define IS_IPAD() ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
|
||||
|
||||
extern void UIUpdateMouse(int i, float x, float y, bool down);
|
||||
|
||||
float dp_xscale = 1.0f;
|
||||
float dp_yscale = 1.0f;
|
||||
|
||||
static uint32_t pad_buttons_async_set = 0;
|
||||
static uint32_t pad_buttons_async_clear = 0;
|
||||
|
||||
extern ScreenManager *screenManager;
|
||||
InputState input_state;
|
||||
|
||||
extern std::string ram_temp_file;
|
||||
|
||||
@interface ViewController ()
|
||||
|
||||
@property (strong, nonatomic) EAGLContext *context;
|
||||
@property (nonatomic,retain) NSString* documentsPath;
|
||||
@property (nonatomic,retain) NSString* bundlePath;
|
||||
@property (nonatomic,retain) NSMutableArray* touches;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ViewController
|
||||
@synthesize documentsPath,bundlePath,touches;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.touches = [[[NSMutableArray alloc] init] autorelease];
|
||||
|
||||
self.documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
|
||||
self.bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/"];
|
||||
|
||||
memset(&input_state, 0, sizeof(input_state));
|
||||
|
||||
net::Init();
|
||||
|
||||
ram_temp_file = [[NSTemporaryDirectory() stringByAppendingPathComponent:@"ram_tmp.file"] fileSystemRepresentation];
|
||||
NativeInit(0, NULL, [self.bundlePath UTF8String], [self.documentsPath UTF8String], NULL);
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
self.view.frame = [[UIScreen mainScreen] bounds];
|
||||
self.view.multipleTouchEnabled = YES;
|
||||
self.context = [[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2] autorelease];
|
||||
|
||||
GLKView *view = (GLKView *)self.view;
|
||||
view.context = self.context;
|
||||
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
|
||||
[EAGLContext setCurrentContext:self.context];
|
||||
|
||||
float scale = [UIScreen mainScreen].scale;
|
||||
CGSize size = [[UIApplication sharedApplication].delegate window].frame.size;
|
||||
|
||||
if (size.height > size.width) {
|
||||
float h = size.height;
|
||||
size.height = size.width;
|
||||
size.width = h;
|
||||
}
|
||||
|
||||
g_dpi = (IS_IPAD() ? 200 : 150) * scale;
|
||||
g_dpi_scale = 240.0f / (float)g_dpi;
|
||||
pixel_xres = size.width * scale;
|
||||
pixel_yres = size.height * scale;
|
||||
pixel_in_dps = (float)pixel_xres / (float)dp_xres;
|
||||
|
||||
dp_xres = pixel_xres * g_dpi_scale;
|
||||
dp_yres = pixel_yres * g_dpi_scale;
|
||||
|
||||
NativeInitGraphics();
|
||||
|
||||
dp_xscale = (float)dp_xres / (float)pixel_xres;
|
||||
dp_yscale = (float)dp_yres / (float)pixel_yres;
|
||||
|
||||
/*
|
||||
UISwipeGestureRecognizer* gesture = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)] autorelease];
|
||||
[self.view addGestureRecognizer:gesture];
|
||||
*/
|
||||
}
|
||||
|
||||
- (void)viewDidUnload
|
||||
{
|
||||
[super viewDidUnload];
|
||||
|
||||
if ([EAGLContext currentContext] == self.context) {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
self.context = nil;
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning
|
||||
{
|
||||
[super didReceiveMemoryWarning];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self viewDidUnload];
|
||||
|
||||
self.touches = nil;
|
||||
self.documentsPath = nil;
|
||||
self.bundlePath = nil;
|
||||
|
||||
NativeShutdown();
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
//static BOOL menuDown = NO;
|
||||
|
||||
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
|
||||
{
|
||||
lock_guard guard(input_state.lock);
|
||||
input_state.pad_buttons |= pad_buttons_async_set;
|
||||
input_state.pad_buttons &= ~pad_buttons_async_clear;
|
||||
UpdateInputState(&input_state);
|
||||
|
||||
{
|
||||
lock_guard guard(input_state.lock);
|
||||
UIUpdateMouse(0, input_state.pointer_x[0], input_state.pointer_y[0], input_state.pointer_down[0]);
|
||||
screenManager->update(input_state);
|
||||
}
|
||||
|
||||
{
|
||||
lock_guard guard(input_state.lock);
|
||||
EndInputState(&input_state);
|
||||
}
|
||||
|
||||
NativeRender();
|
||||
time_update();
|
||||
}
|
||||
|
||||
- (void)swipeGesture:(id)sender
|
||||
{
|
||||
// TODO: Use a swipe gesture to handle BACK
|
||||
/*
|
||||
pad_buttons_async_set |= PAD_BUTTON_MENU;
|
||||
pad_buttons_async_clear &= PAD_BUTTON_MENU;
|
||||
|
||||
int64_t delayInSeconds = 1.5;
|
||||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
|
||||
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
|
||||
pad_buttons_async_set &= PAD_BUTTON_MENU;
|
||||
pad_buttons_async_clear |= PAD_BUTTON_MENU;
|
||||
});
|
||||
|
||||
if (g_Config.bBufferedRendering)
|
||||
fbo_unbind();
|
||||
|
||||
screenManager->push(new InGameMenuScreen());
|
||||
*/
|
||||
}
|
||||
|
||||
- (void)touchX:(float)x y:(float)y code:(int)code pointerId:(int)pointerId
|
||||
{
|
||||
lock_guard guard(input_state.lock);
|
||||
|
||||
float scale = [UIScreen mainScreen].scale;
|
||||
|
||||
float scaledX = (int)(x * dp_xscale) * scale;
|
||||
float scaledY = (int)(y * dp_yscale) * scale;
|
||||
|
||||
input_state.pointer_x[pointerId] = scaledX;
|
||||
input_state.pointer_y[pointerId] = scaledY;
|
||||
if (code == 1) {
|
||||
input_state.pointer_down[pointerId] = true;
|
||||
} else if (code == 2) {
|
||||
input_state.pointer_down[pointerId] = false;
|
||||
}
|
||||
input_state.mouse_valid = true;
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet *)_touches withEvent:(UIEvent *)event
|
||||
{
|
||||
for(UITouch* touch in _touches) {
|
||||
[self.touches addObject:touch];
|
||||
CGPoint point = [touch locationInView:self.view];
|
||||
[self touchX:point.x y:point.y code:1 pointerId:[self.touches indexOfObject:touch]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet *)_touches withEvent:(UIEvent *)event
|
||||
{
|
||||
for(UITouch* touch in _touches) {
|
||||
CGPoint point = [touch locationInView:self.view];
|
||||
[self touchX:point.x y:point.y code:0 pointerId:[self.touches indexOfObject:touch]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet *)_touches withEvent:(UIEvent *)event
|
||||
{
|
||||
for(UITouch* touch in _touches) {
|
||||
CGPoint point = [touch locationInView:self.view];
|
||||
[self touchX:point.x y:point.y code:2 pointerId:[self.touches indexOfObject:touch]];
|
||||
[self.touches removeObject:touch];
|
||||
}
|
||||
}
|
||||
|
||||
void LaunchBrowser(char const* url)
|
||||
{
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithCString:url encoding:NSStringEncodingConversionAllowLossy]]];
|
||||
}
|
||||
|
||||
void EnableFZ(){};
|
||||
void DisableFZ(){};
|
||||
|
||||
@end
|
|
@ -4,10 +4,9 @@
|
|||
|
||||
# Options:
|
||||
#
|
||||
# IOS_PLATFORM = OS (default) or SIMULATOR
|
||||
# This decides if SDKS will be selected from the iPhoneOS.platform or iPhoneSimulator.platform folders
|
||||
# IOS_PLATFORM = OS (default)
|
||||
# This needs to be OS as the simulator cannot use the required GLES2.0 environment.
|
||||
# OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch.
|
||||
# SIMULATOR - used to build for the Simulator platforms, which have an x86 arch.
|
||||
#
|
||||
# CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder
|
||||
# By default this location is automatcially chosen based on the IOS_PLATFORM value above.
|
||||
|
@ -96,16 +95,11 @@ set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform")
|
|||
# Check the platform selection and setup for developer root
|
||||
if (${IOS_PLATFORM} STREQUAL "OS")
|
||||
set (IOS_PLATFORM_LOCATION "iPhoneOS.platform")
|
||||
|
||||
# This causes the installers to properly locate the output libraries
|
||||
set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos")
|
||||
elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR")
|
||||
set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform")
|
||||
|
||||
# This causes the installers to properly locate the output libraries
|
||||
set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator")
|
||||
message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. PPSSPP is unable to run on simulator")
|
||||
else (${IOS_PLATFORM} STREQUAL "OS")
|
||||
message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose OS or SIMULATOR")
|
||||
message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose OS or leave default")
|
||||
endif (${IOS_PLATFORM} STREQUAL "OS")
|
||||
|
||||
# Setup iOS developer location unless specified manually with CMAKE_IOS_DEVELOPER_ROOT
|
||||
|
@ -141,9 +135,7 @@ set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS su
|
|||
# set the architecture for iOS
|
||||
# NOTE: Currently both ARCHS_STANDARD_32_BIT and ARCHS_UNIVERSAL_IPHONE_OS set armv7 only, so set both manually
|
||||
if (${IOS_PLATFORM} STREQUAL "OS")
|
||||
set (IOS_ARCH armv6 armv7)
|
||||
else (${IOS_PLATFORM} STREQUAL "OS")
|
||||
set (IOS_ARCH i386)
|
||||
set (IOS_ARCH armv7 armv7s)
|
||||
endif (${IOS_PLATFORM} STREQUAL "OS")
|
||||
|
||||
set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string "Build architecture for iOS")
|
||||
|
|
12
ios/main.m
Normal file
12
ios/main.m
Normal file
|
@ -0,0 +1,12 @@
|
|||
// main.m boilerplate
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue