Merge branch 'master' into armjit-fpu

Conflicts:
	Core/MIPS/ARM/ArmCompFPU.cpp
	Core/MIPS/x86/CompFPU.cpp
This commit is contained in:
Henrik Rydgard
2013-02-10 15:57:16 +01:00
66 changed files with 2249 additions and 324 deletions
+3
View File
@@ -26,6 +26,9 @@ Windows/ipch
# For ppsspp.ini, etc.
*.ini
# Qt Linguist files
*.qm
Logs
Memstick
+5 -1
View File
@@ -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)
+11 -2
View File
@@ -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;
}
+2 -5
View File
@@ -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
+1 -1
View File
@@ -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:
+2 -2
View File
@@ -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;}
};
+57 -63
View File
@@ -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)
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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
{
+1 -1
View File
@@ -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
View File
@@ -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)",
+3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
}
+2 -1
View File
@@ -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"},
+65 -33
View File
@@ -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);
+1 -1
View File
@@ -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();
+1
View File
@@ -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;
+6
View File
@@ -277,6 +277,12 @@ namespace MIPSComp
}
}
void Jit::Comp_Special3(u32 op)
{
// ext, ins
DISABLE;
}
void Jit::Comp_Allegrex(u32 op)
{
DISABLE
+4
View File
@@ -83,6 +83,10 @@ void Jit::Comp_FPULS(u32 op)
}
}
void Jit::Comp_FPUComp(u32 op) {
DISABLE;
}
void Jit::Comp_FPU2op(u32 op)
{
DISABLE
+1 -1
View File
@@ -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
{
+10
View File
@@ -29,4 +29,14 @@ namespace MIPSComp
{
DISABLE;
}
void Jit::Comp_Mftv(u32 op)
{
DISABLE;
}
void Jit::Comp_SV(u32 op) {
DISABLE;
}
}
+1
View File
@@ -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)
+7 -1
View File
@@ -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
View File
@@ -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),
+7
View File
@@ -335,6 +335,13 @@ namespace MIPSComp
}
}
void Jit::Comp_Special3(u32 op)
{
// ext, ins
DISABLE;
}
void Jit::Comp_Allegrex(u32 op)
{
CONDITIONAL_DISABLE
-5
View File
@@ -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
View File
@@ -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(&currentMIPS->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(&currentMIPS->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
View File
@@ -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
View File
@@ -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);
+4
View File
@@ -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);
+4
View File
@@ -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
View File
@@ -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)
+6 -10
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
}
-1
View File
@@ -6,5 +6,4 @@ extern const GLint eqLookup[];
extern const GLint cullingMode[];
extern const GLuint ztests[];
void UpdateViewportAndProjection();
+87 -48
View File
@@ -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
View File
@@ -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*.
+7 -1
View File
@@ -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];
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+2 -2
View File
@@ -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:
+3
View File
@@ -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
View File
@@ -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
}
+1
View File
@@ -25,6 +25,7 @@ public:
void CalibNextButton();
protected:
void showEvent(QShowEvent *);
void changeEvent(QEvent *);
private slots:
void releaseLock();
void on_refreshListBtn_clicked();
+634
View File
@@ -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>&amp;Go to</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../debugger_disasm.ui" line="73"/>
<source>&amp;PC</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../debugger_disasm.ui" line="86"/>
<source>&amp;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>&amp;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 &amp;Into</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../debugger_disasm.ui" line="192"/>
<source>Step &amp;Over</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../debugger_disasm.ui" line="205"/>
<source>S&amp;kip</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../debugger_disasm.ui" line="218"/>
<source>Next &amp;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>&lt;b&gt;No gamepad&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gamepaddialog.cpp" line="146"/>
<source>&lt;b&gt;Unknown gamepad&lt;/b&gt;</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>&lt;b&gt;Current gamepad: %1&lt;/b&gt;</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>&amp;File</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="66"/>
<source>&amp;Emulation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="79"/>
<source>Debu&amp;g</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="91"/>
<source>&amp;Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="95"/>
<source>&amp;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>&amp;Help</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="182"/>
<source>&amp;Open...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="187"/>
<source>&amp;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>&amp;Load State File...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="218"/>
<source>&amp;Save State File...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="223"/>
<source>E&amp;xit</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="228"/>
<source>&amp;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>&amp;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&amp;eset</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="252"/>
<source>&amp;Interpreter</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="260"/>
<source>&amp;Slightly Faster Interpreter</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="268"/>
<source>&amp;Dynarec</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="276"/>
<source>Load &amp;Map File...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="284"/>
<source>&amp;Save Map File...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="292"/>
<source>&amp;Reset Symbol Table</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="300"/>
<source>&amp;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>&amp;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 &amp;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 &amp;Controls</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="335"/>
<source>&amp;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>&amp;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>&amp;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>&amp;Linear Filtering</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="376"/>
<source>&amp;Wireframe (experimental)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="384"/>
<source>&amp;Display Raw Framebuffer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="392"/>
<source>&amp;Show Debug Statistics</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="400"/>
<source>Screen &amp;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 &amp;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 &amp;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 &amp;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>&amp;Fast Memory (dynarec, unstable)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="452"/>
<source>&amp;Ignore illegal reads/writes</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="457"/>
<source>&amp;Go to http://www.ppsspp.org/</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="462"/>
<source>&amp;About PPSSPP...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="467"/>
<source>&amp;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>
+634
View File
@@ -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>&amp;Go to</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../debugger_disasm.ui" line="73"/>
<source>&amp;PC</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../debugger_disasm.ui" line="86"/>
<source>&amp;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>&amp;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 &amp;Into</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../debugger_disasm.ui" line="192"/>
<source>Step &amp;Over</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../debugger_disasm.ui" line="205"/>
<source>S&amp;kip</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../debugger_disasm.ui" line="218"/>
<source>Next &amp;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>&lt;b&gt;No gamepad&lt;/b&gt;</source>
<translation>&lt;b&gt;Nie wykryto pada&lt;/b&gt;</translation>
</message>
<message>
<location filename="../gamepaddialog.cpp" line="146"/>
<source>&lt;b&gt;Unknown gamepad&lt;/b&gt;</source>
<translation>&lt;b&gt;Nieznany pad&lt;/b&gt;</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> %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>&lt;b&gt;Current gamepad: %1&lt;/b&gt;</source>
<translation>&lt;b&gt;Wybrany pad: %1&lt;/b&gt;</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>&amp;File</source>
<translation>&amp;Plik</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="66"/>
<source>&amp;Emulation</source>
<translation>&amp;Emulacja</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="79"/>
<source>Debu&amp;g</source>
<translation>&amp;Debugger</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="91"/>
<source>&amp;Options</source>
<translation>&amp;Opcje</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="95"/>
<source>&amp;Log Levels</source>
<translation>P&amp;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>&amp;Help</source>
<translation>Pomo&amp;c</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="182"/>
<source>&amp;Open...</source>
<translation>&amp;Otwórz...</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="187"/>
<source>&amp;Close</source>
<translation>&amp;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>&amp;Load State File...</source>
<translation>&amp;Wczytaj plik stanu...</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="218"/>
<source>&amp;Save State File...</source>
<translation>&amp;Zapisz plik stanu...</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="223"/>
<source>E&amp;xit</source>
<translation>Wyj&amp;</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="228"/>
<source>&amp;Run</source>
<translation>&amp;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>&amp;Pause</source>
<translation>&amp;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&amp;eset</source>
<translation>&amp;Reset</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="252"/>
<source>&amp;Interpreter</source>
<translation>&amp;Interpreter</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="260"/>
<source>&amp;Slightly Faster Interpreter</source>
<translation>&amp;Szybszy interpreter</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="268"/>
<source>&amp;Dynarec</source>
<translation>R&amp;ekompilacja (Dynarec)</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="276"/>
<source>Load &amp;Map File...</source>
<translation>&amp;Wczytaj plik mapy...</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="284"/>
<source>&amp;Save Map File...</source>
<translation>&amp;Zapisz plik mapy...</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="292"/>
<source>&amp;Reset Symbol Table</source>
<translation>Zresetuj &amp;tablicę symboli</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="300"/>
<source>&amp;Disassembly</source>
<translation>&amp;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>&amp;Log Console</source>
<translation>&amp;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 &amp;View...</source>
<translation>Widok &amp;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 &amp;Controls</source>
<translation>Ustawienia &amp;klawiatury</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="335"/>
<source>&amp;Toggle Full Screen</source>
<translation>&amp;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>&amp;Buffered Rendering</source>
<translation>&amp;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>&amp;Hardware Transform</source>
<translation>&amp;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>&amp;Linear Filtering</source>
<translation>&amp;Linear Filtering</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="376"/>
<source>&amp;Wireframe (experimental)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="384"/>
<source>&amp;Display Raw Framebuffer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="392"/>
<source>&amp;Show Debug Statistics</source>
<translation>Pokaż &amp;statystyki emulacji</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="400"/>
<source>Screen &amp;1x</source>
<translation>&amp;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 &amp;2x</source>
<translation>&amp;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 &amp;3x</source>
<translation>&amp;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 &amp;4x</source>
<translation>&amp;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>&amp;Fast Memory (dynarec, unstable)</source>
<translation>&amp;Fast memory (wymagany Dynarec, niestabilne)</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="452"/>
<source>&amp;Ignore illegal reads/writes</source>
<translation>&amp;Ignoruj nieprawidłowe odczyty/zapisy</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="457"/>
<source>&amp;Go to http://www.ppsspp.org/</source>
<translation>&amp;Idź do http://www.ppsspp.org</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="462"/>
<source>&amp;About PPSSPP...</source>
<translation>&amp;O PPSSPP...</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="467"/>
<source>&amp;Use VBO</source>
<translation>Użyj &amp;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>&amp;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>
+100
View File
@@ -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;
}
}
}
+12
View File
@@ -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
View File
@@ -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">
+2
View File
@@ -191,6 +191,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
}
}
VFSShutdown();
LogManager::Shutdown();
DialogManager::DestroyAll();
timeEndPeriod(1);
+77
View File
@@ -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);
}
+23
View File
@@ -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
View File
@@ -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;
}
+2
View File
@@ -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>
+2
View File
@@ -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>
+1
View File
@@ -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; }
};
+49
View File
@@ -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;
+3
View File
@@ -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
+12 -1
View File
@@ -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