Merge branch 'master' of github.com:hrydgard/ppsspp

This commit is contained in:
Daniel Dressler 2013-06-20 18:56:53 -07:00
commit eefcc9ba83
55 changed files with 1072 additions and 793 deletions

View file

@ -128,8 +128,8 @@ void CPUInfo::Detect()
// Get the information about the CPU // Get the information about the CPU
num_cores = GetCoreCount(); num_cores = GetCoreCount();
#if defined(__SYMBIAN32__) || defined(BLACKBERRY) || defined(IOS) #if defined(__SYMBIAN32__) || defined(BLACKBERRY) || defined(IOS)
bool isVFP3 = false; bool isVFP3 = false;
bool isVFP4 = false; bool isVFP4 = false;
#ifdef IOS #ifdef IOS
isVFP3 = true; isVFP3 = true;
// TODO: Check for swift arch (VFP4) // TODO: Check for swift arch (VFP4)

View file

@ -20,6 +20,7 @@
#include <cstring> #include <cstring>
#include "ChunkFile.h" #include "ChunkFile.h"
#include "MemoryUtil.h"
// STL-look-a-like interface, but name is mixed case to distinguish it clearly from the // STL-look-a-like interface, but name is mixed case to distinguish it clearly from the
// real STL classes. // real STL classes.
@ -30,11 +31,15 @@ template <class T, int N>
class FixedSizeQueue { class FixedSizeQueue {
public: public:
FixedSizeQueue() { FixedSizeQueue() {
// Allocate aligned memory, just because.
//int sizeInBytes = N * sizeof(T);
//storage_ = (T *)AllocateMemoryPages(sizeInBytes);
storage_ = new T[N]; storage_ = new T[N];
clear(); clear();
} }
~FixedSizeQueue() { ~FixedSizeQueue() {
// FreeMemoryPages((void *)storage_, N * sizeof(T));
delete [] storage_; delete [] storage_;
} }
@ -52,6 +57,45 @@ public:
count_++; count_++;
} }
// Gets pointers to write to directly.
void pushPointers(size_t size, T **dest1, size_t *sz1, T **dest2, size_t *sz2) {
if (tail_ + size < N) {
*dest1 = &storage_[tail_];
*sz1 = size;
tail_ += (int)size;
if (tail_ == N) tail_ = 0;
*dest2 = 0;
*sz2 = 0;
} else {
*dest1 = &storage_[tail_];
*sz1 = N - tail_;
tail_ = (int)(size - *sz1);
*dest2 = &storage_[0];
*sz2 = tail_;
}
count_ += (int)size;
}
void popPointers(size_t size, const T **src1, size_t *sz1, const T **src2, size_t *sz2) {
if (size > count_) size = count_;
if (head_ + size < N) {
*src1 = &storage_[head_];
*sz1 = size;
head_ += (int)size;
if (head_ == N) head_ = 0;
*src2 = 0;
*sz2 = 0;
} else {
*src1 = &storage_[head_];
*sz1 = N - head_;
head_ = (int)(size - *sz1);
*src2 = &storage_[0];
*sz2 = head_;
}
count_ -= (int)size;
}
void pop() { void pop() {
head_++; head_++;
if (head_ == N) if (head_ == N)
@ -125,5 +169,61 @@ private:
FixedSizeQueue(FixedSizeQueue &other) { } FixedSizeQueue(FixedSizeQueue &other) { }
}; };
// I'm not sure this is 100% safe but it might be "Good Enough" :)
// TODO: Use this, maybe make it safer first by using proper atomics
// instead of volatile
template<class T, int blockSize, int numBlocks>
class LockFreeBlockQueue {
public:
LockFreeBlockQueue() {
curReadBlock = 0;
curWriteBlock = 0;
for (size_t i = 0; i < numBlocks; i++) {
blocks[i] = new T[blockSize];
}
}
~LockFreeBlockQueue() {
for (size_t i = 0; i < numBlocks; i++) {
delete [] blocks[i];
}
}
// Write to the returned pointer then call EndPush to finish the push.
T *BeginPush() {
return blocks[curWriteBlock];
}
void EndPush() {
curWriteBlock++;
if (curWriteBlock == NUM_BLOCKS)
curWriteBlock = 0;
}
bool CanPush() {
int nextBlock = curWriteBlock + 1;
if (nextBlock == NUM_BLOCKS) nextBlock = 0;
return nextBlock != curReadBlock;
}
bool CanPop() { return curReadBlock != curWriteBlock; }
// Read from the returned pointer then call EndPush to finish the pop.
T *BeginPop() {
return blocks[curReadBlock];
}
T *EndPop() {
curReadBlock++;
if (curReadBlock == NUM_BLOCKS)
curReadBlock = 0;
}
private:
enum { NUM_BLOCKS = 16 };
T **blocks[NUM_BLOCKS];
volatile int curReadBlock;
volatile int curWriteBlock;
};
#endif // _FIXED_SIZE_QUEUE_H_ #endif // _FIXED_SIZE_QUEUE_H_

View file

@ -124,6 +124,7 @@ void* AllocateExecutableMemory(size_t size, bool low)
void* AllocateMemoryPages(size_t size) void* AllocateMemoryPages(size_t size)
{ {
size = (size + 4095) & (~4095);
#ifdef _WIN32 #ifdef _WIN32
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
#elif defined(__SYMBIAN32__) #elif defined(__SYMBIAN32__)
@ -169,6 +170,7 @@ void* AllocateAlignedMemory(size_t size,size_t alignment)
void FreeMemoryPages(void* ptr, size_t size) void FreeMemoryPages(void* ptr, size_t size)
{ {
size = (size + 4095) & (~4095);
if (ptr) if (ptr)
{ {
#ifdef _WIN32 #ifdef _WIN32

View file

@ -87,7 +87,7 @@ void Config::Load(const char *iniFileName)
cpu->Get("FastMemory", &bFastMemory, false); cpu->Get("FastMemory", &bFastMemory, false);
IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics"); IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics");
graphics->Get("ShowFPSCounter", &bShowFPSCounter, false); graphics->Get("ShowFPSCounter", &iShowFPSCounter, false);
graphics->Get("DisplayFramebuffer", &bDisplayFramebuffer, false); graphics->Get("DisplayFramebuffer", &bDisplayFramebuffer, false);
#ifdef _WIN32 #ifdef _WIN32
graphics->Get("ResolutionScale", &iWindowZoom, 2); graphics->Get("ResolutionScale", &iWindowZoom, 2);
@ -138,15 +138,16 @@ void Config::Load(const char *iniFileName)
control->Get("ForceInputDevice", &iForceInputDevice, -1); control->Get("ForceInputDevice", &iForceInputDevice, -1);
control->Get("RightStickBind", &iRightStickBind, 0); control->Get("RightStickBind", &iRightStickBind, 0);
control->Get("TouchButtonOpacity", &iTouchButtonOpacity, 65); control->Get("TouchButtonOpacity", &iTouchButtonOpacity, 65);
control->Get("ButtonScale", &fButtonScale, 1.15);
IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam"); IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam");
pspConfig->Get("NickName", &sNickName, "shadow"); pspConfig->Get("NickName", &sNickName, "shadow");
pspConfig->Get("Language", &ilanguage, PSP_SYSTEMPARAM_LANGUAGE_ENGLISH); pspConfig->Get("Language", &ilanguage, PSP_SYSTEMPARAM_LANGUAGE_ENGLISH);
pspConfig->Get("TimeFormat", &itimeformat, PSP_SYSTEMPARAM_TIME_FORMAT_24HR); pspConfig->Get("TimeFormat", &iTimeFormat, PSP_SYSTEMPARAM_TIME_FORMAT_24HR);
pspConfig->Get("DateFormat", &iDateFormat, PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD); pspConfig->Get("DateFormat", &iDateFormat, PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD);
pspConfig->Get("TimeZone", &iTimeZone, 0); pspConfig->Get("TimeZone", &iTimeZone, 0);
pspConfig->Get("DayLightSavings", &bDayLightSavings, PSP_SYSTEMPARAM_DAYLIGHTSAVINGS_STD); pspConfig->Get("DayLightSavings", &bDayLightSavings, PSP_SYSTEMPARAM_DAYLIGHTSAVINGS_STD);
pspConfig->Get("ButtonPreference", &bButtonPreference, PSP_SYSTEMPARAM_BUTTON_CROSS); pspConfig->Get("ButtonPreference", &iButtonPreference, PSP_SYSTEMPARAM_BUTTON_CROSS);
pspConfig->Get("LockParentalLevel", &iLockParentalLevel, 0); pspConfig->Get("LockParentalLevel", &iLockParentalLevel, 0);
pspConfig->Get("WlanAdhocChannel", &iWlanAdhocChannel, PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC); pspConfig->Get("WlanAdhocChannel", &iWlanAdhocChannel, PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC);
pspConfig->Get("WlanPowerSave", &bWlanPowerSave, PSP_SYSTEMPARAM_WLAN_POWERSAVE_OFF); pspConfig->Get("WlanPowerSave", &bWlanPowerSave, PSP_SYSTEMPARAM_WLAN_POWERSAVE_OFF);
@ -195,7 +196,7 @@ void Config::Save()
cpu->Set("FastMemory", bFastMemory); cpu->Set("FastMemory", bFastMemory);
IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics"); IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics");
graphics->Set("ShowFPSCounter", bShowFPSCounter); graphics->Set("ShowFPSCounter", iShowFPSCounter);
graphics->Set("DisplayFramebuffer", bDisplayFramebuffer); graphics->Set("DisplayFramebuffer", bDisplayFramebuffer);
graphics->Set("ResolutionScale", iWindowZoom); graphics->Set("ResolutionScale", iWindowZoom);
graphics->Set("BufferedRendering", bBufferedRendering); graphics->Set("BufferedRendering", bBufferedRendering);
@ -232,16 +233,16 @@ void Config::Save()
control->Set("ForceInputDevice", iForceInputDevice); control->Set("ForceInputDevice", iForceInputDevice);
control->Set("RightStickBind", iRightStickBind); control->Set("RightStickBind", iRightStickBind);
control->Set("TouchButtonOpacity", iTouchButtonOpacity); control->Set("TouchButtonOpacity", iTouchButtonOpacity);
control->Set("ButtonScale", fButtonScale);
IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam"); IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam");
pspConfig->Set("NickName", sNickName.c_str()); pspConfig->Set("NickName", sNickName.c_str());
pspConfig->Set("Language", ilanguage); pspConfig->Set("Language", ilanguage);
pspConfig->Set("TimeFormat", itimeformat); pspConfig->Set("TimeFormat", iTimeFormat);
pspConfig->Set("DateFormat", iDateFormat); pspConfig->Set("DateFormat", iDateFormat);
pspConfig->Set("TimeZone", iTimeZone); pspConfig->Set("TimeZone", iTimeZone);
pspConfig->Set("DayLightSavings", bDayLightSavings); pspConfig->Set("DayLightSavings", bDayLightSavings);
pspConfig->Set("ButtonPreference", bButtonPreference); pspConfig->Set("ButtonPreference", iButtonPreference);
pspConfig->Set("LockParentalLevel", iLockParentalLevel); pspConfig->Set("LockParentalLevel", iLockParentalLevel);
pspConfig->Set("WlanAdhocChannel", iWlanAdhocChannel); pspConfig->Set("WlanAdhocChannel", iWlanAdhocChannel);
pspConfig->Set("WlanPowerSave", bWlanPowerSave); pspConfig->Set("WlanPowerSave", bWlanPowerSave);

View file

@ -95,7 +95,7 @@ public:
bool bShowTouchControls; bool bShowTouchControls;
bool bShowDebuggerOnLoad; bool bShowDebuggerOnLoad;
bool bShowAnalogStick; bool bShowAnalogStick;
bool bShowFPSCounter; int iShowFPSCounter;
bool bShowDebugStats; bool bShowDebugStats;
bool bLargeControls; bool bLargeControls;
bool bAccelerometerToAnalogHoriz; bool bAccelerometerToAnalogHoriz;
@ -110,21 +110,24 @@ public:
std::map<int,int> iMappingMap; // Can be used differently depending on systems std::map<int,int> iMappingMap; // Can be used differently depending on systems
int iForceInputDevice; int iForceInputDevice;
int iTouchButtonOpacity; int iTouchButtonOpacity;
float fButtonScale;
// SystemParam // SystemParam
std::string sNickName; std::string sNickName;
int ilanguage; int ilanguage;
int itimeformat; int iTimeFormat;
int iDateFormat; int iDateFormat;
int iTimeZone; int iTimeZone;
bool bDayLightSavings; bool bDayLightSavings;
bool bButtonPreference; bool bButtonPreference;
int iButtonPreference;
int iLockParentalLevel; int iLockParentalLevel;
bool bEncryptSave; bool bEncryptSave;
int iWlanAdhocChannel; int iWlanAdhocChannel;
bool bWlanPowerSave; bool bWlanPowerSave;
std::string currentDirectory; std::string currentDirectory;
std::string externalDirectory;
std::string memCardDirectory; std::string memCardDirectory;
std::string flashDirectory; std::string flashDirectory;
std::string internalDataDirectory; std::string internalDataDirectory;

View file

@ -356,14 +356,24 @@ void PSPSaveDialog::DisplaySaveDataInfo1()
char hour_time[10] ; char hour_time[10] ;
int hour = param.GetFileInfo(currentSelectedSave).modif_time.tm_hour; int hour = param.GetFileInfo(currentSelectedSave).modif_time.tm_hour;
int min = param.GetFileInfo(currentSelectedSave).modif_time.tm_min; int min = param.GetFileInfo(currentSelectedSave).modif_time.tm_min;
if (g_Config.itimeformat == PSP_SYSTEMPARAM_TIME_FORMAT_12HR) { switch (g_Config.iTimeFormat) {
case 1:
if (hour > 12) { if (hour > 12) {
strcpy(am_pm, "PM"); strcpy(am_pm, "PM");
hour -= 12; hour -= 12;
} }
snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm); snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm);
} else break;
snprintf(hour_time,10,"%02d:%02d", hour, min); case 2:
snprintf(hour_time,10,"%02d:%02d", hour, min);
break;
default:
if (hour > 12) {
strcpy(am_pm, "PM");
hour -= 12;
}
snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm);
}
snprintf(title, 512, "%s", param.GetFileInfo(currentSelectedSave).title); snprintf(title, 512, "%s", param.GetFileInfo(currentSelectedSave).title);
int day = param.GetFileInfo(currentSelectedSave).modif_time.tm_mday; int day = param.GetFileInfo(currentSelectedSave).modif_time.tm_mday;
@ -371,14 +381,15 @@ void PSPSaveDialog::DisplaySaveDataInfo1()
int year = param.GetFileInfo(currentSelectedSave).modif_time.tm_year + 1900; int year = param.GetFileInfo(currentSelectedSave).modif_time.tm_year + 1900;
s64 sizeK = param.GetFileInfo(currentSelectedSave).size / 1024; s64 sizeK = param.GetFileInfo(currentSelectedSave).size / 1024;
switch (g_Config.iDateFormat) { switch (g_Config.iDateFormat) {
case PSP_SYSTEMPARAM_DATE_FORMAT_DDMMYYYY: case 1:
snprintf(time, 512, "%02d/%02d/%d %s %lld KB", day, month, year, hour_time, sizeK); snprintf(time, 512, "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK);
break; break;
case PSP_SYSTEMPARAM_DATE_FORMAT_MMDDYYYY: case 2:
snprintf(time, 512, "%02d/%02d/%d %s %lld KB", month, day, year, hour_time, sizeK); snprintf(time, 512, "%02d/%02d/%d %s %lld KB", month, day, year, hour_time, sizeK);
break; break;
case PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD: case 3:
// fall through snprintf(time, 512, "%02d/%02d/%d %s %lld KB", day, month, year, hour_time, sizeK);
break;
default: default:
snprintf(time, 512, "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK); snprintf(time, 512, "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK);
} }
@ -408,14 +419,24 @@ void PSPSaveDialog::DisplaySaveDataInfo2()
char hour_time[10] ; char hour_time[10] ;
int hour = param.GetFileInfo(currentSelectedSave).modif_time.tm_hour; int hour = param.GetFileInfo(currentSelectedSave).modif_time.tm_hour;
int min = param.GetFileInfo(currentSelectedSave).modif_time.tm_min; int min = param.GetFileInfo(currentSelectedSave).modif_time.tm_min;
if (g_Config.itimeformat == PSP_SYSTEMPARAM_TIME_FORMAT_12HR) { switch (g_Config.iTimeFormat) {
case 1:
if (hour > 12) { if (hour > 12) {
strcpy(am_pm, "PM"); strcpy(am_pm, "PM");
hour -= 12; hour -= 12;
} }
snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm); snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm);
} else break;
snprintf(hour_time,10,"%02d:%02d", hour, min); case 2:
snprintf(hour_time,10,"%02d:%02d", hour, min);
break;
default:
if (hour > 12) {
strcpy(am_pm, "PM");
hour -= 12;
}
snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm);
}
const char *saveTitle = param.GetFileInfo(currentSelectedSave).saveTitle; const char *saveTitle = param.GetFileInfo(currentSelectedSave).saveTitle;
int day = param.GetFileInfo(currentSelectedSave).modif_time.tm_mday; int day = param.GetFileInfo(currentSelectedSave).modif_time.tm_mday;
@ -423,14 +444,14 @@ void PSPSaveDialog::DisplaySaveDataInfo2()
int year = param.GetFileInfo(currentSelectedSave).modif_time.tm_year + 1900; int year = param.GetFileInfo(currentSelectedSave).modif_time.tm_year + 1900;
s64 sizeK = param.GetFileInfo(currentSelectedSave).size / 1024; s64 sizeK = param.GetFileInfo(currentSelectedSave).size / 1024;
switch (g_Config.iDateFormat) { switch (g_Config.iDateFormat) {
case PSP_SYSTEMPARAM_DATE_FORMAT_DDMMYYYY: case 1:
snprintf(date, 256, "%02d/%02d/%d", day, month, year); snprintf(date, 256, "%d/%02d/%02d", year, month, day);
break; case 2:
case PSP_SYSTEMPARAM_DATE_FORMAT_MMDDYYYY:
snprintf(date, 256, "%02d/%02d/%d", month, day, year); snprintf(date, 256, "%02d/%02d/%d", month, day, year);
break; break;
case PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD: case 3:
// fall through snprintf(date, 256, "%02d/%02d/%d", day, month, year);
break;
default: default:
snprintf(date, 256, "%d/%02d/%02d", year, month, day); snprintf(date, 256, "%d/%02d/%02d", year, month, day);
} }

View file

@ -34,19 +34,18 @@ BlockDevice *constructBlockDevice(const char *filename) {
return 0; return 0;
char buffer[4]; char buffer[4];
auto size = fread(buffer, 1, 4, f); //size_t auto size = fread(buffer, 1, 4, f); //size_t
fclose(f); fseek(f, 0, SEEK_SET);
if (!memcmp(buffer, "CISO", 4) && size == 4) if (!memcmp(buffer, "CISO", 4) && size == 4)
return new CISOFileBlockDevice(filename); return new CISOFileBlockDevice(f);
else if (!memcmp(buffer, "\x00PBP", 4) && size == 4) else if (!memcmp(buffer, "\x00PBP", 4) && size == 4)
return new NPDRMDemoBlockDevice(filename); return new NPDRMDemoBlockDevice(f);
else else
return new FileBlockDevice(filename); return new FileBlockDevice(f);
} }
FileBlockDevice::FileBlockDevice(std::string _filename) FileBlockDevice::FileBlockDevice(FILE *file)
: filename(_filename) : f(file)
{ {
f = fopen(_filename.c_str(), "rb");
fseek(f,0,SEEK_END); fseek(f,0,SEEK_END);
filesize = ftell(f); filesize = ftell(f);
fseek(f,0,SEEK_SET); fseek(f,0,SEEK_SET);
@ -94,12 +93,12 @@ typedef struct ciso_header
// TODO: Need much better error handling. // TODO: Need much better error handling.
CISOFileBlockDevice::CISOFileBlockDevice(std::string _filename) CISOFileBlockDevice::CISOFileBlockDevice(FILE *file)
: filename(_filename) : f(file)
{ {
// CISO format is EXTREMELY crappy and incomplete. All tools make broken CISO. // CISO format is EXTREMELY crappy and incomplete. All tools make broken CISO.
f = fopen(_filename.c_str(), "rb"); f = file;
CISO_H hdr; CISO_H hdr;
size_t readSize = fread(&hdr, sizeof(CISO_H), 1, f); size_t readSize = fread(&hdr, sizeof(CISO_H), 1, f);
if (readSize != 1 || memcmp(hdr.magic, "CISO", 4) != 0) if (readSize != 1 || memcmp(hdr.magic, "CISO", 4) != 0)
@ -206,8 +205,8 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)
} }
NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(std::string _filename) NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FILE *file)
: filename_(_filename) : f(file)
{ {
MAC_KEY mkey; MAC_KEY mkey;
CIPHER_KEY ckey; CIPHER_KEY ckey;
@ -215,8 +214,6 @@ NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(std::string _filename)
u32 tableOffset, tableSize; u32 tableOffset, tableSize;
u32 lbaStart, lbaEnd; u32 lbaStart, lbaEnd;
f = fopen(_filename.c_str(), "rb");
fseek(f, 0x24, SEEK_SET); fseek(f, 0x24, SEEK_SET);
fread(&psarOffset, 1, 4, f); fread(&psarOffset, 1, 4, f);
fseek(f, psarOffset, SEEK_SET); fseek(f, psarOffset, SEEK_SET);

View file

@ -39,13 +39,12 @@ public:
class CISOFileBlockDevice : public BlockDevice class CISOFileBlockDevice : public BlockDevice
{ {
public: public:
CISOFileBlockDevice(std::string _filename); CISOFileBlockDevice(FILE *file);
~CISOFileBlockDevice(); ~CISOFileBlockDevice();
bool ReadBlock(int blockNumber, u8 *outPtr); bool ReadBlock(int blockNumber, u8 *outPtr);
u32 GetNumBlocks() { return numBlocks;} u32 GetNumBlocks() { return numBlocks;}
private: private:
std::string filename;
FILE *f; FILE *f;
u32 *index; u32 *index;
int indexShift; int indexShift;
@ -57,13 +56,12 @@ private:
class FileBlockDevice : public BlockDevice class FileBlockDevice : public BlockDevice
{ {
public: public:
FileBlockDevice(std::string _filename); FileBlockDevice(FILE *file);
~FileBlockDevice(); ~FileBlockDevice();
bool ReadBlock(int blockNumber, u8 *outPtr); bool ReadBlock(int blockNumber, u8 *outPtr);
u32 GetNumBlocks() {return (u32)(filesize / GetBlockSize());} u32 GetNumBlocks() {return (u32)(filesize / GetBlockSize());}
private: private:
std::string filename;
FILE *f; FILE *f;
size_t filesize; size_t filesize;
}; };
@ -82,14 +80,13 @@ struct table_info {
class NPDRMDemoBlockDevice : public BlockDevice class NPDRMDemoBlockDevice : public BlockDevice
{ {
public: public:
NPDRMDemoBlockDevice(std::string _filename); NPDRMDemoBlockDevice(FILE *file);
~NPDRMDemoBlockDevice(); ~NPDRMDemoBlockDevice();
bool ReadBlock(int blockNumber, u8 *outPtr); bool ReadBlock(int blockNumber, u8 *outPtr);
u32 GetNumBlocks() {return (u32)lbaSize;} u32 GetNumBlocks() {return (u32)lbaSize;}
private: private:
std::string filename_;
FILE *f; FILE *f;
u32 lbaSize; u32 lbaSize;

View file

@ -47,6 +47,8 @@ const int audioHostIntervalUs = (int)(1000000ULL * hostAttemptBlockSize / hwSamp
const int chanQueueMaxSizeFactor = 2; const int chanQueueMaxSizeFactor = 2;
const int chanQueueMinSizeFactor = 1; const int chanQueueMinSizeFactor = 1;
// TODO: Need to replace this with something lockless. Mutexes in the audio pipeline
// is bad mojo.
FixedSizeQueue<s16, hostAttemptBlockSize * 16> outAudioQueue; FixedSizeQueue<s16, hostAttemptBlockSize * 16> outAudioQueue;
static inline s16 clamp_s16(int i) { static inline s16 clamp_s16(int i) {
@ -70,6 +72,8 @@ void hleAudioUpdate(u64 userdata, int cyclesLate)
void hleHostAudioUpdate(u64 userdata, int cyclesLate) void hleHostAudioUpdate(u64 userdata, int cyclesLate)
{ {
// Not all hosts need this call to poke their audio system once in a while, but those that don't
// can just ignore it.
host->UpdateSound(); host->UpdateSound();
CoreTiming::ScheduleEvent(usToCycles(audioHostIntervalUs) - cyclesLate, eventHostAudioUpdate, 0); CoreTiming::ScheduleEvent(usToCycles(audioHostIntervalUs) - cyclesLate, eventHostAudioUpdate, 0);
} }
@ -166,10 +170,33 @@ u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking)
// Walking a pointer for speed. But let's make sure we wouldn't trip on an invalid ptr. // Walking a pointer for speed. But let's make sure we wouldn't trip on an invalid ptr.
if (Memory::IsValidAddress(chan.sampleAddress + (totalSamples - 1) * sizeof(s16))) if (Memory::IsValidAddress(chan.sampleAddress + (totalSamples - 1) * sizeof(s16)))
{ {
#if 0
for (u32 i = 0; i < totalSamples; i += 2) { for (u32 i = 0; i < totalSamples; i += 2) {
chan.sampleQueue.push(adjustvolume(*sampleData++, chan.leftVolume)); chan.sampleQueue.push(adjustvolume(*sampleData++, chan.leftVolume));
chan.sampleQueue.push(adjustvolume(*sampleData++, chan.rightVolume)); chan.sampleQueue.push(adjustvolume(*sampleData++, chan.rightVolume));
} }
#else
s16 *buf1 = 0, *buf2 = 0;
size_t sz1, sz2;
chan.sampleQueue.pushPointers(totalSamples, &buf1, &sz1, &buf2, &sz2);
int leftVol = chan.leftVolume;
int rightVol = chan.rightVolume;
// TODO: SSE/NEON implementations
for (u32 i = 0; i < sz1; i += 2)
{
buf1[i] = adjustvolume(sampleData[i], leftVol);
buf1[i + 1] = adjustvolume(sampleData[i + 1], rightVol);
}
if (buf2) {
sampleData += sz1;
for (u32 i = 0; i < sz2; i += 2)
{
buf2[i] = adjustvolume(sampleData[i], leftVol);
buf2[i + 1] = adjustvolume(sampleData[i + 1], rightVol);
}
}
#endif
} }
} }
else else
@ -227,56 +254,74 @@ void __AudioWakeThreads(AudioChannel &chan, int result)
__AudioWakeThreads(chan, result, 0x7FFFFFFF); __AudioWakeThreads(chan, result, 0x7FFFFFFF);
} }
void __AudioSetOutputFrequency(int freq)
{
WARN_LOG(HLE, "Switching audio frequency to %i", freq);
mixFrequency = freq;
}
// Mix samples from the various audio channels into a single sample queue. // Mix samples from the various audio channels into a single sample queue.
// This single sample queue is where __AudioMix should read from. If the sample queue is full, we should // This single sample queue is where __AudioMix should read from. If the sample queue is full, we should
// just sleep the main emulator thread a little. // just sleep the main emulator thread a little.
void __AudioUpdate() void __AudioUpdate() {
{
// Audio throttle doesn't really work on the PSP since the mixing intervals are so closely tied // Audio throttle doesn't really work on the PSP since the mixing intervals are so closely tied
// to the CPU. Much better to throttle the frame rate on frame display and just throw away audio // to the CPU. Much better to throttle the frame rate on frame display and just throw away audio
// if the buffer somehow gets full. // if the buffer somehow gets full.
s32 mixBuffer[hwBlockSize * 2]; s32 mixBuffer[hwBlockSize * 2];
memset(mixBuffer, 0, sizeof(mixBuffer)); bool firstChannel = true;
for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++) for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++) {
{
if (!chans[i].reserved) if (!chans[i].reserved)
continue; continue;
__AudioWakeThreads(chans[i], 0, hwBlockSize); __AudioWakeThreads(chans[i], 0, hwBlockSize);
if (!chans[i].sampleQueue.size()) { if (!chans[i].sampleQueue.size()) {
// ERROR_LOG(HLE, "No queued samples, skipping channel %i", i);
continue; continue;
} }
for (int s = 0; s < hwBlockSize; s++) if (hwBlockSize * 2 > chans[i].sampleQueue.size()) {
{ ERROR_LOG(HLE, "Channel %i buffer underrun at %i of %i", i, (int)chans[i].sampleQueue.size() / 2, hwBlockSize);
if (chans[i].sampleQueue.size() >= 2) }
{
s16 sampleL = chans[i].sampleQueue.pop_front(); const s16 *buf1 = 0, *buf2 = 0;
s16 sampleR = chans[i].sampleQueue.pop_front(); size_t sz1, sz2;
mixBuffer[s * 2 + 0] += sampleL;
mixBuffer[s * 2 + 1] += sampleR; chans[i].sampleQueue.popPointers(hwBlockSize * 2, &buf1, &sz1, &buf2, &sz2);
}
else if (firstChannel) {
{ for (int s = 0; s < sz1; s++)
ERROR_LOG(HLE, "Channel %i buffer underrun at %i of %i", i, s, hwBlockSize); mixBuffer[s] = buf1[s];
break; if (buf2) {
for (int s = 0; s < sz2; s++)
mixBuffer[s + sz1] = buf2[s];
}
firstChannel = false;
} else {
for (int s = 0; s < sz1; s++)
mixBuffer[s] += buf1[s];
if (buf2) {
for (int s = 0; s < sz2; s++)
mixBuffer[s + sz1] += buf2[s];
} }
} }
} }
if (firstChannel) {
memset(mixBuffer, 0, sizeof(mixBuffer));
}
if (g_Config.bEnableSound) { if (g_Config.bEnableSound) {
lock_guard guard(section); lock_guard guard(section);
if (outAudioQueue.room() >= hwBlockSize * 2) { if (outAudioQueue.room() >= hwBlockSize * 2) {
// Push the mixed samples onto the output audio queue. s16 *buf1 = 0, *buf2 = 0;
for (int i = 0; i < hwBlockSize; i++) { size_t sz1, sz2;
s16 sampleL = clamp_s16(mixBuffer[i * 2 + 0]); outAudioQueue.pushPointers(hwBlockSize * 2, &buf1, &sz1, &buf2, &sz2);
s16 sampleR = clamp_s16(mixBuffer[i * 2 + 1]); for (int s = 0; s < sz1; s++)
buf1[s] = clamp_s16(mixBuffer[s]);
outAudioQueue.push((s16)sampleL); if (buf2) {
outAudioQueue.push((s16)sampleR); for (int s = 0; s < sz2; s++)
buf2[s] = clamp_s16(mixBuffer[s + sz1]);
} }
} else { } else {
// This happens quite a lot. There's still something slightly off // This happens quite a lot. There's still something slightly off
@ -284,13 +329,6 @@ void __AudioUpdate()
DEBUG_LOG(HLE, "Audio outbuffer overrun! room = %i / %i", outAudioQueue.room(), (u32)outAudioQueue.capacity()); DEBUG_LOG(HLE, "Audio outbuffer overrun! room = %i / %i", outAudioQueue.room(), (u32)outAudioQueue.capacity());
} }
} }
}
void __AudioSetOutputFrequency(int freq)
{
WARN_LOG(HLE, "Switching audio frequency to %i", freq);
mixFrequency = freq;
} }
// numFrames is number of stereo frames. // numFrames is number of stereo frames.
@ -298,28 +336,28 @@ void __AudioSetOutputFrequency(int freq)
int __AudioMix(short *outstereo, int numFrames) int __AudioMix(short *outstereo, int numFrames)
{ {
// TODO: if mixFrequency != the actual output frequency, resample! // TODO: if mixFrequency != the actual output frequency, resample!
lock_guard guard(section);
int underrun = -1; int underrun = -1;
s16 sampleL = 0; s16 sampleL = 0;
s16 sampleR = 0; s16 sampleR = 0;
bool anythingToPlay = false;
for (int i = 0; i < numFrames; i++) { const s16 *buf1 = 0, *buf2 = 0;
if (outAudioQueue.size() >= 2) { size_t sz1, sz2;
sampleL = outAudioQueue.pop_front(); {
sampleR = outAudioQueue.pop_front(); lock_guard guard(section);
outstereo[i * 2 + 0] = sampleL; outAudioQueue.popPointers(numFrames * 2, &buf1, &sz1, &buf2, &sz2);
outstereo[i * 2 + 1] = sampleR; memcpy(outstereo, buf1, sz1 * sizeof(s16));
anythingToPlay = true; if (buf2) {
} else { memcpy(outstereo + sz1, buf2, sz2 * sizeof(s16));
if (underrun == -1) underrun = i;
outstereo[i * 2 + 0] = sampleL; // repeat last sample, can reduce clicking
outstereo[i * 2 + 1] = sampleR; // repeat last sample, can reduce clicking
} }
} }
if (anythingToPlay && underrun >= 0) {
int remains = (int)(numFrames * 2 - sz1 - sz2);
if (remains > 0)
memset(outstereo + numFrames * 2 - remains, 0, remains);
if (sz1 + sz2 < numFrames) {
underrun = (int)(sz1 + sz2) / 2;
DEBUG_LOG(HLE, "Audio out buffer UNDERRUN at %i of %i", underrun, numFrames); DEBUG_LOG(HLE, "Audio out buffer UNDERRUN at %i of %i", underrun, numFrames);
} else {
// DEBUG_LOG(HLE, "No underrun, mixed %i samples fine", numFrames);
} }
return underrun >= 0 ? underrun : numFrames; return underrun >= 0 ? underrun : numFrames;
} }

View file

@ -339,6 +339,7 @@ int createAtrac(Atrac *atrac, int codecType) {
for (int i = 0; i < (int)ARRAY_SIZE(atracIDs); ++i) { for (int i = 0; i < (int)ARRAY_SIZE(atracIDs); ++i) {
if (atracIDTypes[i] == codecType && atracIDs[i] == 0) { if (atracIDTypes[i] == codecType && atracIDs[i] == 0) {
atracIDs[i] = atrac; atracIDs[i] = atrac;
atrac->atracID = i;
return i; return i;
} }
} }
@ -483,7 +484,7 @@ void Atrac::Analyze()
} }
u32 sceAtracGetAtracID(int codecType) { u32 sceAtracGetAtracID(int codecType) {
if (codecType != PSP_MODE_AT_3 && codecType > PSP_MODE_AT_3_PLUS) { if (codecType != PSP_MODE_AT_3 && codecType != PSP_MODE_AT_3_PLUS) {
ERROR_LOG_REPORT(HLE, "sceAtracGetAtracID(%i): invalid codecType", codecType); ERROR_LOG_REPORT(HLE, "sceAtracGetAtracID(%i): invalid codecType", codecType);
return ATRAC_ERROR_INVALID_CODECTYPE; return ATRAC_ERROR_INVALID_CODECTYPE;
} }
@ -527,7 +528,7 @@ u32 _AtracAddStreamData(int atracID, u8 *buf, u32 bytesToAdd) {
// because that function would tell games how to add the left stream data. // because that function would tell games how to add the left stream data.
u32 sceAtracAddStreamData(int atracID, u32 bytesToAdd) u32 sceAtracAddStreamData(int atracID, u32 bytesToAdd)
{ {
INFO_LOG(HLE, "sceAtracAddStreamData(%i, %08x)", atracID, bytesToAdd); DEBUG_LOG(HLE, "sceAtracAddStreamData(%i, %08x)", atracID, bytesToAdd);
Atrac *atrac = getAtrac(atracID); Atrac *atrac = getAtrac(atracID);
if (!atrac) { if (!atrac) {
return 0; return 0;
@ -579,7 +580,11 @@ u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int
if (avret < 0) { if (avret < 0) {
ERROR_LOG(HLE, "avcodec_decode_audio4: Error decoding audio %d", avret); ERROR_LOG(HLE, "avcodec_decode_audio4: Error decoding audio %d", avret);
av_free_packet(&packet); av_free_packet(&packet);
break; // Avoid getting stuck in a loop (Virtua Tennis)
*SamplesNum = 0;
*finish = 1;
*remains = 0;
return ATRAC_ERROR_ALL_DATA_DECODED;
} }
if (got_frame) { if (got_frame) {

View file

@ -27,321 +27,217 @@ extern "C"
u8 dataBuf[2048+20]; u8 dataBuf[2048+20];
u8* dataBuf2 = dataBuf + 20; u8* dataBuf2 = dataBuf + 20;
static const u8 hash198C[16] = {0xFA, 0xAA, 0x50, 0xEC, 0x2F, 0xDE, 0x54, 0x93, 0xAD, 0x14, 0xB2, 0xCE, 0xA5, 0x30, 0x05, 0xDF }; static const u8 hash198C[16] = {0xFA, 0xAA, 0x50, 0xEC, 0x2F, 0xDE, 0x54, 0x93, 0xAD, 0x14, 0xB2, 0xCE, 0xA5, 0x30, 0x05, 0xDF};
static const u8 hash19BC[16] = {0xCB, 0x15, 0xF4, 0x07, 0xF9, 0x6A, 0x52, 0x3C, 0x04, 0xB9, 0xB2, 0xEE, 0x5C, 0x53, 0xFA, 0x86 }; static const u8 hash19BC[16] = {0xCB, 0x15, 0xF4, 0x07, 0xF9, 0x6A, 0x52, 0x3C, 0x04, 0xB9, 0xB2, 0xEE, 0x5C, 0x53, 0xFA, 0x86};
static const u8 key000019CC[16] = {0x70, 0x44, 0xA3, 0xAE, 0xEF, 0x5D, 0xA5, 0xF2, 0x85, 0x7F, 0xF2, 0xD6, 0x94, 0xF5, 0x36, 0x3B}; static const u8 key19CC[16] = {0x70, 0x44, 0xA3, 0xAE, 0xEF, 0x5D, 0xA5, 0xF2, 0x85, 0x7F, 0xF2, 0xD6, 0x94, 0xF5, 0x36, 0x3B};
static const u8 key000019DC[16] = {0xEC, 0x6D, 0x29, 0x59, 0x26, 0x35, 0xA5, 0x7F, 0x97, 0x2A, 0x0D, 0xBC, 0xA3, 0x26, 0x33, 0x00}; static const u8 key19DC[16] = {0xEC, 0x6D, 0x29, 0x59, 0x26, 0x35, 0xA5, 0x7F, 0x97, 0x2A, 0x0D, 0xBC, 0xA3, 0x26, 0x33, 0x00};
static const u8 key0000199C[16] = {0x36, 0xA5, 0x3E, 0xAC, 0xC5, 0x26, 0x9E, 0xA3, 0x83, 0xD9, 0xEC, 0x25, 0x6C, 0x48, 0x48, 0x72}; static const u8 key199C[16] = {0x36, 0xA5, 0x3E, 0xAC, 0xC5, 0x26, 0x9E, 0xA3, 0x83, 0xD9, 0xEC, 0x25, 0x6C, 0x48, 0x48, 0x72};
static const u8 key000019AC[16] = {0xD8, 0xC0, 0xB0, 0xF3, 0x3E, 0x6B, 0x76, 0x85, 0xFD, 0xFB, 0x4D, 0x7D, 0x45, 0x1E, 0x92, 0x03}; static const u8 key19AC[16] = {0xD8, 0xC0, 0xB0, 0xF3, 0x3E, 0x6B, 0x76, 0x85, 0xFD, 0xFB, 0x4D, 0x7D, 0x45, 0x1E, 0x92, 0x03};
int sub_000014BC(u8* data, int length) void *memxor(void * dest, const void * src, size_t n)
{ {
*(s32*)(data + 0) = 5; char const *s = (char const*)src;
*(s32*)(data + 12) = 256; char *d = (char*)dest;
*(s32*)(data + 4) = 0;
*(s32*)(data + 8) = 0; for (; n > 0; n--)
*(s32*)(data + 16) = length; *d++ ^= *s++;
int res = sceUtilsBufferCopyWithRange(data, length + 20, data, length + 20, 8);
if (res == 0) return dest;
return 0;
return -258;
} }
int sub_00001418(u8* data, int length, int val2) // The reason for the values from *FromMode calculations are not known.
int numFromMode(int mode)
{ {
*(s32*)(data + 12) = val2;
*(s32*)(data + 0) = 5;
*(s32*)(data + 4) = 0;
*(s32*)(data + 8) = 0;
*(s32*)(data + 16) = length;
int res = sceUtilsBufferCopyWithRange(data, length + 20, data, length + 20, 7);
if (res == 0)
return 0;
return -257;
}
int sub_000015B0(u8* data, int alignedLen, u8* buf, int val)
{
u8 sp0[16];
for(int i = 0; i < 16; i++)
{
sp0[i] = data[alignedLen+i+4];
}
int res = sub_00001418(data, alignedLen, val);
if (res != 0)
{
return res;
}
for(int i = 0; i < 16; i++)
{
data[i] = data[i] ^ buf[i];
}
for(int i = 0; i < 16; i++)
{
buf[i] = sp0[i];
}
return 0;
}
int sub_00000000(u8* data_out, u8* data, int alignedLen, u8* data2, int& data3, int mode)
{
for(int i = 0; i < 16; i++)
{
data_out[20+i] = data2[i];
}
int valS4 = 100;
int res;
if (mode == 6)
{
valS4 = 100;
for(int i = 0; i < 16; i++)
{
data_out[20+i] = data_out[20+i] ^ key000019DC[i];
}
res = sub_000014BC(data_out, 16);
for(int i = 0; i < 16; i++)
{
data_out[i] = data_out[i] ^ key000019CC[i];
}
}
else if (mode == 4)
{
valS4 = 87;
for(int i = 0; i < 16; i++)
{
data_out[20+i] = data_out[20+i] ^ key000019AC[i];
}
res = sub_000014BC(data_out, 16);
for(int i = 0; i < 16; i++)
{
data_out[i] = data_out[i] ^ key0000199C[i];
}
}
else if (mode == 2)
{
res = sub_000014BC(data_out, 16);
valS4 = 83;
}
else if (mode == 1)
{
res = sub_00001418(data_out, 16, 4);
valS4 = 83;
}
else if (mode == 3)
{
valS4 = 87;
for(int i = 0; i < 16; i++)
{
data_out[i+20] = data_out[i+20] ^ key000019AC[i];
}
res = sub_00001418(data_out, 16, 14);
for(int i = 0; i < 16; i++)
{
data_out[i] = data_out[i] ^ key0000199C[i];
}
}
else
{
valS4 = 100;
for(int i = 0; i < 16; i++)
{
data_out[i + 20] = data_out[i + 20] ^ key000019DC[i];
}
res = sub_00001418(data_out, 16, 18);
for(int i = 0; i < 16; i++)
{
data_out[i] = data_out[i] ^ key000019CC[i];
}
}
u8 sp16[16];
if (res != 0)
{
return res;
}
for(int i = 0; i < 16; i++)
{
sp16[i] = data_out[i];
}
u8 sp0[16];
if (data3 == 1)
{
for(int i = 0; i < 16; i++)
{
sp0[i] = 0;
}
}
else
{
for(int i = 0; i < 12; i++)
{
sp0[i] = sp16[i];
}
sp0[12] = (data3-1) & 0xFF ;
sp0[13] = ((data3-1) >> 8) & 0xFF;
sp0[14] = ((data3-1) >> 16) & 0xFF;
sp0[15] = ((data3-1) >> 24) & 0xFF;
}
if ((u32)20 < (u32)alignedLen + 20)
{
for(int i = 20; i < alignedLen + 20; i += 16)
{
for(int j = 0; j < 12; j++)
{
data_out[i+j] = sp16[j];
}
data_out[12+i] = data3;
data_out[13+i] = (data3 >> 8) & 0xFF;
data_out[14+i] = (data3 >> 16) & 0xFF;
data_out[15+i] = (data3 >> 24) & 0xFF;
data3++;
}
}
res = sub_000015B0(data_out, alignedLen, sp0, valS4);
if (res != 0)
{
return res;
}
if (res >= alignedLen)
{
return 0;
}
for(int i = 0; i < alignedLen; i++)
{
data[i] = data[i] ^ data_out[i];
}
return 0;
}
int sub_000013C8(u8* data, int size, int num)
{
*(int*)(data+0) = 4;
*(int*)(data+4) = 0;
*(int*)(data+8) = 0;
*(int*)(data+12) = num;
*(int*)(data+16) = size;
size = size + 20;
int res = sceUtilsBufferCopyWithRange(data,size,data,size,4);
if(res != 0)
{
return -257;
}
return 0;
}
int sub_00001468(u8* data, int size)
{
*(int*)(data+0) = 4;
*(int*)(data+12) = 256;
*(int*)(data+4) = 0;
*(int*)(data+8) = 0;
*(int*)(data+16) = size;
size = size + 20;
int res = sceUtilsBufferCopyWithRange(data,size,data,size,5);
if(res != 0)
{
return -258;
}
return 0;
}
int sub_00001510(u8* data, int size, u8* result , int num)
{
for(int i = 0; i < 16; i++)
{
int v1 = data[i+20];
v1 = v1 ^ result[i];
data[i+20] = v1;
}
int res = sub_000013C8(data, size, num);
if(res != 0)
{
return res;
}
for(int i = 0; i < 16; i++)
{
result[i] = data[size + i + 4];
}
return 0;
}
int sub_000017A8(u8* data)
{
int res = sceUtilsBufferCopyWithRange(data, 20, 0, 0, 14);
if (res == 0)
return 0;
return -261;
}
int sceSdGetLastIndex(u32 addressCtx,u32 addressHash, u32 addressKey)
{
pspChnnlsvContext1 ctx;
Memory::ReadStruct(addressCtx,&ctx);
u8* in_hash;
u8* in_key;
in_hash = Memory::GetPointer(addressHash);
in_key = Memory::GetPointer(addressKey);
int res = sceSdGetLastIndex_(ctx, in_hash, in_key);
Memory::WriteStruct(addressCtx,&ctx);
return res;
}
int sceSdGetLastIndex_(pspChnnlsvContext1& ctx, u8* in_hash, u8* in_key)
{
if(ctx.keyLength >= 17)
{
return -1026;
}
int num = 0; int num = 0;
switch(ctx.mode) switch(mode)
{ {
case 6: case 1:
num = 17; num = 3;
break;
case 4:
num = 13;
break; break;
case 2: case 2:
num = 5; num = 5;
break; break;
case 1:
num = 3;
break;
case 3: case 3:
num = 12; num = 12;
break; break;
case 4:
num = 13;
break;
case 6:
num = 17;
break;
default: default:
num = 16; num = 16;
break; break;
} }
return num;
}
int numFromMode2(int mode)
{
int num = 18;
if (mode == 1)
num = 4;
else if (mode == 3)
num = 14;
return num;
}
memset(dataBuf2,0,16); int typeFromMode(int mode)
{
return (mode == 1 || mode == 2) ? 83 :
((mode == 3 || mode == 4) ? 87 : 100);
}
int res = sub_000013C8(dataBuf,16,num); int kirkSendCmd(u8* data, int length, int num, bool encrypt)
if(res != 0) {
{ *(int*)(data+0) = encrypt ? KIRK_MODE_ENCRYPT_CBC : KIRK_MODE_DECRYPT_CBC;
*(int*)(data+4) = 0;
*(int*)(data+8) = 0;
*(int*)(data+12) = num;
*(int*)(data+16) = length;
if (sceUtilsBufferCopyWithRange(data, length + 20, data, length + 20, encrypt ? KIRK_CMD_ENCRYPT_IV_0 : KIRK_CMD_DECRYPT_IV_0))
return -257;
return 0;
}
int kirkSendFuseCmd(u8* data, int length, bool encrypt)
{
*(int*)(data+0) = encrypt ? KIRK_MODE_ENCRYPT_CBC : KIRK_MODE_DECRYPT_CBC;
*(int*)(data+4) = 0;
*(int*)(data+8) = 0;
*(int*)(data+12) = 256;
*(int*)(data+16) = length;
// Note: CMD 5 and 8 are not available, will always return -1
if (sceUtilsBufferCopyWithRange(data, length + 20, data, length + 20, encrypt ? KIRK_CMD_ENCRYPT_IV_FUSE : KIRK_CMD_DECRYPT_IV_FUSE))
return -258;
return 0;
}
int sub_15B0(u8* data, int alignedLen, u8* buf, int val)
{
u8 sp0[16];
memcpy(sp0, data+alignedLen+4, 16);
int res = kirkSendCmd(data, alignedLen, val, false);
if (res)
return res; return res;
memxor(data, buf, 16);
memcpy(buf, sp0, 16);
return 0;
}
int sub_0000(u8* data_out, u8* data, int alignedLen, u8* data2, int& data3, int mode)
{
memcpy(data_out+20, data2, 16);
// Mode 1:2 is 83, 3:4 is 87, 5:6 is 100
int type = typeFromMode(mode);
int res;
if (type == 87)
memxor(data_out+20, key19AC, 16);
else if (type == 100)
memxor(data_out+20, key19DC, 16);
// Odd is Cmd, Even is FuseCmd
switch(mode)
{
case 2: case 4: case 6: res = kirkSendFuseCmd(data_out, 16, false);
break;
case 1: case 3: default:res = kirkSendCmd(data_out, 16, numFromMode2(mode), false);
break;
} }
u8 data1[16]; if (type == 87)
u8 data2[16]; memxor(data_out, key199C, 16);
else if (type == 100)
memxor(data_out, key19CC, 16);
memcpy(data1,dataBuf2,16); if (res)
int tmp1 = 0; return res;
if((s8)data1[0] < 0)
tmp1 = 135; u8 sp0[16], sp16[16];
memcpy(sp16, data_out, 16);
if (data3 == 1)
{
memset(sp0, 0, 16);
}
else
{
memcpy(sp0, sp16, 12);
*(u32*)(sp0+12) = data3-1;
}
if (alignedLen > 0)
{
for(int i = 20; i < alignedLen + 20; i += 16)
{
memcpy(data_out+i, sp16, 12);
*(u32*)(data_out+12+i) = data3;
data3++;
}
}
res = sub_15B0(data_out, alignedLen, sp0, type);
if (res)
return res;
if (alignedLen > 0)
memxor(data, data_out, alignedLen);
return 0;
}
int sub_1510(u8* data, int size, u8* result , int num)
{
memxor(data+20, result, 16);
int res = kirkSendCmd(data, size, num, true);
if(res)
return res;
memcpy(result, data+size+4, 16);
return 0;
}
int sub_17A8(u8* data)
{
if (sceUtilsBufferCopyWithRange(data, 20, 0, 0, 14) == 0)
return 0;
return -261;
}
int sceSdGetLastIndex(u32 addressCtx, u32 addressHash, u32 addressKey)
{
pspChnnlsvContext1 ctx;
Memory::ReadStruct(addressCtx, &ctx);
int res = sceSdGetLastIndex_(ctx, Memory::GetPointer(addressHash), Memory::GetPointer(addressKey));
Memory::WriteStruct(addressCtx, &ctx);
return res;
}
int sceSdGetLastIndex_(pspChnnlsvContext1& ctx, u8* in_hash, u8* in_key)
{
if(ctx.keyLength >= 17)
return -1026;
int num = numFromMode(ctx.mode);
memset(dataBuf2, 0, 16);
int res = kirkSendCmd(dataBuf, 16, num, true);
if(res)
return res;
u8 data1[16], data2[16];
memcpy(data1, dataBuf2, 16);
int tmp1 = (data1[0] & 0x80) ? 135 : 0;
for(int i = 0; i < 15; i++) for(int i = 0; i < 15; i++)
{ {
@ -373,72 +269,37 @@ int sceSdGetLastIndex_(pspChnnlsvContext1& ctx, u8* in_hash, u8* in_key)
int oldKeyLength = ctx.keyLength; int oldKeyLength = ctx.keyLength;
*(s8*)(ctx.key + ctx.keyLength) = -128; *(s8*)(ctx.key + ctx.keyLength) = -128;
if(oldKeyLength + 1 < 16) int i = oldKeyLength + 1;
{ if(i < 16)
for(int i = oldKeyLength + 1; i < 16; i++) memset(ctx.key + i, 0, 16 - i);
{
*(s8*)(ctx.key + i) = 0;
}
}
} }
for(int i = 0; i < 16; i++) memxor(ctx.key, data1, 16);
{ memcpy(dataBuf2, ctx.key, 16);
ctx.key[i] = ctx.key[i] ^ data1[i]; memcpy(data2, ctx.result, 16);
}
for(int i = 0; i < 16; i++) int ret = sub_1510(dataBuf, 16, data2, num);
{ if(ret)
dataBuf2[i] = ctx.key[i];
}
for(int i = 0; i < 16; i++)
{
data2[i] = ctx.result[i];
}
int ret = sub_00001510(dataBuf,16,data2,num);
if(ret != 0)
{
return ret; return ret;
}
if((u32)(ctx.mode-3) < 2) if(ctx.mode == 3 || ctx.mode == 4)
{ memxor(data2, hash198C, 16);
for(int i = 0; i < 16; i++) else if(ctx.mode == 5 || ctx.mode == 6)
{ memxor(data2, hash19BC, 16);
data2[i] = data2[i] ^ hash198C[i];
}
}
else if((u32)(ctx.mode-5) < 2)
{
for(int i = 0; i < 16; i++)
{
data2[i] = data2[i] ^ hash19BC[i];
}
}
int cond = ((ctx.mode ^ 0x2) < 1 || (ctx.mode ^ 0x4) < 1 || ctx.mode == 6); int cond = ((ctx.mode ^ 0x2) < 1 || (ctx.mode ^ 0x4) < 1 || ctx.mode == 6);
if(cond != 0) if(cond != 0)
{ {
for(int i = 0; i < 16; i++) memcpy(dataBuf2, data2, 16);
{ int ret = kirkSendFuseCmd(dataBuf, 16, true);
dataBuf2[i] = data2[i]; if(ret)
}
int ret = sub_00001468(dataBuf,16);
if(ret != 0)
{
return ret; return ret;
}
int res = sub_000013C8(dataBuf,16,num);
if(res != 0)
{
return res;
}
for(int i = 0; i < 16; i++) int res = kirkSendCmd(dataBuf, 16, num, true);
{ if(res)
data2[i] = dataBuf2[i]; return res;
}
memcpy(data2, dataBuf2, 16);
} }
if(in_key != 0) if(in_key != 0)
@ -448,37 +309,16 @@ int sceSdGetLastIndex_(pspChnnlsvContext1& ctx, u8* in_hash, u8* in_key)
data2[i] = in_key[i] ^ data2[i]; data2[i] = in_key[i] ^ data2[i];
} }
for(int i = 0; i < 16; i++) memcpy(dataBuf2, data2, 16);
{
dataBuf2[i] = data2[i];
}
int res = sub_000013C8(dataBuf,16,num); int res = kirkSendCmd(dataBuf, 16, num, true);
if(res != 0) if(res)
{
return res; return res;
}
for(int i = 0; i < 16; i++)
{
data2[i] = dataBuf2[i];
}
}
for(int i = 0; i < 16; i++)
{
in_hash[i] = data2[i];
}
for(int i = 0; i < 16; i++) memcpy(data2, dataBuf2, 16);
{
ctx.result[i] = 0;
} }
memcpy(in_hash, data2, 16);
for(int i = 0; i < 16; i++) sceSdSetIndex_(ctx, 0);
{
ctx.key[i] = 0;
}
ctx.keyLength = 0;
ctx.mode = 0;
return 0; return 0;
} }
@ -495,8 +335,8 @@ int sceSdSetIndex(u32 addressCtx, int value)
int sceSdSetIndex_(pspChnnlsvContext1& ctx, int value) int sceSdSetIndex_(pspChnnlsvContext1& ctx, int value)
{ {
ctx.mode = value; ctx.mode = value;
memset(ctx.result,0,16); memset(ctx.result, 0, 16);
memset(ctx.key,0,16); memset(ctx.key, 0, 16);
ctx.keyLength = 0; ctx.keyLength = 0;
return 0; return 0;
} }
@ -505,104 +345,52 @@ int sceSdSetIndex_(pspChnnlsvContext1& ctx, int value)
int sceSdRemoveValue(u32 addressCtx, u32 addressData, int length) int sceSdRemoveValue(u32 addressCtx, u32 addressData, int length)
{ {
pspChnnlsvContext1 ctx; pspChnnlsvContext1 ctx;
Memory::ReadStruct(addressCtx,&ctx); Memory::ReadStruct(addressCtx, &ctx);
u8* data; int res = sceSdRemoveValue_(ctx, Memory::GetPointer(addressData), length);
data = Memory::GetPointer(addressData); Memory::WriteStruct(addressCtx, &ctx);
int res = sceSdRemoveValue_(ctx, data, length);
Memory::WriteStruct(addressCtx,&ctx);
return res; return res;
} }
int sceSdRemoveValue_(pspChnnlsvContext1& ctx, u8* data, int length) int sceSdRemoveValue_(pspChnnlsvContext1& ctx, u8* data, int length)
{ {
if(ctx.keyLength >= 17) if(ctx.keyLength >= 17)
{
return -1026; return -1026;
}
if(ctx.keyLength + length < 17) if(ctx.keyLength + length < 17)
{ {
if(length == 0) memcpy(ctx.key+ctx.keyLength, data, length);
{
return 0;
}
for(int i = 0; i < length; i++)
{
ctx.key[ctx.keyLength+i] = data[i];
}
ctx.keyLength = ctx.keyLength + length; ctx.keyLength = ctx.keyLength + length;
return 0; return 0;
} }
int mode = ctx.mode; int num = numFromMode(ctx.mode);
int num = 0;
switch(mode)
{
case 6:
num = 17;
break;
case 4:
num = 13;
break;
case 2:
num = 5;
break;
case 1:
num = 3;
break;
case 3:
num = 12;
break;
default:
num = 16;
break;
}
memset(dataBuf2,0,2048); memset(dataBuf2, 0, 2048);
memcpy(dataBuf2, ctx.key, ctx.keyLength);
if(ctx.keyLength > 0)
{
memcpy(dataBuf2,ctx.key,ctx.keyLength);
}
int len = (ctx.keyLength + length) & 0xF; int len = (ctx.keyLength + length) & 0xF;
if(len == 0) len = 16; if(len == 0) len = 16;
int oldLength = ctx.keyLength; int newSize = ctx.keyLength;
ctx.keyLength = len; ctx.keyLength = len;
int diff = length - len; int diff = length - len;
if(len != 0) memcpy(ctx.key, data+diff, len);
for(int i = 0; i < diff; i++)
{ {
memcpy(ctx.key,data+diff,len); if(newSize == 2048)
}
int newSize = oldLength;
if(diff != 0)
{
for(int i = 0; i < diff; i++)
{ {
if(newSize == 2048) int res = sub_1510(dataBuf, 2048, ctx.result, num);
{ if(res)
int res = sub_00001510(dataBuf,2048,ctx.result,num); return res;
if(res != 0) newSize = 0;
{
return res;
}
newSize = 0;
}
dataBuf2[newSize] = data[i];
newSize++;
} }
dataBuf2[newSize] = data[i];
newSize++;
} }
if(newSize == 0) if(newSize)
{ sub_1510(dataBuf, newSize, ctx.result, num);
return 0; // The RE code showed this always returning 0. I suspect it would want to return res instead.
}
int res = sub_00001510(dataBuf,newSize,ctx.result, num);
if(res == 0)
{
return res;
}
return 0; return 0;
} }
@ -626,116 +414,49 @@ int sceSdCreateList_(pspChnnlsvContext2& ctx2, int mode, int uknw, u8* data, u8*
ctx2.unkn = 1; ctx2.unkn = 1;
if (uknw == 2) if (uknw == 2)
{ {
for(int i = 0; i < 16; i++) memcpy(ctx2.cryptedData, data, 16);
{ if (cryptkey)
ctx2.unknown[i] = data[i]; memxor(ctx2.cryptedData, cryptkey, 16);
}
if (cryptkey == 0)
{
return 0;
}
for(int i = 0; i < 16; i++)
{
ctx2.unknown[i] = ctx2.unknown[i] ^ cryptkey[i];
}
return 0; return 0;
} }
else if (uknw == 1) else if (uknw == 1)
{ {
u8 kirkHeader[37]; u8 kirkHeader[37];
u8* kirkData = kirkHeader+20; u8* kirkData = kirkHeader+20;
int res = sub_000017A8(kirkHeader); int res = sub_17A8(kirkHeader);
if (res != 0) if (res)
{
return res; return res;
}
for(int i = 15; i >= 0 ; i--) memcpy(kirkHeader+20, kirkHeader, 16);
memset(kirkHeader+32, 0, 4);
int type = typeFromMode(mode);
if (type == 87)
memxor(kirkData, key199C, 16);
else if (type == 100)
memxor(kirkData, key19CC, 16);
switch (mode)
{ {
kirkHeader[i+20] = kirkHeader[i]; case 2: case 4: case 6: res = kirkSendFuseCmd(kirkHeader, 16, true);
} break;
for(int i = 0; i < 4; i++) case 1: case 3: default:res = kirkSendCmd(kirkHeader, 16, numFromMode2(mode), true);
{ break;
kirkHeader[i+32] = 0;
} }
if (mode == 6) if (type == 87)
{ memxor(kirkData, key19AC, 16);
for(int i = 0; i < 16; i++) else if (type == 100)
{ memxor(kirkData, key19DC, 16);
kirkData[i] = kirkData[i] ^ key000019CC[i];
}
res = sub_00001468(kirkHeader, 16);
for(int i = 0; i < 16; i++)
{
kirkData[i] = kirkData[i] ^ key000019DC[i];
}
}
else if (mode == 4)
{
for(int i = 0; i < 16; i++)
{
kirkData[i] = kirkData[i] ^ key0000199C[i];
}
res = sub_00001468(kirkHeader, 16);
for(int i = 0; i < 16; i++)
{
kirkData[i] = kirkData[i] ^ key000019AC[i];
}
}
else if (mode == 2)
{
res = sub_00001468(kirkHeader, 16);
}
else if (mode == 1)
{
res = sub_000013C8(kirkHeader, 16, 4);
}
else if (mode == 3)
{
for(int i = 0; i < 16; i++)
{
kirkData[i] = kirkData[i] ^ key0000199C[i];
}
res = sub_000013C8(kirkHeader, 16, 14);
for(int i = 0; i < 16; i++)
{
kirkData[i] = kirkData[i] ^ key000019AC[i];
}
}
else
{
for(int i = 0; i < 16; i++)
{
kirkData[i] = kirkData[i] ^ key000019CC[i];
}
res = sub_000013C8(kirkHeader, 16, 18);
for(int i = 0; i < 16; i++)
{
kirkData[i] = kirkData[i] ^ key000019DC[i];
}
}
if (res != 0) if (res)
{
return res; return res;
}
for(int i = 0; i < 16; i++) memcpy(ctx2.cryptedData, kirkData, 16);
{ memcpy(data, kirkData, 16);
ctx2.unknown[i] = kirkData[i]; if (cryptkey)
} memxor(ctx2.cryptedData, cryptkey, 16);
for(int i = 0; i < 16; i++)
{
data[i] = kirkData[i];
}
if (cryptkey != 0)
{
for(int i = 0; i < 16; i++)
{
ctx2.unknown[i] = ctx2.unknown[i] ^ cryptkey[i];
}
}
} }
return 0; return 0;
@ -770,12 +491,10 @@ int sceSdSetMember_(pspChnnlsvContext2& ctx, u8* data, int alignedLen)
{ {
for(i = 0; alignedLen >= 2048; i += 2048) for(i = 0; alignedLen >= 2048; i += 2048)
{ {
int res = sub_00000000(kirkData, data + i, 2048, ctx.unknown, ctx.unkn, ctx.mode); int res = sub_0000(kirkData, data + i, 2048, ctx.cryptedData, ctx.unkn, ctx.mode);
alignedLen = alignedLen - 2048; alignedLen -= 2048;
if (res != 0) if (res)
{
return res; return res;
}
} }
} }
if (alignedLen == 0) if (alignedLen == 0)
@ -783,8 +502,7 @@ int sceSdSetMember_(pspChnnlsvContext2& ctx, u8* data, int alignedLen)
return 0; return 0;
} }
int res = sub_00000000(kirkData, data + i, alignedLen, ctx.unknown, ctx.unkn, ctx.mode); return sub_0000(kirkData, data + i, alignedLen, ctx.cryptedData, ctx.unkn, ctx.mode);
return res;
} }
int sceChnnlsv_21BE78B4(u32 ctxAddr) int sceChnnlsv_21BE78B4(u32 ctxAddr)
@ -800,10 +518,7 @@ int sceChnnlsv_21BE78B4(u32 ctxAddr)
int sceChnnlsv_21BE78B4_(pspChnnlsvContext2& ctx) int sceChnnlsv_21BE78B4_(pspChnnlsvContext2& ctx)
{ {
for(int i = 0; i < 16; i++) memset(ctx.cryptedData, 0, 16);
{
ctx.unknown[i] = 0;
}
ctx.unkn = 0; ctx.unkn = 0;
ctx.mode = 0; ctx.mode = 0;
@ -822,6 +537,6 @@ const HLEFunction sceChnnlsv[] =
void Register_sceChnnlsv() void Register_sceChnnlsv()
{ {
RegisterModule("sceChnnlsv",ARRAY_SIZE(sceChnnlsv),sceChnnlsv); RegisterModule("sceChnnlsv", ARRAY_SIZE(sceChnnlsv), sceChnnlsv);
kirk_init(); kirk_init();
} }

View file

@ -23,7 +23,7 @@ typedef struct _pspChnnlsvContext1 {
/** Context data */ /** Context data */
u8 result[0x10]; u8 result[0x10];
u8 key[0x10]; u8 key[0x10];
int keyLength; int keyLength;
} pspChnnlsvContext1; } pspChnnlsvContext1;
@ -31,7 +31,7 @@ typedef struct _pspChnnlsvContext2 {
/** Context data */ /** Context data */
int mode; int mode;
int unkn; int unkn;
u8 unknown[0x92]; u8 cryptedData[0x92];
} pspChnnlsvContext2; } pspChnnlsvContext2;
int sceSdSetIndex_(pspChnnlsvContext1& ctx, int value); int sceSdSetIndex_(pspChnnlsvContext1& ctx, int value);

View file

@ -161,11 +161,11 @@ void __CtrlSetAnalog(float x, float y, int stick)
{ {
std::lock_guard<std::recursive_mutex> guard(ctrlMutex); std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
if (stick == 0) { if (stick == 0) {
ctrlCurrent.analog[0] = (u8)(x * 127.f + 128.f); ctrlCurrent.analog[0] = (u8)ceilf(x * 127.5f + 127.5f);
ctrlCurrent.analog[1] = (u8)(-y * 127.f + 128.f); ctrlCurrent.analog[1] = (u8)ceilf(-y * 127.5f + 127.5f);
} else { } else {
ctrlCurrent.analogRight[0] = (u8)(x * 127.f + 128.f); ctrlCurrent.analogRight[0] = (u8)ceilf(x * 127.5f + 127.5f);
ctrlCurrent.analogRight[1] = (u8)(-y * 127.f + 128.f); ctrlCurrent.analogRight[1] = (u8)ceilf(-y * 127.5f + 127.5f);
} }
} }

View file

@ -426,7 +426,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) {
gpuStats.numFrames++; gpuStats.numFrames++;
if (g_Config.bShowFPSCounter) { if (g_Config.iShowFPSCounter) {
CalculateFPS(); CalculateFPS();
} }

View file

@ -25,14 +25,24 @@ int sceHttpSetResolveRetry(int connectionID, int retryCount)
return 0; return 0;
} }
int sceHttpInit() {
ERROR_LOG(HLE, "UNIMPL sceHttpInit()");
return 0;
}
int sceHttpEnd() {
ERROR_LOG(HLE, "UNIMPL sceHttpInit()");
return 0;
}
/* /*
* 0x62411801 sceSircsInit * 0x62411801 sceSircsInit
0x19155a2f sceSircsEnd 0x19155a2f sceSircsEnd
0x71eef62d sceSircsSend 0x71eef62d sceSircsSend
*/ */
const HLEFunction sceHttp[] = { const HLEFunction sceHttp[] = {
{0xab1abe07,0,"sceHttpInit"}, {0xab1abe07,WrapI_V<sceHttpInit>,"sceHttpInit"},
{0xd1c8945e,0,"sceHttpEnd"}, {0xd1c8945e,WrapI_V<sceHttpEnd>,"sceHttpEnd"},
{0xa6800c34,0,"sceHttpInitCache"}, {0xa6800c34,0,"sceHttpInitCache"},
{0x78b54c09,0,"sceHttpEndCache"}, {0x78b54c09,0,"sceHttpEndCache"},
{0x59e6d16f,0,"sceHttpEnableCache"}, {0x59e6d16f,0,"sceHttpEnableCache"},

View file

@ -158,6 +158,7 @@ public:
sprintf(ptr, "Seekpos: %08x", (u32)pspFileSystem.GetSeekPos(handle)); sprintf(ptr, "Seekpos: %08x", (u32)pspFileSystem.GetSeekPos(handle));
} }
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_BADF; } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_BADF; }
static int GetStaticIDType() { return PPSSPP_KERNEL_TMID_File; }
int GetIDType() const { return PPSSPP_KERNEL_TMID_File; } int GetIDType() const { return PPSSPP_KERNEL_TMID_File; }
virtual void DoState(PointerWrap &p) { virtual void DoState(PointerWrap &p) {
@ -1441,6 +1442,7 @@ public:
const char *GetName() {return name.c_str();} const char *GetName() {return name.c_str();}
const char *GetTypeName() {return "DirListing";} const char *GetTypeName() {return "DirListing";}
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_BADF; } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_BADF; }
static int GetStaticIDType() { return PPSSPP_KERNEL_TMID_DirList; }
int GetIDType() const { return PPSSPP_KERNEL_TMID_DirList; } int GetIDType() const { return PPSSPP_KERNEL_TMID_DirList; }
virtual void DoState(PointerWrap &p) { virtual void DoState(PointerWrap &p) {

View file

@ -404,6 +404,7 @@ public:
// Implement this in all subclasses: // Implement this in all subclasses:
// static u32 GetMissingErrorCode() // static u32 GetMissingErrorCode()
// static int GetStaticIDType()
virtual void DoState(PointerWrap &p) virtual void DoState(PointerWrap &p)
{ {
@ -443,7 +444,7 @@ public:
if (handle < handleOffset || handle >= handleOffset+maxCount || !occupied[handle-handleOffset]) if (handle < handleOffset || handle >= handleOffset+maxCount || !occupied[handle-handleOffset])
{ {
ERROR_LOG(HLE, "Kernel: Bad object handle %i (%08x)", handle, handle); ERROR_LOG(HLE, "Kernel: Bad object handle %i (%08x)", handle, handle);
outError = T::GetMissingErrorCode(); // ? outError = T::GetMissingErrorCode();
return 0; return 0;
} }
else else
@ -452,10 +453,10 @@ public:
// it just acted as a static case and everything worked. This means that we will never // it just acted as a static case and everything worked. This means that we will never
// see the Wrong type object error below, but we'll just have to live with that danger. // see the Wrong type object error below, but we'll just have to live with that danger.
T* t = static_cast<T*>(pool[handle - handleOffset]); T* t = static_cast<T*>(pool[handle - handleOffset]);
if (t == 0) if (t == 0 || t->GetIDType() != T::GetStaticIDType())
{ {
ERROR_LOG(HLE, "Kernel: Wrong type object %i (%08x)", handle, handle); ERROR_LOG(HLE, "Kernel: Wrong object type for %i (%08x)", handle, handle);
outError = T::GetMissingErrorCode(); //FIX outError = T::GetMissingErrorCode();
return 0; return 0;
} }
outError = SCE_KERNEL_ERROR_OK; outError = SCE_KERNEL_ERROR_OK;
@ -477,8 +478,9 @@ public:
} }
template <class T, typename ArgT> template <class T, typename ArgT>
void Iterate(bool func(T *, ArgT), ArgT arg, int type) void Iterate(bool func(T *, ArgT), ArgT arg)
{ {
int type = T::GetStaticIDType();
for (int i = 0; i < maxCount; i++) for (int i = 0; i < maxCount; i++)
{ {
if (!occupied[i]) if (!occupied[i])
@ -491,8 +493,6 @@ public:
} }
} }
static u32 GetMissingErrorCode() { return -1; } // TODO
bool GetIDType(SceUID handle, int *type) const bool GetIDType(SceUID handle, int *type) const
{ {
if (handle < handleOffset || handle >= handleOffset+maxCount || !occupied[handle-handleOffset]) if (handle < handleOffset || handle >= handleOffset+maxCount || !occupied[handle-handleOffset])

View file

@ -40,6 +40,7 @@ struct Alarm : public KernelObject
const char *GetName() {return "[Alarm]";} const char *GetName() {return "[Alarm]";}
const char *GetTypeName() {return "Alarm";} const char *GetTypeName() {return "Alarm";}
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_ALMID; } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_ALMID; }
static int GetStaticIDType() { return SCE_KERNEL_TMID_Alarm; }
int GetIDType() const { return SCE_KERNEL_TMID_Alarm; } int GetIDType() const { return SCE_KERNEL_TMID_Alarm; }
virtual void DoState(PointerWrap &p) virtual void DoState(PointerWrap &p)

View file

@ -64,6 +64,7 @@ public:
static u32 GetMissingErrorCode() { static u32 GetMissingErrorCode() {
return SCE_KERNEL_ERROR_UNKNOWN_EVFID; return SCE_KERNEL_ERROR_UNKNOWN_EVFID;
} }
static int GetStaticIDType() { return SCE_KERNEL_TMID_EventFlag; }
int GetIDType() const { return SCE_KERNEL_TMID_EventFlag; } int GetIDType() const { return SCE_KERNEL_TMID_EventFlag; }
virtual void DoState(PointerWrap &p) virtual void DoState(PointerWrap &p)

View file

@ -53,6 +53,7 @@ struct Mbx : public KernelObject
const char *GetName() {return nmb.name;} const char *GetName() {return nmb.name;}
const char *GetTypeName() {return "Mbx";} const char *GetTypeName() {return "Mbx";}
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MBXID; } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MBXID; }
static int GetStaticIDType() { return SCE_KERNEL_TMID_Mbox; }
int GetIDType() const { return SCE_KERNEL_TMID_Mbox; } int GetIDType() const { return SCE_KERNEL_TMID_Mbox; }
void AddWaitingThread(SceUID id, u32 addr) void AddWaitingThread(SceUID id, u32 addr)

View file

@ -72,6 +72,7 @@ struct FPL : public KernelObject
const char *GetName() {return nf.name;} const char *GetName() {return nf.name;}
const char *GetTypeName() {return "FPL";} const char *GetTypeName() {return "FPL";}
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_FPLID; } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_FPLID; }
static int GetStaticIDType() { return SCE_KERNEL_TMID_Fpl; }
int GetIDType() const { return SCE_KERNEL_TMID_Fpl; } int GetIDType() const { return SCE_KERNEL_TMID_Fpl; }
int findFreeBlock() { int findFreeBlock() {
@ -133,6 +134,7 @@ struct VPL : public KernelObject
const char *GetName() {return nv.name;} const char *GetName() {return nv.name;}
const char *GetTypeName() {return "VPL";} const char *GetTypeName() {return "VPL";}
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_VPLID; } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_VPLID; }
static int GetStaticIDType() { return SCE_KERNEL_TMID_Vpl; }
int GetIDType() const { return SCE_KERNEL_TMID_Vpl; } int GetIDType() const { return SCE_KERNEL_TMID_Vpl; }
VPL() : alloc(8) {} VPL() : alloc(8) {}
@ -424,6 +426,7 @@ public:
sprintf(ptr, "MemPart: %08x - %08x size: %08x", address, address + sz, sz); sprintf(ptr, "MemPart: %08x - %08x size: %08x", address, address + sz, sz);
} }
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_UID; } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_UID; }
static int GetStaticIDType() { return PPSSPP_KERNEL_TMID_PMB; }
int GetIDType() const { return PPSSPP_KERNEL_TMID_PMB; } int GetIDType() const { return PPSSPP_KERNEL_TMID_PMB; }
PartitionMemoryBlock(BlockAllocator *_alloc, const char *_name, u32 size, MemblockType type, u32 alignment) PartitionMemoryBlock(BlockAllocator *_alloc, const char *_name, u32 size, MemblockType type, u32 alignment)
@ -1331,6 +1334,7 @@ struct TLS : public KernelObject
const char *GetName() {return ntls.name;} const char *GetName() {return ntls.name;}
const char *GetTypeName() {return "TLS";} const char *GetTypeName() {return "TLS";}
static u32 GetMissingErrorCode() { return PSP_ERROR_UNKNOWN_TLS_ID; } static u32 GetMissingErrorCode() { return PSP_ERROR_UNKNOWN_TLS_ID; }
static int GetStaticIDType() { return SCE_KERNEL_TMID_Tls; }
int GetIDType() const { return SCE_KERNEL_TMID_Tls; } int GetIDType() const { return SCE_KERNEL_TMID_Tls; }
TLS() : next(0) {} TLS() : next(0) {}

View file

@ -179,6 +179,7 @@ public:
nm.entry_addr); nm.entry_addr);
} }
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MODULE; } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MODULE; }
static int GetStaticIDType() { return PPSSPP_KERNEL_TMID_Module; }
int GetIDType() const { return PPSSPP_KERNEL_TMID_Module; } int GetIDType() const { return PPSSPP_KERNEL_TMID_Module; }
virtual void DoState(PointerWrap &p) virtual void DoState(PointerWrap &p)
@ -1349,7 +1350,7 @@ u32 sceKernelGetModuleIdByAddress(u32 moduleAddr)
state.addr = moduleAddr; state.addr = moduleAddr;
state.result = SCE_KERNEL_ERROR_UNKNOWN_MODULE; state.result = SCE_KERNEL_ERROR_UNKNOWN_MODULE;
kernelObjects.Iterate(&__GetModuleIdByAddressIterator, &state, PPSSPP_KERNEL_TMID_Module); kernelObjects.Iterate(&__GetModuleIdByAddressIterator, &state);
if (state.result == SCE_KERNEL_ERROR_UNKNOWN_MODULE) if (state.result == SCE_KERNEL_ERROR_UNKNOWN_MODULE)
ERROR_LOG(HLE, "sceKernelGetModuleIdByAddress(%08x): module not found", moduleAddr) ERROR_LOG(HLE, "sceKernelGetModuleIdByAddress(%08x): module not found", moduleAddr)
else else

View file

@ -55,6 +55,7 @@ struct MsgPipe : public KernelObject
const char *GetName() {return nmp.name;} const char *GetName() {return nmp.name;}
const char *GetTypeName() {return "MsgPipe";} const char *GetTypeName() {return "MsgPipe";}
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MPPID; } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MPPID; }
static int GetStaticIDType() { return SCE_KERNEL_TMID_Mpipe; }
int GetIDType() const { return SCE_KERNEL_TMID_Mpipe; } int GetIDType() const { return SCE_KERNEL_TMID_Mpipe; }
MsgPipe() : buffer(NULL) {} MsgPipe() : buffer(NULL) {}

View file

@ -64,6 +64,7 @@ struct Mutex : public KernelObject
const char *GetName() {return nm.name;} const char *GetName() {return nm.name;}
const char *GetTypeName() {return "Mutex";} const char *GetTypeName() {return "Mutex";}
static u32 GetMissingErrorCode() { return PSP_MUTEX_ERROR_NO_SUCH_MUTEX; } static u32 GetMissingErrorCode() { return PSP_MUTEX_ERROR_NO_SUCH_MUTEX; }
static int GetStaticIDType() { return SCE_KERNEL_TMID_Mutex; }
int GetIDType() const { return SCE_KERNEL_TMID_Mutex; } int GetIDType() const { return SCE_KERNEL_TMID_Mutex; }
virtual void DoState(PointerWrap &p) virtual void DoState(PointerWrap &p)
@ -125,6 +126,7 @@ struct LwMutex : public KernelObject
const char *GetName() {return nm.name;} const char *GetName() {return nm.name;}
const char *GetTypeName() {return "LwMutex";} const char *GetTypeName() {return "LwMutex";}
static u32 GetMissingErrorCode() { return PSP_LWMUTEX_ERROR_NO_SUCH_LWMUTEX; } static u32 GetMissingErrorCode() { return PSP_LWMUTEX_ERROR_NO_SUCH_LWMUTEX; }
static int GetStaticIDType() { return SCE_KERNEL_TMID_LwMutex; }
int GetIDType() const { return SCE_KERNEL_TMID_LwMutex; } int GetIDType() const { return SCE_KERNEL_TMID_LwMutex; }
virtual void DoState(PointerWrap &p) virtual void DoState(PointerWrap &p)

View file

@ -57,6 +57,7 @@ struct Semaphore : public KernelObject
const char *GetTypeName() {return "Semaphore";} const char *GetTypeName() {return "Semaphore";}
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_SEMID; } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_SEMID; }
static int GetStaticIDType() { return SCE_KERNEL_TMID_Semaphore; }
int GetIDType() const { return SCE_KERNEL_TMID_Semaphore; } int GetIDType() const { return SCE_KERNEL_TMID_Semaphore; }
virtual void DoState(PointerWrap &p) virtual void DoState(PointerWrap &p)

View file

@ -82,6 +82,7 @@ public:
} }
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_CBID; } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_CBID; }
static int GetStaticIDType() { return SCE_KERNEL_TMID_Callback; }
int GetIDType() const { return SCE_KERNEL_TMID_Callback; } int GetIDType() const { return SCE_KERNEL_TMID_Callback; }
virtual void DoState(PointerWrap &p) virtual void DoState(PointerWrap &p)
@ -295,7 +296,7 @@ public:
} }
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_THID; } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_THID; }
static int GetStaticIDType() { return SCE_KERNEL_TMID_Thread; }
int GetIDType() const { return SCE_KERNEL_TMID_Thread; } int GetIDType() const { return SCE_KERNEL_TMID_Thread; }
bool AllocateStack(u32 &stackSize) bool AllocateStack(u32 &stackSize)

View file

@ -42,6 +42,7 @@ struct VTimer : public KernelObject {
const char *GetName() {return nvt.name;} const char *GetName() {return nvt.name;}
const char *GetTypeName() {return "VTimer";} const char *GetTypeName() {return "VTimer";}
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_VTID; } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_VTID; }
static int GetStaticIDType() { return SCE_KERNEL_TMID_VTimer; }
int GetIDType() const { return SCE_KERNEL_TMID_VTimer; } int GetIDType() const { return SCE_KERNEL_TMID_VTimer; }
virtual void DoState(PointerWrap &p) { virtual void DoState(PointerWrap &p) {

View file

@ -327,10 +327,11 @@ void __MpegShutdown() {
u32 sceMpegInit() { u32 sceMpegInit() {
if (isMpegInit) { if (isMpegInit) {
WARN_LOG(HLE, "sceMpegInit(): already initialized"); WARN_LOG(HLE, "sceMpegInit(): already initialized");
return ERROR_MPEG_ALREADY_INIT; // TODO: Need to properly hook module load/unload for this to work right.
//return ERROR_MPEG_ALREADY_INIT;
} else {
INFO_LOG(HLE, "sceMpegInit()");
} }
INFO_LOG(HLE, "sceMpegInit()");
isMpegInit = true; isMpegInit = true;
return hleDelayResult(0, "mpeg init", 750); return hleDelayResult(0, "mpeg init", 750);
} }
@ -1009,10 +1010,11 @@ u32 sceMpegFinish()
if (!isMpegInit) if (!isMpegInit)
{ {
WARN_LOG(HLE, "sceMpegFinish(...): not initialized"); WARN_LOG(HLE, "sceMpegFinish(...): not initialized");
return ERROR_MPEG_NOT_YET_INIT; // TODO: Need to properly hook module load/unload for this to work right.
//return ERROR_MPEG_NOT_YET_INIT;
} else {
INFO_LOG(HLE, "sceMpegFinish(...)");
} }
INFO_LOG(HLE, "sceMpegFinish(...)");
isMpegInit = false; isMpegInit = false;
//__MpegFinish(); //__MpegFinish();
return hleDelayResult(0, "mpeg finish", 250); return hleDelayResult(0, "mpeg finish", 250);

View file

@ -24,9 +24,16 @@
#include "sceUtility.h" #include "sceUtility.h"
static bool netInited; static bool netInited;
static bool netInetInited;
static bool netAdhocInited; static bool netAdhocInited;
static bool netApctlInited;
static u32 adhocctlHandlerCount; static u32 adhocctlHandlerCount;
static u32 apctlHandlerCount;
// TODO: Determine how many handlers we can actually have
const u32 MAX_ADHOCCTL_HANDLERS = 32;
const u32 MAX_APCTL_HANDLERS = 32;
enum { enum {
ERROR_NET_BUFFER_TOO_SMALL = 0x80400706, ERROR_NET_BUFFER_TOO_SMALL = 0x80400706,
@ -78,18 +85,26 @@ struct SceNetMallocStat {
static struct SceNetMallocStat netMallocStat; static struct SceNetMallocStat netMallocStat;
struct AdhocctlHandler struct AdhocctlHandler {
{
u32 entryPoint; u32 entryPoint;
u32 argument; u32 argument;
u32 id;
}; };
static std::vector<AdhocctlHandler> adhocctlHandlers; static std::map<int, AdhocctlHandler> adhocctlHandlers;
struct ApctlHandler {
u32 entryPoint;
u32 argument;
};
static std::map<int, ApctlHandler> apctlHandlers;
void __NetInit() { void __NetInit() {
netInited = false; netInited = false;
netAdhocInited = false; netAdhocInited = false;
netApctlInited = false;
netInetInited = false;
memset(&netMallocStat, 0, sizeof(netMallocStat));
} }
void __NetShutdown() { void __NetShutdown() {
@ -98,21 +113,40 @@ void __NetShutdown() {
void __UpdateAdhocctlHandlers(int flag, int error) { void __UpdateAdhocctlHandlers(int flag, int error) {
u32 args[3] = { 0, 0, 0 }; u32 args[3] = { 0, 0, 0 };
for(std::vector<AdhocctlHandler>::iterator it = adhocctlHandlers.begin(); it < adhocctlHandlers.end(); it++) { args[0] = flag;
args[0] = flag; args[1] = error;
args[1] = error;
args[2] = it->argument;
__KernelDirectMipsCall(it->entryPoint, NULL, args, 3, true); for(std::map<int, AdhocctlHandler>::iterator it = adhocctlHandlers.begin(); it != adhocctlHandlers.end(); ++it) {
args[2] = it->second.argument;
__KernelDirectMipsCall(it->second.entryPoint, NULL, args, 3, true);
}
}
void __UpdateApctlHandlers(int oldState, int newState, int flag, int error) {
u32 args[5] = { 0, 0, 0, 0, 0 };
args[0] = oldState;
args[1] = newState;
args[2] = flag;
args[3] = error;
for(std::map<int, ApctlHandler>::iterator it = apctlHandlers.begin(); it != apctlHandlers.end(); ++it) {
args[4] = it->second.argument;
__KernelDirectMipsCall(it->second.entryPoint, NULL, args, 5, true);
} }
} }
// This feels like a dubious proposition, mostly... // This feels like a dubious proposition, mostly...
void __NetDoState(PointerWrap &p) { void __NetDoState(PointerWrap &p) {
p.Do(netInited); p.Do(netInited);
p.Do(netInetInited);
p.Do(netAdhocInited); p.Do(netAdhocInited);
p.Do(netApctlInited);
p.Do(adhocctlHandlers); p.Do(adhocctlHandlers);
p.Do(adhocctlHandlerCount); p.Do(adhocctlHandlerCount);
p.Do(apctlHandlers);
p.Do(apctlHandlerCount);
p.Do(netMallocStat); p.Do(netMallocStat);
p.DoMarker("net"); p.DoMarker("net");
} }
@ -121,12 +155,11 @@ void __NetDoState(PointerWrap &p) {
void sceNetInit() { void sceNetInit() {
ERROR_LOG(HLE,"UNIMPL sceNetInit(poolsize=%d, calloutpri=%i, calloutstack=%d, netintrpri=%i, netintrstack=%d)", PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); ERROR_LOG(HLE,"UNIMPL sceNetInit(poolsize=%d, calloutpri=%i, calloutstack=%d, netintrpri=%i, netintrstack=%d)", PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
netInited = true; netInited = true;
memset(&netMallocStat, 0, sizeof(netMallocStat));
netMallocStat.maximum = PARAM(0); netMallocStat.maximum = PARAM(0);
netMallocStat.free = PARAM(0); netMallocStat.free = PARAM(0);
netMallocStat.pool = 0; netMallocStat.pool = 0;
RETURN(0); //ERROR <- The Dax: Why is it an error when it returns 0 on success? RETURN(0);
} }
u32 sceNetTerm() { u32 sceNetTerm() {
@ -172,29 +205,35 @@ u32 sceWlanGetSwitchState() {
// TODO: Should we allow the same handler to be added more than once? // TODO: Should we allow the same handler to be added more than once?
u32 sceNetAdhocctlAddHandler(u32 handlerPtr, u32 handlerArg) { u32 sceNetAdhocctlAddHandler(u32 handlerPtr, u32 handlerArg) {
bool foundHandler = false; bool foundHandler = false;
u32 retval = adhocctlHandlerCount;
struct AdhocctlHandler handler; struct AdhocctlHandler handler;
memset(&handler, 0, sizeof(handler)); memset(&handler, 0, sizeof(handler));
handler.entryPoint = handlerPtr; handler.entryPoint = handlerPtr;
handler.argument = handlerArg; handler.argument = handlerArg;
handler.id = -1;
for(std::vector<AdhocctlHandler>::iterator it = adhocctlHandlers.begin(); it < adhocctlHandlers.end(); it++) { for(std::map<int, AdhocctlHandler>::iterator it = adhocctlHandlers.begin(); it != adhocctlHandlers.end(); it++) {
if(it->entryPoint == handlerPtr) { if(it->second.entryPoint == handlerPtr) {
foundHandler = true; foundHandler = true;
break; break;
} }
} }
if(!foundHandler && Memory::IsValidAddress(handlerPtr)) { if(!foundHandler && Memory::IsValidAddress(handlerPtr)) {
handler.id = adhocctlHandlerCount > 0? ++adhocctlHandlerCount : 0; if(adhocctlHandlerCount >= MAX_ADHOCCTL_HANDLERS) {
adhocctlHandlers.push_back(handler); ERROR_LOG(HLE, "UNTESTED UNTESTED sceNetAdhocctlAddHandler(%x, %x): Too many handlers", handlerPtr, handlerArg);
WARN_LOG(HLE, "UNTESTED sceNetAdhocctlAddHandler(%x, %x): added handler %d", handlerPtr, handlerArg, handler.id); retval = ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS;
return retval;
}
adhocctlHandlers[adhocctlHandlerCount++] = handler;
WARN_LOG(HLE, "UNTESTED sceNetAdhocctlAddHandler(%x, %x): added handler %d", handlerPtr, handlerArg, adhocctlHandlerCount);
} }
else else
ERROR_LOG(HLE, "UNTESTED sceNetAdhocctlAddHandler(%x, %x): Same handler already exists", handlerPtr, handlerArg); ERROR_LOG(HLE, "UNTESTED sceNetAdhocctlAddHandler(%x, %x): Same handler already exists", handlerPtr, handlerArg);
return handler.id; // The id to return is the number of handlers currently registered
return retval;
} }
u32 sceNetAdhocctlDisconnect() { u32 sceNetAdhocctlDisconnect() {
@ -205,9 +244,14 @@ u32 sceNetAdhocctlDisconnect() {
} }
u32 sceNetAdhocctlDelHandler(u32 handlerID) { u32 sceNetAdhocctlDelHandler(u32 handlerID) {
WARN_LOG(HLE, "UNTESTED sceNetAdhocctlDelHandler(%x)", handlerID);
adhocctlHandlers.erase(adhocctlHandlers.begin() + handlerID); if(adhocctlHandlers.find(handlerID) != adhocctlHandlers.end()) {
adhocctlHandlerCount = adhocctlHandlerCount > 0? --adhocctlHandlerCount : adhocctlHandlerCount; adhocctlHandlers.erase(handlerID);
adhocctlHandlerCount = adhocctlHandlerCount > 0? --adhocctlHandlerCount : 0;
WARN_LOG(HLE, "UNTESTED sceNetAdhocctlDelHandler(%d): deleted handler %d", handlerID, handlerID);
}
else
ERROR_LOG(HLE, "UNTESTED sceNetAdhocctlDelHandler(%d): asked to delete invalid handler %d", handlerID, handlerID);
return 0; return 0;
} }
@ -261,7 +305,7 @@ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown)
// TODO: Should we really write the struct if we're disconnected? // TODO: Should we really write the struct if we're disconnected?
int sceNetAdhocctlGetParameter(u32 paramAddr) { int sceNetAdhocctlGetParameter(u32 paramAddr) {
ERROR_LOG(HLE, "UNTESTED %x=sceNetAdhocctlGetParameter(%x)", 0, paramAddr); WARN_LOG(HLE, "UNTESTED sceNetAdhocctlGetParameter(%x)", paramAddr);
struct SceNetAdhocctlParams params; struct SceNetAdhocctlParams params;
params.channel = 0; params.channel = 0;
for(int i = 0; i < 6; i++) for(int i = 0; i < 6; i++)
@ -318,7 +362,7 @@ int sceNetAdhocctlConnect(u32 ptrToGroupName) {
// Write static data since we don't actually manage any memory for sceNet* yet. // Write static data since we don't actually manage any memory for sceNet* yet.
int sceNetGetMallocStat(u32 statPtr) { int sceNetGetMallocStat(u32 statPtr) {
ERROR_LOG(HLE, "UNTESTED sceNetGetMallocStat(%x)", statPtr); WARN_LOG(HLE, "UNTESTED sceNetGetMallocStat(%x)", statPtr);
if(Memory::IsValidAddress(statPtr)) if(Memory::IsValidAddress(statPtr))
Memory::WriteStruct(statPtr, &netMallocStat); Memory::WriteStruct(statPtr, &netMallocStat);
else else
@ -332,6 +376,88 @@ int sceNetAdhocMatchingInit(u32 memsize) {
return 0; return 0;
} }
int sceNetInetInit() {
ERROR_LOG(HLE, "UNIMPL sceNetInetInit()");
if (netInetInited)
return ERROR_NET_ADHOC_ALREADY_INITIALIZED; // TODO: What's the proper error for netInet already being inited?
netInetInited = true;
return 0;
}
int sceNetInetTerm() {
ERROR_LOG(HLE, "UNIMPL sceNetInetTerm()");
netInetInited = false;
return 0;
}
int sceNetApctlInit() {
ERROR_LOG(HLE, "UNIMPL sceNetApctlInit()");
if (netAdhocInited)
return ERROR_NET_ADHOC_ALREADY_INITIALIZED; // TODO: What's the proper error for apctl already being inited?
netApctlInited = true;
return 0;
}
int sceNetApctlTerm() {
ERROR_LOG(HLE, "UNIMPL sceNeApctlTerm()");
netInetInited = false;
return 0;
}
// TODO: How many handlers can the PSP actually have for Apctl?
// TODO: Should we allow the same handler to be added more than once?
u32 sceNetApctlAddHandler(u32 handlerPtr, u32 handlerArg) {
bool foundHandler = false;
u32 retval = apctlHandlerCount;
struct ApctlHandler handler;
memset(&handler, 0, sizeof(handler));
handler.entryPoint = handlerPtr;
handler.argument = handlerArg;
for(std::map<int, ApctlHandler>::iterator it = apctlHandlers.begin(); it != apctlHandlers.end(); it++) {
if(it->second.entryPoint == handlerPtr) {
foundHandler = true;
break;
}
}
if(!foundHandler && Memory::IsValidAddress(handlerPtr)) {
if(apctlHandlerCount >= MAX_APCTL_HANDLERS) {
ERROR_LOG(HLE, "UNTESTED sceNetApctlAddHandler(%x, %x): Too many handlers", handlerPtr, handlerArg);
retval = ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS; // TODO: What's the proper error code for Apctl's TOO_MANY_HANDLERS?
return retval;
}
apctlHandlers[apctlHandlerCount++] = handler;
WARN_LOG(HLE, "UNTESTED sceNetApctlAddHandler(%x, %x): added handler %d", handlerPtr, handlerArg, apctlHandlerCount);
}
else
ERROR_LOG(HLE, "UNTESTED sceNetApctlAddHandler(%x, %x): Same handler already exists", handlerPtr, handlerArg);
// The id to return is the number of handlers currently registered
return retval;
}
int sceNetApctlDelHandler(u32 handlerID) {
if(apctlHandlers.find(handlerID) != apctlHandlers.end()) {
apctlHandlers.erase(handlerID);
apctlHandlerCount = apctlHandlerCount > 0? --apctlHandlerCount : 0;
WARN_LOG(HLE, "UNTESTED sceNetapctlDelHandler(%d): deleted handler %d", handlerID, handlerID);
}
else
ERROR_LOG(HLE, "UNTESTED sceNetapctlDelHandler(%d): asked to delete invalid handler %d", handlerID, handlerID);
return 0;
}
const HLEFunction sceNet[] = { const HLEFunction sceNet[] = {
{0x39AF39A6, sceNetInit, "sceNetInit"}, {0x39AF39A6, sceNetInit, "sceNetInit"},
{0x281928A9, WrapU_V<sceNetTerm>, "sceNetTerm"}, {0x281928A9, WrapU_V<sceNetTerm>, "sceNetTerm"},
@ -431,7 +557,7 @@ const HLEFunction sceNetResolver[] = {
}; };
const HLEFunction sceNetInet[] = { const HLEFunction sceNetInet[] = {
{0x17943399, 0, "sceNetInetInit"}, {0x17943399, WrapI_V<sceNetInetInit>, "sceNetInetInit"},
{0x2fe71fe7, 0, "sceNetInetSetsockopt"}, {0x2fe71fe7, 0, "sceNetInetSetsockopt"},
{0x410b34aa, 0, "sceNetInetConnect"}, {0x410b34aa, 0, "sceNetInetConnect"},
{0x5be8d595, 0, "sceNetInetSelect"}, {0x5be8d595, 0, "sceNetInetSelect"},
@ -450,7 +576,7 @@ const HLEFunction sceNetInet[] = {
{0xd10a1a7a, 0, "sceNetInetListen"}, {0xd10a1a7a, 0, "sceNetInetListen"},
{0xdb094e1b, 0, "sceNetInetAccept"}, {0xdb094e1b, 0, "sceNetInetAccept"},
{0x8ca3a97e, 0, "sceNetInetGetPspError"}, {0x8ca3a97e, 0, "sceNetInetGetPspError"},
{0xa9ed66b9, 0, "sceNetInetTerm"}, {0xa9ed66b9, WrapI_V<sceNetInetTerm>, "sceNetInetTerm"},
{0xE30B8C19, 0, "sceNetInetInetPton"}, {0xE30B8C19, 0, "sceNetInetInetPton"},
{0xE247B6D6, 0, "sceNetInetGetpeername"}, {0xE247B6D6, 0, "sceNetInetGetpeername"},
{0x162e6fd5, 0, "sceNetInetGetsockname"}, {0x162e6fd5, 0, "sceNetInetGetsockname"},
@ -468,10 +594,10 @@ const HLEFunction sceNetApctl[] = {
{0xCFB957C6, 0, "sceNetApctlConnect"}, {0xCFB957C6, 0, "sceNetApctlConnect"},
{0x24fe91a1, 0, "sceNetApctlDisconnect"}, {0x24fe91a1, 0, "sceNetApctlDisconnect"},
{0x5deac81b, 0, "sceNetApctlGetState"}, {0x5deac81b, 0, "sceNetApctlGetState"},
{0x8abadd51, 0, "sceNetApctlAddHandler"}, {0x8abadd51, WrapU_UU<sceNetApctlAddHandler>, "sceNetApctlAddHandler"},
{0xe2f91f9b, 0, "sceNetApctlInit"}, {0xe2f91f9b, WrapI_V<sceNetApctlInit>, "sceNetApctlInit"},
{0x5963991b, 0, "sceNetApctlDelHandler"}, {0x5963991b, WrapI_U<sceNetApctlDelHandler>, "sceNetApctlDelHandler"},
{0xb3edd0ec, 0, "sceNetApctlTerm"}, {0xb3edd0ec, WrapI_V<sceNetApctlTerm>, "sceNetApctlTerm"},
{0x2BEFDF23, 0, "sceNetApctlGetInfo"}, {0x2BEFDF23, 0, "sceNetApctlGetInfo"},
{0xa3e77e13, 0, "sceNetApctlScanSSID2"}, {0xa3e77e13, 0, "sceNetApctlScanSSID2"},
{0xf25a5006, 0, "sceNetApctlGetBSSDescIDList2"}, {0xf25a5006, 0, "sceNetApctlGetBSSDescIDList2"},

View file

@ -231,8 +231,8 @@ Psmf::Psmf(u32 data) {
streamOffset = bswap32(Memory::Read_U32(data + 8)); streamOffset = bswap32(Memory::Read_U32(data + 8));
streamSize = bswap32(Memory::Read_U32(data + 12)); streamSize = bswap32(Memory::Read_U32(data + 12));
streamDataTotalSize = bswap32(Memory::Read_U32(data + 0x50)); streamDataTotalSize = bswap32(Memory::Read_U32(data + 0x50));
presentationStartTime = bswap32(Memory::Read_U32(data + PSMF_FIRST_TIMESTAMP_OFFSET)); presentationStartTime = getMpegTimeStamp(Memory::GetPointer(data + PSMF_FIRST_TIMESTAMP_OFFSET));
presentationEndTime = bswap32(Memory::Read_U32(data + PSMF_LAST_TIMESTAMP_OFFSET)); presentationEndTime = getMpegTimeStamp(Memory::GetPointer(data + PSMF_LAST_TIMESTAMP_OFFSET));
streamDataNextBlockSize = bswap32(Memory::Read_U32(data + 0x6A)); streamDataNextBlockSize = bswap32(Memory::Read_U32(data + 0x6A));
streamDataNextInnerBlockSize = bswap32(Memory::Read_U32(data + 0x7C)); streamDataNextInnerBlockSize = bswap32(Memory::Read_U32(data + 0x7C));
numStreams = bswap16(Memory::Read_U16(data + 0x80)); numStreams = bswap16(Memory::Read_U16(data + 0x80));

View file

@ -72,6 +72,7 @@ void __UtilityDoState(PointerWrap &p)
msgDialog.DoState(p); msgDialog.DoState(p);
oskDialog.DoState(p); oskDialog.DoState(p);
netDialog.DoState(p); netDialog.DoState(p);
screenshotDialog.DoState(p);
p.Do(currentlyLoadedModules); p.Do(currentlyLoadedModules);
p.DoMarker("sceUtility"); p.DoMarker("sceUtility");
} }
@ -82,6 +83,7 @@ void __UtilityShutdown()
msgDialog.Shutdown(true); msgDialog.Shutdown(true);
oskDialog.Shutdown(true); oskDialog.Shutdown(true);
netDialog.Shutdown(true); netDialog.Shutdown(true);
screenshotDialog.Shutdown(true);
} }
int __UtilityGetStatus() int __UtilityGetStatus()
@ -459,7 +461,7 @@ u32 sceUtilityGetSystemParamInt(u32 id, u32 destaddr)
param = g_Config.iDateFormat; param = g_Config.iDateFormat;
break; break;
case PSP_SYSTEMPARAM_ID_INT_TIME_FORMAT: case PSP_SYSTEMPARAM_ID_INT_TIME_FORMAT:
param = g_Config.itimeformat?PSP_SYSTEMPARAM_TIME_FORMAT_12HR:PSP_SYSTEMPARAM_TIME_FORMAT_24HR; param = g_Config.iTimeFormat?PSP_SYSTEMPARAM_TIME_FORMAT_12HR:PSP_SYSTEMPARAM_TIME_FORMAT_24HR;
break; break;
case PSP_SYSTEMPARAM_ID_INT_TIMEZONE: case PSP_SYSTEMPARAM_ID_INT_TIMEZONE:
param = g_Config.iTimeZone; param = g_Config.iTimeZone;
@ -471,7 +473,7 @@ u32 sceUtilityGetSystemParamInt(u32 id, u32 destaddr)
param = g_Config.ilanguage; param = g_Config.ilanguage;
break; break;
case PSP_SYSTEMPARAM_ID_INT_BUTTON_PREFERENCE: case PSP_SYSTEMPARAM_ID_INT_BUTTON_PREFERENCE:
param = g_Config.bButtonPreference?PSP_SYSTEMPARAM_BUTTON_CROSS:PSP_SYSTEMPARAM_BUTTON_CIRCLE; param = g_Config.iButtonPreference?PSP_SYSTEMPARAM_BUTTON_CROSS:PSP_SYSTEMPARAM_BUTTON_CIRCLE;
break; break;
case PSP_SYSTEMPARAM_ID_INT_LOCK_PARENTAL_LEVEL: case PSP_SYSTEMPARAM_ID_INT_LOCK_PARENTAL_LEVEL:
param = g_Config.iLockParentalLevel; param = g_Config.iLockParentalLevel;

View file

@ -369,14 +369,13 @@ void MediaEngine::updateSwsFormat(int videoPixelMode) {
} }
bool MediaEngine::stepVideo(int videoPixelMode) { bool MediaEngine::stepVideo(int videoPixelMode) {
// if video engine is broken, force to add timestamp
m_videopts += 3003;
#ifdef USE_FFMPEG
if (!m_pFormatCtx) if (!m_pFormatCtx)
return false; return false;
if (!m_pCodecCtx) if (!m_pCodecCtx)
return false; return false;
// if video engine is broken, force to add timestamp
m_videopts += 3003;
#ifdef USE_FFMPEG
updateSwsFormat(videoPixelMode); updateSwsFormat(videoPixelMode);
// TODO: Technically we could set this to frameWidth instead of m_desWidth for better perf. // TODO: Technically we could set this to frameWidth instead of m_desWidth for better perf.
// Update the linesize for the new format too. We started with the largest size, so it should fit. // Update the linesize for the new format too. We started with the largest size, so it should fit.
@ -525,7 +524,7 @@ int MediaEngine::writeVideoImage(u8* buffer, int frameWidth, int videoPixelMode)
} }
return videoImageSize; return videoImageSize;
#endif // USE_FFMPEG #endif // USE_FFMPEG
return true; return 0;
} }
int MediaEngine::writeVideoImageWithRange(u8* buffer, int frameWidth, int videoPixelMode, int MediaEngine::writeVideoImageWithRange(u8* buffer, int frameWidth, int videoPixelMode,
@ -590,7 +589,7 @@ int MediaEngine::writeVideoImageWithRange(u8* buffer, int frameWidth, int videoP
} }
return videoImageSize; return videoImageSize;
#endif // USE_FFMPEG #endif // USE_FFMPEG
return true; return 0;
} }
static bool isHeader(u8* audioStream, int offset) static bool isHeader(u8* audioStream, int offset)

View file

@ -211,7 +211,7 @@ namespace Reporting
postdata.Add("pixel_height", PSP_CoreParameter().pixelHeight); postdata.Add("pixel_height", PSP_CoreParameter().pixelHeight);
postdata.Add("ticks", (const uint64_t)CoreTiming::GetTicks()); postdata.Add("ticks", (const uint64_t)CoreTiming::GetTicks());
if (g_Config.bShowFPSCounter) if (g_Config.iShowFPSCounter)
{ {
float vps, fps; float vps, fps;
__DisplayGetAveragedFPS(&vps, &fps); __DisplayGetAveragedFPS(&vps, &fps);

View file

@ -32,6 +32,7 @@ enum GlobalUIState {
UISTATE_MENU, UISTATE_MENU,
UISTATE_PAUSEMENU, UISTATE_PAUSEMENU,
UISTATE_INGAME, UISTATE_INGAME,
UISTATE_EXIT,
}; };

View file

@ -956,9 +956,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
break; break;
case GE_CMD_TEXLEVEL: case GE_CMD_TEXLEVEL:
if (data == 1) // We support 000001, it means fixed at mip level 0. Don't report 0 as it's normal.
WARN_LOG_REPORT_ONCE(texLevel1, G3D, "Unsupported texture level bias settings: %06x", data) if (data != 1 && data != 0)
else if (data != 0)
WARN_LOG_REPORT_ONCE(texLevel2, G3D, "Unsupported texture level bias settings: %06x", data); WARN_LOG_REPORT_ONCE(texLevel2, G3D, "Unsupported texture level bias settings: %06x", data);
break; break;
#endif #endif

View file

@ -350,16 +350,35 @@ void FramebufferManager::SetRenderFrameBuffer() {
int drawing_width, drawing_height; int drawing_width, drawing_height;
GuessDrawingSize(drawing_width, drawing_height); GuessDrawingSize(drawing_width, drawing_height);
// Find a matching framebuffer int buffer_width = drawing_width;
int buffer_height = drawing_height;
// Find a matching framebuffer, same size or bigger
VirtualFramebuffer *vfb = 0; VirtualFramebuffer *vfb = 0;
for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) { for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) {
VirtualFramebuffer *v = *iter; VirtualFramebuffer *v = *iter;
if (MaskedEqual(v->fb_address, fb_address) && v->width == drawing_width && v->height == drawing_height && v->format == fmt) { if (MaskedEqual(v->fb_address, fb_address) && v->format == fmt) {
// Let's not be so picky for now. Let's say this is the one. // Okay, let's check the sizes. If the new one is bigger than the old one, recreate.
vfb = v; // If the opposite, just use it and hope that the game sets scissors accordingly.
// Update fb stride in case it changed if (v->bufferWidth >= drawing_width && v->bufferHeight >= drawing_height) {
vfb->fb_stride = fb_stride; // Let's not be so picky for now. Let's say this is the one.
break; vfb = v;
// Update fb stride in case it changed
vfb->fb_stride = fb_stride;
// Just hack the width/height and we should be fine. also hack renderwidth/renderheight?
v->width = drawing_width;
v->height = drawing_height;
break;
} else {
INFO_LOG(HLE, "Embiggening framebuffer (%i, %i) -> (%i, %i)", (int)v->width, (int)v->height, drawing_width, drawing_height);
// drawing_width or drawing_height is bigger. Let's recreate with the max.
// To do this right we should copy the data over too, but meh.
buffer_width = std::max((int)v->width, drawing_width);
buffer_height = std::max((int)v->height, drawing_height);
delete v;
vfbs_.erase(iter);
break;
}
} }
} }
@ -379,6 +398,8 @@ void FramebufferManager::SetRenderFrameBuffer() {
vfb->height = drawing_height; vfb->height = drawing_height;
vfb->renderWidth = (u16)(drawing_width * renderWidthFactor); vfb->renderWidth = (u16)(drawing_width * renderWidthFactor);
vfb->renderHeight = (u16)(drawing_height * renderHeightFactor); vfb->renderHeight = (u16)(drawing_height * renderHeightFactor);
vfb->bufferWidth = buffer_width;
vfb->bufferHeight = buffer_height;
vfb->format = fmt; vfb->format = fmt;
vfb->usageFlags = FB_USAGE_RENDERTARGET; vfb->usageFlags = FB_USAGE_RENDERTARGET;
vfb->dirtyAfterDisplay = true; vfb->dirtyAfterDisplay = true;

View file

@ -54,10 +54,16 @@ struct VirtualFramebuffer {
int z_stride; int z_stride;
// There's also a top left of the drawing region, but meh... // There's also a top left of the drawing region, but meh...
// width/height: The detected size of the current framebuffer.
u16 width; u16 width;
u16 height; u16 height;
// renderWidth/renderHeight: The actual size we render at. May be scaled to render at higher resolutions.
u16 renderWidth; u16 renderWidth;
u16 renderHeight; u16 renderHeight;
// bufferWidth/bufferHeight: The actual (but non scaled) size of the buffer we render to. May only be bigger than width/height.
u16 bufferWidth;
u16 bufferHeight;
u16 usageFlags; u16 usageFlags;

View file

@ -390,7 +390,22 @@ void LinkedShader::updateUniforms() {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (dirtyUniforms & (DIRTY_LIGHT0 << i)) { if (dirtyUniforms & (DIRTY_LIGHT0 << i)) {
if (u_lightpos[i] != -1) glUniform3fv(u_lightpos[i], 1, gstate_c.lightpos[i]); GELightType type = (GELightType)((gstate.ltype[i] >> 8) & 3);
if (type == GE_LIGHTTYPE_DIRECTIONAL) {
// Prenormalize
float x = gstate_c.lightpos[i][0];
float y = gstate_c.lightpos[i][1];
float z = gstate_c.lightpos[i][2];
float len = sqrtf(x*x+y*y+z*z);
if (len == 0.0f)
len = 1.0f;
else
len = 1.0f / len;
float vec[3] = { x / len, y / len, z / len };
if (u_lightpos[i] != -1) glUniform3fv(u_lightpos[i], 1, vec);
} else {
if (u_lightpos[i] != -1) glUniform3fv(u_lightpos[i], 1, gstate_c.lightpos[i]);
}
if (u_lightdir[i] != -1) glUniform3fv(u_lightdir[i], 1, gstate_c.lightdir[i]); if (u_lightdir[i] != -1) glUniform3fv(u_lightdir[i], 1, gstate_c.lightdir[i]);
if (u_lightatt[i] != -1) glUniform3fv(u_lightatt[i], 1, gstate_c.lightatt[i]); if (u_lightatt[i] != -1) glUniform3fv(u_lightatt[i], 1, gstate_c.lightatt[i]);
if (u_lightangle[i] != -1) glUniform1f(u_lightangle[i], gstate_c.lightangle[i]); if (u_lightangle[i] != -1) glUniform1f(u_lightangle[i], gstate_c.lightangle[i]);

View file

@ -265,8 +265,8 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
if (g_Config.bBufferedRendering) { if (g_Config.bBufferedRendering) {
renderX = 0; renderX = 0;
renderY = 0; renderY = 0;
renderWidth = framebufferManager_->GetRenderWidth(); renderWidth = framebufferManager_->GetRenderWidth();
renderHeight = framebufferManager_->GetRenderHeight(); renderHeight = framebufferManager_->GetRenderHeight();
renderWidthFactor = (float)renderWidth / framebufferManager_->GetTargetWidth(); renderWidthFactor = (float)renderWidth / framebufferManager_->GetTargetWidth();
renderHeightFactor = (float)renderHeight / framebufferManager_->GetTargetHeight(); renderHeightFactor = (float)renderHeight / framebufferManager_->GetTargetHeight();
} else { } else {

View file

@ -484,16 +484,6 @@ static const GLuint MagFiltGL[2] = {
GL_LINEAR GL_LINEAR
}; };
// 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
#ifndef GL_TEXTURE_MAX_LOD
#define GL_TEXTURE_MAX_LOD 0x813B
#endif
// This should not have to be done per texture! OpenGL is silly yo // This should not have to be done per texture! OpenGL is silly yo
// TODO: Dirty-check this against the current texture. // TODO: Dirty-check this against the current texture.
void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) { void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
@ -502,6 +492,8 @@ void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
bool sClamp = gstate.texwrap & 1; bool sClamp = gstate.texwrap & 1;
bool tClamp = (gstate.texwrap>>8) & 1; bool tClamp = (gstate.texwrap>>8) & 1;
bool noMip = (gstate.texlevel & 0xFFFFFF) == 0x000001; // Fix texlevel at 0
if (entry.maxLevel == 0) { if (entry.maxLevel == 0) {
// Enforce no mip filtering, for safety. // Enforce no mip filtering, for safety.
minFilt &= 1; // no mipmaps yet minFilt &= 1; // no mipmaps yet
@ -509,7 +501,9 @@ void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
// TODO: Is this a signed value? Which direction? // TODO: Is this a signed value? Which direction?
float lodBias = 0.0; // -(float)((gstate.texlevel >> 16) & 0xFF) / 16.0f; float lodBias = 0.0; // -(float)((gstate.texlevel >> 16) & 0xFF) / 16.0f;
if (force || entry.lodBias != lodBias) { if (force || entry.lodBias != lodBias) {
#ifndef USING_GLES2
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, lodBias); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, lodBias);
#endif
entry.lodBias = lodBias; entry.lodBias = lodBias;
} }
} }
@ -519,7 +513,7 @@ void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
minFilt |= 1; minFilt |= 1;
} }
if (!g_Config.bMipMap) { if (!g_Config.bMipMap || noMip) {
magFilt &= 1; magFilt &= 1;
minFilt &= 1; minFilt &= 1;
} }
@ -1117,8 +1111,8 @@ void TextureCache::SetTexture() {
LoadTextureLevel(*entry, i, replaceImages); LoadTextureLevel(*entry, i, replaceImages);
} }
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel);
#endif
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (float)maxLevel); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (float)maxLevel);
#endif
} else { } else {
LoadTextureLevel(*entry, 0, replaceImages); LoadTextureLevel(*entry, 0, replaceImages);
#ifndef USING_GLES2 #ifndef USING_GLES2

View file

@ -429,9 +429,10 @@ void GenerateVertexShader(int prim, char *buffer, bool useHWTransform) {
GELightComputation comp = (GELightComputation)(gstate.ltype[i] & 3); GELightComputation comp = (GELightComputation)(gstate.ltype[i] & 3);
GELightType type = (GELightType)((gstate.ltype[i] >> 8) & 3); GELightType type = (GELightType)((gstate.ltype[i] >> 8) & 3);
if (type == GE_LIGHTTYPE_DIRECTIONAL) if (type == GE_LIGHTTYPE_DIRECTIONAL) {
WRITE(p, " toLight = normalize(u_lightpos%i);\n", i); // We prenormalize light positions for directional lights.
else { WRITE(p, " toLight = u_lightpos%i;\n", i);
} else {
WRITE(p, " toLight = u_lightpos%i - worldpos;\n", i); WRITE(p, " toLight = u_lightpos%i - worldpos;\n", i);
WRITE(p, " distance = length(toLight);\n"); WRITE(p, " distance = length(toLight);\n");
WRITE(p, " toLight /= distance;\n"); WRITE(p, " toLight /= distance;\n");

View file

@ -337,11 +337,18 @@ void EmuScreen::render() {
ui_draw2d.SetFontScale(1.0f, 1.0f); ui_draw2d.SetFontScale(1.0f, 1.0f);
} }
if (g_Config.bShowFPSCounter) { if (g_Config.iShowFPSCounter) {
float vps, fps; float vps, fps;
__DisplayGetFPS(&vps, &fps); __DisplayGetFPS(&vps, &fps);
char fpsbuf[256]; char fpsbuf[256];
sprintf(fpsbuf, "VPS: %0.1f\nFPS: %0.1f", vps, fps); switch (g_Config.iShowFPSCounter) {
case 1:
sprintf(fpsbuf, "VPS: %0.1f", vps); break;
case 2:
sprintf(fpsbuf, "FPS: %0.1f", fps); break;
case 3:
sprintf(fpsbuf, "VPS: %0.1f\nFPS: %0.1f", vps, fps); break;
}
ui_draw2d.DrawText(UBUNTU24, fpsbuf, dp_xres - 8, 12, 0xc0000000, ALIGN_TOPRIGHT); ui_draw2d.DrawText(UBUNTU24, fpsbuf, dp_xres - 8, 12, 0xc0000000, ALIGN_TOPRIGHT);
ui_draw2d.DrawText(UBUNTU24, fpsbuf, dp_xres - 10, 10, 0xFF3fFF3f, ALIGN_TOPRIGHT); ui_draw2d.DrawText(UBUNTU24, fpsbuf, dp_xres - 10, 10, 0xFF3fFF3f, ALIGN_TOPRIGHT);
} }

View file

@ -40,7 +40,7 @@ TouchStick leftStick(&ui_atlas, I_STICKBG, I_STICK, 0);
void LayoutGamepad(int w, int h) void LayoutGamepad(int w, int h)
{ {
float controlScale = g_Config.bLargeControls ? 1.6 : 1.15; float controlScale = g_Config.bLargeControls ? g_Config.fButtonScale : 1.15;
const int button_spacing = 50 * controlScale; const int button_spacing = 50 * controlScale;
const int arrow_spacing = 40 * controlScale; const int arrow_spacing = 40 * controlScale;

View file

@ -466,8 +466,6 @@ void PauseScreen::render() {
if (gpu) if (gpu)
gpu->Resized(); gpu->Resized();
} }
UICheckBox(GEN_ID, x, y += stride, ss->T("Show FPS"), ALIGN_TOPLEFT, &g_Config.bShowFPSCounter);
bool enableFrameSkip = g_Config.iFrameSkip != 0; bool enableFrameSkip = g_Config.iFrameSkip != 0;
UICheckBox(GEN_ID, x, y += stride , gs->T("Frame Skipping"), ALIGN_TOPLEFT, &enableFrameSkip); UICheckBox(GEN_ID, x, y += stride , gs->T("Frame Skipping"), ALIGN_TOPLEFT, &enableFrameSkip);
if (enableFrameSkip) { if (enableFrameSkip) {
@ -490,16 +488,52 @@ void PauseScreen::render() {
} else } else
g_Config.iFrameSkip = 0; g_Config.iFrameSkip = 0;
// TODO: Add UI for more than one slot. UICheckBox(GEN_ID, x, y += stride, gs->T("Linear Filtering"), ALIGN_TOPLEFT, &g_Config.bLinearFiltering);
HLinear hlinear2(x, y += 70, 20); ui_draw2d.DrawText(UBUNTU24, gs->T("Save State :"), 30, y += 40, 0xFFFFFFFF, ALIGN_LEFT);
if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH, 0, i->T("Save State"), ALIGN_LEFT)) { HLinear hlinear4(x + 180 , y , 10);
if (UIButton(GEN_ID, hlinear4, 60, 0, "1", ALIGN_LEFT)) {
SaveState::SaveSlot(0, 0, 0); SaveState::SaveSlot(0, 0, 0);
screenManager()->finishDialog(this, DR_CANCEL); screenManager()->finishDialog(this, DR_CANCEL);
} }
if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH, 0, i->T("Load State"), ALIGN_LEFT)) { if (UIButton(GEN_ID, hlinear4, 60, 0, "2", ALIGN_LEFT)) {
SaveState::SaveSlot(1, 0, 0);
screenManager()->finishDialog(this, DR_CANCEL);
}
if (UIButton(GEN_ID, hlinear4, 60, 0, "3", ALIGN_LEFT)) {
SaveState::SaveSlot(2, 0, 0);
screenManager()->finishDialog(this, DR_CANCEL);
}
if (UIButton(GEN_ID, hlinear4, 60, 0, "4", ALIGN_LEFT)) {
SaveState::SaveSlot(3, 0, 0);
screenManager()->finishDialog(this, DR_CANCEL);
}
if (UIButton(GEN_ID, hlinear4, 60, 0, "5", ALIGN_LEFT)) {
SaveState::SaveSlot(4, 0, 0);
screenManager()->finishDialog(this, DR_CANCEL);
}
ui_draw2d.DrawText(UBUNTU24, gs->T("Load State :"), 30, y += 60, 0xFFFFFFFF, ALIGN_LEFT);
HLinear hlinear3(x + 180 , y + 10 , 10);
if (UIButton(GEN_ID, hlinear3, 60, 0, "1", ALIGN_LEFT)) {
SaveState::LoadSlot(0, 0, 0); SaveState::LoadSlot(0, 0, 0);
screenManager()->finishDialog(this, DR_CANCEL); screenManager()->finishDialog(this, DR_CANCEL);
} }
if (UIButton(GEN_ID, hlinear3, 60, 0, "2", ALIGN_LEFT)) {
SaveState::LoadSlot(1, 0, 0);
screenManager()->finishDialog(this, DR_CANCEL);
}
if (UIButton(GEN_ID, hlinear3, 60, 0, "3", ALIGN_LEFT)) {
SaveState::LoadSlot(2, 0, 0);
screenManager()->finishDialog(this, DR_CANCEL);
}
if (UIButton(GEN_ID, hlinear3, 60, 0, "4", ALIGN_LEFT)) {
SaveState::LoadSlot(3, 0, 0);
screenManager()->finishDialog(this, DR_CANCEL);
}
if (UIButton(GEN_ID, hlinear3, 60, 0, "5", ALIGN_LEFT)) {
SaveState::LoadSlot(4, 0, 0);
screenManager()->finishDialog(this, DR_CANCEL);
}
DrawWatermark(); DrawWatermark();
UIEnd(); UIEnd();
@ -666,27 +700,31 @@ void DeveloperScreen::render() {
screenManager()->finishDialog(this, DR_OK); screenManager()->finishDialog(this, DR_OK);
} }
if (UIButton(GEN_ID, vlinear, w, 0, d->T("Load language ini"), ALIGN_LEFT)) { if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH + 80, 0, d->T("Load language ini"), ALIGN_LEFT)) {
i18nrepo.LoadIni(g_Config.languageIni); i18nrepo.LoadIni(g_Config.languageIni);
// After this, g and s are no longer valid. Need to reload them. // After this, g and s are no longer valid. Need to reload them.
g = GetI18NCategory("General"); g = GetI18NCategory("General");
d = GetI18NCategory("Developer"); d = GetI18NCategory("Developer");
} }
if (UIButton(GEN_ID, vlinear, w, 0, d->T("Save language ini"), ALIGN_LEFT)) { if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH + 80, 0, d->T("Save language ini"), ALIGN_LEFT)) {
i18nrepo.SaveIni(g_Config.languageIni); i18nrepo.SaveIni(g_Config.languageIni);
} }
if (UIButton(GEN_ID, vlinear, w, 0, d->T("Run CPU tests"), ALIGN_LEFT)) { if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH + 80, 0, d->T("Run CPU Tests"), ALIGN_LEFT)) {
// TODO: Run tests // TODO: Run tests
RunTests(); RunTests();
// screenManager()->push(new EmuScreen()) // screenManager()->push(new EmuScreen())
} }
if (UIButton(GEN_ID, vlinear, w, 0, d->T("Dump frame to log"), ALIGN_LEFT)) { if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH + 80, 0, d->T("Dump next frame"), ALIGN_LEFT)) {
gpu->DumpNextFrame(); gpu->DumpNextFrame();
} }
if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH + 80, 0, d->T("Cleanup Recents"), ALIGN_LEFT)) {
g_Config.recentIsos.clear();
}
UIEnd(); UIEnd();
} }
@ -908,7 +946,35 @@ void GraphicsScreenP3::render() {
int y = 35; int y = 35;
int stride = 40; int stride = 40;
int columnw = 400; int columnw = 400;
bool ShowCounter = g_Config.iShowFPSCounter > 0;
UICheckBox(GEN_ID, x, y += stride, gs->T("Show VPS/FPS"), ALIGN_TOPLEFT, &ShowCounter);
if (ShowCounter) {
if (g_Config.iShowFPSCounter <= 0)
g_Config.iShowFPSCounter = 1;
char counter[256];
std::string type;
switch (g_Config.iShowFPSCounter) {
case 1: type = "VPS";break;
case 2: type = "FPS";break;
case 3: type = "Both";break;
}
sprintf(counter, "%s %s", gs->T("Format :"), type.c_str());
ui_draw2d.DrawText(UBUNTU24, counter, x + 60, y += stride , 0xFFFFFFFF, ALIGN_LEFT);
HLinear hlinear1(x + 250, y, 20);
if (UIButton(GEN_ID, hlinear1, 80, 0, gs->T("VPS"), ALIGN_LEFT))
g_Config.iShowFPSCounter = 1;
if (UIButton(GEN_ID, hlinear1, 80, 0, gs->T("FPS"), ALIGN_LEFT))
g_Config.iShowFPSCounter = 2;
if (UIButton(GEN_ID, hlinear1, 90, 0, gs->T("Both"), ALIGN_LEFT))
g_Config.iShowFPSCounter = 3;
y += 20;
} else
g_Config.iShowFPSCounter = 0;
bool FpsLimit = g_Config.iFpsLimit != 0; bool FpsLimit = g_Config.iFpsLimit != 0;
UICheckBox(GEN_ID, x, y += stride, gs->T("FPS Limit"), ALIGN_TOPLEFT, &FpsLimit); UICheckBox(GEN_ID, x, y += stride, gs->T("FPS Limit"), ALIGN_TOPLEFT, &FpsLimit);
if (FpsLimit) { if (FpsLimit) {
@ -976,7 +1042,7 @@ void LanguageScreen::render() {
I18NCategory *g = GetI18NCategory("General"); I18NCategory *g = GetI18NCategory("General");
I18NCategory *l = GetI18NCategory("Language"); I18NCategory *l = GetI18NCategory("Language");
bool small = dp_xres < 720; bool small = dp_xres < 790;
if (!small) { if (!small) {
ui_draw2d.SetFontScale(1.5f, 1.5f); ui_draw2d.SetFontScale(1.5f, 1.5f);
@ -999,6 +1065,12 @@ void LanguageScreen::render() {
for (size_t i = 0; i < langs_.size(); i++) { for (size_t i = 0; i < langs_.size(); i++) {
// Skip README
if (langs_[i].name.find("README") != std::string::npos) {
continue;
}
std::string code; std::string code;
size_t dot = langs_[i].name.find('.'); size_t dot = langs_[i].name.find('.');
if (dot != std::string::npos) if (dot != std::string::npos)
@ -1022,6 +1094,7 @@ void LanguageScreen::render() {
langValuesMapping["zh_CN"] = std::make_pair("简体中文", PSP_SYSTEMPARAM_LANGUAGE_CHINESE_SIMPLIFIED); langValuesMapping["zh_CN"] = std::make_pair("简体中文", PSP_SYSTEMPARAM_LANGUAGE_CHINESE_SIMPLIFIED);
//langValuesMapping["ar_AE"] = std::make_pair("العربية", PSP_SYSTEMPARAM_LANGUAGE_ENGLISH); //langValuesMapping["ar_AE"] = std::make_pair("العربية", PSP_SYSTEMPARAM_LANGUAGE_ENGLISH);
langValuesMapping["az_AZ"] = std::make_pair("Azeri", PSP_SYSTEMPARAM_LANGUAGE_ENGLISH);
langValuesMapping["ca_ES"] = std::make_pair("Català", PSP_SYSTEMPARAM_LANGUAGE_ENGLISH); langValuesMapping["ca_ES"] = std::make_pair("Català", PSP_SYSTEMPARAM_LANGUAGE_ENGLISH);
langValuesMapping["gr_EL"] = std::make_pair("ελληνικά", PSP_SYSTEMPARAM_LANGUAGE_ENGLISH); langValuesMapping["gr_EL"] = std::make_pair("ελληνικά", PSP_SYSTEMPARAM_LANGUAGE_ENGLISH);
langValuesMapping["he_IL"] = std::make_pair("עברית", PSP_SYSTEMPARAM_LANGUAGE_ENGLISH); langValuesMapping["he_IL"] = std::make_pair("עברית", PSP_SYSTEMPARAM_LANGUAGE_ENGLISH);
@ -1035,7 +1108,7 @@ void LanguageScreen::render() {
if (!code.empty()) { if (!code.empty()) {
if(langValuesMapping.find(code) == langValuesMapping.end()) { if(langValuesMapping.find(code) == langValuesMapping.end()) {
//No title found, show locale code // No title found, show locale code
buttonTitle = code; buttonTitle = code;
} else { } else {
buttonTitle = langValuesMapping[code].first; buttonTitle = langValuesMapping[code].first;
@ -1102,18 +1175,84 @@ void SystemScreen::render() {
#endif #endif
if (g_Config.bJit) if (g_Config.bJit)
UICheckBox(GEN_ID, x, y += stride, s->T("Fast Memory", "Fast Memory (unstable)"), ALIGN_TOPLEFT, &g_Config.bFastMemory); UICheckBox(GEN_ID, x, y += stride, s->T("Fast Memory", "Fast Memory (unstable)"), ALIGN_TOPLEFT, &g_Config.bFastMemory);
UICheckBox(GEN_ID, x, y += stride, s->T("Show FPS"), ALIGN_TOPLEFT, &g_Config.bShowFPSCounter);
UICheckBox(GEN_ID, x, y += stride, s->T("Encrypt Save"), ALIGN_TOPLEFT, &g_Config.bEncryptSave); UICheckBox(GEN_ID, x, y += stride, s->T("Daylight Savings"), ALIGN_TOPLEFT, &g_Config.bDayLightSavings);
UICheckBox(GEN_ID, x, y += stride, s->T("Use Button X to Confirm"), ALIGN_TOPLEFT, &g_Config.bButtonPreference); UICheckBox(GEN_ID, x, y += stride, s->T("Button Preference"), ALIGN_TOPLEFT, &g_Config.bButtonPreference);
bool tf = g_Config.itimeformat == 1; if (g_Config.bButtonPreference) {
if (UICheckBox(GEN_ID, x, y += stride, s->T("12HR Time Format"), ALIGN_TOPLEFT, &tf)) { char button[256];
g_Config.itimeformat = tf ? 1 : 0; std::string type;
switch (g_Config.iButtonPreference) {
case 0: type = "O to Enter";break;
case 1: type = "X to Enter";break;
}
sprintf(button, "%s %s", s->T("Type :"), type.c_str());
ui_draw2d.DrawText(UBUNTU24, button, x + 60, y += stride , 0xFFFFFFFF, ALIGN_LEFT);
HLinear hlinear1(x + 280, y, 20);
if (UIButton(GEN_ID, hlinear1, 90, 0, s->T("Use O"), ALIGN_LEFT))
g_Config.iButtonPreference = 0;
if (UIButton(GEN_ID, hlinear1, 90, 0, s->T("Use X"), ALIGN_LEFT))
g_Config.iButtonPreference = 1;
y += 10;
} }
/*
bool time = g_Config.iTimeFormat > 0 ;
UICheckBox(GEN_ID, x, y += stride, s->T("Time Format"), ALIGN_TOPLEFT, &time);
if (time) {
if (g_Config.iTimeFormat <= 0)
g_Config.iTimeFormat = 1;
char button[256];
std::string type;
switch (g_Config.iTimeFormat) {
case 1: type = "12HR";break;
case 2: type = "24HR";break;
}
sprintf(button, "%s %s", s->T("Format :"), type.c_str());
ui_draw2d.DrawText(UBUNTU24, button, x + 60, y += stride , 0xFFFFFFFF, ALIGN_LEFT);
HLinear hlinear1(x + 280, y, 20);
if (UIButton(GEN_ID, hlinear1, 80, 0, s->T("12HR"), ALIGN_LEFT))
g_Config.iTimeFormat = 1;
if (UIButton(GEN_ID, hlinear1, 80, 0, s->T("24HR"), ALIGN_LEFT))
g_Config.iTimeFormat = 2;
y += 10;
} else
g_Config.iTimeFormat = 0 ;
bool date = g_Config.iDateFormat > 0;
UICheckBox(GEN_ID, x, y += stride, s->T("Date Format"), ALIGN_TOPLEFT, &date);
if (date) {
if (g_Config.iDateFormat <= 0)
g_Config.iDateFormat = 1;
char button[256];
std::string type;
switch (g_Config.iDateFormat) {
case 1: type = "YYYYMMDD";break;
case 2: type = "MMDDYYYY";break;
case 3: type = "DDMMYYYY";break;
}
sprintf(button, "%s %s", s->T("Format :"), type.c_str());
ui_draw2d.DrawText(UBUNTU24, button, x + 60, y += stride , 0xFFFFFFFF, ALIGN_LEFT);
HLinear hlinear1(x + 350, y, 10);
if (UIButton(GEN_ID, hlinear1, 70, 0, s->T("YMD"), ALIGN_LEFT))
g_Config.iDateFormat = 1;
if (UIButton(GEN_ID, hlinear1, 70, 0, s->T("MDY"), ALIGN_LEFT))
g_Config.iDateFormat = 2;
if (UIButton(GEN_ID, hlinear1, 70, 0, s->T("DMY"), ALIGN_LEFT))
g_Config.iDateFormat = 3;
y += 10;
} else
g_Config.iDateFormat = 0;
*/
UICheckBox(GEN_ID, x, y += stride, s->T("Enable Cheats"), ALIGN_TOPLEFT, &g_Config.bEnableCheats); UICheckBox(GEN_ID, x, y += stride, s->T("Enable Cheats"), ALIGN_TOPLEFT, &g_Config.bEnableCheats);
HLinear hlinear2(x, y += stride + 10, 20); if (g_Config.bEnableCheats) {
if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH + 50, 0, s->T("Reload Cheats"), ALIGN_TOPLEFT)) { HLinear hlinear1(x + 60, y += stride + 10, 20);
g_Config.bReloadCheats = true; if (UIButton(GEN_ID, hlinear1, LARGE_BUTTON_WIDTH + 50, 0, s->T("Reload Cheats"), ALIGN_TOPLEFT))
g_Config.bReloadCheats = true;
y += 10;
} }
HLinear hlinear2(x, y += stride + 10, 20);
if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH, 0, s->T("Language"), ALIGN_TOPLEFT)) { if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH, 0, s->T("Language"), ALIGN_TOPLEFT)) {
screenManager()->push(new LanguageScreen()); screenManager()->push(new LanguageScreen());
} }
@ -1143,17 +1282,47 @@ void ControlsScreen::render() {
int columnw = 440; int columnw = 440;
UICheckBox(GEN_ID, x, y += stride, c->T("OnScreen", "On-Screen Touch Controls"), ALIGN_TOPLEFT, &g_Config.bShowTouchControls); UICheckBox(GEN_ID, x, y += stride, c->T("OnScreen", "On-Screen Touch Controls"), ALIGN_TOPLEFT, &g_Config.bShowTouchControls);
UICheckBox(GEN_ID, x, y += stride, c->T("Show Analog Stick"), ALIGN_TOPLEFT, &g_Config.bShowAnalogStick);
UICheckBox(GEN_ID, x, y += stride, c->T("Tilt", "Tilt to Analog (horizontal)"), ALIGN_TOPLEFT, &g_Config.bAccelerometerToAnalogHoriz);
if (g_Config.bShowTouchControls) { if (g_Config.bShowTouchControls) {
UICheckBox(GEN_ID, x, y += stride, c->T("Large Controls"), ALIGN_TOPLEFT, &g_Config.bLargeControls); UICheckBox(GEN_ID, x, y += stride, c->T("Buttons Scaling"), ALIGN_TOPLEFT, &g_Config.bLargeControls);
UICheckBox(GEN_ID, x, y += stride, c->T("Show Analog Stick"), ALIGN_TOPLEFT, &g_Config.bShowAnalogStick); if (g_Config.bLargeControls) {
char scale[256];
sprintf(scale, "%s %0.2f", c->T("Scale :"), g_Config.fButtonScale);
ui_draw2d.DrawText(UBUNTU24, scale, x + 60, y += stride , 0xFFFFFFFF, ALIGN_LEFT);
HLinear hlinear1(x + 250, y, 20);
if (UIButton(GEN_ID, hlinear1, 80, 0, c->T("Auto"), ALIGN_LEFT))
g_Config.fButtonScale = 1.15;
if (UIButton(GEN_ID, hlinear1, 60, 0, c->T("-0.1"), ALIGN_LEFT))
if (g_Config.fButtonScale > 1.15)
g_Config.fButtonScale -= 0.1;
if (UIButton(GEN_ID, hlinear1, 60, 0, c->T("+0.1"), ALIGN_LEFT))
if (g_Config.fButtonScale < 2.05)
g_Config.fButtonScale += 0.1;
y += 20;
}
// This will be a slider in the new UI later // This will be a slider in the new UI later
bool bTransparent = g_Config.iTouchButtonOpacity < 30; bool bTransparent = g_Config.iTouchButtonOpacity < 65;
bool prev = bTransparent; bool prev = bTransparent;
UICheckBox(GEN_ID, x, y += stride, c->T("Transparent Buttons"), ALIGN_TOPLEFT, &bTransparent); UICheckBox(GEN_ID, x, y += stride, c->T("Buttons Opacity"), ALIGN_TOPLEFT, &bTransparent);
if (bTransparent) {
char opacity[256];
sprintf(opacity, "%s %d", c->T("Opacity :"), g_Config.iTouchButtonOpacity);
ui_draw2d.DrawText(UBUNTU24, opacity, x + 60, y += stride , 0xFFFFFFFF, ALIGN_LEFT);
HLinear hlinear1(x + 250, y, 20);
if (UIButton(GEN_ID, hlinear1, 80, 0, c->T("Auto"), ALIGN_LEFT))
g_Config.iTouchButtonOpacity = 15;
if (UIButton(GEN_ID, hlinear1, 40, 0, c->T("-5"), ALIGN_LEFT))
if (g_Config.iTouchButtonOpacity > 15)
g_Config.iTouchButtonOpacity -= 5;
if (UIButton(GEN_ID, hlinear1, 40, 0, c->T("+5"), ALIGN_LEFT))
if (g_Config.iTouchButtonOpacity < 65)
g_Config.iTouchButtonOpacity += 5;
y += 20;
}
if (bTransparent != prev) if (bTransparent != prev)
g_Config.iTouchButtonOpacity = bTransparent ? 15 : 65; g_Config.iTouchButtonOpacity = bTransparent ? 15 : 65;
} }
UICheckBox(GEN_ID, x, y += stride, c->T("Tilt", "Tilt to Analog (horizontal)"), ALIGN_TOPLEFT, &g_Config.bAccelerometerToAnalogHoriz);
// Button to KeyMapping screen // Button to KeyMapping screen
I18NCategory *keyI18N = GetI18NCategory("KeyMapping"); I18NCategory *keyI18N = GetI18NCategory("KeyMapping");
@ -1457,7 +1626,7 @@ static const char * credits[] = {
"PPSSPP is intended for educational purposes only.", "PPSSPP is intended for educational purposes only.",
"", "",
"Please make sure that you own the rights to any games", "Please make sure that you own the rights to any games",
"you play by owning the UMD or buying the digital", "you play by owning the UMD or by buying the digital",
"download from the PSN store on your real PSP.", "download from the PSN store on your real PSP.",
"", "",
"", "",

View file

@ -237,6 +237,15 @@ void NativeInit(int argc, const char *argv[],
g_Config.externalDirectory = external_directory; g_Config.externalDirectory = external_directory;
#endif #endif
#ifdef ANDROID
// On Android, create a PSP directory tree in the external_directory,
// to hopefully reduce confusion a bit.
ILOG("Creating %s", (g_Config.externalDirectory + "/PSP").c_str());
mkDir((g_Config.externalDirectory + "/PSP").c_str());
mkDir((g_Config.externalDirectory + "/PSP/SAVEDATA").c_str());
mkDir((g_Config.externalDirectory + "/PSP/GAME").c_str());
#endif
const char *fileToLog = 0; const char *fileToLog = 0;
const char *stateToLoad = 0; const char *stateToLoad = 0;

View file

@ -55,7 +55,7 @@ void PluginScreen::CreateViews() {
Margins textMargins(20,17); Margins textMargins(20,17);
Margins buttonMargins(10,10); Margins buttonMargins(10,10);
root_->Add(new TextView(UBUNTU24, "Atrac3+ Audio Decoding Support", ALIGN_HCENTER, 1.0f, new LinearLayoutParams(textMargins))); root_->Add(new TextView(UBUNTU24, "Atrac3+ Audio Support", ALIGN_HCENTER, 1.5f, new LinearLayoutParams(textMargins)));
ViewGroup *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0)); ViewGroup *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0));
LinearLayout *scrollContents = new LinearLayout(ORIENT_VERTICAL); LinearLayout *scrollContents = new LinearLayout(ORIENT_VERTICAL);
@ -66,11 +66,11 @@ void PluginScreen::CreateViews() {
const char *legalityNotice = const char *legalityNotice =
p->T("Origins are dubious", "* Mai's Atrac3+ decoder is currently required\n" p->T("Origins are dubious", "* Mai's Atrac3+ decoder is currently required\n"
"for audio in many games.\n" "for background audio and voice in many games.\n"
"Please note that the origins of this code are dubious.\n" "Please note that the origins of this code are dubious.\n"
"Choose More Information for more information."); "Choose More Information for more information.");
scrollContents->Add(new TextView(0, legalityNotice, ALIGN_LEFT, 1.0f, new LinearLayoutParams(textMargins) )); scrollContents->Add(new TextView(0, legalityNotice, ALIGN_LEFT, 0.65f, new LinearLayoutParams(textMargins) ));
progress_ = root_->Add(new ProgressBar()); progress_ = root_->Add(new ProgressBar());
progress_->SetVisibility(V_GONE); progress_->SetVisibility(V_GONE);

View file

@ -49,7 +49,7 @@ namespace DSound
pcmwf.wBitsPerSample = 16; pcmwf.wBitsPerSample = 16;
dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; // //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS; // //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
dsbdesc.dwBufferBytes = bufferSize = BUFSIZE; //FIX32(pcmwf.wf.nAvgBytesPerSec); //change to set buffer size dsbdesc.dwBufferBytes = bufferSize = BUFSIZE; //FIX32(pcmwf.wf.nAvgBytesPerSec); //change to set buffer size
dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&pcmwf; dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&pcmwf;

View file

@ -16,6 +16,8 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <limits.h> #include <limits.h>
#include <algorithm>
#include "Core/HLE/sceCtrl.h" #include "Core/HLE/sceCtrl.h"
#include "DinputDevice.h" #include "DinputDevice.h"
#include "ControlMapping.h" #include "ControlMapping.h"
@ -25,6 +27,11 @@
#include "Xinput.h" #include "Xinput.h"
#pragma comment(lib,"dinput8.lib") #pragma comment(lib,"dinput8.lib")
#ifdef min
#undef min
#undef max
#endif
unsigned int dinput_ctrl_map[] = { unsigned int dinput_ctrl_map[] = {
11, PAD_BUTTON_MENU, // Open PauseScreen 11, PAD_BUTTON_MENU, // Open PauseScreen
10, PAD_BUTTON_BACK, // Toggle PauseScreen & Back Setting Page 10, PAD_BUTTON_BACK, // Toggle PauseScreen & Back Setting Page
@ -183,8 +190,15 @@ int DinputDevice::UpdateState(InputState &input_state)
if (analog) if (analog)
{ {
input_state.pad_lstick_x += (float)js.lX / 10000.f; float x = (float)js.lX / 10000.f;
input_state.pad_lstick_y += -((float)js.lY / 10000.f); float y = -((float)js.lY / 10000.f);
// Expand and clamp. Hack to let us reach the corners on most pads.
x = std::min(1.0f, std::max(-1.0f, x * 1.2f));
y = std::min(1.0f, std::max(-1.0f, y * 1.2f));
input_state.pad_lstick_x += x;
input_state.pad_lstick_y += y;
} }
for (u8 i = 0; i < sizeof(dinput_ctrl_map)/sizeof(dinput_ctrl_map[0]); i += 2) for (u8 i = 0; i < sizeof(dinput_ctrl_map)/sizeof(dinput_ctrl_map[0]); i += 2)

View file

@ -67,6 +67,7 @@ void EmuThread_Start()
void EmuThread_Stop() void EmuThread_Stop()
{ {
globalUIState = UISTATE_EXIT;
// DSound_UpdateSound(); // DSound_UpdateSound();
Core_Stop(); Core_Stop();
Core_WaitInactive(800); Core_WaitInactive(800);
@ -137,7 +138,14 @@ unsigned int WINAPI TheThread(void *)
Core_EnableStepping(FALSE); Core_EnableStepping(FALSE);
Core_Run(); while (globalUIState != UISTATE_EXIT)
{
Core_Run();
// We're here again, so the game quit. Restart Core_Run() which controls the UI.
// This way they can load a new game.
Core_UpdateState(CORE_RUNNING);
}
shutdown: shutdown:
_InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN); _InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN);

View file

@ -726,7 +726,7 @@ namespace MainWindow
g_Config.bVertexCache = !g_Config.bVertexCache; g_Config.bVertexCache = !g_Config.bVertexCache;
break; break;
case ID_OPTIONS_SHOWFPS: case ID_OPTIONS_SHOWFPS:
g_Config.bShowFPSCounter = !g_Config.bShowFPSCounter; g_Config.iShowFPSCounter = !g_Config.iShowFPSCounter;
break; break;
case ID_OPTIONS_DISPLAYRAWFRAMEBUFFER: case ID_OPTIONS_DISPLAYRAWFRAMEBUFFER:
g_Config.bDisplayFramebuffer = !g_Config.bDisplayFramebuffer; g_Config.bDisplayFramebuffer = !g_Config.bDisplayFramebuffer;
@ -898,7 +898,7 @@ namespace MainWindow
CHECKITEM(ID_EMULATION_RUNONLOAD, g_Config.bAutoRun); CHECKITEM(ID_EMULATION_RUNONLOAD, g_Config.bAutoRun);
CHECKITEM(ID_OPTIONS_USEVBO, g_Config.bUseVBO); CHECKITEM(ID_OPTIONS_USEVBO, g_Config.bUseVBO);
CHECKITEM(ID_OPTIONS_VERTEXCACHE, g_Config.bVertexCache); CHECKITEM(ID_OPTIONS_VERTEXCACHE, g_Config.bVertexCache);
CHECKITEM(ID_OPTIONS_SHOWFPS, g_Config.bShowFPSCounter); CHECKITEM(ID_OPTIONS_SHOWFPS, g_Config.iShowFPSCounter);
CHECKITEM(ID_OPTIONS_FRAMESKIP, g_Config.iFrameSkip != 0); CHECKITEM(ID_OPTIONS_FRAMESKIP, g_Config.iFrameSkip != 0);
CHECKITEM(ID_OPTIONS_MIPMAP, g_Config.bMipMap); CHECKITEM(ID_OPTIONS_MIPMAP, g_Config.bMipMap);
CHECKITEM(ID_OPTIONS_VSYNC, g_Config.iVSyncInterval != 0); CHECKITEM(ID_OPTIONS_VSYNC, g_Config.iVSyncInterval != 0);

View file

@ -23,7 +23,8 @@
<application <application
android:icon="@drawable/ic_launcher" android:icon="@drawable/ic_launcher"
android:label="@string/app_name"> android:label="@string/app_name"
android:allowBackup="true">
<activity <activity
android:name=".PpssppActivity" android:name=".PpssppActivity"
android:label="@string/app_name" android:label="@string/app_name"

2
ffmpeg

@ -1 +1 @@
Subproject commit 969f062d319ab9e3d341c6e661eedd51eefa50a2 Subproject commit e8ef410aac458a35064e67582fb80103c29e6474

View file

@ -200,12 +200,12 @@ int main(int argc, const char* argv[])
g_Config.bVertexCache = true; g_Config.bVertexCache = true;
g_Config.bTrueColor = true; g_Config.bTrueColor = true;
g_Config.ilanguage = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH; g_Config.ilanguage = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH;
g_Config.itimeformat = PSP_SYSTEMPARAM_TIME_FORMAT_24HR; g_Config.iTimeFormat = PSP_SYSTEMPARAM_TIME_FORMAT_24HR;
g_Config.bEncryptSave = true; g_Config.bEncryptSave = true;
g_Config.sNickName = "shadow"; g_Config.sNickName = "shadow";
g_Config.iTimeZone = 60; g_Config.iTimeZone = 60;
g_Config.iDateFormat = PSP_SYSTEMPARAM_DATE_FORMAT_DDMMYYYY; g_Config.iDateFormat = PSP_SYSTEMPARAM_DATE_FORMAT_DDMMYYYY;
g_Config.bButtonPreference = true; g_Config.iButtonPreference = PSP_SYSTEMPARAM_BUTTON_CROSS;
g_Config.iLockParentalLevel = 9; g_Config.iLockParentalLevel = 9;
#if defined(ANDROID) #if defined(ANDROID)

2
lang

@ -1 +1 @@
Subproject commit cf710f2017db93c4019ce53a03764edf3136fa84 Subproject commit 81dc0b9141e7d1445efc7b152b88ab16ff75c737

2
native

@ -1 +1 @@
Subproject commit 4c2f26ff35b9833752d956a97265261f1e149e58 Subproject commit 0a26fae856aecdaa426d92fa5dde101b19487796