mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-04 03:35:19 +02:00
Merge branch 'master' into armjit-fpu
Conflicts: Core/MIPS/ARM/ArmCompFPU.cpp Core/MIPS/x86/CompFPU.cpp
This commit is contained in:
@@ -26,6 +26,9 @@ Windows/ipch
|
||||
# For ppsspp.ini, etc.
|
||||
*.ini
|
||||
|
||||
# Qt Linguist files
|
||||
*.qm
|
||||
|
||||
Logs
|
||||
Memstick
|
||||
|
||||
|
||||
+5
-1
@@ -918,7 +918,11 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
if(HEADLESS)
|
||||
add_executable(PPSSPPHeadless headless/Headless.cpp headless/StubHost.h)
|
||||
add_executable(PPSSPPHeadless
|
||||
headless/Headless.cpp
|
||||
headless/StubHost.h
|
||||
headless/Compare.cpp
|
||||
headless/Compare.h)
|
||||
target_link_libraries(PPSSPPHeadless ${CoreLibName}
|
||||
${COCOA_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
|
||||
setup_target_project(PPSSPPHeadless headless)
|
||||
|
||||
@@ -123,6 +123,12 @@ CISOFileBlockDevice::~CISOFileBlockDevice()
|
||||
|
||||
bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)
|
||||
{
|
||||
if ((u32)blockNumber >= numBlocks)
|
||||
{
|
||||
memset(outPtr, 0, 2048);
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 idx = index[blockNumber];
|
||||
u32 idx2 = index[blockNumber+1];
|
||||
u8 inbuffer[4096]; //too big
|
||||
@@ -153,7 +159,7 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)
|
||||
if(inflateInit2(&z, -15) != Z_OK)
|
||||
{
|
||||
ERROR_LOG(LOADER, "deflateInit ERROR : %s\n", (z.msg) ? z.msg : "???");
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
z.avail_in = readSize;
|
||||
z.next_out = outPtr;
|
||||
@@ -165,14 +171,17 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)
|
||||
//if (status != Z_OK)
|
||||
{
|
||||
ERROR_LOG(LOADER, "block %d:inflate : %s[%d]\n", blockNumber, (z.msg) ? z.msg : "error", status);
|
||||
inflateEnd(&z);
|
||||
return 1;
|
||||
}
|
||||
int cmp_size = blockSize - z.avail_out;
|
||||
if (cmp_size != (int)blockSize)
|
||||
{
|
||||
ERROR_LOG(LOADER, "block %d : block size error %d != %d\n", blockNumber, cmp_size, blockSize);
|
||||
return 1;
|
||||
inflateEnd(&z);
|
||||
return false;
|
||||
}
|
||||
inflateEnd(&z);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -31,9 +31,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
#undef DeleteFile
|
||||
|
||||
|
||||
#if HOST_IS_CASE_SENSITIVE
|
||||
|
||||
static bool FixFilenameCase(const std::string &path, std::string &filename)
|
||||
@@ -248,7 +245,7 @@ bool DirectoryFileSystem::RenameFile(const std::string &from, const std::string
|
||||
return retValue;
|
||||
}
|
||||
|
||||
bool DirectoryFileSystem::DeleteFile(const std::string &filename) {
|
||||
bool DirectoryFileSystem::RemoveFile(const std::string &filename) {
|
||||
std::string fullName = GetLocalPath(filename);
|
||||
#ifdef _WIN32
|
||||
bool retValue = (::DeleteFileA(fullName.c_str()) == TRUE);
|
||||
@@ -266,7 +263,7 @@ bool DirectoryFileSystem::DeleteFile(const std::string &filename) {
|
||||
fullName = GetLocalPath(fullName);
|
||||
|
||||
#ifdef _WIN32
|
||||
retValue = (::DeleteFile(fullName.c_str()) == TRUE);
|
||||
retValue = (::DeleteFileA(fullName.c_str()) == TRUE);
|
||||
#else
|
||||
retValue = (0 == unlink(fullName.c_str()));
|
||||
#endif
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
bool MkDir(const std::string &dirname);
|
||||
bool RmDir(const std::string &dirname);
|
||||
bool RenameFile(const std::string &from, const std::string &to);
|
||||
bool DeleteFile(const std::string &filename);
|
||||
bool RemoveFile(const std::string &filename);
|
||||
bool GetHostPath(const std::string &inpath, std::string &outpath);
|
||||
|
||||
private:
|
||||
|
||||
@@ -110,7 +110,7 @@ public:
|
||||
virtual bool MkDir(const std::string &dirname) = 0;
|
||||
virtual bool RmDir(const std::string &dirname) = 0;
|
||||
virtual bool RenameFile(const std::string &from, const std::string &to) = 0;
|
||||
virtual bool DeleteFile(const std::string &filename) = 0;
|
||||
virtual bool RemoveFile(const std::string &filename) = 0;
|
||||
virtual bool GetHostPath(const std::string &inpath, std::string &outpath) = 0;
|
||||
};
|
||||
|
||||
@@ -130,7 +130,7 @@ public:
|
||||
virtual bool MkDir(const std::string &dirname) {return false;}
|
||||
virtual bool RmDir(const std::string &dirname) {return false;}
|
||||
virtual bool RenameFile(const std::string &from, const std::string &to) {return false;}
|
||||
virtual bool DeleteFile(const std::string &filename) {return false;}
|
||||
virtual bool RemoveFile(const std::string &filename) {return false;}
|
||||
virtual bool GetHostPath(const std::string &inpath, std::string &outpath) {return false;}
|
||||
};
|
||||
|
||||
|
||||
@@ -178,80 +178,74 @@ ISOFileSystem::~ISOFileSystem()
|
||||
|
||||
void ISOFileSystem::ReadDirectory(u32 startsector, u32 dirsize, TreeEntry *root)
|
||||
{
|
||||
u8 buffer[2048];
|
||||
int offset = 0;
|
||||
u32 secnum = startsector;
|
||||
|
||||
u8 theSector[2048];
|
||||
blockDevice->ReadBlock(secnum, theSector);
|
||||
|
||||
while (secnum < (dirsize/2048 + startsector))
|
||||
for (u32 secnum = startsector, endsector = dirsize/2048 + startsector; secnum < endsector; ++secnum)
|
||||
{
|
||||
DirectoryEntry &dir = *((DirectoryEntry *)buffer);
|
||||
u8 sz = theSector[offset];
|
||||
if (sz == 0) // NOT the correct way
|
||||
goto nextblock; //done
|
||||
u8 theSector[2048];
|
||||
blockDevice->ReadBlock(secnum, theSector);
|
||||
|
||||
memcpy(&dir, theSector + offset, sz);
|
||||
|
||||
buffer[2047]=0;
|
||||
offset += dir.size;
|
||||
if (offset >= 2048)
|
||||
for (int offset = 0; offset < 2048; )
|
||||
{
|
||||
nextblock:
|
||||
offset=0;
|
||||
secnum++;
|
||||
blockDevice->ReadBlock(secnum, theSector);
|
||||
memcpy(&dir, theSector + offset, sz);
|
||||
}
|
||||
bool isFile = (dir.flags & 2) ? false : true;
|
||||
DirectoryEntry &dir = *(DirectoryEntry *)&theSector[offset];
|
||||
u8 sz = theSector[offset];
|
||||
|
||||
int fnLength = dir.identifierLength;
|
||||
// Nothing left in this sector. There might be more in the next one.
|
||||
if (sz == 0)
|
||||
break;
|
||||
|
||||
char name[256];
|
||||
for (int i = 0; i < fnLength; i++)
|
||||
name[i] = buffer[33+i] ? buffer[33+i] : '.';
|
||||
name[fnLength] = '\0';
|
||||
|
||||
bool relative = false;
|
||||
|
||||
if (!strcmp(name, ".")) // "." record
|
||||
{
|
||||
relative = true;
|
||||
}
|
||||
|
||||
if (strlen(name) == 1 && name[0] == '\x01') // ".." record
|
||||
{
|
||||
strcpy(name,"..");
|
||||
relative = true;
|
||||
}
|
||||
|
||||
TreeEntry *e = new TreeEntry;
|
||||
e->name = name;
|
||||
e->size = dir.dataLengthLE;
|
||||
e->startingPosition = dir.firstDataSectorLE * 2048;
|
||||
e->isDirectory = !isFile;
|
||||
e->flags = dir.flags;
|
||||
e->isBlockSectorMode = false;
|
||||
e->parent = root;
|
||||
|
||||
// Let's not excessively spam the log - I commented this line out.
|
||||
//DEBUG_LOG(FILESYS, "%s: %s %08x %08x %i", e->isDirectory?"D":"F", name, dir.firstDataSectorLE, e->startingPosition, e->startingPosition);
|
||||
|
||||
if (e->isDirectory && !relative)
|
||||
{
|
||||
if (dir.firstDataSectorLE == startsector)
|
||||
const int IDENTIFIER_OFFSET = 33;
|
||||
if (offset + IDENTIFIER_OFFSET + dir.identifierLength > 2048)
|
||||
{
|
||||
ERROR_LOG(FILESYS, "WARNING: Appear to have a recursive file system, breaking recursion");
|
||||
ERROR_LOG(FILESYS, "Directory entry crosses sectors, corrupt iso?");
|
||||
break;
|
||||
}
|
||||
|
||||
offset += dir.size;
|
||||
|
||||
bool isFile = (dir.flags & 2) ? false : true;
|
||||
bool relative;
|
||||
int fnLength = dir.identifierLength;
|
||||
|
||||
TreeEntry *e = new TreeEntry();
|
||||
if (dir.identifierLength == 1 && (dir.firstIdChar == '\x00' || dir.firstIdChar == '.'))
|
||||
{
|
||||
e->name = ".";
|
||||
relative = true;
|
||||
}
|
||||
else if (dir.identifierLength == 1 && dir.firstIdChar == '\x01')
|
||||
{
|
||||
e->name = "..";
|
||||
relative = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadDirectory(dir.firstDataSectorLE, dir.dataLengthLE, e);
|
||||
e->name = std::string((char *)&dir.firstIdChar, dir.identifierLength);
|
||||
relative = false;
|
||||
}
|
||||
}
|
||||
root->children.push_back(e);
|
||||
}
|
||||
|
||||
e->size = dir.dataLengthLE;
|
||||
e->startingPosition = dir.firstDataSectorLE * 2048;
|
||||
e->isDirectory = !isFile;
|
||||
e->flags = dir.flags;
|
||||
e->isBlockSectorMode = false;
|
||||
e->parent = root;
|
||||
|
||||
// Let's not excessively spam the log - I commented this line out.
|
||||
//DEBUG_LOG(FILESYS, "%s: %s %08x %08x %i", e->isDirectory?"D":"F", e->name.c_str(), dir.firstDataSectorLE, e->startingPosition, e->startingPosition);
|
||||
|
||||
if (e->isDirectory && !relative)
|
||||
{
|
||||
if (dir.firstDataSectorLE == startsector)
|
||||
{
|
||||
ERROR_LOG(FILESYS, "WARNING: Appear to have a recursive file system, breaking recursion");
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadDirectory(dir.firstDataSectorLE, dir.dataLengthLE, e);
|
||||
}
|
||||
}
|
||||
root->children.push_back(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ISOFileSystem::TreeEntry *ISOFileSystem::GetFromPath(std::string path, bool catchError)
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
virtual bool MkDir(const std::string &dirname) {return false;}
|
||||
virtual bool RmDir(const std::string &dirname) {return false;}
|
||||
virtual bool RenameFile(const std::string &from, const std::string &to) {return false;}
|
||||
virtual bool DeleteFile(const std::string &filename) {return false;}
|
||||
virtual bool RemoveFile(const std::string &filename) {return false;}
|
||||
|
||||
private:
|
||||
struct TreeEntry
|
||||
|
||||
@@ -363,13 +363,13 @@ bool MetaFileSystem::RenameFile(const std::string &from, const std::string &to)
|
||||
}
|
||||
}
|
||||
|
||||
bool MetaFileSystem::DeleteFile(const std::string &filename)
|
||||
bool MetaFileSystem::RemoveFile(const std::string &filename)
|
||||
{
|
||||
std::string of;
|
||||
IFileSystem *system;
|
||||
if (MapFilePath(filename, of, &system))
|
||||
{
|
||||
return system->DeleteFile(of);
|
||||
return system->RemoveFile(of);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
virtual bool MkDir(const std::string &dirname);
|
||||
virtual bool RmDir(const std::string &dirname);
|
||||
virtual bool RenameFile(const std::string &from, const std::string &to);
|
||||
virtual bool DeleteFile(const std::string &filename);
|
||||
virtual bool RemoveFile(const std::string &filename);
|
||||
|
||||
// TODO: void IoCtl(...)
|
||||
|
||||
|
||||
+15
-3
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "Thread.h"
|
||||
#include "../Core/CoreTiming.h"
|
||||
#include "../Core/CoreParameter.h"
|
||||
#include "../MIPS/MIPS.h"
|
||||
#include "../HLE/HLE.h"
|
||||
#include "sceAudio.h"
|
||||
@@ -78,7 +79,7 @@ static int hCountTotal; //unused
|
||||
static int vCount;
|
||||
static int isVblank;
|
||||
static bool hasSetMode;
|
||||
double lastFrameTime;
|
||||
static double lastFrameTime;
|
||||
|
||||
std::vector<WaitVBlankInfo> vblankWaitingThreads;
|
||||
|
||||
@@ -269,12 +270,11 @@ void hleEnterVblank(u64 userdata, int cyclesLate) {
|
||||
host->EndFrame();
|
||||
|
||||
#ifdef _WIN32
|
||||
static double lastFrameTime = 0.0;
|
||||
// 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)) {
|
||||
if (!GetAsyncKeyState(VK_TAB) && !PSP_CoreParameter().headLess) {
|
||||
while (time_now_d() < lastFrameTime + 1.0 / 60.0) {
|
||||
Common::SleepCurrentThread(1);
|
||||
time_update();
|
||||
@@ -357,6 +357,18 @@ u32 sceDisplaySetFramebuf() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool __DisplayGetFramebuf(u8 **topaddr, u32 *linesize, u32 *pixelFormat, int mode) {
|
||||
const FrameBufferState &fbState = mode == 1 ? latchedFramebuf : framebuf;
|
||||
if (topaddr != NULL)
|
||||
*topaddr = Memory::GetPointer(fbState.topaddr);
|
||||
if (linesize != NULL)
|
||||
*linesize = fbState.pspFramebufLinesize;
|
||||
if (pixelFormat != NULL)
|
||||
*pixelFormat = fbState.pspFramebufFormat;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 sceDisplayGetFramebuf(u32 topaddrPtr, u32 linesizePtr, u32 pixelFormatPtr, int mode) {
|
||||
const FrameBufferState &fbState = mode == 1 ? latchedFramebuf : framebuf;
|
||||
DEBUG_LOG(HLE,"sceDisplayGetFramebuf(*%08x = %08x, *%08x = %08x, *%08x = %08x, %i)",
|
||||
|
||||
@@ -26,6 +26,9 @@ void Register_sceDisplay();
|
||||
// will return true once after every end-of-frame.
|
||||
bool __DisplayFrameDone();
|
||||
|
||||
// Get information about the current framebuffer.
|
||||
bool __DisplayGetFramebuf(u8 **topaddr, u32 *linesize, u32 *pixelFormat, int mode);
|
||||
|
||||
typedef void (*VblankCallback)();
|
||||
// Listen for vblank events. Only register during init.
|
||||
void __DisplayListenVblank(VblankCallback callback);
|
||||
|
||||
+9
-4
@@ -33,6 +33,8 @@ struct GeInterruptData
|
||||
{
|
||||
int listid;
|
||||
u32 pc;
|
||||
u32 subIntrBase;
|
||||
u16 subIntrToken;
|
||||
};
|
||||
|
||||
static std::list<GeInterruptData> ge_pending_cb;
|
||||
@@ -50,20 +52,21 @@ public:
|
||||
if (dl == NULL)
|
||||
{
|
||||
WARN_LOG(HLE, "Unable to run GE interrupt: list doesn't exist: %d", intrdata.listid);
|
||||
return false;
|
||||
// TODO: Use dl instead of just saving everything instead?
|
||||
//return false;
|
||||
}
|
||||
|
||||
gpu->InterruptStart();
|
||||
|
||||
u32 cmd = Memory::ReadUnchecked_U32(intrdata.pc) >> 24;
|
||||
int subintr = dl->subIntrBase | (cmd == GE_CMD_FINISH ? PSP_GE_SUBINTR_FINISH : PSP_GE_SUBINTR_SIGNAL);
|
||||
int subintr = intrdata.subIntrBase | (cmd == GE_CMD_FINISH ? PSP_GE_SUBINTR_FINISH : PSP_GE_SUBINTR_SIGNAL);
|
||||
SubIntrHandler* handler = get(subintr);
|
||||
|
||||
if(handler != NULL)
|
||||
{
|
||||
DEBUG_LOG(CPU, "Entering interrupt handler %08x", handler->handlerAddress);
|
||||
currentMIPS->pc = handler->handlerAddress;
|
||||
u32 data = dl->subIntrToken;
|
||||
u32 data = intrdata.subIntrToken;
|
||||
currentMIPS->r[MIPS_REG_A0] = data & 0xFFFF;
|
||||
currentMIPS->r[MIPS_REG_A1] = handler->handlerArg;
|
||||
currentMIPS->r[MIPS_REG_A2] = sceKernelGetCompiledSdkVersion() <= 0x02000010 ? 0 : intrdata.pc + 4;
|
||||
@@ -109,11 +112,13 @@ void __GeShutdown()
|
||||
|
||||
}
|
||||
|
||||
void __GeTriggerInterrupt(int listid, u32 pc)
|
||||
void __GeTriggerInterrupt(int listid, u32 pc, u32 subIntrBase, u16 subIntrToken)
|
||||
{
|
||||
GeInterruptData intrdata;
|
||||
intrdata.listid = listid;
|
||||
intrdata.pc = pc;
|
||||
intrdata.subIntrBase = subIntrBase;
|
||||
intrdata.subIntrToken = subIntrToken;
|
||||
ge_pending_cb.push_back(intrdata);
|
||||
__TriggerInterrupt(PSP_INTR_HLE, PSP_GE_INTR, PSP_INTR_SUB_NONE);
|
||||
}
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ void Register_sceGe_user();
|
||||
void __GeInit();
|
||||
void __GeDoState(PointerWrap &p);
|
||||
void __GeShutdown();
|
||||
void __GeTriggerInterrupt(int listid, u32 pc);
|
||||
void __GeTriggerInterrupt(int listid, u32 pc, u32 subIntrBase, u16 subIntrToken);
|
||||
bool __GeHasPendingInterrupt();
|
||||
|
||||
|
||||
|
||||
+21
-8
@@ -17,7 +17,6 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#undef DeleteFile
|
||||
#endif
|
||||
|
||||
#include "../Config.h"
|
||||
@@ -38,6 +37,9 @@
|
||||
#include "sceKernelMemory.h"
|
||||
#include "sceKernelThread.h"
|
||||
|
||||
// For headless screenshots.
|
||||
#include "sceDisplay.h"
|
||||
|
||||
#define ERROR_ERRNO_FILE_NOT_FOUND 0x80010002
|
||||
|
||||
#define ERROR_MEMSTICK_DEVCTL_BAD_PARAMS 0x80220081
|
||||
@@ -144,9 +146,10 @@ public:
|
||||
p.Do(callbackID);
|
||||
p.Do(callbackArg);
|
||||
p.Do(asyncResult);
|
||||
p.Do(closePending);
|
||||
p.Do(pendingAsyncResult);
|
||||
p.Do(sectorBlockMode);
|
||||
p.Do(closePending);
|
||||
p.Do(info);
|
||||
p.Do(openMode);
|
||||
p.DoMarker("File");
|
||||
}
|
||||
@@ -549,7 +552,7 @@ u32 sceIoRemove(const char *filename) {
|
||||
if(!pspFileSystem.GetFileInfo(filename).exists)
|
||||
return ERROR_ERRNO_FILE_NOT_FOUND;
|
||||
|
||||
pspFileSystem.DeleteFile(filename);
|
||||
pspFileSystem.RemoveFile(filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -782,6 +785,15 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr,
|
||||
SaveState::Verify();
|
||||
// TODO: Maybe save/load to a file just to be sure?
|
||||
return 0;
|
||||
|
||||
case 0x20: // EMULATOR_DEVCTL__EMIT_SCREENSHOT
|
||||
u8 *topaddr;
|
||||
u32 linesize, pixelFormat;
|
||||
|
||||
__DisplayGetFramebuf(&topaddr, &linesize, &pixelFormat, 0);
|
||||
// TODO: Convert based on pixel format / mode / something?
|
||||
host->SendDebugScreenshot(topaddr, linesize, 272);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ERROR_LOG(HLE, "sceIoDevCtl: UNKNOWN PARAMETERS");
|
||||
@@ -1019,26 +1031,27 @@ u32 sceIoDread(int id, u32 dirent_addr) {
|
||||
u32 error;
|
||||
DirListing *dir = kernelObjects.Get<DirListing>(id, error);
|
||||
if (dir) {
|
||||
SceIoDirEnt *entry = (SceIoDirEnt*) Memory::GetPointer(dirent_addr);
|
||||
|
||||
if (dir->index == (int) dir->listing.size()) {
|
||||
DEBUG_LOG(HLE, "sceIoDread( %d %08x ) - end of the line", id, dirent_addr);
|
||||
entry->d_name[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
PSPFileInfo &info = dir->listing[dir->index];
|
||||
|
||||
SceIoDirEnt *entry = (SceIoDirEnt*) Memory::GetPointer(dirent_addr);
|
||||
|
||||
__IoGetStat(&entry->d_stat, info);
|
||||
|
||||
strncpy(entry->d_name, info.name.c_str(), 256);
|
||||
entry->d_name[255] = '\0';
|
||||
entry->d_private = 0xC0DEBABE;
|
||||
DEBUG_LOG(HLE, "sceIoDread( %d %08x ) = %s", id, dirent_addr, entry->d_name);
|
||||
|
||||
dir->index++;
|
||||
return (u32)(dir->listing.size() - dir->index + 1);
|
||||
return 1;
|
||||
} else {
|
||||
DEBUG_LOG(HLE, "sceIoDread - invalid listing %i, error %08x", id, error);
|
||||
return -1; // TODO
|
||||
return SCE_KERNEL_ERROR_BADF;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -157,6 +157,7 @@ void __KernelDoState(PointerWrap &p)
|
||||
p.DoMarker("KernelObjects");
|
||||
|
||||
__InterruptsDoState(p);
|
||||
// Memory needs to be after kernel objects, which may free kernel memory.
|
||||
__KernelMemoryDoState(p);
|
||||
__KernelThreadingDoState(p);
|
||||
__KernelAlarmDoState(p);
|
||||
@@ -589,7 +590,7 @@ const HLEFunction ThreadManForUser[] =
|
||||
{0x75156e8f,sceKernelResumeThread,"sceKernelResumeThread"},
|
||||
{0x3ad58b8c,&WrapU_V<sceKernelSuspendDispatchThread>,"sceKernelSuspendDispatchThread"},
|
||||
{0x27e22ec2,&WrapU_U<sceKernelResumeDispatchThread>,"sceKernelResumeDispatchThread"},
|
||||
{0x912354a7,sceKernelRotateThreadReadyQueue,"sceKernelRotateThreadReadyQueue"},
|
||||
{0x912354a7,&WrapI_I<sceKernelRotateThreadReadyQueue>,"sceKernelRotateThreadReadyQueue"},
|
||||
{0x9ACE131E,sceKernelSleepThread,"sceKernelSleepThread"},
|
||||
{0x82826f70,sceKernelSleepThreadCB,"sceKernelSleepThreadCB"},
|
||||
{0xF475845D,&WrapI_IUU<sceKernelStartThread>,"sceKernelStartThread"},
|
||||
|
||||
@@ -446,16 +446,17 @@ int g_inCbCount = 0;
|
||||
// Normally, the same as currentThread. In an interrupt, remembers the callback's thread id.
|
||||
SceUID currentCallbackThreadID = 0;
|
||||
int readyCallbacksCount = 0;
|
||||
SceUID currentThread;
|
||||
SceUID currentThread = 0;
|
||||
u32 idleThreadHackAddr;
|
||||
u32 threadReturnHackAddr;
|
||||
u32 cbReturnHackAddr;
|
||||
u32 intReturnHackAddr;
|
||||
std::vector<ThreadCallback> threadEndListeners;
|
||||
|
||||
typedef std::vector<SceUID> ThreadList;
|
||||
// Lists all thread ids that aren't deleted/etc.
|
||||
ThreadList threadqueue;
|
||||
std::vector<SceUID> threadqueue;
|
||||
|
||||
typedef std::list<SceUID> ThreadList;
|
||||
// Lists only ready thread ids.
|
||||
std::map<u32, ThreadList> threadReadyQueue;
|
||||
|
||||
@@ -657,30 +658,23 @@ void __KernelFireThreadEnd(SceUID threadID)
|
||||
}
|
||||
|
||||
// TODO: Use __KernelChangeThreadState instead? It has other affects...
|
||||
void __KernelChangeReadyState(Thread *thread, SceUID threadID, bool ready, bool atStart = false)
|
||||
void __KernelChangeReadyState(Thread *thread, SceUID threadID, bool ready)
|
||||
{
|
||||
int prio = thread->nt.currentPriority;
|
||||
|
||||
if (thread->isReady())
|
||||
{
|
||||
if (!ready)
|
||||
threadReadyQueue[prio].erase(std::remove(threadReadyQueue[prio].begin(), threadReadyQueue[prio].end(), threadID), threadReadyQueue[prio].end());
|
||||
threadReadyQueue[prio].remove(threadID);
|
||||
}
|
||||
else if (ready)
|
||||
{
|
||||
if (atStart)
|
||||
{
|
||||
size_t oldSize = threadReadyQueue[prio].size();
|
||||
threadReadyQueue[prio].resize(oldSize + 1);
|
||||
if (oldSize > 0)
|
||||
memmove(&threadReadyQueue[prio][1], &threadReadyQueue[prio][0], oldSize * sizeof(SceUID));
|
||||
threadReadyQueue[prio][0] = threadID;
|
||||
}
|
||||
if (thread->isRunning())
|
||||
threadReadyQueue[prio].push_front(threadID);
|
||||
else
|
||||
threadReadyQueue[prio].push_back(threadID);
|
||||
thread->nt.status = THREADSTATUS_READY;
|
||||
}
|
||||
|
||||
thread->nt.status = THREADSTATUS_READY;
|
||||
}
|
||||
|
||||
void __KernelChangeReadyState(SceUID threadID, bool ready)
|
||||
@@ -1130,7 +1124,7 @@ void __KernelRemoveFromThreadQueue(SceUID threadID)
|
||||
{
|
||||
int prio = __KernelGetThreadPrio(threadID);
|
||||
if (prio != 0)
|
||||
threadReadyQueue[prio].erase(std::remove(threadReadyQueue[prio].begin(), threadReadyQueue[prio].end(), threadID), threadReadyQueue[prio].end());
|
||||
threadReadyQueue[prio].remove(threadID);
|
||||
|
||||
threadqueue.erase(std::remove(threadqueue.begin(), threadqueue.end(), threadID), threadqueue.end());
|
||||
}
|
||||
@@ -1168,7 +1162,7 @@ Thread *__KernelNextThread() {
|
||||
{
|
||||
if (!it->second.empty())
|
||||
{
|
||||
bestThread = it->second[0];
|
||||
bestThread = it->second.front();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1182,10 +1176,6 @@ Thread *__KernelNextThread() {
|
||||
|
||||
void __KernelReSchedule(const char *reason)
|
||||
{
|
||||
// TODO: Not sure if this is correct?
|
||||
if (__GetCurrentThread() && __GetCurrentThread()->isRunning())
|
||||
__KernelChangeReadyState(currentThread, true);
|
||||
|
||||
// cancel rescheduling when in interrupt or callback, otherwise everything will be fucked up
|
||||
if (__IsInInterrupt() || __KernelInCallback())
|
||||
{
|
||||
@@ -1208,6 +1198,10 @@ void __KernelReSchedule(const char *reason)
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Not sure if this is correct? Probably should remove.
|
||||
if (__GetCurrentThread() && __GetCurrentThread()->isRunning())
|
||||
__KernelChangeReadyState(currentThread, true);
|
||||
|
||||
retry:
|
||||
Thread *nextThread = __KernelNextThread();
|
||||
|
||||
@@ -1361,8 +1355,11 @@ void __KernelSetupRootThread(SceUID moduleID, int args, const char *argp, int pr
|
||||
Thread *thread = __KernelCreateThread(id, moduleID, "root", currentMIPS->pc, prio, stacksize, attr);
|
||||
__KernelResetThread(thread);
|
||||
|
||||
Thread *prevThread = __GetCurrentThread();
|
||||
if (prevThread && prevThread->isRunning())
|
||||
__KernelChangeReadyState(currentThread, true);
|
||||
currentThread = id;
|
||||
__KernelChangeReadyState(thread, id, true); // do not schedule
|
||||
thread->nt.status = THREADSTATUS_RUNNING; // do not schedule
|
||||
|
||||
strcpy(thread->nt.name, "root");
|
||||
|
||||
@@ -1439,7 +1436,6 @@ int sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr)
|
||||
threadToStartID,argSize,argBlockPtr);
|
||||
|
||||
__KernelResetThread(startThread);
|
||||
__KernelChangeReadyState(startThread, threadToStartID, true, true);
|
||||
|
||||
u32 sp = startThread->context.r[MIPS_REG_SP];
|
||||
if (argBlockPtr && argSize > 0)
|
||||
@@ -1462,7 +1458,14 @@ int sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr)
|
||||
WARN_LOG(HLE,"sceKernelStartThread : had NULL arg");
|
||||
}
|
||||
|
||||
hleReSchedule("thread started");
|
||||
Thread *cur = __GetCurrentThread();
|
||||
// Smaller is better for priority. Only switch if the new thread is better.
|
||||
if (cur && cur->nt.currentPriority > startThread->nt.currentPriority)
|
||||
{
|
||||
__KernelChangeReadyState(currentThread, true);
|
||||
hleReSchedule("thread started");
|
||||
}
|
||||
__KernelChangeReadyState(startThread, threadToStartID, true);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@@ -1600,10 +1603,39 @@ u32 sceKernelResumeDispatchThread(u32 suspended)
|
||||
return oldDispatchSuspended;
|
||||
}
|
||||
|
||||
void sceKernelRotateThreadReadyQueue()
|
||||
int sceKernelRotateThreadReadyQueue(int priority)
|
||||
{
|
||||
DEBUG_LOG(HLE,"sceKernelRotateThreadReadyQueue : rescheduling");
|
||||
hleReSchedule("rotatethreadreadyqueue");
|
||||
DEBUG_LOG(HLE, "sceKernelRotateThreadReadyQueue(%x)", priority);
|
||||
|
||||
Thread *cur = __GetCurrentThread();
|
||||
|
||||
// 0 is special, it means "my current priority."
|
||||
if (priority == 0)
|
||||
priority = cur->nt.currentPriority;
|
||||
|
||||
if (priority <= 0x07 || priority > 0x77)
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_PRIORITY;
|
||||
|
||||
if (!threadReadyQueue[priority].empty())
|
||||
{
|
||||
// In other words, yield to everyone else.
|
||||
if (cur->nt.currentPriority == priority)
|
||||
{
|
||||
threadReadyQueue[priority].push_back(currentThread);
|
||||
cur->nt.status = THREADSTATUS_READY;
|
||||
}
|
||||
// Yield the next thread of this priority to all other threads of same priority.
|
||||
else if (threadReadyQueue[priority].size() > 1)
|
||||
{
|
||||
SceUID first = threadReadyQueue[priority].front();
|
||||
threadReadyQueue[priority].pop_front();
|
||||
threadReadyQueue[priority].push_back(first);
|
||||
}
|
||||
|
||||
hleReSchedule("rotatethreadreadyqueue");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sceKernelDeleteThread(int threadHandle)
|
||||
@@ -2257,15 +2289,15 @@ void __KernelSwitchContext(Thread *target, const char *reason)
|
||||
oldName = cur->GetName();
|
||||
|
||||
if (cur->isRunning())
|
||||
{
|
||||
__KernelChangeReadyState(cur, oldUID, false);
|
||||
cur->nt.status = (cur->nt.status | THREADSTATUS_READY) & ~THREADSTATUS_RUNNING;
|
||||
}
|
||||
__KernelChangeReadyState(cur, oldUID, true);
|
||||
}
|
||||
|
||||
currentThread = target->GetUID();
|
||||
if (target && target->isRunning())
|
||||
__KernelChangeReadyState(target, currentThread, true);
|
||||
if (target)
|
||||
{
|
||||
__KernelChangeReadyState(target, currentThread, false);
|
||||
target->nt.status = (target->nt.status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY;
|
||||
}
|
||||
|
||||
__KernelLoadContext(&target->context);
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ u32 sceKernelReferThreadStatus(u32 uid, u32 statusPtr);
|
||||
u32 sceKernelReferThreadRunStatus(u32 uid, u32 statusPtr);
|
||||
int sceKernelReleaseWaitThread(SceUID threadID);
|
||||
void sceKernelChangeCurrentThreadAttr();
|
||||
void sceKernelRotateThreadReadyQueue();
|
||||
int sceKernelRotateThreadReadyQueue(int priority);
|
||||
void sceKernelCheckThreadStack();
|
||||
void sceKernelSuspendThread();
|
||||
void sceKernelResumeThread();
|
||||
|
||||
@@ -63,6 +63,7 @@ public:
|
||||
|
||||
// Used for headless.
|
||||
virtual void SendDebugOutput(const std::string &output) {}
|
||||
virtual void SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) {}
|
||||
};
|
||||
|
||||
extern Host *host;
|
||||
|
||||
@@ -277,6 +277,12 @@ namespace MIPSComp
|
||||
}
|
||||
}
|
||||
|
||||
void Jit::Comp_Special3(u32 op)
|
||||
{
|
||||
// ext, ins
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
void Jit::Comp_Allegrex(u32 op)
|
||||
{
|
||||
DISABLE
|
||||
|
||||
@@ -83,6 +83,10 @@ void Jit::Comp_FPULS(u32 op)
|
||||
}
|
||||
}
|
||||
|
||||
void Jit::Comp_FPUComp(u32 op) {
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
void Jit::Comp_FPU2op(u32 op)
|
||||
{
|
||||
DISABLE
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
#define _POS ((op>>6 ) & 0x1F)
|
||||
#define _SIZE ((op>>11 ) & 0x1F)
|
||||
|
||||
#define OLDD Comp_Generic(op); return;
|
||||
#define DISABLE Comp_Generic(op); return;
|
||||
|
||||
namespace MIPSComp
|
||||
{
|
||||
|
||||
@@ -29,4 +29,14 @@ namespace MIPSComp
|
||||
{
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
void Jit::Comp_Mftv(u32 op)
|
||||
{
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
void Jit::Comp_SV(u32 op) {
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -291,6 +291,7 @@ void Jit::LogBlockNumber()
|
||||
INFO_LOG(CPU, "Block number: %i", blocks.GetNumBlocks() - 1);
|
||||
}
|
||||
|
||||
void Jit::Comp_DoNothing(u32 op) { }
|
||||
|
||||
#define _RS ((op>>21) & 0x1F)
|
||||
#define _RT ((op>>16) & 0x1F)
|
||||
|
||||
@@ -87,6 +87,7 @@ public:
|
||||
void Comp_RelBranchRI(u32 op);
|
||||
void Comp_FPUBranch(u32 op);
|
||||
void Comp_FPULS(u32 op);
|
||||
void Comp_FPUComp(u32 op);
|
||||
void Comp_Jump(u32 op);
|
||||
void Comp_JumpReg(u32 op);
|
||||
void Comp_Syscall(u32 op);
|
||||
@@ -97,13 +98,18 @@ public:
|
||||
void Comp_ShiftType(u32 op);
|
||||
void Comp_Allegrex(u32 op);
|
||||
void Comp_VBranch(u32 op);
|
||||
void Comp_VDot(u32 op);
|
||||
void Comp_MulDivType(u32 op);
|
||||
void Comp_Special3(u32 op);
|
||||
|
||||
void Comp_FPU3op(u32 op);
|
||||
void Comp_FPU2op(u32 op);
|
||||
void Comp_mxc1(u32 op);
|
||||
void Comp_Mftv(u32 op);
|
||||
void Comp_VDot(u32 op);
|
||||
|
||||
void Comp_DoNothing(u32 op);
|
||||
|
||||
void Comp_SV(u32 op);
|
||||
void Comp_SVQ(u32 op);
|
||||
|
||||
ArmJitBlockCache *GetBlockCache() { return &blocks; }
|
||||
|
||||
+25
-25
@@ -147,7 +147,7 @@ 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_Generic, Dis_SV, Int_SV, IS_VFPU),
|
||||
INSTR("lv.s", &Jit::Comp_SV, Dis_SV, Int_SV, IS_VFPU),
|
||||
{-2}, // HIT THIS IN WIPEOUT
|
||||
{VFPU4Jump},
|
||||
INSTR("lv", &Jit::Comp_SVQ, Dis_SVLRQ, Int_SVQ, IS_VFPU),
|
||||
@@ -156,7 +156,7 @@ const MIPSInstruction tableImmediate[64] = //xxxxxx .....
|
||||
//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_Generic, Dis_SV, Int_SV,IS_VFPU),
|
||||
INSTR("sv.s", &Jit::Comp_SV, Dis_SV, Int_SV,IS_VFPU),
|
||||
{-2},
|
||||
//60
|
||||
{VFPU6},
|
||||
@@ -185,7 +185,7 @@ const MIPSInstruction tableSpecial[64] = /// 000000 ...... ...... .......... xxx
|
||||
INSTR("syscall", &Jit::Comp_Syscall, Dis_Syscall, Int_Syscall,0),
|
||||
INSTR("break", &Jit::Comp_Break, Dis_Generic, Int_Break, 0),
|
||||
{-2},
|
||||
INSTR("sync", &Jit::Comp_Generic, Dis_Generic, Int_Sync, 0),
|
||||
INSTR("sync", &Jit::Comp_DoNothing, Dis_Generic, Int_Sync, 0),
|
||||
|
||||
//16
|
||||
INSTR("mfhi", &Jit::Comp_MulDivType, Dis_FromHiloTransfer, Int_MulDivType, OUT_RD|IN_OTHER),
|
||||
@@ -224,8 +224,8 @@ const MIPSInstruction tableSpecial[64] = /// 000000 ...... ...... .......... xxx
|
||||
INSTR("sltu", &Jit::Comp_RType3, Dis_RType3, Int_RType3,IN_RS|IN_RT|OUT_RD),
|
||||
INSTR("max", &Jit::Comp_RType3, Dis_RType3, Int_RType3,IN_RS|IN_RT|OUT_RD),
|
||||
INSTR("min", &Jit::Comp_RType3, Dis_RType3, Int_RType3,IN_RS|IN_RT|OUT_RD),
|
||||
INSTR("msub", &Jit::Comp_Generic, Dis_MulDivType, Int_MulDivType, IN_RS|IN_RT|OUT_OTHER),
|
||||
INSTR("msubu", &Jit::Comp_Generic, Dis_MulDivType, Int_MulDivType, IN_RS|IN_RT|OUT_OTHER),
|
||||
INSTR("msub", &Jit::Comp_RType3, Dis_MulDivType, Int_MulDivType, IN_RS|IN_RT|OUT_OTHER),
|
||||
INSTR("msubu", &Jit::Comp_RType3, Dis_MulDivType, Int_MulDivType, IN_RS|IN_RT|OUT_OTHER),
|
||||
|
||||
//48
|
||||
INSTR("tge", &Jit::Comp_Generic, Dis_RType3, 0, 0),
|
||||
@@ -276,32 +276,32 @@ const MIPSInstruction tableSpecial2[64] =
|
||||
//40
|
||||
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
|
||||
//48
|
||||
INSTR("c.f", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.un", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.eq", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ueq", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.olt", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ult", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ole", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ule", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.sf", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ngle",&Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.seq", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ngl", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.lt", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.nge", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.le", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ngt", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.f", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.un", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.eq", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ueq", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.olt", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ult", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ole", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ule", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.sf", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ngle",&Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.seq", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ngl", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.lt", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.nge", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.le", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
INSTR("c.ngt", &Jit::Comp_FPUComp, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
|
||||
};
|
||||
|
||||
|
||||
const MIPSInstruction tableSpecial3[64] =
|
||||
{
|
||||
INSTR("ext", &Jit::Comp_Generic, Dis_Special3, Int_Special3, IN_RS|OUT_RT),
|
||||
INSTR("ext", &Jit::Comp_Special3, Dis_Special3, Int_Special3, IN_RS|OUT_RT),
|
||||
{-2},
|
||||
{-2},
|
||||
{-2},
|
||||
INSTR("ins", &Jit::Comp_Generic, Dis_Special3, Int_Special3, IN_RS|OUT_RT),
|
||||
INSTR("ins", &Jit::Comp_Special3, Dis_Special3, Int_Special3, IN_RS|OUT_RT),
|
||||
{-2},
|
||||
{-2},
|
||||
{-2},
|
||||
@@ -363,11 +363,11 @@ const MIPSInstruction tableCop2[32] =
|
||||
INSTR("mfc2", &Jit::Comp_Generic, Dis_Generic, 0, OUT_RT),
|
||||
{-2},
|
||||
INSTR("cfc2", &Jit::Comp_Generic, Dis_Generic, 0, 0),
|
||||
INSTR("mfv", &Jit::Comp_Generic, Dis_Mftv, Int_Mftv, 0),
|
||||
INSTR("mfv", &Jit::Comp_Mftv, Dis_Mftv, Int_Mftv, 0),
|
||||
INSTR("mtc2", &Jit::Comp_Generic, Dis_Generic, 0, IN_RT),
|
||||
{-2},
|
||||
INSTR("ctc2", &Jit::Comp_Generic, Dis_Generic, 0, 0),
|
||||
INSTR("mtv", &Jit::Comp_Generic, Dis_Mftv, Int_Mftv, 0),
|
||||
INSTR("mtv", &Jit::Comp_Mftv, Dis_Mftv, Int_Mftv, 0),
|
||||
|
||||
{Cop2BC2},
|
||||
INSTR("??", &Jit::Comp_Generic, Dis_Generic, 0, 0),
|
||||
|
||||
@@ -335,6 +335,13 @@ namespace MIPSComp
|
||||
}
|
||||
}
|
||||
|
||||
void Jit::Comp_Special3(u32 op)
|
||||
{
|
||||
// ext, ins
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
|
||||
void Jit::Comp_Allegrex(u32 op)
|
||||
{
|
||||
CONDITIONAL_DISABLE
|
||||
|
||||
@@ -148,10 +148,6 @@ static const u64 GC_ALIGNED16(ssOneBits[2]) = {0x0000000100000001ULL, 0x00000001
|
||||
static const u64 GC_ALIGNED16(ssSignBits2[2]) = {0x8000000080000000ULL, 0x8000000080000000ULL};
|
||||
static const u64 GC_ALIGNED16(ssNoSignMask[2]) = {0x7FFFFFFF7FFFFFFFULL, 0x7FFFFFFF7FFFFFFFULL};
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
void Jit::Comp_FPU2op(u32 op)
|
||||
{
|
||||
=======
|
||||
void Jit::Comp_FPUComp(u32 op) {
|
||||
// TODO: Doesn't work yet.
|
||||
DISABLE;
|
||||
@@ -207,7 +203,6 @@ void Jit::Comp_FPUComp(u32 op) {
|
||||
}
|
||||
|
||||
void Jit::Comp_FPU2op(u32 op) {
|
||||
>>>>>>> Stashed changes
|
||||
CONDITIONAL_DISABLE;
|
||||
|
||||
int fs = _FS;
|
||||
|
||||
+109
-1
@@ -141,11 +141,77 @@ void Jit::ApplyPrefixD(const u8 *vregs, u32 prefix, VectorSize sz, bool onlyWrit
|
||||
|
||||
static u32 GC_ALIGNED16(ssLoadStoreTemp[1]);
|
||||
|
||||
void Jit::Comp_SV(u32 op) {
|
||||
// DISABLE;
|
||||
|
||||
s32 imm = (signed short)(op&0xFFFC);
|
||||
int vt = ((op >> 16) & 0x1f) | ((op & 3) << 5);
|
||||
int rs = _RS;
|
||||
|
||||
switch (op >> 26)
|
||||
{
|
||||
case 50: //lv.s // VI(vt) = Memory::Read_U32(addr);
|
||||
{
|
||||
gpr.BindToRegister(rs, true, false);
|
||||
fpr.MapRegV(vt, MAP_NOINIT);
|
||||
|
||||
JitSafeMem safe(this, rs, imm);
|
||||
safe.SetFar();
|
||||
OpArg src;
|
||||
if (safe.PrepareRead(src))
|
||||
{
|
||||
MOVSS(fpr.VX(vt), safe.NextFastAddress(0));
|
||||
}
|
||||
if (safe.PrepareSlowRead((void *) &Memory::Read_U32))
|
||||
{
|
||||
safe.NextSlowRead((void *) &Memory::Read_U32, 0);
|
||||
MOV(32, M((void *)&ssLoadStoreTemp), R(EAX));
|
||||
MOVSS(fpr.VX(vt), M((void *)&ssLoadStoreTemp));
|
||||
}
|
||||
safe.Finish();
|
||||
|
||||
gpr.UnlockAll();
|
||||
fpr.ReleaseSpillLocks();
|
||||
}
|
||||
break;
|
||||
|
||||
case 58: //sv.s // Memory::Write_U32(VI(vt), addr);
|
||||
{
|
||||
gpr.BindToRegister(rs, true, true);
|
||||
|
||||
// Even if we don't use real SIMD there's still 8 or 16 scalar float registers.
|
||||
fpr.MapRegV(vt, 0);
|
||||
|
||||
JitSafeMem safe(this, rs, imm);
|
||||
safe.SetFar();
|
||||
OpArg dest;
|
||||
if (safe.PrepareWrite(dest))
|
||||
{
|
||||
MOVSS(safe.NextFastAddress(0), fpr.VX(vt));
|
||||
}
|
||||
if (safe.PrepareSlowWrite())
|
||||
{
|
||||
MOVSS(M((void *)&ssLoadStoreTemp), fpr.VX(vt));
|
||||
safe.DoSlowWrite((void *) &Memory::Write_U32, M((void *)&ssLoadStoreTemp), 0);
|
||||
}
|
||||
safe.Finish();
|
||||
|
||||
fpr.ReleaseSpillLocks();
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
_dbg_assert_msg_(CPU,0,"Trying to interpret instruction that can't be interpreted");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Jit::Comp_SVQ(u32 op)
|
||||
{
|
||||
int imm = (signed short)(op&0xFFFC);
|
||||
int rs = _RS;
|
||||
int vt = (((op >> 16) & 0x1f)) | ((op&1) << 5);
|
||||
int rs = _RS;
|
||||
|
||||
switch (op >> 26)
|
||||
{
|
||||
@@ -263,5 +329,47 @@ void Jit::Comp_VDot(u32 op) {
|
||||
js.EatPrefix();
|
||||
}
|
||||
|
||||
void Jit::Comp_Mftv(u32 op) {
|
||||
int imm = op & 0xFF;
|
||||
int rt = _RT;
|
||||
switch ((op >> 21) & 0x1f)
|
||||
{
|
||||
case 3: //mfv / mfvc
|
||||
if (imm < 128) { //R(rt) = VI(imm);
|
||||
fpr.StoreFromRegisterV(imm);
|
||||
gpr.BindToRegister(rt, false, true);
|
||||
MOV(32, gpr.R(rt), fpr.V(imm));
|
||||
} else if (imm < 128 + VFPU_CTRL_MAX) { //mtvc
|
||||
gpr.BindToRegister(rt, false, true);
|
||||
MOV(32, gpr.R(rt), M(¤tMIPS->vfpuCtrl[imm - 128]));
|
||||
} else if (rt == 0 && imm == 255) {
|
||||
// This appears to be used as a CPU interlock by some games. Do nothing.
|
||||
} else {
|
||||
//ERROR - maybe need to make this value too an "interlock" value?
|
||||
_dbg_assert_msg_(CPU,0,"mfv - invalid register");
|
||||
}
|
||||
break;
|
||||
|
||||
case 7: //mtv
|
||||
if (imm < 128) {
|
||||
fpr.StoreFromRegisterV(imm);
|
||||
gpr.BindToRegister(rt, true, false);
|
||||
MOV(32, fpr.V(imm), gpr.R(rt));
|
||||
// VI(imm) = R(rt);
|
||||
} else if (imm < 128 + VFPU_CTRL_MAX) { //mtvc //currentMIPS->vfpuCtrl[imm - 128] = R(rt);
|
||||
gpr.BindToRegister(rt, true, false);
|
||||
MOV(32, M(¤tMIPS->vfpuCtrl[imm - 128]), gpr.R(rt));
|
||||
} else {
|
||||
//ERROR
|
||||
_dbg_assert_msg_(CPU,0,"mtv - invalid register");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DISABLE;
|
||||
_dbg_assert_msg_(CPU,0,"Trying to interpret instruction that can't be interpreted");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+31
-5
@@ -288,7 +288,31 @@ void Jit::WriteExitDestInEAX()
|
||||
// TODO: Some wasted potential, dispatcher will always read this back into EAX.
|
||||
MOV(32, M(&mips_->pc), R(EAX));
|
||||
WriteDowncount();
|
||||
JMP(asm_.dispatcher, true);
|
||||
|
||||
// Validate the jump to avoid a crash?
|
||||
if (!g_Config.bFastMemory)
|
||||
{
|
||||
CMP(32, R(EAX), Imm32(PSP_GetKernelMemoryBase()));
|
||||
FixupBranch tooLow = J_CC(CC_L);
|
||||
CMP(32, R(EAX), Imm32(PSP_GetUserMemoryEnd()));
|
||||
FixupBranch tooHigh = J_CC(CC_GE);
|
||||
|
||||
JMP(asm_.dispatcher, true);
|
||||
|
||||
SetJumpTarget(tooLow);
|
||||
SetJumpTarget(tooHigh);
|
||||
|
||||
ABI_CallFunctionA(thunks.ProtectFunction((void *) Memory::GetPointer, 1), R(EAX));
|
||||
CMP(32, R(EAX), Imm32(0));
|
||||
J_CC(CC_NE, asm_.dispatcher, true);
|
||||
|
||||
// TODO: "Ignore" this so other threads can continue?
|
||||
if (g_Config.bIgnoreBadMemAccess)
|
||||
MOV(32, M((void*)&coreState), Imm32(CORE_ERROR));
|
||||
JMP(asm_.dispatcherCheckCoreState, true);
|
||||
}
|
||||
else
|
||||
JMP(asm_.dispatcher, true);
|
||||
}
|
||||
|
||||
void Jit::WriteSyscallExit()
|
||||
@@ -413,9 +437,9 @@ OpArg Jit::JitSafeMem::PrepareMemoryOpArg()
|
||||
if (!g_Config.bFastMemory)
|
||||
{
|
||||
// Is it in physical ram?
|
||||
jit_->CMP(32, R(xaddr_), Imm32(PSP_GetKernelMemoryBase()));
|
||||
jit_->CMP(32, R(xaddr_), Imm32(PSP_GetKernelMemoryBase() - offset_));
|
||||
tooLow_ = jit_->J_CC(CC_L);
|
||||
jit_->CMP(32, R(xaddr_), Imm32(PSP_GetUserMemoryEnd()));
|
||||
jit_->CMP(32, R(xaddr_), Imm32(PSP_GetUserMemoryEnd() - offset_));
|
||||
tooHigh_ = jit_->J_CC(CC_GE);
|
||||
|
||||
// We may need to jump back up here.
|
||||
@@ -448,9 +472,9 @@ void Jit::JitSafeMem::PrepareSlowAccess()
|
||||
jit_->SetJumpTarget(tooHigh_);
|
||||
|
||||
// Might also be the scratchpad.
|
||||
jit_->CMP(32, R(xaddr_), Imm32(PSP_GetScratchpadMemoryBase()));
|
||||
jit_->CMP(32, R(xaddr_), Imm32(PSP_GetScratchpadMemoryBase() - offset_));
|
||||
FixupBranch tooLow = jit_->J_CC(CC_L);
|
||||
jit_->CMP(32, R(xaddr_), Imm32(PSP_GetScratchpadMemoryEnd()));
|
||||
jit_->CMP(32, R(xaddr_), Imm32(PSP_GetScratchpadMemoryEnd() - offset_));
|
||||
jit_->J_CC(CC_L, safe_);
|
||||
jit_->SetJumpTarget(tooLow);
|
||||
}
|
||||
@@ -545,4 +569,6 @@ void Jit::JitSafeMem::Finish()
|
||||
jit_->SetJumpTarget(skip_);
|
||||
}
|
||||
|
||||
void Jit::Comp_DoNothing(u32 op) { }
|
||||
|
||||
} // namespace
|
||||
|
||||
+7
-1
@@ -118,6 +118,7 @@ public:
|
||||
void Comp_RelBranchRI(u32 op);
|
||||
void Comp_FPUBranch(u32 op);
|
||||
void Comp_FPULS(u32 op);
|
||||
void Comp_FPUComp(u32 op);
|
||||
void Comp_Jump(u32 op);
|
||||
void Comp_JumpReg(u32 op);
|
||||
void Comp_Syscall(u32 op);
|
||||
@@ -129,15 +130,20 @@ public:
|
||||
void Comp_Allegrex(u32 op);
|
||||
void Comp_VBranch(u32 op);
|
||||
void Comp_MulDivType(u32 op);
|
||||
void Comp_Special3(u32 op);
|
||||
|
||||
void Comp_FPU3op(u32 op);
|
||||
void Comp_FPU2op(u32 op);
|
||||
void Comp_mxc1(u32 op);
|
||||
|
||||
void Comp_SV(u32 op);
|
||||
void Comp_SVQ(u32 op);
|
||||
void Comp_VPFX(u32 op);
|
||||
void Comp_VDot(u32 op);
|
||||
|
||||
void Comp_Mftv(u32 op);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -59,6 +59,10 @@ void FPURegCache::SpillLockV(int vec, VectorSize sz) {
|
||||
SpillLockV(v, sz);
|
||||
}
|
||||
|
||||
void FPURegCache::MapRegV(int vreg, int flags) {
|
||||
BindToRegister(vreg + 32, (flags & MAP_NOINIT) == 0, (flags & MAP_DIRTY) != 0);
|
||||
}
|
||||
|
||||
void FPURegCache::MapRegsV(int vec, VectorSize sz, int flags) {
|
||||
u8 v[4];
|
||||
GetVectorRegs(v, sz, vec);
|
||||
|
||||
@@ -64,6 +64,9 @@ public:
|
||||
void Start(MIPSState *mips, MIPSAnalyst::AnalysisResults &stats);
|
||||
void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true);
|
||||
void StoreFromRegister(int preg);
|
||||
void StoreFromRegisterV(int preg) {
|
||||
StoreFromRegister(preg + 32);
|
||||
}
|
||||
OpArg GetDefaultLocation(int reg) const;
|
||||
|
||||
void SetEmitter(XEmitter *emitter) {emit = emitter;}
|
||||
@@ -94,6 +97,7 @@ public:
|
||||
void SpillLock(int p1, int p2=0xff, int p3=0xff, int p4=0xff);
|
||||
void ReleaseSpillLocks();
|
||||
|
||||
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(const u8 *v, VectorSize vsz);
|
||||
|
||||
+2
-1
@@ -77,9 +77,10 @@ namespace SaveState
|
||||
Memory::DoState(p);
|
||||
MemoryStick_DoState(p);
|
||||
currentMIPS->DoState(p);
|
||||
pspFileSystem.DoState(p);
|
||||
HLEDoState(p);
|
||||
__KernelDoState(p);
|
||||
// Kernel object destructors might close open files, so do the filesystem last.
|
||||
pspFileSystem.DoState(p);
|
||||
}
|
||||
|
||||
void Enqueue(SaveState::Operation op)
|
||||
|
||||
@@ -110,6 +110,7 @@ static const int flushOnChangedBeforeCommandList[] = {
|
||||
GE_CMD_TEXFORMAT,
|
||||
GE_CMD_TEXWRAP,
|
||||
GE_CMD_ZTESTENABLE,
|
||||
GE_CMD_ZWRITEDISABLE,
|
||||
GE_CMD_STENCILTESTENABLE,
|
||||
GE_CMD_STENCILOP,
|
||||
GE_CMD_STENCILTEST,
|
||||
@@ -166,6 +167,8 @@ GLES_GPU::GLES_GPU()
|
||||
shaderManager_ = new ShaderManager();
|
||||
transformDraw_.SetShaderManager(shaderManager_);
|
||||
transformDraw_.SetTextureCache(&textureCache_);
|
||||
transformDraw_.SetFramebufferManager(&framebufferManager_);
|
||||
framebufferManager_.SetTextureCache(&textureCache_);
|
||||
|
||||
// Sanity check gstate
|
||||
if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) {
|
||||
@@ -448,7 +451,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
currentList->subIntrToken = data & 0xFFFF;
|
||||
// TODO: Should this run while interrupts are suspended?
|
||||
if (interruptsEnabled_)
|
||||
__GeTriggerInterrupt(currentList->id, currentList->pc);
|
||||
__GeTriggerInterrupt(currentList->id, currentList->pc, currentList->subIntrBase, currentList->subIntrToken);
|
||||
break;
|
||||
|
||||
case GE_CMD_END:
|
||||
@@ -486,7 +489,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
}
|
||||
// TODO: Should this run while interrupts are suspended?
|
||||
if (interruptsEnabled_)
|
||||
__GeTriggerInterrupt(currentList->id, currentList->pc);
|
||||
__GeTriggerInterrupt(currentList->id, currentList->pc, currentList->subIntrBase, currentList->subIntrToken);
|
||||
}
|
||||
break;
|
||||
case GE_CMD_FINISH:
|
||||
@@ -677,6 +680,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
case GE_CMD_TEXSIZE0:
|
||||
gstate_c.curTextureWidth = 1 << (gstate.texsize[0] & 0xf);
|
||||
gstate_c.curTextureHeight = 1 << ((gstate.texsize[0]>>8) & 0xf);
|
||||
shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET);
|
||||
//fall thru - ignoring the mipmap sizes for now
|
||||
case GE_CMD_TEXSIZE1:
|
||||
case GE_CMD_TEXSIZE2:
|
||||
@@ -797,16 +801,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
case GE_CMD_VIEWPORTY1:
|
||||
case GE_CMD_VIEWPORTX2:
|
||||
case GE_CMD_VIEWPORTY2:
|
||||
break;
|
||||
|
||||
case GE_CMD_VIEWPORTZ1:
|
||||
gstate_c.zScale = getFloat24(data) / 65535.f;
|
||||
break;
|
||||
|
||||
case GE_CMD_VIEWPORTZ2:
|
||||
gstate_c.zOff = getFloat24(data) / 65535.f;
|
||||
break;
|
||||
|
||||
case GE_CMD_LIGHTENABLE0:
|
||||
case GE_CMD_LIGHTENABLE1:
|
||||
case GE_CMD_LIGHTENABLE2:
|
||||
|
||||
+52
-18
@@ -29,6 +29,7 @@
|
||||
#include "GPU/GPUState.h"
|
||||
|
||||
#include "GPU/GLES/Framebuffer.h"
|
||||
#include "GPU/GLES/TextureCache.h"
|
||||
|
||||
static const char tex_fs[] =
|
||||
"#ifdef GL_ES\n"
|
||||
@@ -66,7 +67,8 @@ static bool MaskedEqual(u32 addr1, u32 addr2) {
|
||||
FramebufferManager::FramebufferManager() :
|
||||
displayFramebufPtr_(0),
|
||||
prevDisplayFramebuf_(0),
|
||||
prevPrevDisplayFramebuf_(0)
|
||||
prevPrevDisplayFramebuf_(0),
|
||||
currentRenderVfb_(0)
|
||||
{
|
||||
glGenTextures(1, &backbufTex);
|
||||
|
||||
@@ -216,6 +218,13 @@ FramebufferManager::VirtualFramebuffer *FramebufferManager::GetDisplayFBO() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GetViewportDimensions(int *w, int *h) {
|
||||
float vpXa = getFloat24(gstate.viewportx1);
|
||||
float vpYa = getFloat24(gstate.viewporty1);
|
||||
*w = (int)fabsf(vpXa * 2);
|
||||
*h = (int)fabsf(vpYa * 2);
|
||||
}
|
||||
|
||||
void FramebufferManager::SetRenderFrameBuffer() {
|
||||
if (!g_Config.bBufferedRendering)
|
||||
return;
|
||||
@@ -226,12 +235,23 @@ void FramebufferManager::SetRenderFrameBuffer() {
|
||||
u32 z_address = (gstate.zbptr & 0xFFE000) | ((gstate.zbwidth & 0xFF0000) << 8);
|
||||
int z_stride = gstate.zbwidth & 0x3C0;
|
||||
|
||||
// We guess that the viewport size during the first draw call is an appropriate
|
||||
// size for a render target.
|
||||
//UpdateViewportAndProjection();
|
||||
|
||||
// Yeah this is not completely right. but it'll do for now.
|
||||
int drawing_width = ((gstate.region2) & 0x3FF) + 1;
|
||||
int drawing_height = ((gstate.region2 >> 10) & 0x3FF) + 1;
|
||||
//int drawing_width = ((gstate.region2) & 0x3FF) + 1;
|
||||
//int drawing_height = ((gstate.region2 >> 10) & 0x3FF) + 1;
|
||||
|
||||
// As there are no clear "framebuffer width" and "framebuffer height" registers,
|
||||
// we need to infer the size of the current framebuffer somehow. Let's try the viewport.
|
||||
|
||||
int drawing_width, drawing_height;
|
||||
GetViewportDimensions(&drawing_width, &drawing_height);
|
||||
|
||||
// HACK for first frame where some games don't init things right
|
||||
if (drawing_width == 1 && drawing_height == 1) {
|
||||
|
||||
if (drawing_width <= 1 && drawing_height <= 1) {
|
||||
drawing_width = 480;
|
||||
drawing_height = 272;
|
||||
}
|
||||
@@ -251,6 +271,9 @@ void FramebufferManager::SetRenderFrameBuffer() {
|
||||
}
|
||||
}
|
||||
|
||||
float renderWidthFactor = (float)PSP_CoreParameter().renderWidth / 480.0f;
|
||||
float renderHeightFactor = (float)PSP_CoreParameter().renderHeight / 272.0f;
|
||||
|
||||
// None found? Create one.
|
||||
if (!vfb) {
|
||||
gstate_c.textureChanged = true;
|
||||
@@ -261,6 +284,8 @@ void FramebufferManager::SetRenderFrameBuffer() {
|
||||
vfb->z_stride = z_stride;
|
||||
vfb->width = drawing_width;
|
||||
vfb->height = drawing_height;
|
||||
vfb->renderWidth = (u16)(drawing_width * renderWidthFactor);
|
||||
vfb->renderHeight = (u16)(drawing_height * renderHeightFactor);
|
||||
vfb->format = fmt;
|
||||
|
||||
vfb->colorDepth = FBO_8888;
|
||||
@@ -273,15 +298,16 @@ void FramebufferManager::SetRenderFrameBuffer() {
|
||||
//#ifdef ANDROID
|
||||
// vfb->colorDepth = FBO_8888;
|
||||
//#endif
|
||||
float renderWidthFactor = (float)PSP_CoreParameter().renderWidth / 480.0f;
|
||||
float renderHeightFactor = (float)PSP_CoreParameter().renderHeight / 272.0f;
|
||||
vfb->fbo = fbo_create((int)(vfb->width * renderWidthFactor), (int)(vfb->height * renderHeightFactor), 1, true, vfb->colorDepth);
|
||||
|
||||
vfb->fbo = fbo_create(vfb->renderWidth, vfb->renderHeight, 1, true, vfb->colorDepth);
|
||||
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb->fbo);
|
||||
|
||||
vfb->last_frame_used = gpuStats.numFrames;
|
||||
vfbs_.push_back(vfb);
|
||||
|
||||
fbo_bind_as_render_target(vfb->fbo);
|
||||
glEnable(GL_DITHER);
|
||||
glstate.viewport.set(0, 0, PSP_CoreParameter().renderWidth, PSP_CoreParameter().renderHeight);
|
||||
glstate.viewport.set(0, 0, vfb->renderWidth, vfb->renderHeight);
|
||||
currentRenderVfb_ = vfb;
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
INFO_LOG(HLE, "Creating FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format);
|
||||
@@ -292,8 +318,15 @@ void FramebufferManager::SetRenderFrameBuffer() {
|
||||
// Use it as a render target.
|
||||
DEBUG_LOG(HLE, "Switching render target to FBO for %08x", vfb->fb_address);
|
||||
gstate_c.textureChanged = true;
|
||||
if (vfb->last_frame_used != gpuStats.numFrames) {
|
||||
// Android optimization
|
||||
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
vfb->last_frame_used = gpuStats.numFrames;
|
||||
|
||||
fbo_bind_as_render_target(vfb->fbo);
|
||||
|
||||
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb->fbo);
|
||||
#ifdef USING_GLES2
|
||||
// Some tiled mobile GPUs benefit IMMENSELY from clearing an FBO before rendering
|
||||
// to it. This broke stuff before, so now it only clears on the first use of an
|
||||
@@ -302,9 +335,8 @@ void FramebufferManager::SetRenderFrameBuffer() {
|
||||
if (vfb->last_frame_used != gpuStats.numFrames)
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
#endif
|
||||
glstate.viewport.set(0, 0, PSP_CoreParameter().renderWidth, PSP_CoreParameter().renderHeight);
|
||||
glstate.viewport.set(0, 0, vfb->renderWidth, vfb->renderHeight);
|
||||
currentRenderVfb_ = vfb;
|
||||
vfb->last_frame_used = gpuStats.numFrames;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,15 +407,16 @@ void FramebufferManager::SetDisplayFramebuffer(u32 framebuf, u32 stride, int for
|
||||
|
||||
void FramebufferManager::DecimateFBOs() {
|
||||
for (auto iter = vfbs_.begin(); iter != vfbs_.end();) {
|
||||
VirtualFramebuffer *v = *iter;
|
||||
if (v == displayFramebuf_ || v == prevDisplayFramebuf_ || v == prevPrevDisplayFramebuf_) {
|
||||
VirtualFramebuffer *vfb = *iter;
|
||||
if (vfb == displayFramebuf_ || vfb == prevDisplayFramebuf_ || vfb == prevPrevDisplayFramebuf_) {
|
||||
++iter;
|
||||
continue;
|
||||
}
|
||||
if ((*iter)->last_frame_used + FBO_OLD_AGE < gpuStats.numFrames) {
|
||||
INFO_LOG(HLE, "Destroying FBO %i (%i x %i x %i)", v->fb_address, v->width, v->height, v->format)
|
||||
fbo_destroy(v->fbo);
|
||||
delete v;
|
||||
INFO_LOG(HLE, "Destroying FBO for %08x (%i x %i x %i)", vfb->fb_address, vfb->width, vfb->height, vfb->format)
|
||||
textureCache_->NotifyFramebufferDestroyed(vfb->fb_address, vfb->fbo);
|
||||
fbo_destroy(vfb->fbo);
|
||||
delete vfb;
|
||||
vfbs_.erase(iter++);
|
||||
}
|
||||
else
|
||||
@@ -393,9 +426,10 @@ void FramebufferManager::DecimateFBOs() {
|
||||
|
||||
void FramebufferManager::DestroyAllFBOs() {
|
||||
for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) {
|
||||
VirtualFramebuffer *v = *iter;
|
||||
fbo_destroy(v->fbo);
|
||||
delete v;
|
||||
VirtualFramebuffer *vfb = *iter;
|
||||
textureCache_->NotifyFramebufferDestroyed(vfb->fb_address, vfb->fbo);
|
||||
fbo_destroy(vfb->fbo);
|
||||
delete vfb;
|
||||
}
|
||||
vfbs_.clear();
|
||||
}
|
||||
|
||||
+18
-2
@@ -28,6 +28,7 @@
|
||||
#include "../Globals.h"
|
||||
|
||||
struct GLSLProgram;
|
||||
class TextureCache;
|
||||
|
||||
enum PspDisplayPixelFormat {
|
||||
PSP_DISPLAY_PIXEL_FORMAT_565 = 0,
|
||||
@@ -41,6 +42,10 @@ public:
|
||||
FramebufferManager();
|
||||
~FramebufferManager();
|
||||
|
||||
void SetTextureCache(TextureCache *tc) {
|
||||
textureCache_ = tc;
|
||||
}
|
||||
|
||||
struct VirtualFramebuffer {
|
||||
int last_frame_used;
|
||||
|
||||
@@ -50,8 +55,10 @@ public:
|
||||
int z_stride;
|
||||
|
||||
// There's also a top left of the drawing region, but meh...
|
||||
int width;
|
||||
int height;
|
||||
u16 width;
|
||||
u16 height;
|
||||
u16 renderWidth;
|
||||
u16 renderHeight;
|
||||
|
||||
int format; // virtual, right now they are all RGBA8888
|
||||
FBOColorDepth colorDepth;
|
||||
@@ -73,6 +80,11 @@ public:
|
||||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, int format);
|
||||
size_t NumVFBs() const { return vfbs_.size(); }
|
||||
|
||||
int GetRenderWidth() const { return currentRenderVfb_ ? currentRenderVfb_->renderWidth : 480; }
|
||||
int GetRenderHeight() const { return currentRenderVfb_ ? currentRenderVfb_->renderHeight : 272; }
|
||||
int GetTargetWidth() const { return currentRenderVfb_ ? currentRenderVfb_->width : 480; }
|
||||
int GetTargetHeight() const { return currentRenderVfb_ ? currentRenderVfb_->height : 272; }
|
||||
|
||||
private:
|
||||
// Deletes old FBOs.
|
||||
|
||||
@@ -93,5 +105,9 @@ private:
|
||||
|
||||
u8 *convBuf;
|
||||
GLSLProgram *draw2dprogram;
|
||||
|
||||
|
||||
TextureCache *textureCache_;
|
||||
|
||||
bool resized_;
|
||||
};
|
||||
|
||||
+12
-16
@@ -208,25 +208,20 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
|
||||
|
||||
bool wantDepthWrite = gstate.isModeClear() || gstate.isDepthWriteEnabled();
|
||||
glstate.depthWrite.set(wantDepthWrite ? GL_TRUE : GL_FALSE);
|
||||
|
||||
float depthRangeMin = gstate_c.zOff - gstate_c.zScale;
|
||||
float depthRangeMax = gstate_c.zOff + gstate_c.zScale;
|
||||
glstate.depthRange.set(depthRangeMin, depthRangeMax);
|
||||
}
|
||||
|
||||
void UpdateViewportAndProjection() {
|
||||
void TransformDrawEngine::UpdateViewportAndProjection() {
|
||||
int renderWidth, renderHeight;
|
||||
|
||||
if (g_Config.bBufferedRendering) {
|
||||
renderWidth = PSP_CoreParameter().renderWidth;
|
||||
renderHeight = PSP_CoreParameter().renderHeight;
|
||||
renderWidth = framebufferManager_->GetRenderWidth();
|
||||
renderHeight = framebufferManager_->GetRenderHeight();
|
||||
} else {
|
||||
// TODO: Aspect-ratio aware and centered
|
||||
renderWidth = PSP_CoreParameter().pixelWidth;
|
||||
renderHeight = PSP_CoreParameter().pixelHeight;
|
||||
}
|
||||
float renderWidthFactor = (float)renderWidth / 480.0f;
|
||||
float renderHeightFactor = (float)renderHeight / 272.0f;
|
||||
float renderWidthFactor = (float)renderWidth / framebufferManager_->GetTargetWidth();
|
||||
float renderHeightFactor = (float)renderHeight / framebufferManager_->GetTargetHeight();
|
||||
bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0;
|
||||
|
||||
// We can probably use these to simply set scissors? Maybe we need to offset by regionX1/Y1
|
||||
@@ -241,14 +236,13 @@ void UpdateViewportAndProjection() {
|
||||
if (throughmode) {
|
||||
// No viewport transform here. Let's experiment with using region.
|
||||
glstate.viewport.set((0 + regionX1) * renderWidthFactor, (0 - regionY1) * renderHeightFactor, (regionX2 - regionX1) * renderWidthFactor, (regionY2 - regionY1) * renderHeightFactor);
|
||||
glstate.depthRange.set(1.0, 0.0);
|
||||
} else {
|
||||
// These we can turn into a glViewport call, offset by offsetX and offsetY. Math after.
|
||||
float vpXa = getFloat24(gstate.viewportx1);
|
||||
float vpXb = getFloat24(gstate.viewportx2);
|
||||
float vpYa = getFloat24(gstate.viewporty1);
|
||||
float vpYb = getFloat24(gstate.viewporty2);
|
||||
float vpZa = getFloat24(gstate.viewportz1); // / 65536.0f should map it to OpenGL's 0.0-1.0 Z range
|
||||
float vpZb = getFloat24(gstate.viewportz2); // / 65536.0f
|
||||
|
||||
// The viewport transform appears to go like this:
|
||||
// Xscreen = -offsetX + vpXb + vpXa * Xview
|
||||
@@ -264,10 +258,6 @@ void UpdateViewportAndProjection() {
|
||||
float vpWidth = fabsf(gstate_c.vpWidth);
|
||||
float vpHeight = fabsf(gstate_c.vpHeight);
|
||||
|
||||
// TODO: These two should feed into glDepthRange somehow.
|
||||
float vpZ0 = (vpZb - vpZa) / 65536.0f;
|
||||
float vpZ1 = (vpZa * 2) / 65536.0f;
|
||||
|
||||
vpX0 *= renderWidthFactor;
|
||||
vpY0 *= renderHeightFactor;
|
||||
vpWidth *= renderWidthFactor;
|
||||
@@ -278,5 +268,11 @@ void UpdateViewportAndProjection() {
|
||||
glstate.viewport.set(vpX0, vpY0, vpWidth, vpHeight);
|
||||
// Sadly, as glViewport takes integers, we will not be able to support sub pixel offsets this way. But meh.
|
||||
// shaderManager_->DirtyUniform(DIRTY_PROJMATRIX);
|
||||
|
||||
float zScale = getFloat24(gstate.viewportz1) / 65535.f;
|
||||
float zOff = getFloat24(gstate.viewportz2) / 65535.f;
|
||||
float depthRangeMin = zOff - zScale;
|
||||
float depthRangeMax = zOff + zScale;
|
||||
glstate.depthRange.set(depthRangeMin, depthRangeMax);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,5 +6,4 @@ extern const GLint eqLookup[];
|
||||
extern const GLint cullingMode[];
|
||||
extern const GLuint ztests[];
|
||||
|
||||
void UpdateViewportAndProjection();
|
||||
|
||||
|
||||
+87
-48
@@ -111,6 +111,33 @@ void TextureCache::InvalidateAll(bool force) {
|
||||
Invalidate(0, 0xFFFFFFFF, force);
|
||||
}
|
||||
|
||||
TextureCache::TexCacheEntry *TextureCache::GetEntryAt(u32 texaddr) {
|
||||
// If no CLUT, as in framebuffer textures, cache key is simply texaddr.
|
||||
auto iter = cache.find(texaddr);
|
||||
if (iter != cache.end() && iter->second.addr == texaddr)
|
||||
return &iter->second;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TextureCache::NotifyFramebuffer(u32 address, FBO *fbo) {
|
||||
// Must be in VRAM so | 0x04000000 it is.
|
||||
TexCacheEntry *entry = GetEntryAt(address | 0x04000000);
|
||||
if (entry) {
|
||||
// INFO_LOG(HLE, "Render to texture detected at %08x!", address);
|
||||
if (!entry->fbo)
|
||||
entry->fbo = fbo;
|
||||
// TODO: Delete the original non-fbo texture too.
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::NotifyFramebufferDestroyed(u32 address, FBO *fbo) {
|
||||
TexCacheEntry *entry = GetEntryAt(address | 0x04000000);
|
||||
if (entry && entry->fbo) {
|
||||
entry->fbo = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 GetClutAddr(u32 clutEntrySize) {
|
||||
return ((gstate.clutaddr & 0xFFFFFF) | ((gstate.clutaddrupper << 8) & 0x0F000000)) + ((gstate.clutformat >> 16) & 0x1f) * clutEntrySize;
|
||||
}
|
||||
@@ -363,7 +390,8 @@ static const GLuint MagFiltGL[2] = {
|
||||
GL_LINEAR
|
||||
};
|
||||
|
||||
// OpenGL ES 2.0 workaround. Let's see if this hackery works.
|
||||
// OpenGL ES 2.0 workaround. This SHOULD be available but is NOT in the headers in Android.
|
||||
// Let's see if this hackery works.
|
||||
#ifndef GL_TEXTURE_LOD_BIAS
|
||||
#define GL_TEXTURE_LOD_BIAS 0x8501
|
||||
#endif
|
||||
@@ -372,8 +400,6 @@ static const GLuint MagFiltGL[2] = {
|
||||
#define GL_TEXTURE_MAX_LOD 0x813B
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// This should not have to be done per texture! OpenGL is silly yo
|
||||
// TODO: Dirty-check this against the current texture.
|
||||
void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
|
||||
@@ -641,23 +667,52 @@ void TextureCache::SetTexture() {
|
||||
ERROR_LOG(G3D, "Unknown texture format %i", format);
|
||||
format = 0;
|
||||
}
|
||||
bool hasClut = formatUsesClut[format];
|
||||
|
||||
const u8 *texptr = Memory::GetPointer(texaddr);
|
||||
|
||||
u32 clutformat = gstate.clutformat & 3;
|
||||
u32 clutaddr = GetClutAddr(clutformat == GE_CMODE_32BIT_ABGR8888 ? 4 : 2);
|
||||
|
||||
u64 cachekey = texaddr;
|
||||
if (formatUsesClut[format])
|
||||
cachekey |= (u64)clutaddr << 32;
|
||||
|
||||
int maxLevel = ((gstate.texmode >> 16) & 0x7);
|
||||
|
||||
const u8 *texptr = Memory::GetPointer(texaddr);
|
||||
u32 texhash = texptr ? MiniHash((const u32*)texptr) : 0;
|
||||
// Adjust maxLevel to actually present levels..
|
||||
for (int i = 0; i <= maxLevel; i++) {
|
||||
// If encountering levels pointing to nothing, adjust max level.
|
||||
u32 levelTexaddr = (gstate.texaddr[i] & 0xFFFFF0) | ((gstate.texbufwidth[i] << 8) & 0x0F000000);
|
||||
if (!Memory::IsValidAddress(levelTexaddr)) {
|
||||
maxLevel = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u64 cachekey = texaddr ^ texhash;
|
||||
if (formatUsesClut[format])
|
||||
cachekey |= (u64) clutaddr << 32;
|
||||
u32 texhash = MiniHash((const u32 *)Memory::GetPointer(texaddr));
|
||||
|
||||
int w = 1 << (gstate.texsize[0] & 0xf);
|
||||
int h = 1 << ((gstate.texsize[0] >> 8) & 0xf);
|
||||
|
||||
TexCache::iterator iter = cache.find(cachekey);
|
||||
if (iter != cache.end()) {
|
||||
//Validate the texture here (width, height etc)
|
||||
TexCacheEntry &entry = iter->second;
|
||||
// Check for FBO - slow!
|
||||
if (entry.fbo) {
|
||||
fbo_bind_color_as_texture(entry.fbo, 0);
|
||||
UpdateSamplingParams(entry, false);
|
||||
|
||||
int fbow, fboh;
|
||||
fbo_get_dimensions(entry.fbo, &fbow, &fboh);
|
||||
|
||||
// Almost certain this isn't right.
|
||||
gstate_c.curTextureWidth = fbow;
|
||||
gstate_c.curTextureHeight = fboh;
|
||||
return;
|
||||
}
|
||||
|
||||
//Validate the texture here (width, height etc)
|
||||
|
||||
int dim = gstate.texsize[0] & 0xF0F;
|
||||
bool match = true;
|
||||
@@ -716,6 +771,7 @@ void TextureCache::SetTexture() {
|
||||
entry.hash = texhash;
|
||||
entry.format = format;
|
||||
entry.frameCounter = gpuStats.numFrames;
|
||||
entry.fbo = 0;
|
||||
entry.maxLevel = maxLevel;
|
||||
entry.lodBias = 0.0f;
|
||||
|
||||
@@ -731,9 +787,6 @@ void TextureCache::SetTexture() {
|
||||
|
||||
entry.dim = gstate.texsize[0] & 0xF0F;
|
||||
|
||||
int w = 1 << (gstate.texsize[0] & 0xf);
|
||||
int h = 1 << ((gstate.texsize[0] >> 8) & 0xf);
|
||||
|
||||
// This would overestimate the size in many case so we underestimate instead
|
||||
// to avoid excessive clearing caused by cache invalidations.
|
||||
entry.sizeInRAM = (bitsPerPixel[format < 11 ? format : 0] * bufw * h / 2) / 8;
|
||||
@@ -748,21 +801,26 @@ void TextureCache::SetTexture() {
|
||||
glGenTextures(1, &entry.texture);
|
||||
glBindTexture(GL_TEXTURE_2D, entry.texture);
|
||||
|
||||
#ifdef USING_GLES2
|
||||
// GLES2 doesn't have support for a "Max lod" which is critical as PSP games often
|
||||
// don't specify mips all the way down. As a result, we either need to manually generate
|
||||
// the bottom few levels or rely on OpenGL's autogen mipmaps instead, which might not
|
||||
// be as good quality as the game's own (might even be better in some cases though).
|
||||
|
||||
// For now, I choose to use autogen mips on GLES2 and the game's own on other platforms.
|
||||
// As is usual, GLES3 will solve this problem nicely but wide distribution of that is
|
||||
// years away.
|
||||
LoadTextureLevel(entry, 0);
|
||||
if (entry.maxLevel > 0)
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
#else
|
||||
for (int i = 0; i <= entry.maxLevel; i++) {
|
||||
// If encountering levels pointing to nothing, adjust max level.
|
||||
u32 levelTexaddr = (gstate.texaddr[i] & 0xFFFFF0) | ((gstate.texbufwidth[i] << 8) & 0x0F000000);
|
||||
if (!Memory::IsValidAddress(levelTexaddr)) {
|
||||
entry.maxLevel = i - 1;
|
||||
break;
|
||||
}
|
||||
LoadTextureLevel(entry, i);
|
||||
}
|
||||
|
||||
#ifndef USING_GLES2
|
||||
// See horrifying hack at the bottom of LoadTextureLevel!
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, entry.maxLevel);
|
||||
#endif
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, entry.maxLevel);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (float)entry.maxLevel);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 4.0);
|
||||
|
||||
UpdateSamplingParams(entry, true);
|
||||
|
||||
@@ -799,7 +857,7 @@ void TextureCache::LoadTextureLevel(TexCacheEntry &entry, int level)
|
||||
switch (entry.format)
|
||||
{
|
||||
case GE_TFMT_CLUT4:
|
||||
dstFmt = getClutDestFormat((GEPaletteFormat)(gstate.clutformat & 3));
|
||||
dstFmt = getClutDestFormat((GEPaletteFormat)(entry.clutformat));
|
||||
|
||||
switch (entry.clutformat) {
|
||||
case GE_CMODE_16BIT_BGR5650:
|
||||
@@ -808,15 +866,15 @@ void TextureCache::LoadTextureLevel(TexCacheEntry &entry, int level)
|
||||
{
|
||||
ReadClut16(clutBuf16);
|
||||
const u16 *clut = clutBuf16;
|
||||
u32 clutSharingOff = 0;//gstate.mipmapShareClut ? 0 : level * 16;
|
||||
u32 clutSharingOffset = 0; //(gstate.mipmapShareClut & 1) ? 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];
|
||||
tmpTexBuf16[i + 0] = clut[GetClutIndex((index >> 0) & 0xf) + clutSharingOffset];
|
||||
tmpTexBuf16[i + 1] = clut[GetClutIndex((index >> 4) & 0xf) + clutSharingOffset];
|
||||
}
|
||||
} else {
|
||||
UnswizzleFromMem(texaddr, 0, level);
|
||||
@@ -826,7 +884,7 @@ void TextureCache::LoadTextureLevel(TexCacheEntry &entry, int level)
|
||||
u32 k, index;
|
||||
for (k = 0; k < 8; k++) {
|
||||
index = (n >> (k * 4)) & 0xf;
|
||||
tmpTexBuf16[i + k] = clut[GetClutIndex(index) + clutSharingOff];
|
||||
tmpTexBuf16[i + k] = clut[GetClutIndex(index) + clutSharingOffset];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1025,27 +1083,8 @@ void TextureCache::LoadTextureLevel(TexCacheEntry &entry, int level)
|
||||
//glPixelStorei(GL_PACK_ROW_LENGTH, bufw);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, texByteAlign);
|
||||
|
||||
INFO_LOG(HLE, "Creating texture level %i/%i from %08x: %i x %i (stride: %i). fmt: %i", level, entry.maxLevel, texaddr, w, h, bufw, entry.format);
|
||||
// INFO_LOG(G3D, "Creating texture level %i/%i from %08x: %i x %i (stride: %i). fmt: %i", level, entry.maxLevel, texaddr, w, h, bufw, entry.format);
|
||||
|
||||
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);
|
||||
|
||||
#ifdef USING_GLES2
|
||||
// ARGH! OpenGL ES does not support max texture level!
|
||||
// Let's do a HORRIBLE hack for now and re-specify the last level, but with changed dimensions.
|
||||
// Will at least give us sort of the right colors and hopefully it'll be too blurry anyway.
|
||||
// Later I will add proper downsampling of the bottom level.
|
||||
// TEXTURE_MAX_LOD should ensure that we never get to see these anyway.
|
||||
if (level == entry.maxLevel) {
|
||||
while (w >= 2 || h >= 2) {
|
||||
w /= 2;
|
||||
h /= 2;
|
||||
if (w == 0) w = 1;
|
||||
if (h == 0) h = 1;
|
||||
++level;
|
||||
INFO_LOG(HLE, "Specifying extra texture level %i : %ix%i", level, w, h);
|
||||
glTexImage2D(GL_TEXTURE_2D, level, components, w, h, 0, components, dstFmt, finalBuf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
+13
-3
@@ -18,6 +18,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Globals.h"
|
||||
#include "gfx_es2/fbo.h"
|
||||
|
||||
class TextureCache
|
||||
{
|
||||
@@ -32,21 +33,28 @@ public:
|
||||
void Invalidate(u32 addr, int size, bool force);
|
||||
void InvalidateAll(bool force);
|
||||
|
||||
// FramebufferManager keeps TextureCache updated about what regions of memory
|
||||
// are being rendered to. This is barebones so far.
|
||||
void NotifyFramebuffer(u32 address, FBO *fbo);
|
||||
void NotifyFramebufferDestroyed(u32 address, FBO *fbo);
|
||||
|
||||
size_t NumLoadedTextures() const {
|
||||
return cache.size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct TexCacheEntry {
|
||||
u32 addr;
|
||||
u32 hash;
|
||||
FBO *fbo; // if null, not sourced from an FBO.
|
||||
u32 sizeInRAM;
|
||||
int frameCounter;
|
||||
u32 format;
|
||||
u8 format;
|
||||
u8 clutformat;
|
||||
u16 dim;
|
||||
u32 clutaddr;
|
||||
u32 clutformat;
|
||||
u32 cluthash;
|
||||
int dim;
|
||||
u32 texture; //GLuint
|
||||
int invalidHint;
|
||||
u32 fullhash;
|
||||
@@ -66,6 +74,8 @@ private:
|
||||
void UpdateSamplingParams(TexCacheEntry &entry, bool force);
|
||||
void LoadTextureLevel(TexCacheEntry &entry, int level);
|
||||
|
||||
TexCacheEntry *GetEntryAt(u32 texaddr);
|
||||
|
||||
typedef std::map<u64, TexCacheEntry> TexCache;
|
||||
|
||||
// TODO: Speed up by switching to ReadUnchecked*.
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
class LinkedShader;
|
||||
class ShaderManager;
|
||||
class TextureCache;
|
||||
class FramebufferManager;
|
||||
|
||||
struct DecVtxFormat;
|
||||
|
||||
// States transitions:
|
||||
@@ -103,7 +105,9 @@ public:
|
||||
void SetTextureCache(TextureCache *textureCache) {
|
||||
textureCache_ = textureCache;
|
||||
}
|
||||
|
||||
void SetFramebufferManager(FramebufferManager *fbManager) {
|
||||
framebufferManager_ = fbManager;
|
||||
}
|
||||
void InitDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
void GLLost();
|
||||
@@ -114,6 +118,7 @@ public:
|
||||
private:
|
||||
void SoftwareTransformAndDraw(int prim, u8 *decoded, LinkedShader *program, int vertexCount, u32 vertexType, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex);
|
||||
void ApplyDrawState(int prim);
|
||||
void UpdateViewportAndProjection();
|
||||
|
||||
// drawcall ID
|
||||
u32 ComputeFastDCID();
|
||||
@@ -158,6 +163,7 @@ private:
|
||||
// Other
|
||||
ShaderManager *shaderManager_;
|
||||
TextureCache *textureCache_;
|
||||
FramebufferManager *framebufferManager_;
|
||||
|
||||
enum { MAX_DEFERRED_DRAW_CALLS = 128 };
|
||||
DeferredDrawCall drawCalls[MAX_DEFERRED_DRAW_CALLS];
|
||||
|
||||
@@ -375,7 +375,7 @@ void GenerateVertexShader(int prim, char *buffer) {
|
||||
WRITE(p, " vec3 temp_tc = a_position.xyz;\n");
|
||||
break;
|
||||
case 1: // Use unscaled UV as source
|
||||
WRITE(p, " vec3 temp_tc = vec3(a_texcoord.xy * 2.0f, 0.0);\n");
|
||||
WRITE(p, " vec3 temp_tc = vec3(a_texcoord.xy * 2.0, 0.0);\n");
|
||||
break;
|
||||
case 2: // Use normalized transformed normal as source
|
||||
WRITE(p, " vec3 temp_tc = normalize(a_normal);\n");
|
||||
|
||||
+2
-2
@@ -236,8 +236,8 @@ struct GPUStateCache
|
||||
|
||||
bool textureChanged;
|
||||
|
||||
float uScale,vScale,zScale;
|
||||
float uOff,vOff,zOff;
|
||||
float uScale,vScale;
|
||||
float uOff,vOff;
|
||||
float zMin, zMax;
|
||||
float lightpos[4][3];
|
||||
float lightdir[4][3];
|
||||
|
||||
+2
-2
@@ -521,13 +521,13 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) {
|
||||
case GE_CMD_VIEWPORTZ1:
|
||||
{
|
||||
float zScale = getFloat24(data) / 65535.f;
|
||||
sprintf(buffer, "Z scale: %f", zScale);
|
||||
sprintf(buffer, "Viewport Z scale: %f", zScale);
|
||||
}
|
||||
break;
|
||||
case GE_CMD_VIEWPORTZ2:
|
||||
{
|
||||
float zOff = getFloat24(data) / 65535.f;
|
||||
sprintf(buffer, "Z pos: %f", zOff);
|
||||
sprintf(buffer, "Viewport Z pos: %f", zOff);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
|
||||
|
||||
// TODO: Should this run while interrupts are suspended?
|
||||
if (interruptsEnabled_)
|
||||
__GeTriggerInterrupt(currentList->id, currentList->pc);
|
||||
__GeTriggerInterrupt(currentList->id, currentList->pc, currentList->subIntrBase, currentList->subIntrToken);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -188,7 +188,7 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
|
||||
currentList->subIntrToken = data & 0xFFFF;
|
||||
// TODO: Should this run while interrupts are suspended?
|
||||
if (interruptsEnabled_)
|
||||
__GeTriggerInterrupt(currentList->id, currentList->pc);
|
||||
__GeTriggerInterrupt(currentList->id, currentList->pc, currentList->subIntrBase, currentList->subIntrToken);
|
||||
break;
|
||||
|
||||
case GE_CMD_END:
|
||||
|
||||
@@ -21,6 +21,9 @@ desktop_ui {
|
||||
}
|
||||
}
|
||||
|
||||
TRANSLATIONS = languages/ppsspp_en.ts \
|
||||
languages/ppsspp_pl.ts
|
||||
|
||||
# Main
|
||||
SOURCES += ../native/base/QtMain.cpp
|
||||
HEADERS += ../native/base/QtMain.h
|
||||
|
||||
+46
-32
@@ -16,26 +16,26 @@ struct GamePadInfo
|
||||
|
||||
// Initial values are PS3 controller
|
||||
GamePadInfo GamepadPadMapping[] = {
|
||||
{0, 14, 0, "Prev_X", "Cross"}, //A
|
||||
{0, 13, 0, "Prev_O", "Circle"}, //B
|
||||
{0, 15, 0, "Prev_S", "Square"}, //X
|
||||
{0, 12, 0, "Prev_T", "Triangle"}, //Y
|
||||
{0, 10, 0, "Prev_LT", "Left Trigger"}, //LBUMPER
|
||||
{0, 11, 0, "Prev_RT", "Right Trigger"}, //RBUMPER
|
||||
{0, 3, 0, "Prev_Start", "Start"}, //START
|
||||
{0, 0, 0, "Prev_Select", "Select"}, //SELECT
|
||||
{0, 4, 0, "Prev_Up", "Up"}, //UP
|
||||
{0, 6, 0, "Prev_Down", "Down"}, //DOWN
|
||||
{0, 7, 0, "Prev_Left", "Left"}, //LEFT
|
||||
{0, 5, 0, "Prev_Right", "Right"}, //RIGHT
|
||||
{0, 0, 0, ""}, //MENU (event)
|
||||
{0, 16, 0, "Prev_Home", "Home"}, //BACK
|
||||
{0, 14, 0, "Prev_X", QT_TRANSLATE_NOOP("gamepadMapping", "Cross")}, //A
|
||||
{0, 13, 0, "Prev_O", QT_TRANSLATE_NOOP("gamepadMapping", "Circle")}, //B
|
||||
{0, 15, 0, "Prev_S", QT_TRANSLATE_NOOP("gamepadMapping", "Square")}, //X
|
||||
{0, 12, 0, "Prev_T", QT_TRANSLATE_NOOP("gamepadMapping", "Triangle")}, //Y
|
||||
{0, 10, 0, "Prev_LT", QT_TRANSLATE_NOOP("gamepadMapping", "Left Trigger")}, //LBUMPER
|
||||
{0, 11, 0, "Prev_RT", QT_TRANSLATE_NOOP("gamepadMapping", "Right Trigger")}, //RBUMPER
|
||||
{0, 3, 0, "Prev_Start", QT_TRANSLATE_NOOP("gamepadMapping", "Start")}, //START
|
||||
{0, 0, 0, "Prev_Select", QT_TRANSLATE_NOOP("gamepadMapping", "Select")}, //SELECT
|
||||
{0, 4, 0, "Prev_Up", QT_TRANSLATE_NOOP("gamepadMapping", "Up")}, //UP
|
||||
{0, 6, 0, "Prev_Down", QT_TRANSLATE_NOOP("gamepadMapping", "Down")}, //DOWN
|
||||
{0, 7, 0, "Prev_Left", QT_TRANSLATE_NOOP("gamepadMapping", "Left")}, //LEFT
|
||||
{0, 5, 0, "Prev_Right", QT_TRANSLATE_NOOP("gamepadMapping", "Right")}, //RIGHT
|
||||
{0, 0, 0, ""}, //MENU (event)
|
||||
{0, 16, 0, "Prev_Home", QT_TRANSLATE_NOOP("gamepadMapping", "Home")}, //BACK
|
||||
|
||||
// Special case for analog stick
|
||||
{1, 0, -1, "Prev_ALeft", "Stick left"},
|
||||
{1, 0, 1, "Prev_ARight", "Stick right"},
|
||||
{1, 1, -1, "Prev_AUp", "Stick up"},
|
||||
{1, 1, 1, "Prev_ADown", "Stick bottom"}
|
||||
{1, 0, -1, "Prev_ALeft", QT_TRANSLATE_NOOP("gamepadMapping", "Stick left")},
|
||||
{1, 0, 1, "Prev_ARight", QT_TRANSLATE_NOOP("gamepadMapping", "Stick right")},
|
||||
{1, 1, -1, "Prev_AUp", QT_TRANSLATE_NOOP("gamepadMapping", "Stick up")},
|
||||
{1, 1, 1, "Prev_ADown", QT_TRANSLATE_NOOP("gamepadMapping", "Stick bottom")}
|
||||
};
|
||||
|
||||
// id for mapping in config start at offset 200 to not get over key mapping
|
||||
@@ -106,6 +106,20 @@ void GamePadDialog::showEvent(QShowEvent *)
|
||||
#endif
|
||||
}
|
||||
|
||||
void GamePadDialog::changeEvent(QEvent *event)
|
||||
{
|
||||
QDialog::changeEvent(event);
|
||||
|
||||
if (0 != event)
|
||||
{
|
||||
if (event->type() == QEvent::LanguageChange)
|
||||
{
|
||||
ui->retranslateUi(this);
|
||||
on_refreshListBtn_clicked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GamePadDialog::releaseLock()
|
||||
{
|
||||
EmuThread_LockDraw(false);
|
||||
@@ -117,7 +131,7 @@ void GamePadDialog::on_refreshListBtn_clicked()
|
||||
if(m_joystick)
|
||||
{
|
||||
SDL_JoystickClose(m_joystick);
|
||||
ui->JoyName->setText("<b>No GamePad</b>");
|
||||
ui->JoyName->setText(tr("<b>No gamepad</b>"));
|
||||
m_joystick = 0;
|
||||
}
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||
@@ -129,7 +143,7 @@ void GamePadDialog::on_refreshListBtn_clicked()
|
||||
{
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
QString padName = SDL_JoystickName(i);
|
||||
if(padName == "") padName = "<b>Unknown GamePad</b>";
|
||||
if(padName == "") padName = tr("<b>Unknown gamepad</b>");
|
||||
item->setText(padName);
|
||||
item->setData(Qt::UserRole,i);
|
||||
ui->GamePadList->addItem(item);
|
||||
@@ -270,7 +284,7 @@ void GamePadDialog::on_SelectPadBtn_clicked()
|
||||
ui->comboPSPButton->clear();
|
||||
|
||||
QTreeWidgetItem* buttonItem = new QTreeWidgetItem();
|
||||
buttonItem->setText(0,"Buttons");
|
||||
buttonItem->setText(0,tr("Buttons"));
|
||||
ui->padValues->addTopLevelItem(buttonItem);
|
||||
|
||||
for(int i = 0; i < SDL_JoystickNumButtons(m_joystick); i++)
|
||||
@@ -284,37 +298,37 @@ void GamePadDialog::on_SelectPadBtn_clicked()
|
||||
buttonItem->addChild(item);
|
||||
|
||||
int id = i << 8;
|
||||
ui->comboPadInput->addItem("Button "+QVariant(i).toString(),GetIntFromMapping(i,0,0));
|
||||
ui->comboPadInput->addItem(tr("Button %1").arg(i),GetIntFromMapping(i,0,0));
|
||||
}
|
||||
QTreeWidgetItem* axesItem = new QTreeWidgetItem();
|
||||
axesItem->setText(0,"Axes");
|
||||
axesItem->setText(0,tr("Axes"));
|
||||
ui->padValues->addTopLevelItem(axesItem);
|
||||
|
||||
for(int i = 0; i < SDL_JoystickNumAxes(m_joystick); i++)
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
item->setText(0,QVariant(i).toString()+" Neg");
|
||||
item->setText(0,tr("%1 Neg").arg(i));
|
||||
item->setText(1,QVariant(0).toString());
|
||||
item->setData(0, Qt::UserRole,1);
|
||||
item->setData(0, Qt::UserRole+1,i);
|
||||
item->setData(0, Qt::UserRole+2,-1);
|
||||
axesItem->addChild(item);
|
||||
|
||||
ui->comboPadInput->addItem("Axes "+QVariant(i).toString()+" Neg",GetIntFromMapping(i,1,-1));
|
||||
ui->comboPadInput->addItem(tr("Axes %1 Neg").arg(i),GetIntFromMapping(i,1,-1));
|
||||
|
||||
item = new QTreeWidgetItem();
|
||||
item->setText(0,QVariant(i).toString()+" Pos");
|
||||
item->setText(0,tr("%1 Pos").arg(i));
|
||||
item->setText(1,QVariant(0).toString());
|
||||
item->setData(0, Qt::UserRole,1);
|
||||
item->setData(0, Qt::UserRole+1,i);
|
||||
item->setData(0, Qt::UserRole+2,1);
|
||||
axesItem->addChild(item);
|
||||
|
||||
ui->comboPadInput->addItem("Axes "+QVariant(i).toString()+" Pos",GetIntFromMapping(i,1,1));
|
||||
ui->comboPadInput->addItem(tr("Axes %1 Pos").arg(i),GetIntFromMapping(i,1,1));
|
||||
}
|
||||
|
||||
QTreeWidgetItem* hatsItem = new QTreeWidgetItem();
|
||||
hatsItem->setText(0,"Hats");
|
||||
hatsItem->setText(0,tr("Hats"));
|
||||
ui->padValues->addTopLevelItem(hatsItem);
|
||||
|
||||
for(int i = 0; i < SDL_JoystickNumHats(m_joystick); i++)
|
||||
@@ -327,14 +341,14 @@ void GamePadDialog::on_SelectPadBtn_clicked()
|
||||
item->setData(0, Qt::UserRole+2,0);
|
||||
hatsItem->addChild(item);
|
||||
|
||||
ui->comboPadInput->addItem("Button "+QVariant(i).toString(),GetIntFromMapping(i,2,0));
|
||||
ui->comboPadInput->addItem(tr("Button %1").arg(i),GetIntFromMapping(i,2,0));
|
||||
}
|
||||
|
||||
for(int i = 0; i < 18; i++)
|
||||
{
|
||||
if(GamepadPadMapping[i].Name != "")
|
||||
{
|
||||
ui->comboPSPButton->addItem(GamepadPadMapping[i].Name,i);
|
||||
ui->comboPSPButton->addItem(QApplication::translate("gamepadMapping", GamepadPadMapping[i].Name.toStdString().c_str()),i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,9 +363,9 @@ void GamePadDialog::SetViewMode()
|
||||
ui->refreshListBtn->setEnabled(true);
|
||||
ui->SelectPadBtn->setEnabled(true);
|
||||
if(!m_joystick)
|
||||
ui->JoyName->setText("<b>No GamePad</b>");
|
||||
ui->JoyName->setText(tr("<b>No gamepad</b>"));
|
||||
else
|
||||
ui->JoyName->setText(QString("<b>Current gamepad : ")+SDL_JoystickName(m_joyId)+"</b>");
|
||||
ui->JoyName->setText(tr("<b>Current gamepad: %1</b>").arg(SDL_JoystickName(m_joyId)));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ public:
|
||||
void CalibNextButton();
|
||||
protected:
|
||||
void showEvent(QShowEvent *);
|
||||
void changeEvent(QEvent *);
|
||||
private slots:
|
||||
void releaseLock();
|
||||
void on_refreshListBtn_clicked();
|
||||
|
||||
@@ -0,0 +1,634 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.0" language="en_US">
|
||||
<context>
|
||||
<name>Controls</name>
|
||||
<message>
|
||||
<location filename="../controls.ui" line="20"/>
|
||||
<source>Controls</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Debugger_Disasm</name>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="17"/>
|
||||
<source>Dialog</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="25"/>
|
||||
<source>Ctr:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="38"/>
|
||||
<source>&Go to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="73"/>
|
||||
<source>&PC</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="86"/>
|
||||
<source>&LR</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="118"/>
|
||||
<source>Tab 1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="128"/>
|
||||
<source>Tab 2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="153"/>
|
||||
<source>&Go</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="166"/>
|
||||
<source>Stop</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="179"/>
|
||||
<source>Step &Into</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="192"/>
|
||||
<source>Step &Over</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="205"/>
|
||||
<source>S&kip</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="218"/>
|
||||
<source>Next &HLE</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GamePadDialog</name>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="14"/>
|
||||
<source>Gamepad Configuration</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="22"/>
|
||||
<source>GamePad List</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="46"/>
|
||||
<source>Refresh</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="53"/>
|
||||
<source>Select</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="62"/>
|
||||
<source>Gamepad Values :</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="86"/>
|
||||
<source>TextLabel</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="98"/>
|
||||
<source>Assign Gamepad input</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="108"/>
|
||||
<source> to PSP button/axis</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="118"/>
|
||||
<source>Assign</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="127"/>
|
||||
<source>Press buttons on your gamePad to verify mapping :</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="134"/>
|
||||
<location filename="../gamepaddialog.cpp" line="366"/>
|
||||
<source><b>No gamepad</b></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="146"/>
|
||||
<source><b>Unknown gamepad</b></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="287"/>
|
||||
<source>Buttons</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="301"/>
|
||||
<location filename="../gamepaddialog.cpp" line="344"/>
|
||||
<source>Button %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="304"/>
|
||||
<source>Axes</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="310"/>
|
||||
<source>%1 Neg</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="317"/>
|
||||
<source>Axes %1 Neg</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="320"/>
|
||||
<source>%1 Pos</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="327"/>
|
||||
<source>Axes %1 Pos</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="331"/>
|
||||
<source>Hats</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="368"/>
|
||||
<source><b>Current gamepad: %1</b></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="20"/>
|
||||
<source>PPSSPP</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="52"/>
|
||||
<source>&File</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="66"/>
|
||||
<source>&Emulation</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="79"/>
|
||||
<source>Debu&g</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="91"/>
|
||||
<source>&Options</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="95"/>
|
||||
<source>&Log Levels</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="99"/>
|
||||
<source>G3D</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="108"/>
|
||||
<source>HLE</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="117"/>
|
||||
<source>Default</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="131"/>
|
||||
<source>Zoom</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="140"/>
|
||||
<source>Language</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="167"/>
|
||||
<source>&Help</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="182"/>
|
||||
<source>&Open...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="187"/>
|
||||
<source>&Close</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="192"/>
|
||||
<source>-</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="197"/>
|
||||
<source>Quickload state</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="200"/>
|
||||
<source>F4</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="205"/>
|
||||
<source>Quicksave state</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="208"/>
|
||||
<source>F2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="213"/>
|
||||
<source>&Load State File...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="218"/>
|
||||
<source>&Save State File...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="223"/>
|
||||
<source>E&xit</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="228"/>
|
||||
<source>&Run</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="231"/>
|
||||
<source>F7</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="236"/>
|
||||
<source>&Pause</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="239"/>
|
||||
<source>F8</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="244"/>
|
||||
<source>R&eset</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="252"/>
|
||||
<source>&Interpreter</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="260"/>
|
||||
<source>&Slightly Faster Interpreter</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="268"/>
|
||||
<source>&Dynarec</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="276"/>
|
||||
<source>Load &Map File...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="284"/>
|
||||
<source>&Save Map File...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="292"/>
|
||||
<source>&Reset Symbol Table</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="300"/>
|
||||
<source>&Disassembly</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="303"/>
|
||||
<source>Ctrl+D</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="311"/>
|
||||
<source>&Log Console</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="314"/>
|
||||
<source>Ctrl+L</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="322"/>
|
||||
<source>Memory &View...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="325"/>
|
||||
<source>Ctrl+M</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="330"/>
|
||||
<source>Keyboard &Controls</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="335"/>
|
||||
<source>&Toggle Full Screen</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="338"/>
|
||||
<source>F12</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="346"/>
|
||||
<source>&Buffered Rendering</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="349"/>
|
||||
<source>F5</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="357"/>
|
||||
<source>&Hardware Transform</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="360"/>
|
||||
<source>F6</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="368"/>
|
||||
<source>&Linear Filtering</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="376"/>
|
||||
<source>&Wireframe (experimental)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="384"/>
|
||||
<source>&Display Raw Framebuffer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="392"/>
|
||||
<source>&Show Debug Statistics</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="400"/>
|
||||
<source>Screen &1x</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="403"/>
|
||||
<source>Ctrl+1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="411"/>
|
||||
<source>Screen &2x</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="414"/>
|
||||
<source>Ctrl+2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="422"/>
|
||||
<source>Screen &3x</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="425"/>
|
||||
<source>Ctrl+3</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="433"/>
|
||||
<source>Screen &4x</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="436"/>
|
||||
<source>Ctrl+4</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="444"/>
|
||||
<source>&Fast Memory (dynarec, unstable)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="452"/>
|
||||
<source>&Ignore illegal reads/writes</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="457"/>
|
||||
<source>&Go to http://www.ppsspp.org/</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="462"/>
|
||||
<source>&About PPSSPP...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="467"/>
|
||||
<source>&Use VBO</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="475"/>
|
||||
<location filename="../mainwindow.ui" line="507"/>
|
||||
<location filename="../mainwindow.ui" line="539"/>
|
||||
<source>Debug</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="483"/>
|
||||
<location filename="../mainwindow.ui" line="515"/>
|
||||
<location filename="../mainwindow.ui" line="547"/>
|
||||
<source>Warning</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="491"/>
|
||||
<location filename="../mainwindow.ui" line="531"/>
|
||||
<location filename="../mainwindow.ui" line="563"/>
|
||||
<source>Error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="499"/>
|
||||
<location filename="../mainwindow.ui" line="523"/>
|
||||
<location filename="../mainwindow.ui" line="555"/>
|
||||
<source>Info</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="568"/>
|
||||
<source>GamePad Controls</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="828"/>
|
||||
<source>No translations</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>gamepadMapping</name>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="19"/>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="20"/>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="21"/>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="22"/>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="23"/>
|
||||
<source>Left Trigger</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="24"/>
|
||||
<source>Right Trigger</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="25"/>
|
||||
<source>Start</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="26"/>
|
||||
<source>Select</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="27"/>
|
||||
<source>Up</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="28"/>
|
||||
<source>Down</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="29"/>
|
||||
<source>Left</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="30"/>
|
||||
<source>Right</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="32"/>
|
||||
<source>Home</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="35"/>
|
||||
<source>Stick left</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="36"/>
|
||||
<source>Stick right</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="37"/>
|
||||
<source>Stick up</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="38"/>
|
||||
<source>Stick bottom</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
@@ -0,0 +1,634 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.0" language="pl_PL">
|
||||
<context>
|
||||
<name>Controls</name>
|
||||
<message>
|
||||
<location filename="../controls.ui" line="20"/>
|
||||
<source>Controls</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Debugger_Disasm</name>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="17"/>
|
||||
<source>Dialog</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="25"/>
|
||||
<source>Ctr:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="38"/>
|
||||
<source>&Go to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="73"/>
|
||||
<source>&PC</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="86"/>
|
||||
<source>&LR</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="118"/>
|
||||
<source>Tab 1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="128"/>
|
||||
<source>Tab 2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="153"/>
|
||||
<source>&Go</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="166"/>
|
||||
<source>Stop</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="179"/>
|
||||
<source>Step &Into</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="192"/>
|
||||
<source>Step &Over</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="205"/>
|
||||
<source>S&kip</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="218"/>
|
||||
<source>Next &HLE</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GamePadDialog</name>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="14"/>
|
||||
<source>Gamepad Configuration</source>
|
||||
<translation>Konfiguracja kontrolera</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="22"/>
|
||||
<source>GamePad List</source>
|
||||
<translation>Lista kontrolerów</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="46"/>
|
||||
<source>Refresh</source>
|
||||
<translation>Odśwież</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="53"/>
|
||||
<source>Select</source>
|
||||
<translation>Wybierz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="62"/>
|
||||
<source>Gamepad Values :</source>
|
||||
<translation>Wartości przycisków/osi:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="86"/>
|
||||
<source>TextLabel</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="98"/>
|
||||
<source>Assign Gamepad input</source>
|
||||
<translation>Przypisz przycisk</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="108"/>
|
||||
<source> to PSP button/axis</source>
|
||||
<translation>do przycisku/osi PSP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="118"/>
|
||||
<source>Assign</source>
|
||||
<translation>Przypisz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="127"/>
|
||||
<source>Press buttons on your gamePad to verify mapping :</source>
|
||||
<translation>Naciśnij przyciski na kontrolerze:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="134"/>
|
||||
<location filename="../gamepaddialog.cpp" line="366"/>
|
||||
<source><b>No gamepad</b></source>
|
||||
<translation><b>Nie wykryto pada</b></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="146"/>
|
||||
<source><b>Unknown gamepad</b></source>
|
||||
<translation><b>Nieznany pad</b></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="287"/>
|
||||
<source>Buttons</source>
|
||||
<translation>Przyciski</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="301"/>
|
||||
<location filename="../gamepaddialog.cpp" line="344"/>
|
||||
<source>Button %1</source>
|
||||
<translation>Przycisk %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="304"/>
|
||||
<source>Axes</source>
|
||||
<translation>Osie</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="310"/>
|
||||
<source>%1 Neg</source>
|
||||
<translation>%1 zanegowany</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="317"/>
|
||||
<source>Axes %1 Neg</source>
|
||||
<translation>Oś %1 zanegowana</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="320"/>
|
||||
<source>%1 Pos</source>
|
||||
<translation>%1 pozycja</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="327"/>
|
||||
<source>Axes %1 Pos</source>
|
||||
<translation>Pozycja osi %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="331"/>
|
||||
<source>Hats</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="368"/>
|
||||
<source><b>Current gamepad: %1</b></source>
|
||||
<translation><b>Wybrany pad: %1</b></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="20"/>
|
||||
<source>PPSSPP</source>
|
||||
<translation>PPSSPP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="52"/>
|
||||
<source>&File</source>
|
||||
<translation>&Plik</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="66"/>
|
||||
<source>&Emulation</source>
|
||||
<translation>&Emulacja</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="79"/>
|
||||
<source>Debu&g</source>
|
||||
<translation>&Debugger</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="91"/>
|
||||
<source>&Options</source>
|
||||
<translation>&Opcje</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="95"/>
|
||||
<source>&Log Levels</source>
|
||||
<translation>P&oziomy logowania</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="99"/>
|
||||
<source>G3D</source>
|
||||
<translation>G3D</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="108"/>
|
||||
<source>HLE</source>
|
||||
<translation>HLE</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="117"/>
|
||||
<source>Default</source>
|
||||
<translation>Domyślne</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="131"/>
|
||||
<source>Zoom</source>
|
||||
<translation>Zoom</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="140"/>
|
||||
<source>Language</source>
|
||||
<translation>Język</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="167"/>
|
||||
<source>&Help</source>
|
||||
<translation>Pomo&c</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="182"/>
|
||||
<source>&Open...</source>
|
||||
<translation>&Otwórz...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="187"/>
|
||||
<source>&Close</source>
|
||||
<translation>&Zamknij</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="192"/>
|
||||
<source>-</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="197"/>
|
||||
<source>Quickload state</source>
|
||||
<translation>Wczytaj stan</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="200"/>
|
||||
<source>F4</source>
|
||||
<translation>F4</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="205"/>
|
||||
<source>Quicksave state</source>
|
||||
<translation>Zapisz stan</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="208"/>
|
||||
<source>F2</source>
|
||||
<translation>F2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="213"/>
|
||||
<source>&Load State File...</source>
|
||||
<translation>&Wczytaj plik stanu...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="218"/>
|
||||
<source>&Save State File...</source>
|
||||
<translation>&Zapisz plik stanu...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="223"/>
|
||||
<source>E&xit</source>
|
||||
<translation>Wyj&dź</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="228"/>
|
||||
<source>&Run</source>
|
||||
<translation>&Uruchom</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="231"/>
|
||||
<source>F7</source>
|
||||
<translation>F7</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="236"/>
|
||||
<source>&Pause</source>
|
||||
<translation>&Pauza</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="239"/>
|
||||
<source>F8</source>
|
||||
<translation>F8</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="244"/>
|
||||
<source>R&eset</source>
|
||||
<translation>&Reset</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="252"/>
|
||||
<source>&Interpreter</source>
|
||||
<translation>&Interpreter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="260"/>
|
||||
<source>&Slightly Faster Interpreter</source>
|
||||
<translation>&Szybszy interpreter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="268"/>
|
||||
<source>&Dynarec</source>
|
||||
<translation>R&ekompilacja (Dynarec)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="276"/>
|
||||
<source>Load &Map File...</source>
|
||||
<translation>&Wczytaj plik mapy...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="284"/>
|
||||
<source>&Save Map File...</source>
|
||||
<translation>&Zapisz plik mapy...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="292"/>
|
||||
<source>&Reset Symbol Table</source>
|
||||
<translation>Zresetuj &tablicę symboli</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="300"/>
|
||||
<source>&Disassembly</source>
|
||||
<translation>&Dekompiluj</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="303"/>
|
||||
<source>Ctrl+D</source>
|
||||
<translation>Ctrl+D</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="311"/>
|
||||
<source>&Log Console</source>
|
||||
<translation>&Konsola logowania</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="314"/>
|
||||
<source>Ctrl+L</source>
|
||||
<translation>Ctrl+L</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="322"/>
|
||||
<source>Memory &View...</source>
|
||||
<translation>Widok &pamięci...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="325"/>
|
||||
<source>Ctrl+M</source>
|
||||
<translation>Ctrl+M</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="330"/>
|
||||
<source>Keyboard &Controls</source>
|
||||
<translation>Ustawienia &klawiatury</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="335"/>
|
||||
<source>&Toggle Full Screen</source>
|
||||
<translation>&Pełny ekran</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="338"/>
|
||||
<source>F12</source>
|
||||
<translation>F12</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="346"/>
|
||||
<source>&Buffered Rendering</source>
|
||||
<translation>&Buffered rendering</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="349"/>
|
||||
<source>F5</source>
|
||||
<translation>F5</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="357"/>
|
||||
<source>&Hardware Transform</source>
|
||||
<translation>&Hardware Transform</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="360"/>
|
||||
<source>F6</source>
|
||||
<translation>F6</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="368"/>
|
||||
<source>&Linear Filtering</source>
|
||||
<translation>&Linear Filtering</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="376"/>
|
||||
<source>&Wireframe (experimental)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="384"/>
|
||||
<source>&Display Raw Framebuffer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="392"/>
|
||||
<source>&Show Debug Statistics</source>
|
||||
<translation>Pokaż &statystyki emulacji</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="400"/>
|
||||
<source>Screen &1x</source>
|
||||
<translation>&1x</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="403"/>
|
||||
<source>Ctrl+1</source>
|
||||
<translation>Ctrl+1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="411"/>
|
||||
<source>Screen &2x</source>
|
||||
<translation>&2x</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="414"/>
|
||||
<source>Ctrl+2</source>
|
||||
<translation>Ctrl+2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="422"/>
|
||||
<source>Screen &3x</source>
|
||||
<translation>&3x</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="425"/>
|
||||
<source>Ctrl+3</source>
|
||||
<translation>Ctrl+3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="433"/>
|
||||
<source>Screen &4x</source>
|
||||
<translation>&4x</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="436"/>
|
||||
<source>Ctrl+4</source>
|
||||
<translation>Ctrl+4</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="444"/>
|
||||
<source>&Fast Memory (dynarec, unstable)</source>
|
||||
<translation>&Fast memory (wymagany Dynarec, niestabilne)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="452"/>
|
||||
<source>&Ignore illegal reads/writes</source>
|
||||
<translation>&Ignoruj nieprawidłowe odczyty/zapisy</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="457"/>
|
||||
<source>&Go to http://www.ppsspp.org/</source>
|
||||
<translation>&Idź do http://www.ppsspp.org</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="462"/>
|
||||
<source>&About PPSSPP...</source>
|
||||
<translation>&O PPSSPP...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="467"/>
|
||||
<source>&Use VBO</source>
|
||||
<translation>Użyj &VBO</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="475"/>
|
||||
<location filename="../mainwindow.ui" line="507"/>
|
||||
<location filename="../mainwindow.ui" line="539"/>
|
||||
<source>Debug</source>
|
||||
<translation>Debug</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="483"/>
|
||||
<location filename="../mainwindow.ui" line="515"/>
|
||||
<location filename="../mainwindow.ui" line="547"/>
|
||||
<source>Warning</source>
|
||||
<translation>Ostrzeżenia</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="491"/>
|
||||
<location filename="../mainwindow.ui" line="531"/>
|
||||
<location filename="../mainwindow.ui" line="563"/>
|
||||
<source>Error</source>
|
||||
<translation>Błędy</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="499"/>
|
||||
<location filename="../mainwindow.ui" line="523"/>
|
||||
<location filename="../mainwindow.ui" line="555"/>
|
||||
<source>Info</source>
|
||||
<translation>Info</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="568"/>
|
||||
<source>GamePad Controls</source>
|
||||
<translation>&Ustawienia pada</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="828"/>
|
||||
<source>No translations</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>gamepadMapping</name>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="19"/>
|
||||
<source>Cross</source>
|
||||
<translation>Krzyżyk</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="20"/>
|
||||
<source>Circle</source>
|
||||
<translation>Kółko</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="21"/>
|
||||
<source>Square</source>
|
||||
<translation>Kwadrat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="22"/>
|
||||
<source>Triangle</source>
|
||||
<translation>Trójkąt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="23"/>
|
||||
<source>Left Trigger</source>
|
||||
<translation>Lewy trigger</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="24"/>
|
||||
<source>Right Trigger</source>
|
||||
<translation>Prawy trigger</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="25"/>
|
||||
<source>Start</source>
|
||||
<translation>Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="26"/>
|
||||
<source>Select</source>
|
||||
<translation>Select</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="27"/>
|
||||
<source>Up</source>
|
||||
<translation>Góra</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="28"/>
|
||||
<source>Down</source>
|
||||
<translation>Dół</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="29"/>
|
||||
<source>Left</source>
|
||||
<translation>Lewo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="30"/>
|
||||
<source>Right</source>
|
||||
<translation>Prawo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="32"/>
|
||||
<source>Home</source>
|
||||
<translation>Klawisz Home</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="35"/>
|
||||
<source>Stick left</source>
|
||||
<translation>Lewo (analog)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="36"/>
|
||||
<source>Stick right</source>
|
||||
<translation>Prawo (analog)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="37"/>
|
||||
<source>Stick up</source>
|
||||
<translation>Góra (analog)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="38"/>
|
||||
<source>Stick bottom</source>
|
||||
<translation>Dół (analog)</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
@@ -48,6 +48,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
DialogManager::AddDlg(vfpudlg = new CVFPUDlg(_hInstance, hwndMain, currentDebugMIPS));
|
||||
*/
|
||||
// Update();
|
||||
createLanguageMenu();
|
||||
UpdateMenus();
|
||||
|
||||
int zoom = g_Config.iWindowZoom;
|
||||
@@ -779,3 +780,102 @@ void MainWindow::on_action_OptionsGamePadControls_triggered()
|
||||
QMessageBox::information(this,"Gamepad","You need to compile with SDL to have Gamepad support.", QMessageBox::Ok);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::on_language_changed(QAction *action)
|
||||
{
|
||||
if (0 != action)
|
||||
{
|
||||
loadLanguage(action->data().toString());
|
||||
}
|
||||
}
|
||||
|
||||
void switchTranslator(QTranslator &translator, const QString &filename)
|
||||
{
|
||||
qApp->removeTranslator(&translator);
|
||||
|
||||
if (translator.load(filename))
|
||||
qApp->installTranslator(&translator);
|
||||
}
|
||||
|
||||
void MainWindow::loadLanguage(const QString& language)
|
||||
{
|
||||
if (currentLanguage != language)
|
||||
{
|
||||
currentLanguage = language;
|
||||
QLocale locale = QLocale(currentLanguage);
|
||||
QLocale::setDefault(locale);
|
||||
QString languageName = QLocale::languageToString(locale.language());
|
||||
switchTranslator(translator, QString("languages/ppsspp_%1.qm").arg(language));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::createLanguageMenu()
|
||||
{
|
||||
QActionGroup *langGroup = new QActionGroup(ui->menuLanguage);
|
||||
langGroup->setExclusive(true);
|
||||
|
||||
connect(langGroup, SIGNAL(triggered(QAction *)), this, SLOT(on_language_changed(QAction *)));
|
||||
|
||||
QString defaultLocale = QLocale::system().name();
|
||||
defaultLocale.truncate(defaultLocale.lastIndexOf('_'));
|
||||
languagePath = QApplication::applicationDirPath();
|
||||
languagePath.append("/languages");
|
||||
QDir langDir(languagePath);
|
||||
QStringList fileNames = langDir.entryList(QStringList("ppsspp_*.qm"));
|
||||
|
||||
if (fileNames.size() == 0)
|
||||
{
|
||||
QAction *action = new QAction(tr("No translations"), this);
|
||||
action->setCheckable(false);
|
||||
action->setDisabled(true);
|
||||
ui->menuLanguage->addAction(action);
|
||||
langGroup->addAction(action);
|
||||
}
|
||||
|
||||
for (int i = 0; i < fileNames.size(); ++i)
|
||||
{
|
||||
QString locale = fileNames[i];
|
||||
locale.truncate(locale.lastIndexOf('.'));
|
||||
locale.remove(0, locale.indexOf('_') + 1);
|
||||
|
||||
//QString language = QLocale::languageToString(QLocale(locale).language());
|
||||
QString language = QLocale(locale).nativeLanguageName();
|
||||
QAction *action = new QAction(language, this);
|
||||
action->setCheckable(true);
|
||||
action->setData(locale);
|
||||
|
||||
ui->menuLanguage->addAction(action);
|
||||
langGroup->addAction(action);
|
||||
|
||||
// TODO check en as default until we save language to config
|
||||
if ("en" == locale)
|
||||
{
|
||||
action->setChecked(true);
|
||||
currentLanguage = "en";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::changeEvent(QEvent *event)
|
||||
{
|
||||
QMainWindow::changeEvent(event);
|
||||
|
||||
if (0 != event)
|
||||
{
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::LanguageChange:
|
||||
ui->retranslateUi(this);
|
||||
break;
|
||||
case QEvent::LocaleChange:
|
||||
{
|
||||
QString locale = QLocale::system().name();
|
||||
locale.truncate(locale.lastIndexOf('_'));
|
||||
loadLanguage(locale);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QTranslator>
|
||||
|
||||
#include "Core/Core.h"
|
||||
#include "input/input_state.h"
|
||||
@@ -135,7 +136,18 @@ private slots:
|
||||
|
||||
void on_action_OptionsGamePadControls_triggered();
|
||||
|
||||
void on_language_changed(QAction *action);
|
||||
|
||||
private:
|
||||
void loadLanguage(const QString &language);
|
||||
void createLanguageMenu();
|
||||
void changeEvent(QEvent *);
|
||||
|
||||
QTranslator translator;
|
||||
QTranslator qtTranslator;
|
||||
QString currentLanguage;
|
||||
QString languagePath;
|
||||
|
||||
Ui::MainWindow *ui;
|
||||
|
||||
QtEmuGL* w;
|
||||
|
||||
+7
-1
@@ -44,7 +44,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>23</height>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
@@ -135,6 +135,11 @@
|
||||
<addaction name="action_OptionsScreen3x"/>
|
||||
<addaction name="action_OptionsScreen4x"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuLanguage">
|
||||
<property name="title">
|
||||
<string>Language</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="action_OptionsControls"/>
|
||||
<addaction name="action_OptionsGamePadControls"/>
|
||||
<addaction name="separator"/>
|
||||
@@ -155,6 +160,7 @@
|
||||
<addaction name="action_OptionsFastMemory"/>
|
||||
<addaction name="action_OptionsIgnoreIllegalReadsWrites"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menuLanguage"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Help">
|
||||
<property name="title">
|
||||
|
||||
@@ -191,6 +191,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
}
|
||||
}
|
||||
|
||||
VFSShutdown();
|
||||
|
||||
LogManager::Shutdown();
|
||||
DialogManager::DestroyAll();
|
||||
timeEndPeriod(1);
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2012- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "Compare.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
bool CompareOutput(const std::string bootFilename)
|
||||
{
|
||||
std::string expect_filename = bootFilename.substr(bootFilename.length() - 4) + ".expected";
|
||||
if (File::Exists(expect_filename))
|
||||
{
|
||||
// TODO: Do the compare here
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Expectation file %s not found", expect_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline int ComparePixel(u32 pix1, u32 pix2)
|
||||
{
|
||||
// For now, if they're different at all except alpha, it's an error.
|
||||
if ((pix1 & 0xFFFFFF) != (pix2 & 0xFFFFFF))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
double CompareScreenshot(const u8 *pixels, int w, int h, int stride, const std::string screenshotFilename, std::string &error)
|
||||
{
|
||||
u32 *pixels32 = (u32 *) pixels;
|
||||
// We assume the bitmap is the specified size, not including whatever stride.
|
||||
u32 *reference = (u32 *) calloc(w * h, sizeof(u32));
|
||||
|
||||
FILE *bmp = fopen(screenshotFilename.c_str(), "rb");
|
||||
if (bmp)
|
||||
{
|
||||
// The bitmap header is 14 + 40 bytes. We could validate it but the test would fail either way.
|
||||
fseek(bmp, 14 + 40, SEEK_SET);
|
||||
fread(reference, sizeof(u32), w * h, bmp);
|
||||
fclose(bmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = "Unable to read screenshot: " + screenshotFilename;
|
||||
free(reference);
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
u32 errors = 0;
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
errors += ComparePixel(pixels32[y * stride + x], reference[y * w + x]);
|
||||
}
|
||||
|
||||
free(reference);
|
||||
|
||||
return (double) errors / (double) (w * h);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2012- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
bool CompareOutput(std::string bootFilename);
|
||||
double CompareScreenshot(const u8 *pixels, int w, int h, int stride, const std::string screenshotFilename, std::string &error);
|
||||
+16
-13
@@ -13,6 +13,7 @@
|
||||
#include "Log.h"
|
||||
#include "LogManager.h"
|
||||
|
||||
#include "Compare.h"
|
||||
#include "StubHost.h"
|
||||
#ifdef _WIN32
|
||||
#include "WindowsHeadlessHost.h"
|
||||
@@ -59,10 +60,14 @@ void printUsage(const char *progname, const char *reason)
|
||||
HEADLESSHOST_CLASS h1;
|
||||
HeadlessHost h2;
|
||||
if (typeid(h1) != typeid(h2))
|
||||
{
|
||||
fprintf(stderr, " --graphics use the full gpu backend (slower)\n");
|
||||
fprintf(stderr, " --screenshot=FILE compare against a screenshot\n");
|
||||
}
|
||||
|
||||
fprintf(stderr, " -i use the interpreter\n");
|
||||
fprintf(stderr, " -f use the fast interpreter\n");
|
||||
fprintf(stderr, " -j use jit (overrides -f)\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");
|
||||
}
|
||||
@@ -77,6 +82,7 @@ int main(int argc, const char* argv[])
|
||||
|
||||
const char *bootFilename = 0;
|
||||
const char *mountIso = 0;
|
||||
const char *screenshotFilename = 0;
|
||||
bool readMount = false;
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
@@ -91,6 +97,8 @@ int main(int argc, const char* argv[])
|
||||
readMount = true;
|
||||
else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--log"))
|
||||
fullLog = true;
|
||||
else if (!strcmp(argv[i], "-i"))
|
||||
useJit = false;
|
||||
else if (!strcmp(argv[i], "-j"))
|
||||
useJit = true;
|
||||
else if (!strcmp(argv[i], "-f"))
|
||||
@@ -99,6 +107,8 @@ int main(int argc, const char* argv[])
|
||||
autoCompare = true;
|
||||
else if (!strcmp(argv[i], "--graphics"))
|
||||
useGraphics = true;
|
||||
else if (!strncmp(argv[i], "--screenshot=", strlen("--screenshot=")) && strlen(argv[i]) > strlen("--screenshot="))
|
||||
screenshotFilename = argv[i] + strlen("--screenshot=");
|
||||
else if (bootFilename == 0)
|
||||
bootFilename = argv[i];
|
||||
else
|
||||
@@ -146,7 +156,7 @@ int main(int argc, const char* argv[])
|
||||
coreParameter.fileToStart = bootFilename;
|
||||
coreParameter.mountIso = mountIso ? mountIso : "";
|
||||
coreParameter.startPaused = false;
|
||||
coreParameter.cpuCore = useJit ? CPU_JIT : (fastInterpreter ? CPU_FASTINTERPRETER : CPU_INTERPRETER);
|
||||
coreParameter.cpuCore = fastInterpreter ? CPU_FASTINTERPRETER : (useJit ? CPU_JIT : CPU_INTERPRETER);
|
||||
coreParameter.gpuCore = headlessHost->isGLWorking() ? GPU_GLES : GPU_NULL;
|
||||
coreParameter.enableSound = false;
|
||||
coreParameter.headLess = true;
|
||||
@@ -174,6 +184,9 @@ int main(int argc, const char* argv[])
|
||||
|
||||
host->BootDone();
|
||||
|
||||
if (screenshotFilename != 0)
|
||||
headlessHost->SetComparisonScreenshot(screenshotFilename);
|
||||
|
||||
coreState = CORE_RUNNING;
|
||||
while (coreState == CORE_RUNNING)
|
||||
{
|
||||
@@ -195,17 +208,7 @@ int main(int argc, const char* argv[])
|
||||
headlessHost = NULL;
|
||||
|
||||
if (autoCompare)
|
||||
{
|
||||
std::string expect_filename = std::string(bootFilename).substr(strlen(bootFilename - 4)) + ".expected";
|
||||
if (File::Exists(expect_filename))
|
||||
{
|
||||
// TODO: Do the compare here
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Expectation file %s not found", expect_filename.c_str());
|
||||
}
|
||||
}
|
||||
CompareOutput(bootFilename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -145,6 +145,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\native\ext\glew\glew.c" />
|
||||
<ClCompile Include="Compare.cpp" />
|
||||
<ClCompile Include="Headless.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
@@ -177,6 +178,7 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Compare.h" />
|
||||
<ClInclude Include="StubHost.h" />
|
||||
<ClInclude Include="WindowsHeadlessHost.h" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<ClCompile Include="Headless.cpp" />
|
||||
<ClCompile Include="..\native\ext\glew\glew.c" />
|
||||
<ClCompile Include="WindowsHeadlessHost.cpp" />
|
||||
<ClCompile Include="Compare.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="headless.txt" />
|
||||
@@ -11,5 +12,6 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="StubHost.h" />
|
||||
<ClInclude Include="WindowsHeadlessHost.h" />
|
||||
<ClInclude Include="Compare.h" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
virtual bool AttemptLoadSymbolMap() {return false;}
|
||||
|
||||
virtual void SendDebugOutput(const std::string &output) { printf("%s", output.c_str()); }
|
||||
virtual void SetComparisonScreenshot(const std::string &filename) {}
|
||||
|
||||
virtual bool isGLWorking() { return false; }
|
||||
};
|
||||
@@ -16,6 +16,7 @@
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "WindowsHeadlessHost.h"
|
||||
#include "Compare.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
@@ -89,6 +90,54 @@ void WindowsHeadlessHost::SendDebugOutput(const std::string &output)
|
||||
OutputDebugString(output.c_str());
|
||||
}
|
||||
|
||||
void WindowsHeadlessHost::SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h)
|
||||
{
|
||||
// We ignore the current framebuffer parameters and just grab the full screen.
|
||||
const static int FRAME_WIDTH = 512;
|
||||
const static int FRAME_HEIGHT = 272;
|
||||
u8 *pixels = new u8[FRAME_WIDTH * FRAME_HEIGHT * 4];
|
||||
|
||||
// TODO: Maybe this code should be moved into GLES_GPU.
|
||||
glReadBuffer(GL_FRONT);
|
||||
glReadPixels(0, 0, FRAME_WIDTH, FRAME_HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
std::string error;
|
||||
double errors = CompareScreenshot(pixels, FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH, comparisonScreenshot, error);
|
||||
if (errors < 0)
|
||||
fprintf_s(out, "%s\n", error.c_str());
|
||||
|
||||
if (errors > 0)
|
||||
{
|
||||
fprintf_s(out, "Screenshot error: %f%%\n", errors * 100.0f);
|
||||
|
||||
// Lazy, just read in the original header to output the failed screenshot.
|
||||
u8 header[14 + 40] = {0};
|
||||
FILE *bmp = fopen(comparisonScreenshot.c_str(), "rb");
|
||||
if (bmp)
|
||||
{
|
||||
fread(&header, sizeof(header), 1, bmp);
|
||||
fclose(bmp);
|
||||
}
|
||||
|
||||
FILE *saved = fopen("__testfailure.bmp", "wb");
|
||||
if (saved)
|
||||
{
|
||||
fwrite(&header, sizeof(header), 1, saved);
|
||||
fwrite(pixels, sizeof(u32), FRAME_WIDTH * FRAME_HEIGHT, saved);
|
||||
fclose(saved);
|
||||
|
||||
fprintf_s(out, "Actual output written to: __testfailure.bmp\n");
|
||||
}
|
||||
}
|
||||
|
||||
delete [] pixels;
|
||||
}
|
||||
|
||||
void WindowsHeadlessHost::SetComparisonScreenshot(const std::string &filename)
|
||||
{
|
||||
comparisonScreenshot = filename;
|
||||
}
|
||||
|
||||
void WindowsHeadlessHost::InitGL()
|
||||
{
|
||||
glOkay = false;
|
||||
|
||||
@@ -35,6 +35,8 @@ public:
|
||||
virtual bool isGLWorking() { return glOkay; }
|
||||
|
||||
virtual void SendDebugOutput(const std::string &output);
|
||||
virtual void SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h);
|
||||
virtual void SetComparisonScreenshot(const std::string &filename);
|
||||
|
||||
private:
|
||||
bool ResizeGL();
|
||||
@@ -45,4 +47,5 @@ private:
|
||||
HDC hDC;
|
||||
HGLRC hRC;
|
||||
FILE *out;
|
||||
std::string comparisonScreenshot;
|
||||
};
|
||||
+1
-1
Submodule native updated: f22ad17d40...3caced8524
+1
-1
Submodule pspautotests updated: 4f047eb8c7...c4427bd55d
@@ -109,6 +109,12 @@ tests_good = [
|
||||
"threads/semaphores/refer/refer",
|
||||
"threads/semaphores/signal/signal",
|
||||
"threads/semaphores/wait/wait",
|
||||
"threads/vpl/vpl",
|
||||
"threads/vpl/delete",
|
||||
"threads/vpl/free",
|
||||
"threads/vpl/priority",
|
||||
"threads/vpl/refer",
|
||||
"threads/vpl/try",
|
||||
"power/power",
|
||||
"umd/callbacks/umd",
|
||||
"umd/wait/wait",
|
||||
@@ -124,11 +130,13 @@ tests_next = [
|
||||
"threads/msgpipe/msgpipe",
|
||||
"threads/scheduling/scheduling",
|
||||
"threads/threads/threads",
|
||||
"threads/vpl/vpl",
|
||||
"threads/vtimers/vtimer",
|
||||
"threads/vpl/allocate",
|
||||
"threads/vpl/create",
|
||||
"threads/wakeup/wakeup",
|
||||
"gpu/simple/simple",
|
||||
"gpu/triangle/triangle",
|
||||
"gpu/commands/basic",
|
||||
"hle/check_not_used_uids",
|
||||
"font/fonttest",
|
||||
"io/cwd/cwd",
|
||||
@@ -222,6 +230,8 @@ def run_tests(test_list, args):
|
||||
|
||||
cmdline = [PPSSPP_EXE, elf_filename]
|
||||
cmdline.extend([i for i in args if i not in ['-v', '-g']])
|
||||
if os.path.exists(expected_filename + ".bmp"):
|
||||
cmdline.extend(["--screenshot=" + expected_filename + ".bmp", "--graphics"])
|
||||
|
||||
c = Command(cmdline)
|
||||
c.run(TIMEOUT)
|
||||
@@ -231,6 +241,7 @@ def run_tests(test_list, args):
|
||||
if c.timeout:
|
||||
print(output)
|
||||
print("Test exceded limit of %d seconds." % TIMEOUT)
|
||||
tests_failed.append(test)
|
||||
tcprint("##teamcity[testFailed name='%s' message='Test timeout']" % test)
|
||||
tcprint("##teamcity[testFinished name='%s']" % test)
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user