diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1f376a937c..8de40af433 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -588,6 +588,8 @@ add_library(${CoreLibName} ${CoreLinkType}
Core/ELF/ElfTypes.h
Core/ELF/PrxDecrypter.cpp
Core/ELF/PrxDecrypter.h
+ Core/ELF/ParamSFO.cpp
+ Core/ELF/ParamSFO.h
Core/FileSystems/BlockDevices.cpp
Core/FileSystems/BlockDevices.h
Core/FileSystems/DirectoryFileSystem.cpp
diff --git a/Common/Log.h b/Common/Log.h
index 742a96d912..ff788063e6 100644
--- a/Common/Log.h
+++ b/Common/Log.h
@@ -101,6 +101,7 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type,
}
#define _dbg_assert_msg_(_t_, _a_, ...)\
if (!(_a_)) {\
+ printf(__VA_ARGS__); \
ERROR_LOG(_t_, __VA_ARGS__); \
if (!PanicYesNo(__VA_ARGS__)) {Crash();} \
}
diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt
index a8b41ce75d..8428959a2f 100644
--- a/Core/CMakeLists.txt
+++ b/Core/CMakeLists.txt
@@ -13,6 +13,7 @@ set(SRCS
MIPS/MIPSVFPUUtils.cpp
MIPS/JitCommon/JitCommon.cpp
ELF/ElfReader.cpp
+ ELF/ParamSFO.cpp
ELF/PrxDecrypter.cpp
HLE/HLE.cpp
HLE/HLETables.cpp
diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index 8fafb7cdf6..6b8f518c3d 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -120,6 +120,7 @@
+
@@ -251,6 +252,7 @@
+
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index defdfee2b5..65452343d1 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -300,6 +300,9 @@
HLE\Libraries
+
+ ELF
+
@@ -548,6 +551,9 @@
HLE\Libraries
+
+ ELF
+
diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp
index d5b71ec237..57a79e581d 100644
--- a/Core/CoreTiming.cpp
+++ b/Core/CoreTiming.cpp
@@ -500,6 +500,20 @@ void Idle(int maxIdle)
if (maxIdle != 0 && cyclesDown > maxIdle)
cyclesDown = maxIdle;
+ if (first && cyclesDown > 0)
+ {
+ int cyclesExecuted = slicelength - downcount;
+ int cyclesNextEvent = (int) (first->time - globalTimer);
+
+ if (cyclesNextEvent < cyclesExecuted + cyclesDown)
+ {
+ cyclesDown = cyclesNextEvent - cyclesExecuted;
+ // Now, now... no time machines, please.
+ if (cyclesDown < 0)
+ cyclesDown = 0;
+ }
+ }
+
DEBUG_LOG(CPU, "Idle for %i cycles! (%f ms)", cyclesDown, cyclesDown / (float)(CPU_HZ * 0.001f));
idledCycles += cyclesDown;
@@ -520,7 +534,7 @@ std::string GetScheduledEventsSummary()
if (!name)
name = "[unknown]";
char temp[512];
- sprintf(temp, "%s : %i %08x%08x\n", event_types[ptr->type].name, (int)ptr->time, (u32)(ptr->userdata >> 32), (u32)(ptr->userdata));
+ sprintf(temp, "%s : %i %08x%08x\n", name, (int)ptr->time, (u32)(ptr->userdata >> 32), (u32)(ptr->userdata));
text += temp;
ptr = ptr->next;
}
diff --git a/Core/ELF/ParamSFO.cpp b/Core/ELF/ParamSFO.cpp
new file mode 100644
index 0000000000..a86e6c77b8
--- /dev/null
+++ b/Core/ELF/ParamSFO.cpp
@@ -0,0 +1,101 @@
+// Copyright (c) 2012- PPSSPP Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0 or later versions.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official git repository and contact information can be found at
+// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
+
+#include
+#include
+#include "../Globals.h"
+#include "ParamSFO.h"
+
+struct Header
+{
+ u32 magic; /* Always PSF */
+ u32 version; /* Usually 1.1 */
+ u32 key_table_start; /* Start position of key_table */
+ u32 data_table_start; /* Start position of data_table */
+ u32 index_table_entries; /* Number of entries in index_table*/
+};
+
+struct IndexTable
+{
+ u16 key_table_offset; /* Offset of the param_key from start of key_table */
+ u16 param_fmt; /* Type of data of param_data in the data_table */
+ u32 param_len; /* Used Bytes by param_data in the data_table */
+ u32 param_max_len; /* Total bytes reserved for param_data in the data_table */
+ u32 data_table_offset; /* Offset of the param_data from start of data_table */
+};
+
+void ParseDataString(const char *key, const char *utfdata, ParamSFOData *sfodata, int maxlen = 0)
+{
+ std::string data;
+ if (maxlen)
+ data = std::string(utfdata, maxlen);
+ else
+ data = std::string(utfdata);
+ if (!strcmp(key, "DISC_ID")) {
+ sfodata->discID = data;
+ } else if (!strcmp(key, "TITLE")) {
+ sfodata->title = data;
+ }
+}
+
+// I'm so sorry Ced but this is highly endian unsafe :(
+bool ParseParamSFO(const u8 *paramsfo, size_t size, ParamSFOData *data)
+{
+ const Header *header = (const Header *)paramsfo;
+ if (header->magic != 0x46535000)
+ return false;
+ if (header->version != 0x00000101)
+ WARN_LOG(LOADER, "Unexpected SFO header version: %08x", header->version);
+
+ const IndexTable *indexTables = (const IndexTable *)(paramsfo + sizeof(Header));
+
+ const u8 *key_start = paramsfo + header->key_table_start;
+ const u8 *data_start = paramsfo + header->data_table_start;
+
+ for (u32 i = 0; i < header->index_table_entries; i++)
+ {
+ const char *key = (const char *)(key_start + indexTables[i].key_table_offset);
+
+ switch (indexTables[i].param_fmt) {
+ case 0x0404:
+ {
+ // Unsigned int
+ const u32 *data = (const u32 *)(data_start + indexTables[i].data_table_offset);
+ DEBUG_LOG(LOADER, "%s %08x", key, *data);
+ }
+ break;
+ case 0x0004:
+ // Special format UTF-8
+ {
+ const char *utfdata = (const char *)(data_start + indexTables[i].data_table_offset);
+ DEBUG_LOG(LOADER, "%s %s", key, utfdata);
+ ParseDataString(key, utfdata, data, indexTables[i].param_len);
+ }
+ break;
+ case 0x0204:
+ // Regular UTF-8
+ {
+ const char *utfdata = (const char *)(data_start + indexTables[i].data_table_offset);
+ DEBUG_LOG(LOADER, "%s %s", key, utfdata);
+ ParseDataString(key, utfdata, data, indexTables[i].param_len);
+ }
+ break;
+ }
+ }
+
+ return true;
+}
diff --git a/Core/ELF/ParamSFO.h b/Core/ELF/ParamSFO.h
new file mode 100644
index 0000000000..f92bef1a5a
--- /dev/null
+++ b/Core/ELF/ParamSFO.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2012- PPSSPP Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0 or later versions.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official git repository and contact information can be found at
+// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
+
+
+#pragma once
+
+
+struct ParamSFOData
+{
+ std::string discID;
+ std::string title; // utf-8
+};
+
+bool ParseParamSFO(const u8 *paramsfo, size_t size, ParamSFOData *data);
\ No newline at end of file
diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp
index 50ed950f12..bf024fbd44 100644
--- a/Core/HLE/sceKernelMutex.cpp
+++ b/Core/HLE/sceKernelMutex.cpp
@@ -15,8 +15,6 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
-// UNFINISHED
-
#include
#include