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:
Henrik Rydgard 2013-02-19 00:50:33 +01:00
commit e32721c72a
101 changed files with 4642 additions and 999 deletions

View file

@ -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)

View file

@ -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;

View file

@ -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();

View file

@ -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

View file

@ -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);

View file

@ -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", &currentDirectory, "");
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);

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -22,7 +22,6 @@
enum CPUCore {
CPU_INTERPRETER,
CPU_FASTINTERPRETER, // unsafe, a bit faster than INTERPRETER
CPU_JIT,
};

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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.

View file

@ -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) {

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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"},

View file

@ -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) {

View file

@ -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();

View file

@ -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.

View file

@ -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());

View file

@ -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();

View file

@ -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();

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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";

View file

@ -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);

View file

@ -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];
}

View file

@ -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)
{

View file

@ -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) {
}
}
}
}

View file

@ -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)

View file

@ -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_; }

View file

@ -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) {

View file

@ -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;
};

View file

@ -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

View file

@ -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]);

View file

@ -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);

View file

@ -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();

View file

@ -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;

View file

@ -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; }

View file

@ -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;
}

View file

@ -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;
};

View file

@ -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.

View file

@ -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;
}

View file

@ -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:

View file

@ -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.

View file

@ -62,4 +62,13 @@ public:
{
return currentList;
}
virtual bool DecodeTexture(u8* dest, GPUgstate state)
{
return false;
}
std::vector<FramebufferInfo> GetFramebufferList()
{
return std::vector<FramebufferInfo>();
}
};

View file

@ -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;
};

View file

@ -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;

View file

@ -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)

View file

@ -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()

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -72,6 +72,7 @@ signals:
public slots:
void CopyValue();
void Dump();
void Change();
private:
int curAddress;
int align;

View file

@ -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()

View file

@ -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;

View file

@ -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();
}

View file

@ -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);

View file

@ -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

File diff suppressed because it is too large Load diff

124
Qt/debugger_displaylist.h Normal file
View 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
View 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>

View file

@ -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
View 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
View 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
View 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>

View file

@ -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();
}

View file

@ -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

View file

@ -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>&amp;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>&amp;Interpreter</string>
</property>
</action>
<action name="action_CPUFastInterpreter">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;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>

View file

@ -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;

View file

@ -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);
}

View file

@ -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();

View file

@ -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">

View file

@ -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()

View file

@ -21,7 +21,6 @@ public:
void InitGL();
void BeginFrame();
void EndFrame();
void ShutdownGL();
void InitSound(PMixer *mixer);

View file

@ -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);

View file

@ -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.

View file

@ -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

View file

@ -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"/>

View file

@ -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) {

View file

@ -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) {

View file

@ -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 '-':

View file

@ -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();

View file

@ -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() {}
};

View file

@ -218,7 +218,7 @@ void WindowsHeadlessHost::BeginFrame()
}
void WindowsHeadlessHost::EndFrame()
void WindowsHeadlessHost::SwapBuffers()
{
SwapBuffers(hDC);
::SwapBuffers(hDC);
}

View file

@ -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
View 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
View 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
View 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
View 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
View 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
View 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

View file

@ -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
View 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