diff --git a/CMakeLists.txt b/CMakeLists.txt index 26e538ab2a..935be34623 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ else() # Assume x86 set(X86 ON) endif() -if(ANDROID OR BLACKBERRY OR IOS) +if(ANDROID OR BLACKBERRY OR IOS OR PANDORA) set(HEADLESS OFF) elseif(NOT DEFINED HEADLESS) set(HEADLESS ON) @@ -35,6 +35,7 @@ option(ARM "Set to ON if targeting an ARM processor" ${ARM}) option(X86 "Set to ON if targeting an X86 processor" ${X86}) option(ANDROID "Set to ON if targeting an Android device" ${ANDROID}) option(BLACKBERRY "Set to ON if targeting a Blackberry device" ${BLACKBERRY}) +option(PANDORA "Set to ON if targeting an OpenPandora device" ${PANDORA}) option(IOS "Set to ON if targeting an iOS device" ${IOS}) option(USING_GLES2 "Set to ON if target device uses OpenGL ES 2.0" ${USING_GLES2}) option(USING_QT_UI "Set to ON if you wish to use the Qt frontend wrapper" ${USING_QT_UI}) @@ -95,6 +96,10 @@ if(IOS) add_definitions(-DIOS) endif() +if(PANDORA) + add_definitions(-DPANDORA) +endif() + if(ARM) add_definitions(-DARM) endif() @@ -416,6 +421,8 @@ elseif(SDL_FOUND) if(APPLE) set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm) set(nativeExtraLibs ${nativeExtraLibs} ${COCOA_LIBRARY}) + elseif(PANDORA) + set(nativeExtraLibs ${nativeExtraLibs} pthread EGL X11) endif() if(NOT IOS) # No target set(TargetBin PPSSPPSDL) diff --git a/Common/ArmEmitter.h b/Common/ArmEmitter.h index 8307841894..59365f3e12 100644 --- a/Common/ArmEmitter.h +++ b/Common/ArmEmitter.h @@ -26,12 +26,21 @@ #include #endif -namespace ArmGen -{ +#ifdef PANDORA +#ifdef __USE_POSIX +extern "C" +int kill (__pid_t __pid, int __sig) __THROW; +#endif +#define SIGINT 2 +#endif + #undef _IP #undef _SP #undef _LR #undef _PC + +namespace ArmGen +{ enum ARMReg { // GPRs diff --git a/Common/CommonFuncs.h b/Common/CommonFuncs.h index 1b0f75f42f..486fb4d567 100644 --- a/Common/CommonFuncs.h +++ b/Common/CommonFuncs.h @@ -15,8 +15,7 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#ifndef _COMMONFUNCS_H_ -#define _COMMONFUNCS_H_ +#pragma once #ifdef _WIN32 #define SLEEP(x) Sleep(x) @@ -39,22 +38,6 @@ template<> struct CompileTimeAssert {}; #define b32(x) (b16(x) | (b16(x) >>16) ) #define ROUND_UP_POW2(x) (b32(x - 1) + 1) -#if defined __GNUC__ && !defined __SSSE3__ -// Assume !ARM = x86 -#if !defined(ARM) -#include -static __inline __m128i __attribute__((__always_inline__)) -_mm_shuffle_epi8(__m128i a, __m128i mask) -{ - __m128i result; - __asm__("pshufb %1, %0" - : "=x" (result) - : "xm" (mask), "0" (a)); - return result; -} -#endif -#endif - #ifndef _WIN32 #include @@ -178,5 +161,3 @@ inline u64 swap64(u64 _data) {return bswap64(_data);} //inline u64 swap64(const u8* _pData) {return swap64(*(const u64*)_pData);} } // Namespace Common - -#endif // _COMMONFUNCS_H_ diff --git a/Core/Debugger/SymbolMap.cpp b/Core/Debugger/SymbolMap.cpp index a78049620f..d11b99bc06 100644 --- a/Core/Debugger/SymbolMap.cpp +++ b/Core/Debugger/SymbolMap.cpp @@ -54,7 +54,7 @@ static u32 ComputeHash(u32 start, u32 size) void SymbolMap::SortSymbols() { - std::sort(entries, entries + numEntries); + std::sort(entries.begin(), entries.end()); } void SymbolMap::AnalyzeBackwards() @@ -112,23 +112,23 @@ void SymbolMap::ResetSymbolMap() entries[i].backwardLinks.clear(); } #endif - numEntries=0; + entries.clear(); } void SymbolMap::AddSymbol(const char *symbolname, unsigned int vaddress, size_t size, SymbolType st) { - MapEntry &e = entries[numEntries++]; + MapEntry e; strcpy(e.name, symbolname); e.vaddress = vaddress; e.size = size; - e.type=st; + e.type = st; + entries.push_back(e); } bool SymbolMap::LoadSymbolMap(const char *filename) { SymbolMap::ResetSymbolMap(); - numEntries=0; FILE *f = fopen(filename,"r"); if (!f) return false; @@ -168,17 +168,21 @@ bool SymbolMap::LoadSymbolMap(const char *filename) if (temp[1]==']') continue; if (!started) continue; - MapEntry &e = entries[numEntries++]; + MapEntry e; sscanf(line,"%08x %08x %08x %i %s",&e.address,&e.size,&e.vaddress,(int*)&e.type,e.name); if (e.type == ST_DATA && e.size==0) e.size=4; + //e.vaddress|=0x80000000; if (strcmp(e.name,".text")==0 || strcmp(e.name,".init")==0 || strlen(e.name)<=1) - numEntries--; - + { + ; + } else { + entries.push_back(e); + } } - for (int i = 0; i < numEntries; i++) + for (size_t i = 0; i < entries.size(); i++) entries[i].UndecorateName(); fclose(f); SymbolMap::SortSymbols(); @@ -193,7 +197,7 @@ void SymbolMap::SaveSymbolMap(const char *filename) if (!f) return; fprintf(f,".text\n"); - for (int i=0; i= entries[i].vaddress) start = i; @@ -215,7 +219,7 @@ int SymbolMap::GetSymbolNum(unsigned int address, SymbolType symmask) if (start<0) start=0; - for (int i=start; i= addr)) @@ -268,7 +272,7 @@ void SymbolMap::FillSymbolListBox(HWND listbox,SymbolType symmask) //ListBox_AddString(listbox,"(0x80002000)"); //ListBox_SetItemData(listbox,1,0x80002000); - for (int i=0; i= 16 && entries[i].type == ST_FUNCTION) @@ -418,24 +422,19 @@ struct Sig { strncpy(name,_name,63); } - + bool operator <(const Sig &other) { + return inst < other.inst; + } }; -int compare (const void *s1, const void *s2) -{ - return ((Sig *)s2)->inst - ((Sig *)s1)->inst; -} - -#define MAXSIGS 65536*2 -Sig sigs[MAXSIGS]; -int numSigs; +std::vector sigs; typedef std::map Sigmap; Sigmap sigmap; void SymbolMap::UseFuncSignaturesFile(const char *filename, u32 maxAddress) { - numSigs=0; + sigs.clear(); //SymbolMap::ResetSymbolMap(); //#1: Read the signature file and put them in a fast data structure FILE *f = fopen(filename, "r"); @@ -447,13 +446,13 @@ void SymbolMap::UseFuncSignaturesFile(const char *filename, u32 maxAddress) { u32 inst, size, hash; if (fscanf(f,"%08x\t%08x\t%08x\t%s\n",&inst,&size,&hash,name)!=EOF) - sigs[numSigs++]=Sig(inst,size,hash,name); + sigs.push_back(Sig(inst,size,hash,name)); else break; } - + int numSigs = sigs.size(); fclose(f); - qsort(sigs, numSigs,sizeof(Sig),compare); + std::sort(sigs.begin(), sigs.end()); f = fopen("C:\\mojs.txt", "w"); fprintf(f,"00000000\n"); @@ -464,18 +463,15 @@ void SymbolMap::UseFuncSignaturesFile(const char *filename, u32 maxAddress) fclose(f); u32 last = 0xc0d3babe; - int i; - for (i=0; ihash) { //MATCH!!!! - MapEntry &e = entries[numEntries++]; + MapEntry e; e.address=addr; e.size= sig->size; e.vaddress = addr; e.type=ST_FUNCTION; strcpy(e.name,sig->name); addr+=sig->size-4; //don't need to check function interior + entries.push_back(e); break; } sig++; diff --git a/Core/Debugger/SymbolMap.h b/Core/Debugger/SymbolMap.h index 07116afe05..3766b68c81 100644 --- a/Core/Debugger/SymbolMap.h +++ b/Core/Debugger/SymbolMap.h @@ -34,6 +34,7 @@ typedef struct HWND__ *HWND; class SymbolMap { public: + SymbolMap() {} bool LoadSymbolMap(const char *filename); void SaveSymbolMap(const char *filename); void AddSymbol(const char *symbolname, unsigned int vaddress, size_t size, SymbolType symbol); @@ -89,12 +90,7 @@ private: } }; - int numEntries; - MapEntry entries[65536*2]; - - - + std::vector entries; }; - extern SymbolMap symbolMap; diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index f72a246484..0e147475e1 100644 --- a/Core/Dialog/PSPMsgDialog.cpp +++ b/Core/Dialog/PSPMsgDialog.cpp @@ -166,7 +166,7 @@ int PSPMsgDialog::Update() if (IsButtonPressed(cancelButtonFlag)) { status = SCE_UTILITY_STATUS_FINISHED; - messageDialog.buttonPressed = 0; + messageDialog.buttonPressed = 3; } EndDraw(); break; diff --git a/Core/HLE/HLETables.cpp b/Core/HLE/HLETables.cpp index 27f916faeb..9676a49bc2 100644 --- a/Core/HLE/HLETables.cpp +++ b/Core/HLE/HLETables.cpp @@ -75,7 +75,7 @@ const HLEFunction UtilsForUser[] = { {0x91E4F6A7, WrapU_V, "sceKernelLibcClock"}, {0x27CC57F0, WrapU_U, "sceKernelLibcTime"}, - {0x71EC4271, sceKernelLibcGettimeofday, "sceKernelLibcGettimeofday"}, + {0x71EC4271, WrapU_U, "sceKernelLibcGettimeofday"}, {0xBFA98062, WrapI_UI, "sceKernelDcacheInvalidateRange"}, {0xC8186A58, 0, "sceKernelUtilsMd5Digest"}, {0x9E5C5086, 0, "sceKernelUtilsMd5BlockInit"}, @@ -87,8 +87,8 @@ const HLEFunction UtilsForUser[] = {0x585F1C09, 0, "sceKernelUtilsSha1BlockResult"}, {0xE860E75E, 0, "sceKernelUtilsMt19937Init"}, {0x06FB8A63, 0, "sceKernelUtilsMt19937UInt"}, - {0x37FB5C42, sceKernelGetGPI, "sceKernelGetGPI"}, - {0x6AD345D7, sceKernelSetGPO, "sceKernelSetGPO"}, + {0x37FB5C42, WrapU_V, "sceKernelGetGPI"}, + {0x6AD345D7, WrapV_U, "sceKernelSetGPO"}, {0x79D1C3FA, WrapI_V, "sceKernelDcacheWritebackAll"}, {0xB435DEC5, WrapI_V, "sceKernelDcacheWritebackInvalidateAll"}, {0x3EE30821, WrapI_UI, "sceKernelDcacheWritebackRange"}, @@ -98,7 +98,7 @@ const HLEFunction UtilsForUser[] = {0x16641D70, 0, "sceKernelDcacheReadTag"}, {0x4FD31C9D, 0, "sceKernelIcacheProbe"}, {0xFB05FAD0, 0, "sceKernelIcacheReadTag"}, - {0x920f104a, sceKernelIcacheInvalidateAll, "sceKernelIcacheInvalidateAll"} + {0x920f104a, WrapU_V, "sceKernelIcacheInvalidateAll"} }; @@ -126,7 +126,7 @@ const HLEFunction LoadCoreForKernel[] = {0xB4D6FECC, 0, "sceKernelApplyElfRelSection"}, {0x54AB2675, 0, "LoadCoreForKernel_54AB2675"}, {0x2952F5AC, 0, "sceKernelDcacheWBinvAll"}, - {0xD8779AC6, sceKernelIcacheClearAll, "sceKernelIcacheClearAll"}, + {0xD8779AC6, WrapU_V, "sceKernelIcacheClearAll"}, {0x99A695F0, 0, "sceKernelRegisterLibrary"}, {0x5873A31F, 0, "sceKernelRegisterLibraryForUser"}, {0x0B464512, 0, "sceKernelReleaseLibrary"}, @@ -148,7 +148,7 @@ const HLEFunction LoadCoreForKernel[] = {0xCCE4A157, 0, "sceKernelFindModuleByUID"}, {0x82CE54ED, 0, "sceKernelModuleCount"}, {0xC0584F0C, 0, "sceKernelGetModuleList"}, - {0xCF8A41B1, sceKernelFindModuleByName,"sceKernelFindModuleByName"}, + {0xCF8A41B1, WrapU_V,"sceKernelFindModuleByName"}, }; @@ -158,7 +158,7 @@ const HLEFunction KDebugForKernel[] = {0x2FF4E9F9, 0, "sceKernelAssert"}, {0x9B868276, 0, "sceKernelGetDebugPutchar"}, {0xE146606D, 0, "sceKernelRegisterDebugPutchar"}, - {0x7CEB2C09, sceKernelRegisterKprintfHandler, "sceKernelRegisterKprintfHandler"}, + {0x7CEB2C09, WrapU_V, "sceKernelRegisterKprintfHandler"}, {0x84F370BC, 0, "Kprintf"}, {0x5CE9838B, 0, "sceKernelDebugWrite"}, {0x66253C4E, 0, "sceKernelRegisterDebugWrite"}, diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index bf7f514014..da1b19d658 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -284,12 +284,12 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { #ifndef _WIN32 coreState = CORE_NEXTFRAME; #endif + vCount++; } void hleLeaveVblank(u64 userdata, int cyclesLate) { isVblank = 0; DEBUG_LOG(HLE,"Leave VBlank %i", (int)userdata - 1); - vCount++; hCount = 0; CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs) - cyclesLate, enterVblankEvent, userdata); } @@ -366,9 +366,13 @@ void sceDisplayWaitVblankStart() { } void sceDisplayWaitVblank() { - DEBUG_LOG(HLE,"sceDisplayWaitVblank()"); - vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); - __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false); + if (!isVblank) { + DEBUG_LOG(HLE,"sceDisplayWaitVblank()"); + vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); + __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false); + } else { + DEBUG_LOG(HLE,"sceDisplayWaitVblank() - not waiting since in vBlank"); + } } void sceDisplayWaitVblankStartMulti() { @@ -378,9 +382,13 @@ void sceDisplayWaitVblankStartMulti() { } void sceDisplayWaitVblankCB() { - DEBUG_LOG(HLE,"sceDisplayWaitVblankCB()"); - vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); - __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true); + if (!isVblank) { + DEBUG_LOG(HLE,"sceDisplayWaitVblankCB()"); + vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); + __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true); + } else { + DEBUG_LOG(HLE,"sceDisplayWaitVblank() - not waiting since in vBlank"); + } } void sceDisplayWaitVblankStartCB() { @@ -414,7 +422,7 @@ void sceDisplayGetCurrentHcount() { void sceDisplayGetAccumulatedHcount() { // Just do an estimate - u32 accumHCount = CoreTiming::GetTicks() / (222000000 / 60 / 272); + u32 accumHCount = CoreTiming::GetTicks() / (CoreTiming::GetClockFrequencyMHz() * 1000000 / 60 / 272); DEBUG_LOG(HLE,"%i=sceDisplayGetAccumulatedHcount()", accumHCount); RETURN(accumHCount); } diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 1dae0dd5ab..014476134f 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -221,10 +221,10 @@ void sceKernelDevkitVersion() RETURN(1); } -void sceKernelRegisterKprintfHandler() +u32 sceKernelRegisterKprintfHandler() { ERROR_LOG(HLE,"UNIMPL sceKernelRegisterKprintfHandler()"); - RETURN(0); + return 0; } void sceKernelRegisterDefaultExceptionHandler() { @@ -232,17 +232,17 @@ void sceKernelRegisterDefaultExceptionHandler() RETURN(0); } -void sceKernelSetGPO() +void sceKernelSetGPO(u32 ledAddr) { // Sets debug LEDs. - DEBUG_LOG(HLE,"sceKernelSetGPO(%02x)", PARAM(0)); + DEBUG_LOG(HLE,"sceKernelSetGPO(%02x)", ledAddr); } -void sceKernelGetGPI() +u32 sceKernelGetGPI() { // Always returns 0 on production systems. DEBUG_LOG(HLE,"0=sceKernelGetGPI()"); - RETURN(0); + return 0; } // Don't even log these, they're spammy and we probably won't @@ -461,17 +461,17 @@ KernelObject *KernelObjectPool::CreateByIDType(int type) } } -void sceKernelIcacheInvalidateAll() +u32 sceKernelIcacheInvalidateAll() { DEBUG_LOG(CPU, "Icache invalidated - should clear JIT someday"); - RETURN(0); + return 0; } -void sceKernelIcacheClearAll() +u32 sceKernelIcacheClearAll() { DEBUG_LOG(CPU, "Icache cleared - should clear JIT someday"); - RETURN(0); + return 0; } struct SystemStatus { diff --git a/Core/HLE/sceKernel.h b/Core/HLE/sceKernel.h index 09bfade06f..96d597a71a 100644 --- a/Core/HLE/sceKernel.h +++ b/Core/HLE/sceKernel.h @@ -288,21 +288,21 @@ void sceKernelSleepThreadCB(); void sceKernelDevkitVersion(); -void sceKernelRegisterKprintfHandler(); +u32 sceKernelRegisterKprintfHandler(); void sceKernelRegisterDefaultExceptionHandler(); -void sceKernelFindModuleByName(); +u32 sceKernelFindModuleByName(); -void sceKernelSetGPO(); -void sceKernelGetGPI(); +void sceKernelSetGPO(u32 ledAddr); +u32 sceKernelGetGPI(); int sceKernelDcacheInvalidateRange(u32 addr, int size); int sceKernelDcacheWritebackAll(); int sceKernelDcacheWritebackRange(u32 addr, int size); int sceKernelDcacheWritebackInvalidateRange(u32 addr, int size); int sceKernelDcacheWritebackInvalidateAll(); void sceKernelGetThreadStackFreeSize(); -void sceKernelIcacheInvalidateAll(); -void sceKernelIcacheClearAll(); +u32 sceKernelIcacheInvalidateAll(); +u32 sceKernelIcacheClearAll(); #define KERNELOBJECT_MAX_NAME_LENGTH 31 diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 94319a8ccc..1af606d958 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -893,10 +893,10 @@ u32 sceKernelGetModuleId() return __KernelGetCurThreadModuleId(); } -void sceKernelFindModuleByName() +u32 sceKernelFindModuleByName() { ERROR_LOG(HLE,"UNIMPL sceKernelFindModuleByName()"); - RETURN(1); + return 1; } u32 sceKernelLoadModuleByID(u32 id, u32 flags, u32 lmoptionPtr) diff --git a/Core/HLE/sceKernelTime.cpp b/Core/HLE/sceKernelTime.cpp index e5cb09a9f5..3f4649c692 100644 --- a/Core/HLE/sceKernelTime.cpp +++ b/Core/HLE/sceKernelTime.cpp @@ -144,7 +144,7 @@ u32 sceKernelLibcTime(u32 outPtr) return t; } -void sceKernelLibcGettimeofday() +u32 sceKernelLibcGettimeofday(u32 timeAddr) { #ifdef _WIN32 union { @@ -158,12 +158,12 @@ void sceKernelLibcGettimeofday() u32 tv_usec; }; - timeval *tv = (timeval*)Memory::GetPointer(PARAM(0)); + timeval *tv = (timeval*)Memory::GetPointer(timeAddr); DEBUG_LOG(HLE,"sceKernelLibcGettimeofday()"); GetSystemTimeAsFileTime (&now.ft); tv->tv_usec = (long) ((now.ns100 / 10LL) % 1000000LL); tv->tv_sec = (long) ((now.ns100 - 116444736000000000LL) / 10000000LL); #endif - RETURN(0); + return 0; } diff --git a/Core/HLE/sceKernelTime.h b/Core/HLE/sceKernelTime.h index 4ab8e59ec6..5370278d18 100644 --- a/Core/HLE/sceKernelTime.h +++ b/Core/HLE/sceKernelTime.h @@ -17,7 +17,7 @@ #pragma once -void sceKernelLibcGettimeofday(); +u32 sceKernelLibcGettimeofday(u32 timeAddr); u32 sceKernelLibcTime(u32 outPtr); void sceKernelUSec2SysClock(); void sceKernelGetSystemTime(); diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp index 7bffa5ecba..bec83dfbdf 100644 --- a/Core/Loaders.cpp +++ b/Core/Loaders.cpp @@ -16,7 +16,6 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "file/file_util.h" - #include "MIPS/MIPS.h" #include "MIPS/MIPSCodeUtils.h" @@ -44,9 +43,15 @@ EmuFileType Identify_File(const char *filename) if(readSize != 1) return FILETYPE_ERROR; + if (strlen(filename) < 5) { + ERROR_LOG(LOADER, "invalid filename %s", filename); + } + const char *extension = filename + strlen(filename) - 4; + if (id == 'FLE\x7F') { - if (strstr(filename,".plf") || strstr(filename,"BOOT.BIN") || strstr(filename,".elf") || strstr(filename,".prx") ) + if (!strcasecmp(extension, ".plf") || strstr(filename,"BOOT.BIN") || + !strcasecmp(extension, ".elf") || !strcasecmp(extension,".prx") ) { return FILETYPE_PSP_ELF; } @@ -59,19 +64,19 @@ EmuFileType Identify_File(const char *filename) } else { - if (strstr(filename,".pbp") || strstr(filename,".PBP")) + if (!strcasecmp(extension,".pbp")) { return FILETYPE_PSP_PBP; } - else if (strstr(filename,".iso") || strstr(filename,".ISO")) + else if (!strcasecmp(extension,".iso")) { return FILETYPE_PSP_ISO; } - else if (strstr(filename,".cso") || strstr(filename,".CSO")) + else if (!strcasecmp(extension,".cso")) { return FILETYPE_PSP_ISO; } - else if (strstr(filename,".bin") || strstr(filename,".BIN")) + else if (!strcasecmp(extension,".bin")) { return FILETYPE_UNKNOWN_BIN; } diff --git a/Core/MemMapFunctions.cpp b/Core/MemMapFunctions.cpp index 2e0f2a5c15..1f9b17bef7 100644 --- a/Core/MemMapFunctions.cpp +++ b/Core/MemMapFunctions.cpp @@ -45,7 +45,7 @@ u8 *GetPointer(const u32 address) { return m_pRAM + (address & RAM_MASK); } - else if ((address & 0x0F000000) == 0x04000000) + else if ((address & 0x0F800000) == 0x04000000) { return m_pVRAM + (address & VRAM_MASK); } @@ -72,7 +72,7 @@ inline void ReadFromHardware(T &var, const u32 address) { var = *((const T*)&m_pRAM[address & RAM_MASK]); } - else if ((address & 0x0F000000) == 0x04000000) + else if ((address & 0x0F800000) == 0x04000000) { var = *((const T*)&m_pVRAM[address & VRAM_MASK]); } @@ -101,7 +101,7 @@ inline void WriteToHardware(u32 address, const T data) { *(T*)&m_pRAM[address & RAM_MASK] = data; } - else if ((address & 0x0F000000) == 0x04000000) + else if ((address & 0x0F800000) == 0x04000000) { *(T*)&m_pVRAM[address & VRAM_MASK] = data; } @@ -127,7 +127,7 @@ bool IsValidAddress(const u32 address) { return true; } - else if ((address & 0x0F000000) == 0x04000000) + else if ((address & 0x0F800000) == 0x04000000) { return true; } diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index 0e1c599a68..d55d237659 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -41,15 +41,15 @@ BlockDevice *constructBlockDevice(const char *filename) { - char firstInExtension = filename[strlen(filename)-3]; - if (firstInExtension == 'c') - { + // Check for CISO + FILE *f = fopen(filename, "rb"); + char buffer[4]; + auto size = fread(buffer, 1, 4, f); //size_t + fclose(f); + if (!memcmp(buffer, "CISO", 4) && size == 4) return new CISOFileBlockDevice(filename); - } else - { return new FileBlockDevice(filename); - } } diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 113d1c8ba2..3eb5c1826e 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -142,6 +142,8 @@ const int flushBeforeCommandList[] = { GE_CMD_PROJMATRIXDATA, GE_CMD_TGENMATRIXNUMBER, GE_CMD_BONEMATRIXNUMBER, + GE_CMD_MASKRGB, + GE_CMD_MASKALPHA, }; GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) diff --git a/GPU/GLES/StateMapping.cpp b/GPU/GLES/StateMapping.cpp index ba958bb513..4e2be0fd0a 100644 --- a/GPU/GLES/StateMapping.cpp +++ b/GPU/GLES/StateMapping.cpp @@ -60,16 +60,25 @@ const GLuint ztests[] = GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL, }; -void ApplyDrawState() -{ +const GLuint stencilOps[] = { + GL_KEEP, + GL_ZERO, + GL_REPLACE, + GL_INVERT, + GL_INCR_WRAP, + GL_DECR_WRAP, // don't know if these should be wrap or not + GL_KEEP, // reserved + GL_KEEP, // reserved +}; +void ApplyDrawState(int prim) { // TODO: All this setup is soon so expensive that we'll need dirty flags, or simply do it in the command writes where we detect dirty by xoring. Silly to do all this work on every drawcall. // TODO: The top bit of the alpha channel should be written to the stencil bit somehow. This appears to require very expensive multipass rendering :( Alternatively, one could do a // single fullscreen pass that converts alpha to stencil (or 2 passes, to set both the 0 and 1 values) very easily. // Set cull - bool wantCull = !gstate.isModeClear() && !gstate.isModeThrough() && gstate.isCullEnabled(); + bool wantCull = !gstate.isModeClear() && !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); glstate.cullFace.set(wantCull); if (wantCull) { @@ -155,6 +164,29 @@ void ApplyDrawState() glstate.depthFunc.set(ztests[depthTestFunc]); } + // PSP color/alpha mask is per bit but we can only support per byte. + // But let's do that, at least. And let's try a threshold. + if (!gstate.isModeClear()) { + bool rmask = (gstate.pmskc & 0xFF) < 128; + bool gmask = ((gstate.pmskc >> 8) & 0xFF) < 128; + bool bmask = ((gstate.pmskc >> 16) & 0xFF) < 128; + bool amask = (gstate.pmska & 0xFF) < 128; + glstate.colorMask.set(rmask, gmask, bmask, amask); + } + + // Stencil test + if (!gstate.isModeClear() && gstate.isStencilTestEnabled()) { + glstate.stencilTest.enable(); + glstate.stencilFunc.set(ztests[gstate.stenciltest & 0x7], // func + (gstate.stenciltest >> 8) & 0xFF, // ref + (gstate.stenciltest >> 16) & 0xFF); // mask + glstate.stencilOp.set(stencilOps[gstate.stencilop & 0x7], // stencil fail + stencilOps[(gstate.stencilop >> 8) & 0x7], // depth fail + stencilOps[(gstate.stencilop >> 16) & 0x7]); + } else { + glstate.stencilTest.disable(); + } + bool wantDepthWrite = gstate.isModeClear() || gstate.isDepthWriteEnabled(); glstate.depthWrite.set(wantDepthWrite ? GL_TRUE : GL_FALSE); diff --git a/GPU/GLES/StateMapping.h b/GPU/GLES/StateMapping.h index 7532a3f3d4..c36a2423bf 100644 --- a/GPU/GLES/StateMapping.h +++ b/GPU/GLES/StateMapping.h @@ -7,6 +7,6 @@ extern const GLint cullingMode[]; extern const GLuint ztests[]; -void ApplyDrawState(); +void ApplyDrawState(int prim); void UpdateViewportAndProjection(); diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index fd1eddecec..511a38d5ed 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -45,7 +45,7 @@ const GLuint glprim[8] = { }; TransformDrawEngine::TransformDrawEngine() - : numVerts(0), + : collectedVerts(0), lastVType(-1), curVbo_(0), shaderManager_(0) { @@ -615,9 +615,9 @@ void TransformDrawEngine::SoftwareTransformAndDraw( bool useVBO = g_Config.bUseVBO; if (useVBO) { - char title[64]; - sprintf(title, "upload %i verts for sw", indexGen.VertexCount()); - LoggingDeadline deadline(title, 5); + //char title[64]; + //sprintf(title, "upload %i verts for sw", indexGen.VertexCount()); + //LoggingDeadline deadline(title, 5); glBindBuffer(GL_ARRAY_BUFFER, vbo_[curVbo_]); glBufferData(GL_ARRAY_BUFFER, vertexSize * numTrans, drawBuffer, GL_DYNAMIC_DRAW); drawBuffer = 0; // so that the calls use offsets instead. @@ -662,7 +662,7 @@ void TransformDrawEngine::SubmitPrim(void *verts, void *inds, int prim, int vert gpuStats.numDrawCalls++; gpuStats.numVertsTransformed += vertexCount; - indexGen.SetIndex(numVerts); + indexGen.SetIndex(collectedVerts); int indexLowerBound, indexUpperBound; // If vtype has changed, setup the vertex decoder. // TODO: Simply cache the setup decoders instead. @@ -672,8 +672,8 @@ void TransformDrawEngine::SubmitPrim(void *verts, void *inds, int prim, int vert } // Decode the verts and apply morphing - dec.DecodeVerts(decoded + numVerts * (int)dec.GetDecVtxFmt().stride, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound); - numVerts += indexUpperBound - indexLowerBound + 1; + dec.DecodeVerts(decoded + collectedVerts * (int)dec.GetDecVtxFmt().stride, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound); + collectedVerts += indexUpperBound - indexLowerBound + 1; if (bytesRead) *bytesRead = vertexCount * dec.VertexSize(); @@ -742,24 +742,23 @@ void TransformDrawEngine::Flush() { int prim = indexGen.Prim(); - ApplyDrawState(); + ApplyDrawState(prim); UpdateViewportAndProjection(); LinkedShader *program = shaderManager_->ApplyShader(prim); - DEBUG_LOG(G3D, "Flush prim %i! %i verts in one go", prim, numVerts); + DEBUG_LOG(G3D, "Flush prim %i! %i verts in one go", prim, collectedVerts); bool useVBO = g_Config.bUseVBO; if (CanUseHardwareTransform(prim)) { - char title[64]; - sprintf(title, "upload %i verts for hw", indexGen.VertexCount()); - LoggingDeadline deadline(title, 5); if (useVBO) { + //char title[64]; + //sprintf(title, "upload %i verts for hw", indexGen.VertexCount()); + //LoggingDeadline deadline(title, 5); glBindBuffer(GL_ARRAY_BUFFER, vbo_[curVbo_]); glBufferData(GL_ARRAY_BUFFER, dec.GetDecVtxFmt().stride * indexGen.MaxIndex(), decoded, GL_DYNAMIC_DRAW); } - deadline.End(); SetupDecFmtForDraw(program, dec.GetDecVtxFmt(), useVBO ? 0 : decoded); // If there's only been one primitive type, and it's either TRIANGLES, LINES or POINTS, // there is no need for the index buffer we built. We can then use glDrawArrays instead @@ -791,5 +790,5 @@ void TransformDrawEngine::Flush() { } indexGen.Reset(); - numVerts = 0; + collectedVerts = 0; } diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index 78ee856232..6c3164bd40 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -47,7 +47,7 @@ private: // Vertex collector state IndexGenerator indexGen; - int numVerts; + int collectedVerts; // Vertex collector buffers VertexDecoder dec; diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 2580d73518..ef37f86329 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -177,8 +177,8 @@ struct GPUgstate dith4, lop, zmsk, - pmsk1, - pmsk2, + pmskc, + pmska, transferstart, transfersrcpos, transferdstpos, @@ -208,6 +208,7 @@ struct GPUgstate bool isDepthWriteEnabled() const { return !(zmsk & 1); } int getDepthTestFunc() const { return ztestfunc & 0x7; } bool isFogEnabled() const { return fogEnable & 1; } + bool isStencilTestEnabled() const { return stencilTestEnable & 1; } // UV gen int getUVGenMode() const { return texmapmode & 3;} // 2 bits diff --git a/android/jni/UIShader.cpp b/android/jni/UIShader.cpp index 6f618de4ed..4fecc16a51 100644 --- a/android/jni/UIShader.cpp +++ b/android/jni/UIShader.cpp @@ -88,10 +88,12 @@ void UIShader_Prepare() glstate.cullFace.disable(); glstate.depthTest.disable(); glstate.scissorTest.disable(); + glstate.stencilTest.disable(); glstate.blend.enable(); glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.colorMask.set(true, true, true, true); glstate.Restore(); uiTexture->Bind(0); diff --git a/native b/native index c60bda83b6..de36ea9f34 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit c60bda83b6871f151921ca818a4ba292714bd7ec +Subproject commit de36ea9f34187172b8da2bbb25d5b0e03027eb2c diff --git a/pspautotests b/pspautotests index 3da47629d4..10821b6c99 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 3da47629d441b8f2f7f92e51e093a8727a3c3811 +Subproject commit 10821b6c99cb3683ac56cb57488f4479caf8c0fa