Merge remote-tracking branch 'upstream2/master' into cwcheat

Conflicts:
	UI/CwCheatScreen.cpp
This commit is contained in:
Steven Cherry committed 2013-09-01 18:10:18 -05:00
commit ddc8ab967f
202 files changed
+5287 -3051

No files matched your search

+3 -3
View File
@@ -148,8 +148,6 @@ if(NOT MSVC)
add_definitions(-fno-strict-aliasing)
if (CMAKE_C_COMPILER_ID STREQUAL "Intel")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -parallel -fopenmp")
else()
add_definitions(-ffast-math)
endif()
if(NOT APPLE)
if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel")
@@ -163,7 +161,7 @@ if(NOT MSVC)
endif()
if(BLACKBERRY)
add_definitions(-D_QNX_SOURCE=1 -D_C99=1 -O3 -mfpu=neon -mtune=cortex-a9)
add_definitions(-D_QNX_SOURCE -O3 -mfpu=neon -mtune=cortex-a9)
endif()
if(X86 AND NOT MIPS)
@@ -563,6 +561,8 @@ add_library(native STATIC
native/gfx/texture_gen.h
native/gfx_es2/draw_buffer.cpp
native/gfx_es2/draw_buffer.h
native/gfx_es2/draw_text.cpp
native/gfx_es2/draw_text.h
native/gfx_es2/fbo.cpp
native/gfx_es2/fbo.h
native/gfx_es2/gl_state.cpp
+19 -1
View File
@@ -15,7 +15,14 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifdef ANDROID
#include <sys/stat.h>
#include <fcntl.h>
#endif
#include <memory.h>
#include "base/logging.h"
#include "base/basictypes.h"
#ifdef _WIN32
#define _interlockedbittestandset workaround_ms_header_bug_platform_sdk6_set
@@ -39,6 +46,17 @@
#elif !defined(MIPS)
void __cpuid(int regs[4], int cpuid_leaf)
{
#ifdef ANDROID
// Use the /dev/cpu/%i/cpuid interface
int f = open("/dev/cpu/0/cpuid", O_RDONLY);
if (f) {
lseek(f, (uint32_t)cpuid_leaf, SEEK_SET);
read(f, (void *)regs, 16);
close(f);
} else {
ELOG("CPUID %08x failed!", cpuid_leaf);
}
#else
int eax, ebx, ecx, edx;
asm volatile (
#if defined(__i386__)
@@ -60,11 +78,11 @@ void __cpuid(int regs[4], int cpuid_leaf)
"%ebx",
#endif
"%ecx", "%edx");
regs[0] = eax;
regs[1] = ebx;
regs[2] = ecx;
regs[3] = edx;
#endif
}
#endif
+6 -6
View File
@@ -246,7 +246,7 @@ public:
x.clear();
while (number > 0)
{
K first;
K first = K();
Do(first);
T second = default_val;
Do(second);
@@ -283,7 +283,7 @@ public:
template<class T>
void Do(std::vector<T> &x)
{
T dv;
T dv = T();
DoVector(x, dv);
}
@@ -291,7 +291,7 @@ public:
template<class T>
void DoPOD(std::vector<T> &x)
{
T dv;
T dv = T();
DoVectorPOD(x, dv);
}
@@ -332,7 +332,7 @@ public:
template<class T>
void Do(std::deque<T> &x)
{
T dv;
T dv = T();
DoDeque(x, dv);
}
@@ -358,7 +358,7 @@ public:
template<class T>
void Do(std::list<T> &x)
{
T dv;
T dv = T();
DoList(x, dv);
}
@@ -415,7 +415,7 @@ public:
x.clear();
while (number-- > 0)
{
T it;
T it = T();
Do(it);
x.insert(it);
}
+4 -4
View File
@@ -27,22 +27,22 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+42 -4
View File
@@ -28,6 +28,7 @@
#endif
#include "thread/threadutil.h"
#include "util/text/utf8.h"
#include "Common.h"
#include "LogManager.h" // Common
#include "ConsoleListener.h" // Common
@@ -71,6 +72,31 @@ ConsoleListener::~ConsoleListener()
Close();
}
#ifdef _WIN32
// Handle console event
bool WINAPI ConsoleHandler(DWORD msgType)
{
if (msgType == CTRL_C_EVENT)
{
OutputDebugString(L"Ctrl-C!\n");
return TRUE;
}
else if (msgType == CTRL_CLOSE_EVENT)
{
OutputDebugString(L"Close console window!\n");
return TRUE;
}
/*
Other messages:
CTRL_BREAK_EVENT Ctrl-Break pressed
CTRL_LOGOFF_EVENT User log off
CTRL_SHUTDOWN_EVENT System shutdown
*/
return FALSE;
}
#endif
// 100, 100, "Dolphin Log Console"
// Open console window - width and height is the size of console window
// Name is the window title
@@ -84,12 +110,19 @@ void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title
AllocConsole();
HWND hConWnd = GetConsoleWindow();
ShowWindow(hConWnd, SW_SHOWDEFAULT);
// disable console close button
HMENU hMenu=GetSystemMenu(hConWnd,false);
EnableMenuItem(hMenu,SC_CLOSE,MF_GRAYED|MF_BYCOMMAND);
// Hide
if (Hidden) ShowWindow(hConWnd, SW_HIDE);
// Save the window handle that AllocConsole() created
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Set console handler
if(SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler, TRUE)){OutputDebugString(L"Console handler is installed!\n");}
// Set the console window title
SetConsoleTitle(Title);
SetConsoleTitle(ConvertUTF8ToWString(Title).c_str());
SetConsoleCP(CP_UTF8);
// Set letter space
LetterSpace(Width, LOG_MAX_DISPLAY_LINES);
//MoveWindow(GetConsoleWindow(), 200,200, 800,800, true);
@@ -415,6 +448,7 @@ void ConsoleListener::WriteToConsole(LogTypes::LOG_LEVELS Level, const char *Tex
*/
DWORD cCharsWritten;
WORD Color;
static wchar_t tempBuf[2048];
switch (Level)
{
@@ -441,12 +475,16 @@ void ConsoleListener::WriteToConsole(LogTypes::LOG_LEVELS Level, const char *Tex
{
// First 10 chars white
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
WriteConsole(hConsole, Text, 10, &cCharsWritten, NULL);
int wlen = MultiByteToWideChar(CP_UTF8, 0, Text, (int)Len, NULL, NULL);
MultiByteToWideChar(CP_UTF8, 0, Text, (int)Len, tempBuf, wlen);
WriteConsole(hConsole, tempBuf, 10, &cCharsWritten, NULL);
Text += 10;
Len -= 10;
}
SetConsoleTextAttribute(hConsole, Color);
WriteConsole(hConsole, Text, (DWORD)Len, &cCharsWritten, NULL);
int wlen = MultiByteToWideChar(CP_UTF8, 0, Text, (int)Len, NULL, NULL);
MultiByteToWideChar(CP_UTF8, 0, Text, (int)Len, tempBuf, wlen);
WriteConsole(hConsole, tempBuf, (DWORD)Len, &cCharsWritten, NULL);
}
#endif
@@ -476,7 +514,7 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool
static const int MAX_BYTES = 1024 * 16;
std::vector<std::array<CHAR, MAX_BYTES>> Str;
std::vector<std::array<wchar_t, MAX_BYTES>> Str;
std::vector<std::array<WORD, MAX_BYTES>> Attr;
// ReadConsoleOutputAttribute seems to have a limit at this level
+11 -21
View File
@@ -17,6 +17,8 @@
#include "CommonWindows.h"
#include <stdio.h>
#include "ExtendedTrace.h"
#include <string>
using namespace std;
#include <tchar.h>
@@ -320,7 +322,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
GetSourceInfoFromAddress( (ULONG)callStack.AddrPC.Offset, srcInfo );
etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
etfprint(file, wstring(L" ") + srcInfo + L" : " + symInfo + L"\n");
for( ULONG index = 0; ; index++ )
{
@@ -343,7 +345,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo );
etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
etfprint(file, wstring(L" ") + srcInfo + L" : " + symInfo + L"\n");
}
@@ -351,22 +353,6 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
ResumeThread( hThread );
}
#ifndef UNICODE
void StackTrace( HANDLE hThread, wchar_t const*lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
{
// TODO: remove when Common builds as unicode
size_t origsize = wcslen(lpszMessage) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
char nstring[newsize];
wcstombs_s(&convertedChars, nstring, origsize, lpszMessage, _TRUNCATE);
StackTrace(hThread, nstring, file, eip, esp, ebp );
}
#endif
void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
{
STACKFRAME callStack;
@@ -397,7 +383,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO
GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo );
etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
etfprint(file, wstring(L" ") + srcInfo + L" : " + symInfo + L"\n");
for( ULONG index = 0; ; index++ )
{
@@ -420,8 +406,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO
GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo );
etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
etfprint(file, wstring(L" ") + srcInfo + L" : " + symInfo + L"\n");
}
if ( hThread != GetCurrentThread() )
@@ -443,4 +428,9 @@ void etfprint(FILE *file, const std::string &text) {
fwrite(text.data(), 1, len, file);
}
void etfprint(FILE *file, const std::wstring &text) {
size_t len = text.length();
fwrite(text.data(), sizeof(wchar_t), len, file);
}
#endif //WIN32
+1
View File
@@ -39,6 +39,7 @@ void StackTrace( HANDLE hThread, wchar_t const* lpszMessage, FILE *file, DWORD e
// functions by Masken
void etfprintf(FILE *file, const char *format, ...);
void etfprint(FILE *file, const std::string &text);
void etfprint(FILE *file, const std::wstring &text);
#define UEFBUFSIZE 2048
extern char g_uefbuf[UEFBUFSIZE];
+4 -2
View File
@@ -32,6 +32,7 @@
#include "FileSearch.h"
#include "StringUtils.h"
#include "util/text/utf8.h"
CFileSearch::CFileSearch(const CFileSearch::XStringVector& _rSearchStrings, const CFileSearch::XStringVector& _rDirectories)
@@ -53,7 +54,8 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string&
BuildCompleteFilename(GCMSearchPath, _strPath, _searchString);
#ifdef _WIN32
WIN32_FIND_DATA findData;
HANDLE FindFirst = FindFirstFile(GCMSearchPath.c_str(), &findData);
std::wstring searchPathW = ConvertUTF8ToWString(GCMSearchPath);
HANDLE FindFirst = FindFirstFile(searchPathW.c_str(), &findData);
if (FindFirst != INVALID_HANDLE_VALUE)
{
@@ -64,7 +66,7 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string&
if (findData.cFileName[0] != '.')
{
std::string strFilename;
BuildCompleteFilename(strFilename, _strPath, findData.cFileName);
BuildCompleteFilename(strFilename, _strPath, ConvertWStringToUTF8(findData.cFileName));
m_FileNames.push_back(strFilename);
}
+56 -88
View File
@@ -41,6 +41,8 @@
#include <CoreFoundation/CFBundle.h>
#endif
#include "util/text/utf8.h"
#include <fstream>
#include <sys/stat.h>
@@ -77,6 +79,15 @@ static inline int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **res
namespace File
{
FILE *OpenCFile(const std::string &filename, const char *mode)
{
#if defined(_WIN32) && defined(UNICODE)
return _wfopen(ConvertUTF8ToWString(filename).c_str(), ConvertUTF8ToWString(mode).c_str());
#else
return fopen(filename.c_str(), mode);
#endif
}
// Remove any ending forward slashes from directory paths
// Modifies argument.
static void StripTailDirSlashes(std::string &fname)
@@ -94,16 +105,39 @@ static void StripTailDirSlashes(std::string &fname)
return;
}
// _WIN32 only since std::strings are used everywhere else.
#if defined(_WIN32) && defined(UNICODE)
static void StripTailDirSlashes(std::wstring &fname)
{
if (fname.length() > 1)
{
size_t i = fname.length() - 1;
if (i == 2 && fname[1] == ':' && fname[2] == '\\')
return;
while (wcschr(_T(DIR_SEP_CHRS), fname[i]))
fname[i--] = '\0';
}
return;
}
#endif
// Returns true if file filename exists
bool Exists(const std::string &filename)
{
struct stat64 file_info;
#if defined(_WIN32) && defined(UNICODE)
std::wstring copy = ConvertUTF8ToWString(filename);
StripTailDirSlashes(copy);
int result = _wstat64(copy.c_str(), &file_info);
#else
std::string copy(filename);
StripTailDirSlashes(copy);
int result = stat64(copy.c_str(), &file_info);
#endif
return (result == 0);
}
@@ -117,12 +151,17 @@ bool IsDirectory(const struct stat64 &file_info)
bool IsDirectory(const std::string &filename)
{
struct stat64 file_info;
#if defined(_WIN32) && defined(UNICODE)
std::wstring copy = ConvertUTF8ToWString(filename);
StripTailDirSlashes(copy);
int result = _wstat64(copy.c_str(), &file_info);
#else
std::string copy(filename);
StripTailDirSlashes(copy);
int result = stat64(copy.c_str(), &file_info);
#endif
if (result < 0) {
WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s",
filename.c_str(), GetLastErrorMsg());
@@ -154,7 +193,7 @@ bool Delete(const std::string &filename)
}
#ifdef _WIN32
if (!DeleteFile(filename.c_str()))
if (!DeleteFile(ConvertUTF8ToWString(filename).c_str()))
{
WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s",
filename.c_str(), GetLastErrorMsg());
@@ -176,7 +215,7 @@ bool CreateDir(const std::string &path)
{
INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str());
#ifdef _WIN32
if (::CreateDirectory(path.c_str(), NULL))
if (::CreateDirectory(ConvertUTF8ToWString(path).c_str(), NULL))
return true;
DWORD error = GetLastError();
if (error == ERROR_ALREADY_EXISTS)
@@ -267,7 +306,7 @@ bool DeleteDir(const std::string &filename)
}
#ifdef _WIN32
if (::RemoveDirectory(filename.c_str()))
if (::RemoveDirectory(ConvertUTF8ToWString(filename).c_str()))
return true;
#else
if (rmdir(filename.c_str()) == 0)
@@ -296,7 +335,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
INFO_LOG(COMMON, "Copy: %s --> %s",
srcFilename.c_str(), destFilename.c_str());
#ifdef _WIN32
if (CopyFile(srcFilename.c_str(), destFilename.c_str(), FALSE))
if (CopyFile(ConvertUTF8ToWString(srcFilename).c_str(), ConvertUTF8ToWString(destFilename).c_str(), FALSE))
return true;
ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s",
@@ -397,8 +436,11 @@ tm GetModifTime(const std::string &filename)
u64 GetSize(const std::string &filename)
{
struct stat64 file_info;
#if defined(_WIN32) && defined(UNICODE)
int result = _wstat64(ConvertUTF8ToWString(filename).c_str(), &file_info);
#else
int result = stat64(filename.c_str(), &file_info);
#endif
if (result != 0)
{
WARN_LOG(COMMON, "GetSize: failed %s: No such file", filename.c_str());
@@ -451,7 +493,7 @@ bool CreateEmptyFile(const std::string &filename)
{
INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str());
FILE *pFile = fopen(filename.c_str(), "wb");
FILE *pFile = OpenCFile(filename, "wb");
if (!pFile) {
ERROR_LOG(COMMON, "CreateEmptyFile: failed %s: %s",
filename.c_str(), GetLastErrorMsg());
@@ -461,80 +503,6 @@ bool CreateEmptyFile(const std::string &filename)
return true;
}
// Scans the directory tree gets, starting from _Directory and adds the
// results into parentEntry. Returns the number of files+directories found
u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
{
INFO_LOG(COMMON, "ScanDirectoryTree: directory %s", directory.c_str());
// How many files + directories we found
u32 foundEntries = 0;
#ifdef _WIN32
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile((directory + "\\*").c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE)
{
FindClose(hFind);
return foundEntries;
}
// windows loop
do
{
FSTEntry entry;
const std::string virtualName(ffd.cFileName);
#else
struct dirent_large { struct dirent entry; char padding[FILENAME_MAX+1]; };
struct dirent_large diren;
struct dirent *result = NULL;
DIR *dirp = opendir(directory.c_str());
if (!dirp)
return 0;
// non windows loop
while (!readdir_r(dirp, (dirent*)&diren, &result) && result)
{
FSTEntry entry;
const std::string virtualName(result->d_name);
#endif
// check for "." and ".."
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
((virtualName[0] == '.') && (virtualName[1] == '.') &&
(virtualName[2] == '\0')))
continue;
entry.virtualName = virtualName;
entry.physicalName = directory;
entry.physicalName += DIR_SEP + entry.virtualName;
if (IsDirectory(entry.physicalName.c_str()))
{
entry.isDirectory = true;
// is a directory, lets go inside
entry.size = ScanDirectoryTree(entry.physicalName, entry);
foundEntries += (u32)entry.size;
}
else
{ // is a file
entry.isDirectory = false;
entry.size = GetSize(entry.physicalName.c_str());
}
++foundEntries;
// Push into the tree
parentEntry.children.push_back(entry);
#ifdef _WIN32
} while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
#else
}
closedir(dirp);
#endif
// Return number of entries found.
return foundEntries;
}
// Deletes the given directory and anything under it. Returns true on success.
bool DeleteDirRecursively(const std::string &directory)
{
@@ -542,7 +510,7 @@ bool DeleteDirRecursively(const std::string &directory)
#ifdef _WIN32
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile((directory + "\\*").c_str(), &ffd);
HANDLE hFind = FindFirstFile(ConvertUTF8ToWString(directory + "\\*").c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE)
{
@@ -553,7 +521,7 @@ bool DeleteDirRecursively(const std::string &directory)
// windows loop
do
{
const std::string virtualName = ffd.cFileName;
const std::string virtualName = ConvertWStringToUTF8(ffd.cFileName);
#else
struct dirent dirent, *result = NULL;
DIR *dirp = opendir(directory.c_str());
@@ -751,7 +719,7 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath)
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename)
{
FILE *f = fopen(filename, text_file ? "w" : "wb");
FILE *f = OpenCFile(filename, text_file ? "w" : "wb");
if (!f)
return false;
size_t len = str.size();
@@ -766,7 +734,7 @@ bool WriteStringToFile(bool text_file, const std::string &str, const char *filen
bool ReadFileToString(bool text_file, const char *filename, std::string &str)
{
FILE *f = fopen(filename, text_file ? "r" : "rb");
FILE *f = OpenCFile(filename, text_file ? "r" : "rb");
if (!f)
return false;
size_t len = (size_t)GetSize(f);
@@ -800,8 +768,8 @@ IOFile::~IOFile()
bool IOFile::Open(const std::string& filename, const char openmode[])
{
Close();
#ifdef _WIN32
fopen_s(&m_file, filename.c_str(), openmode);
#if defined(_WIN32) && defined(UNICODE)
_wfopen_s(&m_file, ConvertUTF8ToWString(filename).c_str(), ConvertUTF8ToWString(openmode).c_str());
#else
m_file = fopen(filename.c_str(), openmode);
#endif
+3 -4
View File
@@ -59,6 +59,9 @@ struct FSTEntry
std::vector<FSTEntry> children;
};
// Mostly to handle utf-8 filenames better on Windows.
FILE *OpenCFile(const std::string &filename, const char *mode);
// Returns true if file filename exists
bool Exists(const std::string &filename);
@@ -99,10 +102,6 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename);
// creates an empty file filename, returns true on success
bool CreateEmptyFile(const std::string &filename);
// Scans the directory tree gets, starting from _Directory and adds the
// results into parentEntry. Returns the number of files+directories found
u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry);
// deletes the given directory and anything under it. Returns true on success.
bool DeleteDirRecursively(const std::string &directory);
+3 -3
View File
@@ -245,10 +245,10 @@ void UpdateConfirmCancelKeys() {
cancelKeys.push_back(hardcodedCancelKeys[i]);
}
SetConfirmCancelKeys(confirmKeys,cancelKeys);
SetConfirmCancelKeys(confirmKeys, cancelKeys);
}
static void SetDefaultKeyMap(int deviceId, const DefMappingStruct *array, int count, bool replace) {
static void SetDefaultKeyMap(int deviceId, const DefMappingStruct *array, size_t count, bool replace) {
for (size_t i = 0; i < count; i++) {
if (array[i].direction == 0)
SetKeyMapping(array[i].pspKey, KeyDef(deviceId, array[i].key), replace);
@@ -679,7 +679,7 @@ void RestoreDefault() {
std::string name = System_GetName();
if (name == "NVIDIA:SHIELD") {
SetDefaultKeyMap(DEFAULT_MAPPING_SHIELD, true);
} else if (name == "OUYA:OUYA") { // TODO: check!
} else if (name == "OUYA:OUYA Console") { // TODO: check!
SetDefaultKeyMap(DEFAULT_MAPPING_OUYA, true);
} else if (name == "Sony Ericsson:R800i" || name == "Sony Ericsson:zeus") {
SetDefaultKeyMap(DEFAULT_MAPPING_XPERIA_PLAY, true);
+2 -2
View File
@@ -16,7 +16,7 @@
// http://code.google.com/p/dolphin-emu/
#include <algorithm>
#include "base/logging.h"
#include "LogManager.h"
#include "ConsoleListener.h"
#include "Timer.h"
@@ -280,6 +280,6 @@ void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
{
#if _MSC_VER
::OutputDebugStringA(msg);
OutputDebugStringUTF8(msg);
#endif
}
+1 -1
View File
@@ -35,7 +35,7 @@ const char* GetLastErrorMsg()
#ifdef _WIN32
static __declspec(thread) char err_str[buff_size] = {};
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
err_str, buff_size, NULL);
#else
+12 -8
View File
@@ -20,6 +20,7 @@
#include "Common.h" // Local
#include "StringUtils.h"
#include "util/text/utf8.h"
bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style);
static MsgAlertHandler msg_handler = DefaultMsgHandler;
@@ -106,15 +107,18 @@ bool MsgAlert(bool yes_no, int Style, const char* format, ...)
bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style)
{
#ifdef _WIN32
int STYLE = MB_ICONINFORMATION;
if (Style == QUESTION) STYLE = MB_ICONQUESTION;
if (Style == WARNING) STYLE = MB_ICONWARNING;
return IDYES == MessageBox(0, text, caption, STYLE | (yes_no ? MB_YESNO : MB_OK));
int STYLE = MB_ICONINFORMATION;
if (Style == QUESTION) STYLE = MB_ICONQUESTION;
if (Style == WARNING) STYLE = MB_ICONWARNING;
std::wstring wtext = ConvertUTF8ToWString(text);
std::wstring wcaption = ConvertUTF8ToWString(caption);
return IDYES == MessageBox(0, wtext.c_str(), wcaption.c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK));
#else
printf("%s\n", text);
return true;
printf("%s\n", text);
return true;
#endif
}
+36 -13
View File
@@ -48,29 +48,22 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename)
IniFile::Section *general = iniFile.GetOrCreateSection("General");
bSpeedLimit = false;
general->Get("FirstRun", &bFirstRun, true);
general->Get("Enable Logging", &bEnableLogging, true);
general->Get("AutoLoadLast", &bAutoLoadLast, false);
general->Get("AutoRun", &bAutoRun, true);
general->Get("Browse", &bBrowse, false);
general->Get("ConfirmOnQuit", &bConfirmOnQuit, false);
general->Get("IgnoreBadMemAccess", &bIgnoreBadMemAccess, true);
general->Get("CurrentDirectory", &currentDirectory, "");
general->Get("ShowDebuggerOnLoad", &bShowDebuggerOnLoad, false);
general->Get("Language", &languageIni, "en_US");
general->Get("NumWorkerThreads", &iNumWorkerThreads, cpu_info.num_cores);
general->Get("EnableCheats", &bEnableCheats, false);
general->Get("MaxRecent", &iMaxRecent, 30);
general->Get("ScreenshotsAsPNG", &bScreenshotsAsPNG, false);
general->Get("StateSlot", &iCurrentStateSlot, 0);
general->Get("GridView1", &bGridView1, true);
general->Get("GridView2", &bGridView2, true);
general->Get("GridView3", &bGridView3, true);
// Fix issue from switching from uint (hex in .ini) to int (dec)
if (iMaxRecent == 0)
iMaxRecent = 12;
// "default" means let emulator decide, "" means disable.
general->Get("ReportingHost", &sReportHost, "default");
@@ -82,8 +75,23 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename)
general->Get("WindowY", &iWindowY, 100);
#endif
if ((int)recentIsos.size() > iMaxRecent)
recentIsos.resize(iMaxRecent);
IniFile::Section *recent = iniFile.GetOrCreateSection("Recent");
recent->Get("MaxRecent", &iMaxRecent, 30);
// Fix issue from switching from uint (hex in .ini) to int (dec)
if (iMaxRecent == 0)
iMaxRecent = 30;
recentIsos.clear();
for (int i = 0; i < iMaxRecent; i++)
{
char keyName[64];
std::string fileName;
sprintf(keyName,"FileName%d",i);
if (!recent->Get(keyName,&fileName,"") || fileName.length() == 0) break;
recentIsos.push_back(fileName);
}
IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU");
#ifdef IOS
@@ -231,15 +239,12 @@ void Config::Save() {
bFirstRun = false;
general->Set("FirstRun", bFirstRun);
general->Set("Enable Logging", bEnableLogging);
general->Set("AutoLoadLast", bAutoLoadLast);
general->Set("AutoRun", bAutoRun);
general->Set("Browse", bBrowse);
general->Set("ConfirmOnQuit", bConfirmOnQuit);
general->Set("IgnoreBadMemAccess", bIgnoreBadMemAccess);
general->Set("CurrentDirectory", currentDirectory);
general->Set("ShowDebuggerOnLoad", bShowDebuggerOnLoad);
general->Set("ReportingHost", sReportHost);
general->Set("Recent", recentIsos);
general->Set("AutoSaveSymbolMap", bAutoSaveSymbolMap);
#ifdef _WIN32
general->Set("TopMost", bTopMost);
@@ -248,13 +253,23 @@ void Config::Save() {
#endif
general->Set("Language", languageIni);
general->Set("NumWorkerThreads", iNumWorkerThreads);
general->Set("MaxRecent", iMaxRecent);
general->Set("EnableCheats", bEnableCheats);
general->Set("ScreenshotsAsPNG", bScreenshotsAsPNG);
general->Set("StateSlot", iCurrentStateSlot);
general->Set("GridView1", bGridView1);
general->Set("GridView2", bGridView2);
general->Set("GridView3", bGridView3);
IniFile::Section *recent = iniFile.GetOrCreateSection("Recent");
recent->Set("MaxRecent", iMaxRecent);
for (int i = 0; i < (int)recentIsos.size(); i++)
{
char keyName[64];
sprintf(keyName,"FileName%d",i);
recent->Set(keyName,recentIsos[i]);
}
IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU");
cpu->Set("Jit", bJit);
@@ -378,3 +393,11 @@ void Config::CleanRecent() {
}
recentIsos = cleanedRecent;
}
void Config::RestoreDefaults() {
if(File::Exists("ppsspp.ini"))
File::Delete("ppsspp.ini");
recentIsos.clear();
currentDirectory = "";
Load();
}
+7 -9
View File
@@ -34,21 +34,18 @@ public:
bool bSaveSettings;
bool bFirstRun;
// These are broken
bool bAutoLoadLast;
bool bSpeedLimit;
bool bConfirmOnQuit;
bool bAutoRun; // start immediately
bool bBrowse;
#ifdef _WIN32
bool bTopMost;
#endif
bool bBrowse; // when opening the emulator, immediately show a file browser
// General
int iNumWorkerThreads;
bool bScreenshotsAsPNG;
bool bEnableLogging;
#ifdef _WIN32
bool bTopMost;
std::string sFont;
#endif
// Core
bool bIgnoreBadMemAccess;
bool bFastMemory;
@@ -169,6 +166,7 @@ public:
void Load(const char *iniFileName = "ppsspp.ini", const char *controllerIniFilename = "controls.ini");
void Save();
void RestoreDefaults();
// Utility functions for "recent" management
void AddRecent(const std::string &file);
+64 -4
View File
@@ -26,24 +26,24 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -323,6 +323,54 @@
<ClCompile Include="MIPS\MIPSIntVFPU.cpp" />
<ClCompile Include="Mips\MIPSTables.cpp" />
<ClCompile Include="MIPS\MIPSVFPUUtils.cpp" />
<ClCompile Include="MIPS\PPC\PpcAsm.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcCompAlu.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcCompBranch.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcCompFpu.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcCompLoadStore.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcCompVFPU.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcJit.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcRegCache.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="MIPS\x86\Asm.cpp" />
<ClCompile Include="MIPS\x86\CompALU.cpp" />
<ClCompile Include="MIPS\x86\CompBranch.cpp" />
@@ -481,6 +529,18 @@
<ClInclude Include="MIPS\MIPSIntVFPU.h" />
<ClInclude Include="Mips\MIPSTables.h" />
<ClInclude Include="MIPS\MIPSVFPUUtils.h" />
<ClInclude Include="MIPS\PPC\PpcJit.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="MIPS\PPC\PpcRegCache.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="MIPS\x86\Asm.h" />
<ClInclude Include="MIPS\x86\RegCacheFPU.h" />
<ClInclude Include="MIPS\x86\Jit.h" />
+33
View File
@@ -52,6 +52,9 @@
<Filter Include="Font">
<UniqueIdentifier>{1c79e88d-1c48-450b-8af6-f22ce7d40c66}</UniqueIdentifier>
</Filter>
<Filter Include="MIPS\PPC">
<UniqueIdentifier>{ac0e396a-6e16-4796-a0a0-b8ebf46ea74c}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ELF\ElfReader.cpp">
@@ -460,6 +463,30 @@
<ClCompile Include="..\ext\xxhash.c">
<Filter>Ext</Filter>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcCompLoadStore.cpp">
<Filter>MIPS\PPC</Filter>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcCompVFPU.cpp">
<Filter>MIPS\PPC</Filter>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcJit.cpp">
<Filter>MIPS\PPC</Filter>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcRegCache.cpp">
<Filter>MIPS\PPC</Filter>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcCompAlu.cpp">
<Filter>MIPS\PPC</Filter>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcCompBranch.cpp">
<Filter>MIPS\PPC</Filter>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcCompFpu.cpp">
<Filter>MIPS\PPC</Filter>
</ClCompile>
<ClCompile Include="MIPS\PPC\PpcAsm.cpp">
<Filter>MIPS\PPC</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ELF\ElfReader.h">
@@ -858,6 +885,12 @@
<ClInclude Include="..\ext\xxhash.h">
<Filter>Ext</Filter>
</ClInclude>
<ClInclude Include="MIPS\PPC\PpcJit.h">
<Filter>MIPS\PPC</Filter>
</ClInclude>
<ClInclude Include="MIPS\PPC\PpcRegCache.h">
<Filter>MIPS\PPC</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
+2 -1
View File
@@ -298,8 +298,9 @@ void CBreakPoints::Update(u32 addr)
{
if (MIPSComp::jit && Core_IsInactive())
{
// In case this is a delay slot, clear the previous instruction too.
if (addr != 0)
MIPSComp::jit->ClearCacheAt(addr);
MIPSComp::jit->ClearCacheAt(addr - 4, 8);
else
MIPSComp::jit->ClearCache();
}
+6 -2
View File
@@ -21,13 +21,17 @@
#include "DebugInterface.h"
#include <vector>
// TODO: Replace with expression or something.
struct BreakPointCond
{
DebugInterface* debug;
DebugInterface *debug;
PostfixExpression expression;
char expressionString[128];
BreakPointCond() : debug(NULL)
{
expressionString[0] = '\0';
}
u32 Evaluate()
{
u32 result;
+1 -1
View File
@@ -43,7 +43,7 @@ public:
virtual const char *getDescription(unsigned int address) {return "";}
virtual const char *findSymbolForAddress(unsigned int address) { return NULL; };
virtual bool getSymbolValue(char* symbol, u32& dest) { return false; };
virtual bool initExpression(char* exp, PostfixExpression& dest) { return false; };
virtual bool initExpression(const char* exp, PostfixExpression& dest) { return false; };
virtual bool parseExpression(PostfixExpression& exp, u32& dest) { return false; };
+27 -26
View File
@@ -23,13 +23,13 @@
#endif
#include <algorithm>
#include "../../Globals.h"
#include "../../Core/MemMap.h"
#include "SymbolMap.h"
#include <map>
#include "Common/FileUtil.h"
#include "Globals.h"
#include "Core/MemMap.h"
#include "Core/Debugger/SymbolMap.h"
SymbolMap symbolMap;
//need improvement
@@ -46,7 +46,7 @@ static u32 ComputeHash(u32 start, u32 size)
{
u32 hash=0;
for (unsigned int i=start; i<start+size; i+=4)
hash = hasher(hash, Memory::Read_Instruction(i));
hash = hasher(hash, Memory::Read_Instruction(i).encoding);
return hash;
}
@@ -139,7 +139,7 @@ bool SymbolMap::LoadSymbolMap(const char *filename)
{
lock_guard guard(lock_);
SymbolMap::ResetSymbolMap();
FILE *f = fopen(filename,"r");
FILE *f = File::OpenCFile(filename, "r");
if (!f)
return false;
//char temp[256];
@@ -212,7 +212,7 @@ bool SymbolMap::LoadSymbolMap(const char *filename)
void SymbolMap::SaveSymbolMap(const char *filename) const
{
lock_guard guard(lock_);
FILE *f = fopen(filename,"w");
FILE *f = File::OpenCFile(filename, "w");
if (!f)
return;
fprintf(f,".text\n");
@@ -227,7 +227,7 @@ void SymbolMap::SaveSymbolMap(const char *filename) const
bool SymbolMap::LoadNocashSym(const char *filename)
{
lock_guard guard(lock_);
FILE *f = fopen(filename,"r");
FILE *f = File::OpenCFile(filename, "r");
if (!f)
return false;
@@ -336,7 +336,7 @@ bool SymbolMap::getSymbolValue(char* symbol, u32& dest)
{
const MapEntry &entry = *it;
#ifdef _WIN32
if (stricmp(entry.name,symbol) == 0)
if (_stricmp(entry.name,symbol) == 0)
#else
if (strcasecmp(entry.name,symbol) == 0)
#endif
@@ -388,8 +388,8 @@ void SymbolMap::FillSymbolListBox(HWND listbox,SymbolType symmask) const
{
for (int i = 0; i < defaultSymbolsAmount; i++)
{
char temp[256];
sprintf(temp,"0x%08X (%s)",defaultSymbolsAddresses[i],defaultSymbolsNames[i]);
wchar_t temp[256];
wsprintf(temp, L"0x%08X (%S)", defaultSymbolsAddresses[i], defaultSymbolsNames[i]);
int index = ListBox_AddString(listbox,temp);
ListBox_SetItemData(listbox,index,defaultSymbolsAddresses[i]);
}
@@ -404,12 +404,12 @@ void SymbolMap::FillSymbolListBox(HWND listbox,SymbolType symmask) const
const MapEntry &entry = *it;
if (entry.type & symmask)
{
char temp[256];
wchar_t temp[256];
if (entry.type & ST_FUNCTION || !(entry.type & ST_DATA))
{
sprintf(temp,"%s",entry.name);
wsprintf(temp, L"%S", entry.name);
} else {
sprintf(temp,"0x%08X (%s)",entry.vaddress,entry.name);
wsprintf(temp, L"0x%08X (%S)", entry.vaddress, entry.name);
}
int index = ListBox_AddString(listbox,temp);
@@ -429,23 +429,23 @@ void SymbolMap::FillSymbolComboBox(HWND listbox,SymbolType symmask) const
//int style = GetWindowLong(listbox,GWL_STYLE);
ComboBox_AddString(listbox,"(0x02000000)");
ComboBox_SetItemData(listbox,0,0x02000000);
ComboBox_AddString(listbox, L"(0x02000000)");
ComboBox_SetItemData(listbox, 0, 0x02000000);
//ListBox_AddString(listbox,"(0x80002000)");
//ListBox_SetItemData(listbox,1,0x80002000);
//ListBox_AddString(listbox, L"(0x80002000)");
//ListBox_SetItemData(listbox, 1, 0x80002000);
lock_guard guard(lock_);
SendMessage(listbox, WM_SETREDRAW, FALSE, 0);
SendMessage(listbox, CB_INITSTORAGE, (WPARAM)entries.size(), (LPARAM)entries.size() * 30);
SendMessage(listbox, CB_INITSTORAGE, (WPARAM)entries.size(), (LPARAM)entries.size() * 30 * sizeof(wchar_t));
for (size_t i = 0, end = entries.size(); i < end; ++i)
{
const MapEntry &entry = entries[i];
if (entry.type & symmask)
{
char temp[256];
sprintf(temp,"%s (%d)",entry.name,entry.size);
wchar_t temp[256];
wsprintf(temp, L"%S (%d)", entry.name, entry.size);
int index = ComboBox_AddString(listbox,temp);
ComboBox_SetItemData(listbox,index,entry.vaddress);
}
@@ -469,6 +469,7 @@ void SymbolMap::FillListBoxBLinks(HWND listbox, int num) const
for (int i=0; i<e.backwardLinks.size(); i++)
{
u32 addr = e.backwardLinks[i];
// TODO: wchar_t
int index = ListBox_AddString(listbox,SymbolMap::GetSymbolName(SymbolMap::GetSymbolNum(addr)));
ListBox_SetItemData(listbox,index,addr);
}
@@ -537,7 +538,7 @@ unsigned int SymbolMap::GetRunCount(int num) const
void SymbolMap::CompileFuncSignaturesFile(const char *filename) const
{
// Store name,length,first instruction,hash into file
FILE *f = fopen(filename, "w");
FILE *f = File::OpenCFile(filename, "w");
fprintf(f,"00000000\n");
int count=0;
for (auto it = entries.begin(), end = entries.end(); it != end; ++it)
@@ -546,7 +547,7 @@ void SymbolMap::CompileFuncSignaturesFile(const char *filename) const
int size = entry.size;
if (size >= 16 && entry.type == ST_FUNCTION)
{
u32 inst = Memory::Read_Instruction(entry.vaddress); //try to make a bigger number of different vals sometime
u32 inst = Memory::Read_Instruction(entry.vaddress).encoding; //try to make a bigger number of different vals sometime
if (inst != 0)
{
char temp[64];
@@ -588,7 +589,7 @@ void SymbolMap::UseFuncSignaturesFile(const char *filename, u32 maxAddress)
sigs.clear();
//SymbolMap::ResetSymbolMap();
//#1: Read the signature file and put them in a fast data structure
FILE *f = fopen(filename, "r");
FILE *f = File::OpenCFile(filename, "r");
int count;
if (fscanf(f, "%08x\n", &count) != 1)
count = 0;
@@ -633,7 +634,7 @@ void SymbolMap::UseFuncSignaturesFile(const char *filename, u32 maxAddress)
sprintf(temp,"Scanning: %08x",addr);
lastAddr=addr;
}
u32 inst = Memory::Read_Instruction(addr);
u32 inst = Memory::Read_Instruction(addr).encoding;
if (!inst)
continue;
+51 -28
View File
@@ -160,6 +160,32 @@ void PSPOskDialog::ConvertUCS2ToUTF8(std::string& _string, const PSPPointer<u16_
_string = stringBuffer;
}
void GetWideStringFromPSPPointer(std::wstring& _string, const PSPPointer<u16_le> em_address)
{
if (!em_address.IsValid())
{
_string = L"";
return;
}
const size_t maxLength = 2048;
wchar_t stringBuffer[maxLength];
wchar_t *string = stringBuffer;
auto input = em_address;
int c;
u32 count = 0;
while ((c = *input++) != 0)
{
if ( !(++count >= maxLength) )
*string++ = c;
else
break;
}
*string++ = '\0';
_string = stringBuffer;
}
void PSPOskDialog::ConvertUCS2ToUTF8(std::string& _string, const wchar_t *input)
{
char stringBuffer[2048];
@@ -600,7 +626,7 @@ void PSPOskDialog::RemoveKorean()
else
{
i_level = 1;
inputChars += kor_cons[i_value[0]];;
inputChars += kor_cons[i_value[0]];
}
}
else if(i_level == 3)
@@ -739,10 +765,9 @@ void PSPOskDialog::RenderKeyboard()
#ifdef _WIN32
// TODO: Why does this have a 2 button press lag/delay when
// re-opening the dialog box? I don't get it.
// TODO: Use a wstring to allow Japanese/Russian/etc.. on _WIN32(others?)
int PSPOskDialog::NativeKeyboard()
{
char *input = new char[FieldMaxLength()];
wchar_t *input = new wchar_t[FieldMaxLength()];
memset(input, 0, sizeof(input));
if (status == SCE_UTILITY_STATUS_INITIALIZE)
@@ -752,37 +777,35 @@ int PSPOskDialog::NativeKeyboard()
else if (status == SCE_UTILITY_STATUS_RUNNING)
{
std::string initial_text;
ConvertUCS2ToUTF8(initial_text, oskParams->fields[0].intext);
std::wstring titleText;
GetWideStringFromPSPPointer(titleText, oskParams->fields[0].desc);
const size_t defaultText_len = 512;
char defaultText[defaultText_len];
std::wstring defaultText;
GetWideStringFromPSPPointer(defaultText, oskParams->fields[0].intext);
memset(defaultText, 0, sizeof(defaultText));
if(defaultText.length() <= 0)
defaultText.assign(L"VALUE");
if(initial_text.length() < defaultText_len)
strncat(defaultText, initial_text.c_str(), strlen(initial_text.c_str()));
else {
ERROR_LOG(HLE, "NativeKeyboard: initial text length is too long");
strncat(defaultText, "VALUE", strlen("VALUE"));
std::wstring inputWide;
if(!host->InputBoxGetWString(titleText.c_str(), defaultText, inputWide))
{
wcsncat(input, L"", wcslen(L""));
}
else
{
size_t maxInputLength = FieldMaxLength();
char windowTitle[defaultText_len];
memset(windowTitle, 0, sizeof(windowTitle));
std::string description_text;
ConvertUCS2ToUTF8(description_text, oskParams->fields[0].desc);
if(description_text.length() < defaultText_len)
strncat(windowTitle, description_text.c_str(), strlen(description_text.c_str()));
size_t maxInputLength = FieldMaxLength();
if(host->InputBoxGetString(windowTitle, defaultText, input, maxInputLength)) {
strncat(input, "", strlen(""));
if(inputWide.length() < maxInputLength)
{
wcsncat(input, inputWide.c_str(), inputWide.length());
}
else
{
ERROR_LOG(HLE, "NativeKeyboard: input text too long(%d characters/glyphs max), truncating to game-requested length.", maxInputLength);
wcsncat(input, inputWide.c_str(), maxInputLength);
}
}
status = SCE_UTILITY_STATUS_FINISHED;
}
else if (status == SCE_UTILITY_STATUS_FINISHED)
+4 -4
View File
@@ -68,7 +68,7 @@ void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs)
addr += segmentVAddr[readwrite];
u32 op = Memory::ReadUnchecked_U32(addr);
u32 op = Memory::Read_Instruction(addr).encoding;
const bool log = false;
//log=true;
@@ -145,7 +145,7 @@ void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs)
case R_MIPS_16:
{
char temp[256];
MIPSDisAsm(op, 0, temp);
MIPSDisAsm(MIPSOpcode(op), 0, temp);
ERROR_LOG_REPORT(LOADER, "WARNING: Unsupported R_MIPS_16 reloc @ %08x : %s", addr, temp);
}
break;
@@ -157,7 +157,7 @@ void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs)
default:
{
char temp[256];
MIPSDisAsm(op, 0, temp);
MIPSDisAsm(MIPSOpcode(op), 0, temp);
ERROR_LOG_REPORT(LOADER,"ARGH IT'S AN UNKNOWN RELOCATION!!!!!!!! %08x, type=%d : %s", addr, type, temp);
}
break;
@@ -253,7 +253,7 @@ void ElfReader::LoadRelocations2(int rel_seg)
buf += 2;
rel_base += rel_offset;
}else if((flag&0x06)==0x04){
rel_base = buf[0] | (buf[1]<<8) | (buf[2]<<16) | (buf[3]<<24);;
rel_base = buf[0] | (buf[1]<<8) | (buf[2]<<16) | (buf[3]<<24);
buf += 4;
}else{
ERROR_LOG_REPORT(LOADER, "Rel2: invalid relocat size flag! %x", flag);
+2 -1
View File
@@ -20,10 +20,11 @@
#include <cstring>
#include "Common/Log.h"
#include "Common/FileUtil.h"
#include "Core/ELF/PBPReader.h"
PBPReader::PBPReader(const char *filename) : header_() {
file_ = fopen(filename, "rb");
file_ = File::OpenCFile(filename, "rb");
if (!file_) {
return;
}
+3 -2
View File
@@ -16,7 +16,8 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "BlockDevices.h"
#include "Common/FileUtil.h"
#include "Core/FileSystems/BlockDevices.h"
#include <cstdio>
#include <cstring>
@@ -29,7 +30,7 @@ extern "C"
BlockDevice *constructBlockDevice(const char *filename) {
// Check for CISO
FILE *f = fopen(filename, "rb");
FILE *f = File::OpenCFile(filename, "rb");
if (!f)
return 0;
char buffer[4];
+6 -5
View File
@@ -21,6 +21,7 @@
#include "ISOFileSystem.h"
#include "Core/HLE/sceKernel.h"
#include "file/zip_read.h"
#include "util/text/utf8.h"
#ifdef _WIN32
#include "Common/CommonWindows.h"
@@ -184,7 +185,7 @@ bool DirectoryFileHandle::Open(std::string& basePath, std::string& fileName, Fil
openmode = OPEN_EXISTING;
}
//Let's do it!
hFile = CreateFile(fullName.c_str(), desired, sharemode, 0, openmode, 0, 0);
hFile = CreateFile(ConvertUTF8ToWString(fullName).c_str(), desired, sharemode, 0, openmode, 0, 0);
bool success = hFile != INVALID_HANDLE_VALUE;
#else
// Convert flags in access parameter to fopen access mode
@@ -392,7 +393,7 @@ int DirectoryFileSystem::RenameFile(const std::string &from, const std::string &
const char * fullToC = fullTo.c_str();
#ifdef _WIN32
bool retValue = (MoveFile(fullFrom.c_str(), fullToC) == TRUE);
bool retValue = (MoveFile(ConvertUTF8ToWString(fullFrom).c_str(), ConvertUTF8ToWString(fullToC).c_str()) == TRUE);
#else
bool retValue = (0 == rename(fullFrom.c_str(), fullToC));
#endif
@@ -586,7 +587,7 @@ std::vector<PSPFileInfo> DirectoryFileSystem::GetDirListing(std::string path) {
std::string w32path = GetLocalPath(path) + "\\*.*";
hFind = FindFirstFile(w32path.c_str(), &findData);
hFind = FindFirstFile(ConvertUTF8ToWString(w32path).c_str(), &findData);
if (hFind == INVALID_HANDLE_VALUE) {
return myVector; //the empty list
@@ -603,11 +604,11 @@ std::vector<PSPFileInfo> DirectoryFileSystem::GetDirListing(std::string path) {
entry.access = entry.type == FILETYPE_NORMAL ? 0666 : 0777;
// TODO: is this just for .. or all subdirectories? Need to add a directory to the test
// to find out. Also why so different than the old test results?
if (!strcmp(findData.cFileName, "..") )
if (!wcscmp(findData.cFileName, L"..") )
entry.size = 4096;
else
entry.size = findData.nFileSizeLow | ((u64)findData.nFileSizeHigh<<32);
entry.name = findData.cFileName;
entry.name = ConvertWStringToUTF8(findData.cFileName);
tmFromFiletime(entry.atime, findData.ftLastAccessTime);
tmFromFiletime(entry.ctime, findData.ftCreationTime);
tmFromFiletime(entry.mtime, findData.ftLastWriteTime);
+1 -1
View File
@@ -662,7 +662,7 @@ void ISOFileSystem::DoState(PointerWrap &p)
entries.clear();
for (int i = 0; i < n; ++i)
{
u32 fd;
u32 fd = 0;
OpenFileEntry of;
p.Do(fd);
+6 -5
View File
@@ -22,6 +22,7 @@
#include "Core/FileSystems/ISOFileSystem.h"
#include "Core/HLE/sceKernel.h"
#include "file/zip_read.h"
#include "util/text/utf8.h"
#ifdef _WIN32
#include "Common/CommonWindows.h"
@@ -168,7 +169,7 @@ void VirtualDiscFileSystem::DoState(PointerWrap &p)
for (int i = 0; i < entryCount; i++)
{
u32 fd;
u32 fd = 0;
OpenFileEntry of;
p.Do(fd);
@@ -599,14 +600,14 @@ std::vector<PSPFileInfo> VirtualDiscFileSystem::GetDirListing(std::string path)
std::string w32path = GetLocalPath(path) + "\\*.*";
hFind = FindFirstFile(w32path.c_str(), &findData);
hFind = FindFirstFile(ConvertUTF8ToWString(w32path).c_str(), &findData);
if (hFind == INVALID_HANDLE_VALUE) {
return myVector; //the empty list
}
for (BOOL retval = 1; retval; retval = FindNextFile(hFind, &findData)) {
if (!strcmp(findData.cFileName, "..") || !strcmp(findData.cFileName, ".")) {
if (!wcscmp(findData.cFileName, L"..") || !wcscmp(findData.cFileName, L".")) {
continue;
}
@@ -619,7 +620,7 @@ std::vector<PSPFileInfo> VirtualDiscFileSystem::GetDirListing(std::string path)
entry.access = FILEACCESS_READ;
entry.size = findData.nFileSizeLow | ((u64)findData.nFileSizeHigh<<32);
entry.name = findData.cFileName;
entry.name = ConvertWStringToUTF8(findData.cFileName);
tmFromFiletime(entry.atime, findData.ftLastAccessTime);
tmFromFiletime(entry.ctime, findData.ftCreationTime);
tmFromFiletime(entry.mtime, findData.ftLastWriteTime);
@@ -728,7 +729,7 @@ void VirtualDiscFileSystem::HandlerLogger(void *arg, HandlerHandle handle, LogTy
VirtualDiscFileSystem::Handler::Handler(const char *filename, VirtualDiscFileSystem *const sys) {
#ifdef _WIN32
#define dlopen(name, ignore) (void *)LoadLibrary(name)
#define dlopen(name, ignore) (void *)LoadLibrary(ConvertUTF8ToWString(name).c_str())
#define dlsym(mod, name) GetProcAddress((HMODULE)mod, name)
#define dlclose(mod) FreeLibrary((HMODULE)mod)
#endif
+38 -87
View File
@@ -58,8 +58,6 @@ typedef std::vector<Syscall> SyscallVector;
typedef std::map<std::string, SyscallVector> SyscallVectorByModule;
static std::vector<HLEModule> moduleDB;
static SyscallVectorByModule unresolvedSyscalls;
static SyscallVectorByModule exportedCalls;
static int delayedResultEvent = -1;
static int hleAfterSyscall = HLE_AFTER_NOTHING;
static const char *hleAfterSyscallReschedReason;
@@ -87,8 +85,6 @@ void HLEInit()
void HLEDoState(PointerWrap &p)
{
p.Do(unresolvedSyscalls);
p.Do(exportedCalls);
p.Do(delayedResultEvent);
CoreTiming::RestoreRegisterEvent(delayedResultEvent, "HLEDelayedResult", hleDelayResultFinish);
p.DoMarker("HLE");
@@ -98,8 +94,6 @@ void HLEShutdown()
{
hleAfterSyscall = HLE_AFTER_NOTHING;
moduleDB.clear();
unresolvedSyscalls.clear();
exportedCalls.clear();
}
void RegisterModule(const char *name, int numFunctions, const HLEFunction *funcTable)
@@ -159,33 +153,19 @@ const char *GetFuncName(const char *moduleName, u32 nib)
if (func)
return func->name;
SyscallModuleName searchModuleName = {0};
strncpy(searchModuleName, moduleName, KERNELOBJECT_MAX_NAME_LENGTH);
searchModuleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
// Was this function exported previously?
static char temp[256];
const auto exported = exportedCalls.find(searchModuleName);
if (exported != exportedCalls.end())
{
const SyscallVector &syscalls = exported->second;
for (auto it = syscalls.begin(), end = syscalls.end(); it != end; ++it)
{
if (it->nid == nib)
{
sprintf(temp, "[EXP: 0x%08x]", nib);
return temp;
}
}
}
// No good, we can't find it.
sprintf(temp,"[UNK: 0x%08x]", nib);
return temp;
}
u32 GetSyscallOp(const char *moduleName, u32 nib)
{
// Special case to hook up bad imports.
if (moduleName == NULL)
{
return (0x03FFFFCC); // invalid syscall
}
int modindex = GetModuleIndex(moduleName);
if (modindex != -1)
{
@@ -197,7 +177,6 @@ u32 GetSyscallOp(const char *moduleName, u32 nib)
else
{
INFO_LOG(HLE, "Syscall (%s, %08x) unknown", moduleName, nib);
Reporting::ReportMessage("Unknown syscall in known module: %s 0x%08x", moduleName, nib);
return (0x0003FFCC | (modindex<<18)); // invalid syscall
}
}
@@ -208,77 +187,47 @@ u32 GetSyscallOp(const char *moduleName, u32 nib)
}
}
void WriteSyscall(const char *moduleName, u32 nib, u32 address)
bool FuncImportIsSyscall(const char *module, u32 nib)
{
return GetFunc(module, nib) != NULL;
}
void WriteFuncStub(u32 stubAddr, u32 symAddr)
{
// Note that this should be J not JAL, as otherwise control will return to the stub..
Memory::Write_U32(MIPS_MAKE_J(symAddr), stubAddr);
// Note: doing that, we can't trace external module calls, so maybe something else should be done to debug more efficiently
// Perhaps a syscall here (and verify support in jit), marking the module by uid (debugIdentifier)?
Memory::Write_U32(MIPS_MAKE_NOP(), stubAddr + 4);
}
void WriteFuncMissingStub(u32 stubAddr, u32 nid)
{
// Write a trap so we notice this func if it's called before resolving.
Memory::Write_U32(MIPS_MAKE_JR_RA(), stubAddr); // jr ra
Memory::Write_U32(GetSyscallOp(NULL, nid), stubAddr + 4);
}
bool WriteSyscall(const char *moduleName, u32 nib, u32 address)
{
if (nib == 0)
{
WARN_LOG_REPORT(HLE, "Wrote patched out nid=0 syscall (%s)", moduleName);
Memory::Write_U32(MIPS_MAKE_JR_RA(), address); //patched out?
Memory::Write_U32(MIPS_MAKE_NOP(), address+4); //patched out?
return;
return true;
}
int modindex = GetModuleIndex(moduleName);
if (modindex != -1)
{
Memory::Write_U32(MIPS_MAKE_JR_RA(), address); // jr ra
Memory::Write_U32(GetSyscallOp(moduleName, nib), address + 4);
return true;
}
else
{
Syscall sysc = {"", address, nib};
strncpy(sysc.moduleName, moduleName, KERNELOBJECT_MAX_NAME_LENGTH);
sysc.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
// Did another module export this already?
const auto exported = exportedCalls.find(sysc.moduleName);
if (exported != exportedCalls.end())
{
const SyscallVector &syscalls = exported->second;
for (auto it = syscalls.begin(), end = syscalls.end(); it != end; ++it)
{
if (it->nid == nib)
{
Memory::Write_U32(MIPS_MAKE_J(it->symAddr), address); // j symAddr
Memory::Write_U32(MIPS_MAKE_NOP(), address + 4); // nop (delay slot)
return;
}
}
}
// Module inexistent.. for now; let's store the syscall for it to be resolved later
INFO_LOG(HLE,"Syscall (%s,%08x) unresolved, storing for later resolving", moduleName, nib);
unresolvedSyscalls[sysc.moduleName].push_back(sysc);
// Write a trap so we notice this func if it's called before resolving.
Memory::Write_U32(MIPS_MAKE_JR_RA(), address); // jr ra
Memory::Write_U32(GetSyscallOp("(invalid syscall)", nib), address + 4);
}
}
void ResolveSyscall(const char *moduleName, u32 nib, u32 address)
{
_dbg_assert_msg_(HLE, moduleName != NULL, "Invalid module name.");
Syscall ex = {"", address, nib};
strncpy(ex.moduleName, moduleName, KERNELOBJECT_MAX_NAME_LENGTH);
ex.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
exportedCalls[ex.moduleName].push_back(ex);
const auto unresolved = unresolvedSyscalls.find(ex.moduleName);
if (unresolved != unresolvedSyscalls.end())
{
const SyscallVector &syscalls = unresolved->second;
for (size_t i = 0; i < syscalls.size(); i++)
{
const Syscall *sysc = &syscalls[i];
if (sysc->nid == nib)
{
INFO_LOG(HLE,"Resolving %s/%08x",moduleName,nib);
// Note: doing that, we can't trace external module calls, so maybe something else should be done to debug more efficiently
// Note that this should be J not JAL, as otherwise control will return to the stub..
Memory::Write_U32(MIPS_MAKE_J(address), sysc->symAddr);
Memory::Write_U32(MIPS_MAKE_NOP(), sysc->symAddr + 4);
}
}
ERROR_LOG_REPORT(HLE, "Unable to write unknown syscall: %s/%08x", moduleName, nib);
return false;
}
}
@@ -456,7 +405,7 @@ inline void updateSyscallStats(int modulenum, int funcnum, double total)
}
}
void CallSyscall(u32 op)
void CallSyscall(MIPSOpcode op)
{
double start = 0.0; // need to initialize to fix the race condition where g_Config.bShowDebugStats is enabled in the middle of this func.
if (g_Config.bShowDebugStats)
@@ -477,10 +426,12 @@ void CallSyscall(u32 op)
{
// TODO: Move to jit/interp.
u32 flags = moduleDB[modulenum].funcTable[funcnum].flags;
if (flags & HLE_NOT_DISPATCH_SUSPENDED)
if (flags != 0)
{
if (!__KernelIsDispatchEnabled())
if ((flags & HLE_NOT_DISPATCH_SUSPENDED) && !__KernelIsDispatchEnabled())
RETURN(SCE_KERNEL_ERROR_CAN_NOT_WAIT);
else if ((flags & HLE_NOT_IN_INTERRUPT) && __IsInInterrupt())
RETURN(SCE_KERNEL_ERROR_ILLEGAL_CONTEXT);
else
func();
}
+5 -4
View File
@@ -113,7 +113,8 @@ void HLEDoState(PointerWrap &p);
void HLEShutdown();
u32 GetNibByName(const char *module, const char *function);
u32 GetSyscallOp(const char *module, u32 nib);
void WriteSyscall(const char *module, u32 nib, u32 address);
void CallSyscall(u32 op);
void ResolveSyscall(const char *moduleName, u32 nib, u32 address);
bool FuncImportIsSyscall(const char *module, u32 nib);
bool WriteSyscall(const char *module, u32 nib, u32 address);
void CallSyscall(MIPSOpcode op);
void WriteFuncStub(u32 stubAddr, u32 symAddr);
void WriteFuncMissingStub(u32 stubAddr, u32 nid);
+2
View File
@@ -256,12 +256,14 @@ static const int numModules = sizeof(moduleList)/sizeof(HLEModule);
void RegisterAllModules() {
Register_Kernel_Library();
Register_ThreadManForUser();
Register_ThreadManForKernel();
Register_LoadExecForUser();
Register_UtilsForKernel();
Register_SysMemUserForUser();
Register_InterruptManager();
Register_IoFileMgrForUser();
Register_ModuleMgrForUser();
Register_ModuleMgrForKernel();
Register_StdioForUser();
Register_sceHprm();
+11 -6
View File
@@ -85,7 +85,7 @@ void __AudioInit() {
if (g_Config.bLowLatencyAudio) {
chanQueueMaxSizeFactor = 1;
chanQueueMinSizeFactor = 0;
chanQueueMinSizeFactor = 1;
hwBlockSize = 16;
hostAttemptBlockSize = 256;
} else {
@@ -160,10 +160,15 @@ u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking) {
// TODO: Regular multichannel audio seems to block for 64 samples less? Or enqueue the first 64 sync?
int blockSamples = (int)chan.sampleQueue.size() / 2 / chanQueueMinSizeFactor;
AudioChannelWaitInfo waitInfo = {__KernelGetCurThread(), blockSamples};
chan.waitingThreads.push_back(waitInfo);
// Also remember the value to return in the waitValue.
__KernelWaitCurThread(WAITTYPE_AUDIOCHANNEL, (SceUID)chanNum + 1, ret, 0, false, "blocking audio waited");
if (__KernelIsDispatchEnabled()) {
AudioChannelWaitInfo waitInfo = {__KernelGetCurThread(), blockSamples};
chan.waitingThreads.push_back(waitInfo);
// Also remember the value to return in the waitValue.
__KernelWaitCurThread(WAITTYPE_AUDIOCHANNEL, (SceUID)chanNum + 1, ret, 0, false, "blocking audio");
} else {
// TODO: Maybe we shouldn't take this audio after all?
ret = SCE_KERNEL_ERROR_CAN_NOT_WAIT;
}
// Fall through to the sample queueing, don't want to lose the samples even though
// we're getting full. The PSP would enqueue after blocking.
@@ -311,7 +316,7 @@ void __AudioUpdate() {
}
if (firstChannel) {
memset(mixBuffer, 0, sizeof(mixBuffer));
memset(mixBuffer, 0, hwBlockSize * 2 * sizeof(s32));
}
if (g_Config.bEnableSound) {
+2 -2
View File
@@ -65,6 +65,8 @@ const u32 ATRAC3PLUS_MAX_SAMPLES = 0x800;
static const int atracDecodeDelay = 2300;
static const int MAX_CONFIG_VOLUME = 8;
#ifdef USE_FFMPEG
// Urgh! Why is this needed?
@@ -625,7 +627,6 @@ u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int
atrac->sampleQueue.push(buf, decodebytes);
}
}
const int MAX_CONFIG_VOLUME = 8;
s16* out = (s16*)outbuf;
memset(out, 0, ATRAC3PLUS_MAX_SAMPLES * sizeof(s16) * atrac->atracOutputChannels);
int gotsize = atrac->sampleQueue.pop_front(buf, ATRAC3PLUS_MAX_SAMPLES * sizeof(s16) * atrac->atracChannels);
@@ -1696,7 +1697,6 @@ int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesConsumedA
Atrac3plus_Decoder::Decode(atrac->decoder_context, Memory::GetPointer(sourceAddr), sourcebytes, &decodebytes, buf);
atrac->sampleQueue.push(buf, decodebytes);
}
const int MAX_CONFIG_VOLUME = 5;
s16* out = (s16*)Memory::GetPointer(samplesAddr);
memset(out, 0, ATRAC3PLUS_MAX_SAMPLES * sizeof(s16) * atrac->atracOutputChannels);
int gotsize = atrac->sampleQueue.pop_front(buf, ATRAC3PLUS_MAX_SAMPLES * sizeof(s16) * atrac->atracChannels);
+4 -4
View File
@@ -79,7 +79,7 @@ u32 sceAudioOutputBlocking(u32 chan, int vol, u32 samplePtr) {
return SCE_ERROR_AUDIO_INVALID_CHANNEL;
} else if (!chans[chan].reserved) {
ERROR_LOG(HLE,"sceAudioOutputBlocking() - channel not reserved");
return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED;
return SCE_ERROR_AUDIO_CHANNEL_NOT_INIT;
} else {
DEBUG_LOG(HLE, "sceAudioOutputBlocking(%08x, %08x, %08x)", chan, vol, samplePtr);
if (vol >= 0) {
@@ -100,7 +100,7 @@ u32 sceAudioOutputPannedBlocking(u32 chan, int leftvol, int rightvol, u32 sample
return SCE_ERROR_AUDIO_INVALID_CHANNEL;
} else if (!chans[chan].reserved) {
ERROR_LOG(HLE,"sceAudioOutputPannedBlocking() - channel not reserved");
return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED;
return SCE_ERROR_AUDIO_CHANNEL_NOT_INIT;
} else {
DEBUG_LOG(HLE, "sceAudioOutputPannedBlocking(%08x, %08x, %08x, %08x)", chan, leftvol, rightvol, samplePtr);
if (leftvol >= 0) {
@@ -123,7 +123,7 @@ u32 sceAudioOutput(u32 chan, int vol, u32 samplePtr) {
return SCE_ERROR_AUDIO_INVALID_CHANNEL;
} else if (!chans[chan].reserved) {
ERROR_LOG(HLE,"sceAudioOutput(%08x, %08x, %08x) - channel not reserved", chan, vol, samplePtr);
return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED;
return SCE_ERROR_AUDIO_CHANNEL_NOT_INIT;
} else {
DEBUG_LOG(HLE, "sceAudioOutputPanned(%08x, %08x, %08x)", chan, vol, samplePtr);
if (vol >= 0) {
@@ -144,7 +144,7 @@ u32 sceAudioOutputPanned(u32 chan, int leftvol, int rightvol, u32 samplePtr) {
return SCE_ERROR_AUDIO_INVALID_CHANNEL;
} else if (!chans[chan].reserved) {
ERROR_LOG(HLE,"sceAudioOutputPanned(%08x, %08x, %08x, %08x) - channel not reserved", chan, leftvol, rightvol, samplePtr);
return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED;
return SCE_ERROR_AUDIO_CHANNEL_NOT_INIT;
} else {
DEBUG_LOG(HLE,"sceAudioOutputPanned(%08x, %08x, %08x, %08x)", chan, leftvol, rightvol, samplePtr);
if (leftvol >= 0) {
+15 -9
View File
@@ -16,15 +16,16 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <math.h>
#include "HLE.h"
#include "../MIPS/MIPS.h"
#include "../CoreTiming.h"
#include "ChunkFile.h"
#include "StdMutex.h"
#include "sceCtrl.h"
#include "sceDisplay.h"
#include "sceKernel.h"
#include "sceKernelThread.h"
#include "Core/HLE/HLE.h"
#include "Core/MIPS/MIPS.h"
#include "Core/CoreTiming.h"
#include "Common/ChunkFile.h"
#include "Common/StdMutex.h"
#include "Core/HLE/sceCtrl.h"
#include "Core/HLE/sceDisplay.h"
#include "Core/HLE/sceKernel.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernelInterrupt.h"
/* Index for the two analog directions */
#define CTRL_ANALOG_X 0
@@ -216,6 +217,11 @@ int __CtrlReadBuffer(u32 ctrlDataPtr, u32 nBufs, bool negative, bool peek)
if (nBufs > NUM_CTRL_BUFFERS)
return SCE_KERNEL_ERROR_INVALID_SIZE;
if (!peek && !__KernelIsDispatchEnabled())
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
if (!peek && __IsInInterrupt())
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
u32 resetRead = ctrlBufRead;
u32 availBufs;
+49 -13
View File
@@ -115,6 +115,8 @@ static int actualFlips = 0; // taking frameskip into account
static int lastActualFlips = 0;
static float actualFps = 0;
static u64 lastFlipCycles = 0;
// For the "max 60 fps" setting.
static int lastFlipsTooFrequent = 0;
void hleEnterVblank(u64 userdata, int cyclesLate);
void hleLeaveVblank(u64 userdata, int cyclesLate);
@@ -135,6 +137,7 @@ void __DisplayInit() {
framebuf.pspFramebufFormat = GE_FORMAT_8888;
framebuf.pspFramebufLinesize = 480; // ??
lastFlipCycles = 0;
lastFlipsTooFrequent = 0;
enterVblankEvent = CoreTiming::RegisterEvent("EnterVBlank", &hleEnterVblank);
leaveVblankEvent = CoreTiming::RegisterEvent("LeaveVBlank", &hleLeaveVblank);
@@ -272,6 +275,8 @@ void __DisplayGetDebugStats(char stats[2048]) {
"Most active syscall: %s : %0.2f ms\n"
"Draw calls: %i, flushes %i\n"
"Cached Draw calls: %i\n"
"Alpha Tested draws: %i\n"
"Non Alpha Tested draws: %i\n"
"Num Tracked Vertex Arrays: %i\n"
"Cycles executed: %d (%f per vertex)\n"
"Commands per call level: %i %i %i %i\n"
@@ -294,6 +299,8 @@ void __DisplayGetDebugStats(char stats[2048]) {
gpuStats.numDrawCalls,
gpuStats.numFlushes,
gpuStats.numCachedDrawCalls,
gpuStats.numAlphaTestedDraws,
gpuStats.numNonAlphaTestedDraws,
gpuStats.numTrackedVertexArrays,
gpuStats.vertexGPUCycles + gpuStats.otherGPUCycles,
vertexAverageCycles,
@@ -519,15 +526,28 @@ u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync)
fbstate.pspFramebufLinesize = linesize;
}
if (topaddr != framebuf.topaddr) {
if (g_Config.iForceMaxEmulatedFPS) {
u64 now = CoreTiming::GetTicks();
u64 expected = msToCycles(1000) / g_Config.iForceMaxEmulatedFPS;
u64 actual = now - lastFlipCycles;
if (actual < expected)
hleEatCycles((int)(expected - actual));
lastFlipCycles = CoreTiming::GetTicks();
s64 delayCycles = 0;
if (topaddr != framebuf.topaddr && g_Config.iForceMaxEmulatedFPS > 0) {
// Sometimes we get a small number, there's probably no need to delay the thread for this.
// sceDisplaySetFramebuf() isn't supposed to delay threads at all. This is a hack.
const int FLIP_DELAY_CYCLES_MIN = 10;
// Some games (like Final Fantasy 4) only call this too much in spurts.
// The goal is to fix games where this would result in a consistent overhead.
const int FLIP_DELAY_MIN_FLIPS = 30;
u64 now = CoreTiming::GetTicks();
u64 expected = msToCycles(1000) / g_Config.iForceMaxEmulatedFPS;
u64 actual = now - lastFlipCycles;
if (actual < expected - FLIP_DELAY_CYCLES_MIN) {
if (lastFlipsTooFrequent >= FLIP_DELAY_MIN_FLIPS) {
delayCycles = expected - actual;
} else {
++lastFlipsTooFrequent;
}
} else {
--lastFlipsTooFrequent;
}
lastFlipCycles = CoreTiming::GetTicks();
}
if (sync == PSP_DISPLAY_SETBUF_IMMEDIATE) {
@@ -543,7 +563,15 @@ u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync)
latchedFramebuf = fbstate;
framebufIsLatched = true;
}
return 0;
if (delayCycles > 0) {
// Okay, the game is going at too high a frame rate. God of War and Fat Princess both do this.
// Simply eating the cycles works and is fast, but breaks other games (like Jeanne d'Arc.)
// So, instead, we delay this HLE thread only (a small deviation from correct behavior.)
return hleDelayResult(0, "set framebuf", cyclesToUs(delayCycles));
} else {
return 0;
}
}
bool __DisplayGetFramebuf(u8 **topaddr, u32 *linesize, u32 *pixelFormat, int latchedMode) {
@@ -598,6 +626,10 @@ u32 sceDisplayWaitVblankStartMulti(int vblanks) {
return SCE_KERNEL_ERROR_INVALID_VALUE;
}
VERBOSE_LOG(HLE, "sceDisplayWaitVblankStartMulti(%d)", vblanks);
if (!__KernelIsDispatchEnabled())
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
if (__IsInInterrupt())
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread(), vblanks));
__KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false, "vblank start multi waited");
return 0;
@@ -629,6 +661,10 @@ u32 sceDisplayWaitVblankStartMultiCB(int vblanks) {
return SCE_KERNEL_ERROR_INVALID_VALUE;
}
VERBOSE_LOG(HLE,"sceDisplayWaitVblankStartMultiCB(%d)", vblanks);
if (!__KernelIsDispatchEnabled())
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
if (__IsInInterrupt())
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread(), vblanks));
__KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true, "vblank start multi waited");
return 0;
@@ -719,11 +755,11 @@ const HLEFunction sceDisplay[] = {
{0x0E20F177,WrapU_III<sceDisplaySetMode>, "sceDisplaySetMode"},
{0x289D82FE,WrapU_UIII<sceDisplaySetFramebuf>, "sceDisplaySetFrameBuf"},
{0xEEDA2E54,WrapU_UUUI<sceDisplayGetFramebuf>,"sceDisplayGetFrameBuf"},
{0x36CDFADE,WrapU_V<sceDisplayWaitVblank>, "sceDisplayWaitVblank"},
{0x984C27E7,WrapU_V<sceDisplayWaitVblankStart>, "sceDisplayWaitVblankStart"},
{0x36CDFADE,WrapU_V<sceDisplayWaitVblank>, "sceDisplayWaitVblank", HLE_NOT_DISPATCH_SUSPENDED},
{0x984C27E7,WrapU_V<sceDisplayWaitVblankStart>, "sceDisplayWaitVblankStart", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x40f1469c,WrapU_I<sceDisplayWaitVblankStartMulti>, "sceDisplayWaitVblankStartMulti"},
{0x8EB9EC49,WrapU_V<sceDisplayWaitVblankCB>, "sceDisplayWaitVblankCB"},
{0x46F186C3,WrapU_V<sceDisplayWaitVblankStartCB>, "sceDisplayWaitVblankStartCB"},
{0x8EB9EC49,WrapU_V<sceDisplayWaitVblankCB>, "sceDisplayWaitVblankCB", HLE_NOT_DISPATCH_SUSPENDED},
{0x46F186C3,WrapU_V<sceDisplayWaitVblankStartCB>, "sceDisplayWaitVblankStartCB", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x77ed8b3a,WrapU_I<sceDisplayWaitVblankStartMultiCB>,"sceDisplayWaitVblankStartMultiCB"},
{0xdba6c4c4,WrapF_V<sceDisplayGetFramePerSec>,"sceDisplayGetFramePerSec"},
{0x773dd3a3,WrapU_V<sceDisplayGetCurrentHcount>,"sceDisplayGetCurrentHcount"},
+10
View File
@@ -55,6 +55,11 @@ public:
{
GeInterruptData intrdata = ge_pending_cb.front();
DisplayList* dl = gpu->getList(intrdata.listid);
if (!dl->interruptsEnabled)
{
ERROR_LOG_REPORT(HLE, "Unable to run GE interrupt: list has interrupts disabled, should not happen");
return false;
}
if (dl == NULL)
{
@@ -120,6 +125,11 @@ public:
ge_pending_cb.pop_front();
DisplayList* dl = gpu->getList(intrdata.listid);
if (!dl->interruptsEnabled)
{
ERROR_LOG_REPORT(HLE, "Unable to finish GE interrupt: list has interrupts disabled, should not happen");
return;
}
switch (dl->signal)
{
+58 -17
View File
@@ -43,6 +43,7 @@ extern "C" {
#include "Core/HLE/sceKernel.h"
#include "Core/HLE/sceKernelMemory.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernelInterrupt.h"
// For headless screenshots.
#include "Core/HLE/sceDisplay.h"
@@ -644,9 +645,17 @@ bool __IoRead(int &result, int id, u32 data_addr, int size) {
}
u32 sceIoRead(int id, u32 data_addr, int size) {
// TODO: Check id is valid first?
if (!__KernelIsDispatchEnabled() && id > 2) {
return -1;
u32 error;
FileNode *f = __IoGetFd(id, error);
if (id > 2 && f != NULL) {
if (!__KernelIsDispatchEnabled()) {
DEBUG_LOG(HLE, "sceIoRead(%d, %08x, %x): dispatch disabled", id, data_addr, size);
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
}
if (__IsInInterrupt()) {
DEBUG_LOG(HLE, "sceIoRead(%d, %08x, %x): inside interrupt", id, data_addr, size);
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
}
}
// TODO: Timing is probably not very accurate, low estimate.
@@ -660,8 +669,6 @@ u32 sceIoRead(int id, u32 data_addr, int size) {
if (!complete) {
DEBUG_LOG(HLE, "sceIoRead(%d, %08x, %x): deferring result", id, data_addr, size);
u32 error;
FileNode *f = __IoGetFd(id, error);
__IoSchedSync(f, id, us);
__KernelWaitCurThread(WAITTYPE_IO, id, 0, 0, false, "io read");
return 0;
@@ -734,9 +741,18 @@ bool __IoWrite(int &result, int id, void *data_ptr, int size) {
}
u32 sceIoWrite(int id, u32 data_addr, int size) {
// TODO: Check id is valid first?
if (!__KernelIsDispatchEnabled() && id > 2)
return -1;
u32 error;
FileNode *f = __IoGetFd(id, error);
if (id > 2 && f != NULL) {
if (!__KernelIsDispatchEnabled()) {
DEBUG_LOG(HLE, "sceIoWrite(%d, %08x, %x): dispatch disabled", id, data_addr, size);
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
}
if (__IsInInterrupt()) {
DEBUG_LOG(HLE, "sceIoWrite(%d, %08x, %x): inside interrupt", id, data_addr, size);
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
}
}
// TODO: Timing is probably not very accurate, low estimate.
int us = size / 100;
@@ -749,8 +765,6 @@ u32 sceIoWrite(int id, u32 data_addr, int size) {
if (!complete) {
DEBUG_LOG(HLE, "sceIoWrite(%d, %08x, %x): deferring result", id, data_addr, size);
u32 error;
FileNode *f = __IoGetFd(id, error);
__IoSchedSync(f, id, us);
__KernelWaitCurThread(WAITTYPE_IO, id, 0, 0, false, "io write");
return 0;
@@ -1485,24 +1499,33 @@ u32 sceIoOpenAsync(const char *filename, int flags, int mode)
return fd;
}
u32 sceIoGetAsyncStat(int id, u32 poll, u32 address)
{
u32 sceIoGetAsyncStat(int id, u32 poll, u32 address) {
u32 error;
FileNode *f = __IoGetFd(id, error);
if (f)
{
if (f) {
if (__IsInInterrupt()) {
DEBUG_LOG(HLE, "%lli = sceIoGetAsyncStat(%i, %i, %08x): illegal context", f->asyncResult, id, poll, address);
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
}
if (f->pendingAsyncResult) {
if (poll) {
DEBUG_LOG(HLE, "%lli = sceIoGetAsyncStat(%i, %i, %08x): not ready", f->asyncResult, id, poll, address);
return 1;
} else {
if (!__KernelIsDispatchEnabled())
if (!__KernelIsDispatchEnabled()) {
DEBUG_LOG(HLE, "%lli = sceIoGetAsyncStat(%i, %i, %08x): dispatch disabled", f->asyncResult, id, poll, address);
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
}
DEBUG_LOG(HLE, "%lli = sceIoGetAsyncStat(%i, %i, %08x): waiting", f->asyncResult, id, poll, address);
__KernelWaitCurThread(WAITTYPE_IO, id, address, 0, false, "io waited");
}
} else if (f->hasAsyncResult) {
if (!__KernelIsDispatchEnabled()) {
DEBUG_LOG(HLE, "%lli = sceIoGetAsyncStat(%i, %i, %08x): dispatch disabled", f->asyncResult, id, poll, address);
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
}
DEBUG_LOG(HLE, "%lli = sceIoGetAsyncStat(%i, %i, %08x)", f->asyncResult, id, poll, address);
Memory::Write_U64((u64) f->asyncResult, address);
f->hasAsyncResult = false;
@@ -1527,10 +1550,22 @@ int sceIoWaitAsync(int id, u32 address) {
u32 error;
FileNode *f = __IoGetFd(id, error);
if (f) {
if (__IsInInterrupt()) {
DEBUG_LOG(HLE, "%lli = sceIoWaitAsync(%i, %08x): illegal context", f->asyncResult, id, address);
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
}
if (f->pendingAsyncResult) {
if (!__KernelIsDispatchEnabled()) {
DEBUG_LOG(HLE, "%lli = sceIoWaitAsync(%i, %08x): dispatch disabled", f->asyncResult, id, address);
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
}
DEBUG_LOG(HLE, "%lli = sceIoWaitAsync(%i, %08x): waiting", f->asyncResult, id, address);
__KernelWaitCurThread(WAITTYPE_IO, id, address, 0, false, "io waited");
} else if (f->hasAsyncResult) {
if (!__KernelIsDispatchEnabled()) {
DEBUG_LOG(HLE, "%lli = sceIoWaitAsync(%i, %08x): dispatch disabled", f->asyncResult, id, address);
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
}
DEBUG_LOG(HLE, "%lli = sceIoWaitAsync(%i, %08x)", f->asyncResult, id, address);
Memory::Write_U64((u64) f->asyncResult, address);
f->hasAsyncResult = false;
@@ -1554,9 +1589,15 @@ int sceIoWaitAsyncCB(int id, u32 address) {
u32 error;
FileNode *f = __IoGetFd(id, error);
if (f) {
if (__IsInInterrupt()) {
DEBUG_LOG(HLE, "%lli = sceIoWaitAsyncCB(%i, %08x): illegal context", f->asyncResult, id, address);
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
}
hleCheckCurrentCallbacks();
if (f->pendingAsyncResult) {
DEBUG_LOG(HLE, "%lli = sceIoWaitAsyncCB(%i, %08x): waiting", f->asyncResult, id, address);
// TODO: This seems to re-enable dispatch or something?
__KernelWaitCurThread(WAITTYPE_IO, id, address, 0, false, "io waited");
} else if (f->hasAsyncResult) {
DEBUG_LOG(HLE, "%lli = sceIoWaitAsyncCB(%i, %08x)", f->asyncResult, id, address);
@@ -1923,8 +1964,8 @@ const HLEFunction IoFileMgrForUser[] = {
{ 0x6d08a871, &WrapU_C<sceIoUnassign>, "sceIoUnassign" },
{ 0x42EC03AC, &WrapU_IUI<sceIoWrite>, "sceIoWrite" }, //(int fd, void *data, int size);
{ 0x0facab19, &WrapU_IUI<sceIoWriteAsync>, "sceIoWriteAsync" },
{ 0x35dbd746, &WrapI_IU<sceIoWaitAsyncCB>, "sceIoWaitAsyncCB", HLE_NOT_DISPATCH_SUSPENDED },
{ 0xe23eec33, &WrapI_IU<sceIoWaitAsync>, "sceIoWaitAsync", HLE_NOT_DISPATCH_SUSPENDED },
{ 0x35dbd746, &WrapI_IU<sceIoWaitAsyncCB>, "sceIoWaitAsyncCB" },
{ 0xe23eec33, &WrapI_IU<sceIoWaitAsync>, "sceIoWaitAsync" },
{ 0x5C2BE2CC, &WrapU_UIU<sceIoGetFdList>, "sceIoGetFdList"},
};
+92 -63
View File
@@ -636,14 +636,32 @@ int sceKernelReferGlobalProfiler(u32 statusPtr) {
return 0;
}
int ThreadManForKernel_446d8de6(const char *threadName, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr)
{
WARN_LOG(HLE,"Not support this patcher");
return sceKernelCreateThread(threadName, entry, prio, stacksize, attr, optionAddr);
}
int ThreadManForKernel_f475845d(SceUID threadToStartID, int argSize, u32 argBlockPtr)
{
WARN_LOG(HLE,"Not support this patcher");
return sceKernelStartThread(threadToStartID,argSize,argBlockPtr);
}
int ThreadManForKernel_ceadeb47(u32 usec)
{
WARN_LOG(HLE,"Not support this patcher");
return sceKernelDelayThread(usec);
}
const HLEFunction ThreadManForUser[] =
{
{0x55C20A00,&WrapI_CUUU<sceKernelCreateEventFlag>, "sceKernelCreateEventFlag"},
{0x812346E4,&WrapU_IU<sceKernelClearEventFlag>, "sceKernelClearEventFlag"},
{0xEF9E4C70,&WrapU_I<sceKernelDeleteEventFlag>, "sceKernelDeleteEventFlag"},
{0x1fb15a32,&WrapU_IU<sceKernelSetEventFlag>, "sceKernelSetEventFlag"},
{0x402FCF22,&WrapI_IUUUU<sceKernelWaitEventFlag>, "sceKernelWaitEventFlag"},
{0x328C546A,&WrapI_IUUUU<sceKernelWaitEventFlagCB>, "sceKernelWaitEventFlagCB"},
{0x402FCF22,&WrapI_IUUUU<sceKernelWaitEventFlag>, "sceKernelWaitEventFlag", HLE_NOT_IN_INTERRUPT},
{0x328C546A,&WrapI_IUUUU<sceKernelWaitEventFlagCB>, "sceKernelWaitEventFlagCB", HLE_NOT_IN_INTERRUPT},
{0x30FD48F0,&WrapI_IUUU<sceKernelPollEventFlag>, "sceKernelPollEventFlag"},
{0xCD203292,&WrapU_IUU<sceKernelCancelEventFlag>, "sceKernelCancelEventFlag"},
{0xA66B0120,&WrapU_IU<sceKernelReferEventFlagStatus>, "sceKernelReferEventFlagStatus"},
@@ -654,8 +672,8 @@ const HLEFunction ThreadManForUser[] =
{0x58b1f937,&WrapI_II<sceKernelPollSema>, "sceKernelPollSema"},
{0xBC6FEBC5,&WrapI_IU<sceKernelReferSemaStatus>, "sceKernelReferSemaStatus"},
{0x3F53E640,&WrapI_II<sceKernelSignalSema>, "sceKernelSignalSema"},
{0x4E3A1105,&WrapI_IIU<sceKernelWaitSema>, "sceKernelWaitSema", HLE_NOT_DISPATCH_SUSPENDED},
{0x6d212bac,&WrapI_IIU<sceKernelWaitSemaCB>, "sceKernelWaitSemaCB", HLE_NOT_DISPATCH_SUSPENDED},
{0x4E3A1105,&WrapI_IIU<sceKernelWaitSema>, "sceKernelWaitSema", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x6d212bac,&WrapI_IIU<sceKernelWaitSemaCB>, "sceKernelWaitSemaCB", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x60107536,&WrapI_U<sceKernelDeleteLwMutex>, "sceKernelDeleteLwMutex"},
{0x19CFF145,&WrapI_UCUIU<sceKernelCreateLwMutex>, "sceKernelCreateLwMutex"},
@@ -667,14 +685,14 @@ const HLEFunction ThreadManForUser[] =
//{0x31327F19,0, "_sceKernelLockLwMutexCB"},
//{0xBEED3A47,0, "_sceKernelUnlockLwMutex"},
{0xf8170fbe,&WrapI_I<sceKernelDeleteMutex>, "sceKernelDeleteMutex"},
{0xB011B11F,&WrapI_IIU<sceKernelLockMutex>, "sceKernelLockMutex", HLE_NOT_DISPATCH_SUSPENDED},
{0x5bf4dd27,&WrapI_IIU<sceKernelLockMutexCB>, "sceKernelLockMutexCB", HLE_NOT_DISPATCH_SUSPENDED},
{0x6b30100f,&WrapI_II<sceKernelUnlockMutex>, "sceKernelUnlockMutex"},
{0xb7d098c6,&WrapI_CUIU<sceKernelCreateMutex>, "sceKernelCreateMutex"},
{0x0DDCD2C9,&WrapI_II<sceKernelTryLockMutex>, "sceKernelTryLockMutex"},
{0xA9C2CB9A,&WrapI_IU<sceKernelReferMutexStatus>, "sceKernelReferMutexStatus"},
{0x87D9223C,0, "sceKernelCancelMutex"},
{0xf8170fbe,WrapI_I<sceKernelDeleteMutex>, "sceKernelDeleteMutex"},
{0xB011B11F,WrapI_IIU<sceKernelLockMutex>, "sceKernelLockMutex", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x5bf4dd27,WrapI_IIU<sceKernelLockMutexCB>, "sceKernelLockMutexCB", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x6b30100f,WrapI_II<sceKernelUnlockMutex>, "sceKernelUnlockMutex"},
{0xb7d098c6,WrapI_CUIU<sceKernelCreateMutex>, "sceKernelCreateMutex"},
{0x0DDCD2C9,WrapI_II<sceKernelTryLockMutex>, "sceKernelTryLockMutex"},
{0xA9C2CB9A,WrapI_IU<sceKernelReferMutexStatus>, "sceKernelReferMutexStatus"},
{0x87D9223C,WrapI_IIU<sceKernelCancelMutex>, "sceKernelCancelMutex"},
{0xFCCFAD26,WrapI_I<sceKernelCancelWakeupThread>,"sceKernelCancelWakeupThread"},
{0x1AF94D03,0,"sceKernelDonateWakeupThread"},
@@ -682,10 +700,10 @@ const HLEFunction ThreadManForUser[] =
{0x71bc9871,WrapI_II<sceKernelChangeThreadPriority>,"sceKernelChangeThreadPriority"},
{0x446D8DE6,WrapI_CUUIUU<sceKernelCreateThread>,"sceKernelCreateThread"},
{0x9fa03cd3,WrapI_I<sceKernelDeleteThread>,"sceKernelDeleteThread"},
{0xBD123D9E,sceKernelDelaySysClockThread,"sceKernelDelaySysClockThread"},
{0x1181E963,sceKernelDelaySysClockThreadCB,"sceKernelDelaySysClockThreadCB"},
{0xceadeb47,WrapI_U<sceKernelDelayThread>,"sceKernelDelayThread"},
{0x68da9e36,WrapI_U<sceKernelDelayThreadCB>,"sceKernelDelayThreadCB"},
{0xBD123D9E,WrapI_U<sceKernelDelaySysClockThread>, "sceKernelDelaySysClockThread", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x1181E963,WrapI_U<sceKernelDelaySysClockThreadCB>, "sceKernelDelaySysClockThreadCB", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0xceadeb47,WrapI_U<sceKernelDelayThread>, "sceKernelDelayThread", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x68da9e36,WrapI_U<sceKernelDelayThreadCB>, "sceKernelDelayThreadCB", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0xaa73c935,WrapV_I<sceKernelExitThread>,"sceKernelExitThread"},
{0x809ce29b,WrapV_I<sceKernelExitDeleteThread>,"sceKernelExitDeleteThread"},
{0x94aa61ee,sceKernelGetThreadCurrentPriority,"sceKernelGetThreadCurrentPriority"},
@@ -696,11 +714,11 @@ const HLEFunction ThreadManForUser[] =
{0x17c1684e,WrapU_UU<sceKernelReferThreadStatus>,"sceKernelReferThreadStatus"},
{0x2C34E053,WrapI_I<sceKernelReleaseWaitThread>,"sceKernelReleaseWaitThread"},
{0x75156e8f,WrapI_I<sceKernelResumeThread>,"sceKernelResumeThread"},
{0x3ad58b8c,&WrapU_V<sceKernelSuspendDispatchThread>,"sceKernelSuspendDispatchThread"},
{0x27e22ec2,&WrapU_U<sceKernelResumeDispatchThread>,"sceKernelResumeDispatchThread"},
{0x3ad58b8c,&WrapU_V<sceKernelSuspendDispatchThread>, "sceKernelSuspendDispatchThread", HLE_NOT_IN_INTERRUPT},
{0x27e22ec2,&WrapU_U<sceKernelResumeDispatchThread>, "sceKernelResumeDispatchThread", HLE_NOT_IN_INTERRUPT},
{0x912354a7,&WrapI_I<sceKernelRotateThreadReadyQueue>,"sceKernelRotateThreadReadyQueue"},
{0x9ACE131E,WrapI_V<sceKernelSleepThread>,"sceKernelSleepThread"},
{0x82826f70,WrapI_V<sceKernelSleepThreadCB>,"sceKernelSleepThreadCB"},
{0x9ACE131E,WrapI_V<sceKernelSleepThread>, "sceKernelSleepThread", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x82826f70,WrapI_V<sceKernelSleepThreadCB>, "sceKernelSleepThreadCB", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0xF475845D,&WrapI_IIU<sceKernelStartThread>,"sceKernelStartThread"},
{0x9944f31f,WrapI_I<sceKernelSuspendThread>,"sceKernelSuspendThread"},
{0x616403ba,WrapI_I<sceKernelTerminateThread>,"sceKernelTerminateThread"},
@@ -740,51 +758,51 @@ const HLEFunction ThreadManForUser[] =
{0x72F3C145,0,"sceKernelReleaseThreadEventHandler"},
{0x369EEB6B,0,"sceKernelReferThreadEventHandlerStatus"},
{0x349d6d6c,sceKernelCheckCallback, "sceKernelCheckCallback"},
{0xE81CAF8F,WrapI_CUU<sceKernelCreateCallback>, "sceKernelCreateCallback"},
{0xEDBA5844,WrapI_I<sceKernelDeleteCallback>, "sceKernelDeleteCallback"},
{0xC11BA8C4,WrapI_II<sceKernelNotifyCallback>, "sceKernelNotifyCallback"},
{0xBA4051D6,WrapI_I<sceKernelCancelCallback>, "sceKernelCancelCallback"},
{0x2A3D44FF,WrapI_I<sceKernelGetCallbackCount>, "sceKernelGetCallbackCount"},
{0x730ED8BC,WrapI_IU<sceKernelReferCallbackStatus>, "sceKernelReferCallbackStatus"},
{0x349d6d6c,sceKernelCheckCallback, "sceKernelCheckCallback"},
{0xE81CAF8F,WrapI_CUU<sceKernelCreateCallback>, "sceKernelCreateCallback"},
{0xEDBA5844,WrapI_I<sceKernelDeleteCallback>, "sceKernelDeleteCallback"},
{0xC11BA8C4,WrapI_II<sceKernelNotifyCallback>, "sceKernelNotifyCallback"},
{0xBA4051D6,WrapI_I<sceKernelCancelCallback>, "sceKernelCancelCallback"},
{0x2A3D44FF,WrapI_I<sceKernelGetCallbackCount>, "sceKernelGetCallbackCount"},
{0x730ED8BC,WrapI_IU<sceKernelReferCallbackStatus>, "sceKernelReferCallbackStatus"},
{0x8125221D,WrapI_CUU<sceKernelCreateMbx>, "sceKernelCreateMbx"},
{0x86255ADA,WrapI_I<sceKernelDeleteMbx>, "sceKernelDeleteMbx"},
{0xE9B3061E,WrapI_IU<sceKernelSendMbx>, "sceKernelSendMbx"},
{0x18260574,WrapI_IUU<sceKernelReceiveMbx>, "sceKernelReceiveMbx"},
{0xF3986382,WrapI_IUU<sceKernelReceiveMbxCB>, "sceKernelReceiveMbxCB"},
{0x0D81716A,WrapI_IU<sceKernelPollMbx>, "sceKernelPollMbx"},
{0x87D4DD36,WrapI_IU<sceKernelCancelReceiveMbx>, "sceKernelCancelReceiveMbx"},
{0xA8E8C846,WrapI_IU<sceKernelReferMbxStatus>, "sceKernelReferMbxStatus"},
{0x8125221D,WrapI_CUU<sceKernelCreateMbx>, "sceKernelCreateMbx"},
{0x86255ADA,WrapI_I<sceKernelDeleteMbx>, "sceKernelDeleteMbx"},
{0xE9B3061E,WrapI_IU<sceKernelSendMbx>, "sceKernelSendMbx"},
{0x18260574,WrapI_IUU<sceKernelReceiveMbx>, "sceKernelReceiveMbx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0xF3986382,WrapI_IUU<sceKernelReceiveMbxCB>, "sceKernelReceiveMbxCB", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x0D81716A,WrapI_IU<sceKernelPollMbx>, "sceKernelPollMbx"},
{0x87D4DD36,WrapI_IU<sceKernelCancelReceiveMbx>, "sceKernelCancelReceiveMbx"},
{0xA8E8C846,WrapI_IU<sceKernelReferMbxStatus>, "sceKernelReferMbxStatus"},
{0x7C0DC2A0,WrapI_CIUUU<sceKernelCreateMsgPipe>, "sceKernelCreateMsgPipe"},
{0xF0B7DA1C,WrapI_I<sceKernelDeleteMsgPipe>, "sceKernelDeleteMsgPipe"},
{0x876DBFAD,WrapI_IUUUUU<sceKernelSendMsgPipe>, "sceKernelSendMsgPipe"},
{0x7C41F2C2,WrapI_IUUUUU<sceKernelSendMsgPipeCB>, "sceKernelSendMsgPipeCB"},
{0x884C9F90,WrapI_IUUUU<sceKernelTrySendMsgPipe>, "sceKernelTrySendMsgPipe"},
{0x74829B76,WrapI_IUUUUU<sceKernelReceiveMsgPipe>, "sceKernelReceiveMsgPipe"},
{0xFBFA697D,WrapI_IUUUUU<sceKernelReceiveMsgPipeCB>, "sceKernelReceiveMsgPipeCB"},
{0xDF52098F,WrapI_IUUUU<sceKernelTryReceiveMsgPipe>, "sceKernelTryReceiveMsgPipe"},
{0x349B864D,WrapI_IUU<sceKernelCancelMsgPipe>, "sceKernelCancelMsgPipe"},
{0x33BE4024,WrapI_IU<sceKernelReferMsgPipeStatus>, "sceKernelReferMsgPipeStatus"},
{0x7C0DC2A0,WrapI_CIUUU<sceKernelCreateMsgPipe>, "sceKernelCreateMsgPipe"},
{0xF0B7DA1C,WrapI_I<sceKernelDeleteMsgPipe>, "sceKernelDeleteMsgPipe"},
{0x876DBFAD,WrapI_IUUUUU<sceKernelSendMsgPipe>, "sceKernelSendMsgPipe"},
{0x7C41F2C2,WrapI_IUUUUU<sceKernelSendMsgPipeCB>, "sceKernelSendMsgPipeCB"},
{0x884C9F90,WrapI_IUUUU<sceKernelTrySendMsgPipe>, "sceKernelTrySendMsgPipe"},
{0x74829B76,WrapI_IUUUUU<sceKernelReceiveMsgPipe>, "sceKernelReceiveMsgPipe"},
{0xFBFA697D,WrapI_IUUUUU<sceKernelReceiveMsgPipeCB>, "sceKernelReceiveMsgPipeCB"},
{0xDF52098F,WrapI_IUUUU<sceKernelTryReceiveMsgPipe>, "sceKernelTryReceiveMsgPipe"},
{0x349B864D,WrapI_IUU<sceKernelCancelMsgPipe>, "sceKernelCancelMsgPipe"},
{0x33BE4024,WrapI_IU<sceKernelReferMsgPipeStatus>, "sceKernelReferMsgPipeStatus"},
{0x56C039B5,WrapI_CIUUU<sceKernelCreateVpl>,"sceKernelCreateVpl"},
{0x89B3D48C,WrapI_I<sceKernelDeleteVpl>,"sceKernelDeleteVpl"},
{0xBED27435,WrapI_IUUU<sceKernelAllocateVpl>,"sceKernelAllocateVpl"},
{0xEC0A693F,WrapI_IUUU<sceKernelAllocateVplCB>,"sceKernelAllocateVplCB"},
{0xAF36D708,WrapI_IUU<sceKernelTryAllocateVpl>,"sceKernelTryAllocateVpl"},
{0xB736E9FF,WrapI_IU<sceKernelFreeVpl>,"sceKernelFreeVpl"},
{0x1D371B8A,WrapI_IU<sceKernelCancelVpl>,"sceKernelCancelVpl"},
{0x39810265,WrapI_IU<sceKernelReferVplStatus>,"sceKernelReferVplStatus"},
{0x56C039B5,WrapI_CIUUU<sceKernelCreateVpl>, "sceKernelCreateVpl"},
{0x89B3D48C,WrapI_I<sceKernelDeleteVpl>, "sceKernelDeleteVpl"},
{0xBED27435,WrapI_IUUU<sceKernelAllocateVpl>, "sceKernelAllocateVpl", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0xEC0A693F,WrapI_IUUU<sceKernelAllocateVplCB>, "sceKernelAllocateVplCB", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0xAF36D708,WrapI_IUU<sceKernelTryAllocateVpl>, "sceKernelTryAllocateVpl"},
{0xB736E9FF,WrapI_IU<sceKernelFreeVpl>, "sceKernelFreeVpl"},
{0x1D371B8A,WrapI_IU<sceKernelCancelVpl>, "sceKernelCancelVpl"},
{0x39810265,WrapI_IU<sceKernelReferVplStatus>, "sceKernelReferVplStatus"},
{0xC07BB470,sceKernelCreateFpl,"sceKernelCreateFpl"},
{0xED1410E0,sceKernelDeleteFpl,"sceKernelDeleteFpl"},
{0xD979E9BF,sceKernelAllocateFpl,"sceKernelAllocateFpl"},
{0xE7282CB6,sceKernelAllocateFplCB,"sceKernelAllocateFplCB"},
{0x623AE665,sceKernelTryAllocateFpl,"sceKernelTryAllocateFpl"},
{0xF6414A71,sceKernelFreeFpl,"sceKernelFreeFpl"},
{0xA8AA591F,sceKernelCancelFpl,"sceKernelCancelFpl"},
{0xD8199E4C,sceKernelReferFplStatus,"sceKernelReferFplStatus"},
{0xC07BB470,WrapI_CUUUUU<sceKernelCreateFpl>, "sceKernelCreateFpl"},
{0xED1410E0,WrapI_I<sceKernelDeleteFpl>, "sceKernelDeleteFpl"},
{0xD979E9BF,WrapI_IUU<sceKernelAllocateFpl>, "sceKernelAllocateFpl", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0xE7282CB6,WrapI_IUU<sceKernelAllocateFplCB>, "sceKernelAllocateFplCB", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x623AE665,WrapI_IU<sceKernelTryAllocateFpl>, "sceKernelTryAllocateFpl"},
{0xF6414A71,WrapI_IU<sceKernelFreeFpl>, "sceKernelFreeFpl"},
{0xA8AA591F,WrapI_IU<sceKernelCancelFpl>, "sceKernelCancelFpl"},
{0xD8199E4C,WrapI_IU<sceKernelReferFplStatus>, "sceKernelReferFplStatus"},
{0x20fff560,WrapU_CU<sceKernelCreateVTimer>,"sceKernelCreateVTimer"},
{0x328F9E52,WrapU_U<sceKernelDeleteVTimer>,"sceKernelDeleteVTimer"},
@@ -820,6 +838,13 @@ const HLEFunction ThreadManForUser[] =
// {0x6E9EA350, _sceKernelReturnFromCallback,"_sceKernelReturnFromCallback"},
};
const HLEFunction ThreadManForKernel[] =
{
{0xceadeb47, WrapI_U<ThreadManForKernel_ceadeb47>, "ThreadManForKernel_ceadeb47"},
{0x446d8de6, WrapI_CUUIUU<ThreadManForKernel_446d8de6>, "ThreadManForKernel_446d8de6"},//Not sure right
{0xf475845d, &WrapI_IIU<ThreadManForKernel_f475845d>, "ThreadManForKernel_f475845d"},//Not sure right
};
void Register_ThreadManForUser()
{
RegisterModule("ThreadManForUser", ARRAY_SIZE(ThreadManForUser), ThreadManForUser);
@@ -841,8 +866,6 @@ void Register_LoadExecForUser()
RegisterModule("LoadExecForUser", ARRAY_SIZE(LoadExecForUser), LoadExecForUser);
}
const HLEFunction ExceptionManagerForKernel[] =
{
{0x3FB264FC, 0, "sceKernelRegisterExceptionHandler"},
@@ -888,3 +911,9 @@ void Register_UtilsForKernel()
{
RegisterModule("UtilsForKernel", ARRAY_SIZE(UtilsForKernel), UtilsForKernel);
}
void Register_ThreadManForKernel()
{
RegisterModule("ThreadManForKernel", ARRAY_SIZE(ThreadManForKernel), ThreadManForKernel);
}
+1
View File
@@ -557,5 +557,6 @@ extern KernelStats kernelStats;
extern u32 registeredExitCbId;
void Register_ThreadManForUser();
void Register_ThreadManForKernel();
void Register_LoadExecForUser();
void Register_UtilsForKernel();
+10 -6
View File
@@ -324,7 +324,11 @@ int sceKernelCreateEventFlag(const char *name, u32 flag_attr, u32 flag_initPatte
DEBUG_LOG(HLE, "%i=sceKernelCreateEventFlag(\"%s\", %08x, %08x, %08x)", id, e->nef.name, e->nef.attr, e->nef.currentPattern, optPtr);
if (optPtr != 0)
WARN_LOG_REPORT(HLE, "sceKernelCreateEventFlag(%s) unsupported options parameter: %08x", name, optPtr);
{
u32 size = Memory::Read_U32(optPtr);
if (size > 4)
WARN_LOG_REPORT(HLE, "sceKernelCreateEventFlag(%s) unsupported options parameter, size = %d", name, size);
}
if ((flag_attr & ~PSP_EVENT_WAITMULTIPLE) != 0)
WARN_LOG_REPORT(HLE, "sceKernelCreateEventFlag(%s) unsupported attr parameter: %08x", name, flag_attr);
@@ -654,7 +658,7 @@ int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr)
// Can't wait on 0, it never matches.
if (bits == 0)
{
DEBUG_LOG(HLE, "sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x): bad pattern", id, bits, wait, outBitsPtr);
DEBUG_LOG(HLE, "sceKernelPollEventFlag(%i, %08x, %i, %08x): bad pattern", id, bits, wait, outBitsPtr);
return SCE_KERNEL_ERROR_EVF_ILPAT;
}
@@ -669,23 +673,23 @@ int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr)
if (e->waitingThreads.size() > 0 && (e->nef.attr & PSP_EVENT_WAITMULTIPLE) == 0)
{
DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_EVF_MULTI=sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr);
DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_EVF_MULTI=sceKernelPollEventFlag(%i, %08x, %i, %08x)", id, bits, wait, outBitsPtr);
return SCE_KERNEL_ERROR_EVF_MULTI;
}
// No match - return that, this is polling, not waiting.
DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_EVF_COND=sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr);
DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_EVF_COND=sceKernelPollEventFlag(%i, %08x, %i, %08x)", id, bits, wait, outBitsPtr);
return SCE_KERNEL_ERROR_EVF_COND;
}
else
{
DEBUG_LOG(HLE, "0=sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr);
DEBUG_LOG(HLE, "0=sceKernelPollEventFlag(%i, %08x, %i, %08x)", id, bits, wait, outBitsPtr);
return 0;
}
}
else
{
DEBUG_LOG(HLE, "sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x): invalid event flag", id, bits, wait, outBitsPtr);
DEBUG_LOG(HLE, "sceKernelPollEventFlag(%i, %08x, %i, %08x): invalid event flag", id, bits, wait, outBitsPtr);
return error;
}
}
+6 -5
View File
@@ -89,6 +89,7 @@ void sceKernelCpuResumeIntr(u32 enable)
{
__EnableInterrupts();
hleRunInterrupts();
hleReSchedule("interrupts resumed");
}
else
{
@@ -165,7 +166,7 @@ void IntrHandler::enable(int subIntrNum)
}
void IntrHandler::disable(int subIntrNum)
{
subIntrHandlers[subIntrNum].enabled = true;
subIntrHandlers[subIntrNum].enabled = false;
}
SubIntrHandler* IntrHandler::get(int subIntrNum)
{
@@ -407,9 +408,9 @@ void __KernelReturnFromInterrupt()
{
// Otherwise, we reschedule when dispatch was enabled, or switch back otherwise.
if (__KernelIsDispatchEnabled())
__KernelReSchedule("return from interrupt");
__KernelReSchedule("left interrupt");
else
__KernelSwitchToThread(threadBeforeInterrupt, "return from interrupt");
__KernelSwitchToThread(threadBeforeInterrupt, "left interrupt");
}
}
@@ -574,8 +575,8 @@ const HLEFunction Kernel_Library[] =
{0xa089eca4,WrapU_UUU<sceKernelMemset>, "sceKernelMemset"},
{0xDC692EE3,WrapI_UI<sceKernelTryLockLwMutex>, "sceKernelTryLockLwMutex"},
{0x37431849,WrapI_UI<sceKernelTryLockLwMutex_600>, "sceKernelTryLockLwMutex_600"},
{0xbea46419,WrapI_UIU<sceKernelLockLwMutex>, "sceKernelLockLwMutex", HLE_NOT_DISPATCH_SUSPENDED},
{0x1FC64E09,WrapI_UIU<sceKernelLockLwMutexCB>, "sceKernelLockLwMutexCB", HLE_NOT_DISPATCH_SUSPENDED},
{0xbea46419,WrapI_UIU<sceKernelLockLwMutex>, "sceKernelLockLwMutex", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x1FC64E09,WrapI_UIU<sceKernelLockLwMutexCB>, "sceKernelLockLwMutexCB", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x15b6446b,WrapI_UI<sceKernelUnlockLwMutex>, "sceKernelUnlockLwMutex"},
{0xc1734599,WrapI_UU<sceKernelReferLwMutexStatus>, "sceKernelReferLwMutexStatus"},
{0x293b45b8,WrapI_V<sceKernelGetThreadId>, "sceKernelGetThreadId"},
+5 -1
View File
@@ -316,7 +316,11 @@ SceUID sceKernelCreateMbx(const char *name, u32 attr, u32 optAddr)
DEBUG_LOG(HLE, "%i=sceKernelCreateMbx(%s, %08x, %08x)", id, name, attr, optAddr);
if (optAddr != 0)
WARN_LOG_REPORT(HLE, "sceKernelCreateMbx(%s) unsupported options parameter: %08x", name, optAddr);
{
u32 size = Memory::Read_U32(optAddr);
if (size > 4)
WARN_LOG_REPORT(HLE, "sceKernelCreateMbx(%s) unsupported options parameter, size = %d", name, size);
}
if ((attr & ~SCE_KERNEL_MBA_ATTR_KNOWN) != 0)
WARN_LOG_REPORT(HLE, "sceKernelCreateMbx(%s) unsupported attr parameter: %08x", name, attr);
+379 -111
View File
@@ -17,16 +17,17 @@
#include <algorithm>
#include <string>
#include "HLE.h"
#include "../System.h"
#include "../MIPS/MIPS.h"
#include "../MemMap.h"
#include "Core/HLE/HLE.h"
#include "Core/System.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MemMap.h"
#include "Core/CoreTiming.h"
#include "Core/Reporting.h"
#include "sceKernel.h"
#include "sceKernelThread.h"
#include "sceKernelMemory.h"
#include "Core/HLE/sceKernel.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernelInterrupt.h"
#include "Core/HLE/sceKernelMemory.h"
const int TLS_NUM_INDEXES = 16;
@@ -36,6 +37,7 @@ BlockAllocator userMemory(256);
BlockAllocator kernelMemory(256);
static int vplWaitTimer = -1;
static int fplWaitTimer = -1;
static bool tlsUsedIndexes[TLS_NUM_INDEXES];
// STATE END
//////////////////////////////////////////////////////////////////////////
@@ -47,11 +49,16 @@ int flags_ = 0;
int sdkVersion_;
int compilerVersion_;
struct FplWaitingThread
{
SceUID threadID;
u32 addrPtr;
};
struct NativeFPL
{
u32_le size;
char name[KERNELOBJECT_MAX_NAME_LENGTH+1];
SceUID_le mpid;
u32_le attr;
s32_le blocksize;
@@ -63,7 +70,7 @@ struct NativeFPL
//FPL - Fixed Length Dynamic Memory Pool - every item has the same length
struct FPL : public KernelObject
{
FPL() : blocks(NULL) {}
FPL() : blocks(NULL), nextBlock(0) {}
~FPL() {
if (blocks != NULL) {
delete [] blocks;
@@ -77,8 +84,10 @@ struct FPL : public KernelObject
int findFreeBlock() {
for (int i = 0; i < nf.numBlocks; i++) {
if (!blocks[i])
return i;
int b = nextBlock++ % nf.numBlocks;
if (!blocks[b]) {
return b;
}
}
return -1;
}
@@ -105,12 +114,19 @@ struct FPL : public KernelObject
blocks = new bool[nf.numBlocks];
p.DoArray(blocks, nf.numBlocks);
p.Do(address);
p.Do(alignedSize);
p.Do(nextBlock);
FplWaitingThread dv = {0};
p.Do(waitingThreads, dv);
p.DoMarker("FPL");
}
NativeFPL nf;
bool *blocks;
u32 address;
int alignedSize;
int nextBlock;
std::vector<FplWaitingThread> waitingThreads;
};
struct VplWaitingThread
@@ -156,6 +172,7 @@ struct VPL : public KernelObject
};
void __KernelVplTimeout(u64 userdata, int cyclesLate);
void __KernelFplTimeout(u64 userdata, int cyclesLate);
void __KernelMemoryInit()
{
@@ -164,6 +181,7 @@ void __KernelMemoryInit()
INFO_LOG(HLE, "Kernel and user memory pools initialized");
vplWaitTimer = CoreTiming::RegisterEvent("VplTimeout", __KernelVplTimeout);
fplWaitTimer = CoreTiming::RegisterEvent("FplTimeout", __KernelFplTimeout);
flags_ = 0;
sdkVersion_ = 0;
@@ -178,6 +196,8 @@ void __KernelMemoryDoState(PointerWrap &p)
p.Do(vplWaitTimer);
CoreTiming::RestoreRegisterEvent(vplWaitTimer, "VplTimeout", __KernelVplTimeout);
p.Do(fplWaitTimer);
CoreTiming::RestoreRegisterEvent(fplWaitTimer, "FplTimeout", __KernelFplTimeout);
p.Do(flags_);
p.Do(sdkVersion_);
p.Do(compilerVersion_);
@@ -195,209 +215,428 @@ void __KernelMemoryShutdown()
kernelMemory.Shutdown();
}
//sceKernelCreateFpl(const char *name, SceUID mpid, SceUint attr, SceSize blocksize, int numBlocks, optparam)
void sceKernelCreateFpl()
enum SceKernelFplAttr
{
const char *name = Memory::GetCharPointer(PARAM(0));
PSP_FPL_ATTR_FIFO = 0x0000,
PSP_FPL_ATTR_PRIORITY = 0x0100,
PSP_FPL_ATTR_HIGHMEM = 0x4000,
PSP_FPL_ATTR_KNOWN = PSP_FPL_ATTR_FIFO | PSP_FPL_ATTR_PRIORITY | PSP_FPL_ATTR_HIGHMEM,
};
u32 mpid = PARAM(1);
u32 attr = PARAM(2);
u32 blockSize = PARAM(3);
u32 numBlocks = PARAM(4);
bool __KernelUnlockFplForThread(FPL *fpl, FplWaitingThread &threadInfo, u32 &error, int result, bool &wokeThreads)
{
const SceUID threadID = threadInfo.threadID;
SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_FPL, error);
u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error);
u32 totalSize = blockSize * numBlocks;
// The waitID may be different after a timeout.
if (waitID != fpl->GetUID())
return true;
bool atEnd = false; // attr can change this I think
// If result is an error code, we're just letting it go.
if (result == 0)
{
int blockNum = fpl->allocateBlock();
if (blockNum >= 0)
{
u32 blockPtr = fpl->address + fpl->alignedSize * blockNum;
Memory::Write_U32(blockPtr, threadInfo.addrPtr);
}
else
return false;
}
if (timeoutPtr != 0 && fplWaitTimer != -1)
{
// Remove any event for this thread.
s64 cyclesLeft = CoreTiming::UnscheduleEvent(fplWaitTimer, threadID);
Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr);
}
__KernelResumeThreadFromWait(threadID, result);
wokeThreads = true;
return true;
}
void __KernelFplRemoveThread(FPL *fpl, SceUID threadID)
{
for (size_t i = 0; i < fpl->waitingThreads.size(); i++)
{
FplWaitingThread *t = &fpl->waitingThreads[i];
if (t->threadID == threadID)
{
fpl->waitingThreads.erase(fpl->waitingThreads.begin() + i);
break;
}
}
}
bool __FplThreadSortPriority(FplWaitingThread thread1, FplWaitingThread thread2)
{
return __KernelThreadSortPriority(thread1.threadID, thread2.threadID);
}
bool __KernelClearFplThreads(FPL *fpl, int reason)
{
u32 error;
bool wokeThreads = false;
for (auto iter = fpl->waitingThreads.begin(), end = fpl->waitingThreads.end(); iter != end; ++iter)
__KernelUnlockFplForThread(fpl, *iter, error, reason, wokeThreads);
fpl->waitingThreads.clear();
return wokeThreads;
}
void __KernelSortFplThreads(FPL *fpl)
{
// Remove any that are no longer waiting.
u32 error;
SceUID uid = fpl->GetUID();
for (size_t i = 0; i < fpl->waitingThreads.size(); i++)
{
SceUID waitID = __KernelGetWaitID(fpl->waitingThreads[i].threadID, WAITTYPE_FPL, error);
if (waitID != uid)
{
fpl->waitingThreads.erase(fpl->waitingThreads.begin() + i);
--i;
}
}
if ((fpl->nf.attr & PSP_FPL_ATTR_PRIORITY) != 0)
std::stable_sort(fpl->waitingThreads.begin(), fpl->waitingThreads.end(), __FplThreadSortPriority);
}
int sceKernelCreateFpl(const char *name, u32 mpid, u32 attr, u32 blockSize, u32 numBlocks, u32 optPtr)
{
if (!name)
{
WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateFpl(): invalid name", SCE_KERNEL_ERROR_NO_MEMORY);
return SCE_KERNEL_ERROR_NO_MEMORY;
}
if (mpid < 1 || mpid > 9 || mpid == 7)
{
WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateFpl(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, mpid);
return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;
}
// We only support user right now.
if (mpid != 2 && mpid != 6)
{
WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateFpl(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_PERM, mpid);
return SCE_KERNEL_ERROR_ILLEGAL_PERM;
}
if (((attr & ~PSP_FPL_ATTR_KNOWN) & ~0xFF) != 0)
{
WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateFpl(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, attr);
return SCE_KERNEL_ERROR_ILLEGAL_ATTR;
}
// There's probably a simpler way to get this same basic formula...
// This is based on results from a PSP.
bool illegalMemSize = blockSize == 0 || numBlocks == 0;
if (!illegalMemSize && (u64) blockSize > ((0x100000000ULL / (u64) numBlocks) - 4ULL))
illegalMemSize = true;
if (!illegalMemSize && (u64) numBlocks >= 0x100000000ULL / (((u64) blockSize + 3ULL) & ~3ULL))
illegalMemSize = true;
if (illegalMemSize)
{
WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateFpl(): invalid blockSize/count", SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE);
return SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE;
}
int alignment = 4;
if (optPtr != 0)
{
u32 size = Memory::Read_U32(optPtr);
if (size > 8)
WARN_LOG_REPORT(HLE, "sceKernelCreateFpl(): unsupported extra options, size = %d", size);
if (size >= 4)
alignment = Memory::Read_U32(optPtr + 4);
// Must be a power of 2 to be valid.
if ((alignment & (alignment - 1)) != 0)
{
WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateFpl(): invalid alignment %d", SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, alignment);
return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;
}
}
if (alignment < 4)
alignment = 4;
int alignedSize = ((int)blockSize + alignment - 1) & ~(alignment - 1);
u32 totalSize = alignedSize * numBlocks;
bool atEnd = (attr & PSP_FPL_ATTR_HIGHMEM) != 0;
u32 address = userMemory.Alloc(totalSize, atEnd, "FPL");
if (address == (u32)-1)
{
DEBUG_LOG(HLE,"sceKernelCreateFpl(\"%s\", partition=%i, attr=%i, bsize=%i, nb=%i) FAILED - out of ram",
DEBUG_LOG(HLE, "sceKernelCreateFpl(\"%s\", partition=%i, attr=%08x, bsize=%i, nb=%i) FAILED - out of ram",
name, mpid, attr, blockSize, numBlocks);
RETURN(SCE_KERNEL_ERROR_NO_MEMORY);
return;
return SCE_KERNEL_ERROR_NO_MEMORY;
}
FPL *fpl = new FPL;
SceUID id = kernelObjects.Create(fpl);
strncpy(fpl->nf.name, name, 32);
fpl->nf.size = sizeof(fpl->nf);
fpl->nf.mpid = mpid; // partition
strncpy(fpl->nf.name, name, KERNELOBJECT_MAX_NAME_LENGTH);
fpl->nf.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0;
fpl->nf.attr = attr;
fpl->nf.size = sizeof(fpl->nf);
fpl->nf.blocksize = blockSize;
fpl->nf.numBlocks = numBlocks;
fpl->nf.numFreeBlocks = numBlocks;
fpl->nf.numWaitThreads = 0;
fpl->blocks = new bool[fpl->nf.numBlocks];
memset(fpl->blocks, 0, fpl->nf.numBlocks * sizeof(bool));
fpl->address = address;
fpl->alignedSize = alignedSize;
DEBUG_LOG(HLE,"%i=sceKernelCreateFpl(\"%s\", partition=%i, attr=%i, bsize=%i, nb=%i)",
DEBUG_LOG(HLE, "%i=sceKernelCreateFpl(\"%s\", partition=%i, attr=%08x, bsize=%i, nb=%i)",
id, name, mpid, attr, blockSize, numBlocks);
RETURN(id);
return id;
}
void sceKernelDeleteFpl()
int sceKernelDeleteFpl(SceUID uid)
{
SceUID id = PARAM(0);
u32 error;
FPL *fpl = kernelObjects.Get<FPL>(id, error);
FPL *fpl = kernelObjects.Get<FPL>(uid, error);
if (fpl)
{
DEBUG_LOG(HLE, "sceKernelDeleteFpl(%i)", uid);
bool wokeThreads = __KernelClearFplThreads(fpl, SCE_KERNEL_ERROR_WAIT_DELETE);
if (wokeThreads)
hleReSchedule("fpl deleted");
userMemory.Free(fpl->address);
DEBUG_LOG(HLE,"sceKernelDeleteFpl(%i)", id);
RETURN(kernelObjects.Destroy<FPL>(id));
return kernelObjects.Destroy<FPL>(uid);
}
else
{
RETURN(error);
DEBUG_LOG(HLE, "sceKernelDeleteFpl(%i): invalid fpl", uid);
return error;
}
}
void sceKernelAllocateFpl()
void __KernelFplTimeout(u64 userdata, int cyclesLate)
{
SceUID id = PARAM(0);
SceUID threadID = (SceUID) userdata;
u32 error;
FPL *fpl = kernelObjects.Get<FPL>(id, error);
u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error);
if (timeoutPtr != 0)
Memory::Write_U32(0, timeoutPtr);
SceUID uid = __KernelGetWaitID(threadID, WAITTYPE_FPL, error);
FPL *fpl = kernelObjects.Get<FPL>(uid, error);
if (fpl)
{
u32 blockPtrAddr = PARAM(1);
int timeOut = PARAM(2);
// This thread isn't waiting anymore, but we'll remove it from waitingThreads later.
// The reason is, if it times out, but while it was waiting on is DELETED prior to it
// actually running, it will get a DELETE result instead of a TIMEOUT.
// So, we need to remember it or we won't be able to mark it DELETE instead later.
__KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT);
}
}
void __KernelSetFplTimeout(u32 timeoutPtr)
{
if (timeoutPtr == 0 || fplWaitTimer == -1)
return;
int micro = (int) Memory::Read_U32(timeoutPtr);
// TODO: test for fpls.
// This happens to be how the hardware seems to time things.
if (micro <= 5)
micro = 10;
// Yes, this 7 is reproducible. 6 is (a lot) longer than 7.
else if (micro == 7)
micro = 15;
else if (micro <= 215)
micro = 250;
CoreTiming::ScheduleEvent(usToCycles(micro), fplWaitTimer, __KernelGetCurThread());
}
int sceKernelAllocateFpl(SceUID uid, u32 blockPtrAddr, u32 timeoutPtr)
{
u32 error;
FPL *fpl = kernelObjects.Get<FPL>(uid, error);
if (fpl)
{
DEBUG_LOG(HLE, "sceKernelAllocateFpl(%i, %08x, %08x)", uid, blockPtrAddr, timeoutPtr);
int blockNum = fpl->allocateBlock();
if (blockNum >= 0) {
u32 blockPtr = fpl->address + fpl->nf.blocksize * blockNum;
u32 blockPtr = fpl->address + fpl->alignedSize * blockNum;
Memory::Write_U32(blockPtr, blockPtrAddr);
RETURN(0);
} else {
// TODO: Should block!
ERROR_LOG_REPORT(HLE, "sceKernelAllocateFpl: should block");
RETURN(0);
SceUID threadID = __KernelGetCurThread();
__KernelFplRemoveThread(fpl, threadID);
FplWaitingThread waiting = {threadID, blockPtrAddr};
fpl->waitingThreads.push_back(waiting);
__KernelSetFplTimeout(timeoutPtr);
__KernelWaitCurThread(WAITTYPE_FPL, uid, 0, timeoutPtr, false, "fpl waited");
}
DEBUG_LOG(HLE,"sceKernelAllocateFpl(%i, %08x, %i)", id, blockPtrAddr, timeOut);
RETURN(0);
return 0;
}
else
{
DEBUG_LOG(HLE,"ERROR: sceKernelAllocateFpl(%i)", id);
RETURN(error);
DEBUG_LOG(HLE, "sceKernelAllocateFpl(%i, %08x, %08x): invalid fpl", uid, blockPtrAddr, timeoutPtr);
return error;
}
}
void sceKernelAllocateFplCB()
int sceKernelAllocateFplCB(SceUID uid, u32 blockPtrAddr, u32 timeoutPtr)
{
SceUID id = PARAM(0);
u32 error;
FPL *fpl = kernelObjects.Get<FPL>(id, error);
FPL *fpl = kernelObjects.Get<FPL>(uid, error);
if (fpl)
{
u32 blockPtrAddr = PARAM(1);
int timeOut = PARAM(2);
DEBUG_LOG(HLE, "sceKernelAllocateFplCB(%i, %08x, %08x)", uid, blockPtrAddr, timeoutPtr);
int blockNum = fpl->allocateBlock();
if (blockNum >= 0) {
u32 blockPtr = fpl->address + fpl->nf.blocksize * blockNum;
u32 blockPtr = fpl->address + fpl->alignedSize * blockNum;
Memory::Write_U32(blockPtr, blockPtrAddr);
RETURN(0);
} else {
// TODO: Should block and process callbacks!
ERROR_LOG_REPORT(HLE, "sceKernelAllocateFplCB: should block");
__KernelCheckCallbacks();
SceUID threadID = __KernelGetCurThread();
__KernelFplRemoveThread(fpl, threadID);
FplWaitingThread waiting = {threadID, blockPtrAddr};
fpl->waitingThreads.push_back(waiting);
__KernelSetFplTimeout(timeoutPtr);
__KernelWaitCurThread(WAITTYPE_FPL, uid, 0, timeoutPtr, true, "fpl waited");
}
DEBUG_LOG(HLE,"sceKernelAllocateFpl(%i, %08x, %i)", id, PARAM(1), timeOut);
return 0;
}
else
{
DEBUG_LOG(HLE,"ERROR: sceKernelAllocateFplCB(%i)", id);
RETURN(error);
DEBUG_LOG(HLE, "sceKernelAllocateFplCB(%i, %08x, %08x): invalid fpl", uid, blockPtrAddr, timeoutPtr);
return error;
}
}
void sceKernelTryAllocateFpl()
int sceKernelTryAllocateFpl(SceUID uid, u32 blockPtrAddr)
{
SceUID id = PARAM(0);
u32 error;
FPL *fpl = kernelObjects.Get<FPL>(id, error);
FPL *fpl = kernelObjects.Get<FPL>(uid, error);
if (fpl)
{
u32 blockPtrAddr = PARAM(1);
DEBUG_LOG(HLE,"sceKernelTryAllocateFpl(%i, %08x)", id, PARAM(1));
DEBUG_LOG(HLE, "sceKernelTryAllocateFpl(%i, %08x)", uid, blockPtrAddr);
int blockNum = fpl->allocateBlock();
if (blockNum >= 0) {
u32 blockPtr = fpl->address + fpl->nf.blocksize * blockNum;
u32 blockPtr = fpl->address + fpl->alignedSize * blockNum;
Memory::Write_U32(blockPtr, blockPtrAddr);
RETURN(0);
return 0;
} else {
RETURN(SCE_KERNEL_ERROR_NO_MEMORY);
return SCE_KERNEL_ERROR_NO_MEMORY;
}
}
else
{
DEBUG_LOG(HLE,"sceKernelTryAllocateFpl(%i) - bad UID", id);
RETURN(error);
DEBUG_LOG(HLE, "sceKernelTryAllocateFpl(%i, %08x): invalid fpl", uid, blockPtrAddr);
return error;
}
}
void sceKernelFreeFpl()
int sceKernelFreeFpl(SceUID uid, u32 blockPtr)
{
SceUID id = PARAM(0);
u32 blockAddr = PARAM(1);
if (blockPtr > PSP_GetUserMemoryEnd()) {
WARN_LOG(HLE, "%08x=sceKernelFreeFpl(%i, %08x): invalid address", SCE_KERNEL_ERROR_ILLEGAL_ADDR, uid, blockPtr);
return SCE_KERNEL_ERROR_ILLEGAL_ADDR;
}
DEBUG_LOG(HLE,"sceKernelFreeFpl(%i, %08x)", id, blockAddr);
u32 error;
FPL *fpl = kernelObjects.Get<FPL>(id, error);
FPL *fpl = kernelObjects.Get<FPL>(uid, error);
if (fpl) {
int blockNum = (blockAddr - fpl->address) / fpl->nf.blocksize;
int blockNum = (blockPtr - fpl->address) / fpl->alignedSize;
if (blockNum < 0 || blockNum >= fpl->nf.numBlocks) {
RETURN(SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK);
DEBUG_LOG(HLE, "sceKernelFreeFpl(%i, %08x): bad block ptr", uid, blockPtr);
return SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK;
} else {
if (fpl->freeBlock(blockNum)) {
// TODO: If there are waiting threads, wake them up
DEBUG_LOG(HLE, "sceKernelFreeFpl(%i, %08x)", uid, blockPtr);
__KernelSortFplThreads(fpl);
bool wokeThreads = false;
retry:
for (auto iter = fpl->waitingThreads.begin(), end = fpl->waitingThreads.end(); iter != end; ++iter)
{
if (__KernelUnlockFplForThread(fpl, *iter, error, 0, wokeThreads))
{
fpl->waitingThreads.erase(iter);
goto retry;
}
}
if (wokeThreads)
hleReSchedule("fpl freed");
return 0;
} else {
DEBUG_LOG(HLE, "sceKernelFreeFpl(%i, %08x): already free", uid, blockPtr);
return SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK;
}
RETURN(0);
}
}
else
{
RETURN(error);
DEBUG_LOG(HLE, "sceKernelFreeFpl(%i, %08x): invalid fpl", uid, blockPtr);
return error;
}
}
void sceKernelCancelFpl()
int sceKernelCancelFpl(SceUID uid, u32 numWaitThreadsPtr)
{
SceUID id = PARAM(0);
DEBUG_LOG(HLE,"UNIMPL: sceKernelCancelFpl(%i)", id);
u32 error;
FPL *fpl = kernelObjects.Get<FPL>(id, error);
FPL *fpl = kernelObjects.Get<FPL>(uid, error);
if (fpl)
{
RETURN(0);
DEBUG_LOG(HLE, "sceKernelCancelFpl(%i, %08x)", uid, numWaitThreadsPtr);
fpl->nf.numWaitThreads = (int) fpl->waitingThreads.size();
if (Memory::IsValidAddress(numWaitThreadsPtr))
Memory::Write_U32(fpl->nf.numWaitThreads, numWaitThreadsPtr);
bool wokeThreads = __KernelClearFplThreads(fpl, SCE_KERNEL_ERROR_WAIT_CANCEL);
if (wokeThreads)
hleReSchedule("fpl canceled");
return 0;
}
else
{
RETURN(error);
DEBUG_LOG(HLE, "sceKernelCancelFpl(%i, %08x): invalid fpl", uid, numWaitThreadsPtr);
return error;
}
}
void sceKernelReferFplStatus()
int sceKernelReferFplStatus(SceUID uid, u32 statusPtr)
{
SceUID id = PARAM(0);
u32 statusAddr = PARAM(1);
DEBUG_LOG(HLE,"sceKernelReferFplStatus(%i, %08x)", id, statusAddr);
u32 error;
FPL *fpl = kernelObjects.Get<FPL>(id, error);
FPL *fpl = kernelObjects.Get<FPL>(uid, error);
if (fpl)
{
Memory::WriteStruct(statusAddr, &fpl->nf);
RETURN(0);
DEBUG_LOG(HLE, "sceKernelReferFplStatus(%i, %08x)", uid, statusPtr);
// Refresh waiting threads and free block count.
__KernelSortFplThreads(fpl);
fpl->nf.numWaitThreads = (int) fpl->waitingThreads.size();
fpl->nf.numFreeBlocks = 0;
for (int i = 0; i < (int)fpl->nf.numBlocks; ++i)
{
if (!fpl->blocks[i])
++fpl->nf.numFreeBlocks;
}
if (Memory::Read_U32(statusPtr) != 0)
Memory::WriteStruct(statusPtr, &fpl->nf);
return 0;
}
else
{
RETURN(error);
DEBUG_LOG(HLE, "sceKernelReferFplStatus(%i, %08x): invalid fpl", uid, statusPtr);
return error;
}
}
@@ -937,6 +1176,25 @@ bool __KernelClearVplThreads(VPL *vpl, int reason)
return wokeThreads;
}
void __KernelSortFplThreads(VPL *vpl)
{
// Remove any that are no longer waiting.
u32 error;
SceUID uid = vpl->GetUID();
for (size_t i = 0; i < vpl->waitingThreads.size(); i++)
{
SceUID waitID = __KernelGetWaitID(vpl->waitingThreads[i].threadID, WAITTYPE_VPL, error);
if (waitID != uid)
{
vpl->waitingThreads.erase(vpl->waitingThreads.begin() + i);
--i;
}
}
if ((vpl->nv.attr & PSP_VPL_ATTR_PRIORITY) != 0)
std::stable_sort(vpl->waitingThreads.begin(), vpl->waitingThreads.end(), __VplThreadSortPriority);
}
SceUID sceKernelCreateVpl(const char *name, int partition, u32 attr, u32 vplSize, u32 optPtr)
{
if (!name)
@@ -982,7 +1240,7 @@ SceUID sceKernelCreateVpl(const char *name, int partition, u32 attr, u32 vplSize
u32 memBlockPtr = userMemory.Alloc(allocSize, (attr & PSP_VPL_ATTR_HIGHMEM) != 0, "VPL");
if (memBlockPtr == (u32)-1)
{
ERROR_LOG(HLE, "sceKernelCreateVpl: Failed to allocate %i bytes of pool data", vplSize);
ERROR_LOG(HLE, "sceKernelCreateVpl(): Failed to allocate %i bytes of pool data", vplSize);
return SCE_KERNEL_ERROR_NO_MEMORY;
}
@@ -1004,6 +1262,15 @@ SceUID sceKernelCreateVpl(const char *name, int partition, u32 attr, u32 vplSize
DEBUG_LOG(HLE, "%x=sceKernelCreateVpl(\"%s\", block=%i, attr=%i, size=%i)",
id, name, partition, vpl->nv.attr, vpl->nv.poolSize);
if (optPtr != 0)
{
u32 size = Memory::Read_U32(optPtr);
if (size > 4)
WARN_LOG_REPORT(HLE, "sceKernelCreateVpl(): unsupported options parameter, size = %d", size);
}
if (attr & PSP_VPL_ATTR_SMALLEST)
WARN_LOG_REPORT(HLE, "sceKernelCreateVpl(): unsupported SMALLEST wake priority attr");
return id;
}
@@ -1133,8 +1400,6 @@ int sceKernelAllocateVplCB(SceUID uid, u32 size, u32 addrPtr, u32 timeoutPtr)
{
if (vpl)
{
vpl->nv.numWaitThreads++;
SceUID threadID = __KernelGetCurThread();
__KernelVplRemoveThread(vpl, threadID);
VplWaitingThread waiting = {threadID, addrPtr};
@@ -1170,8 +1435,7 @@ int sceKernelFreeVpl(SceUID uid, u32 addr)
{
if (vpl->alloc.FreeExact(addr))
{
if ((vpl->nv.attr & PSP_VPL_ATTR_PRIORITY) != 0)
std::stable_sort(vpl->waitingThreads.begin(), vpl->waitingThreads.end(), __VplThreadSortPriority);
__KernelSortFplThreads(vpl);
bool wokeThreads = false;
retry:
@@ -1201,11 +1465,11 @@ retry:
int sceKernelCancelVpl(SceUID uid, u32 numWaitThreadsPtr)
{
DEBUG_LOG(HLE, "sceKernelCancelVpl(%i, %08x)", uid, numWaitThreadsPtr);
u32 error;
VPL *vpl = kernelObjects.Get<VPL>(uid, error);
if (vpl)
{
DEBUG_LOG(HLE, "sceKernelCancelVpl(%i, %08x)", uid, numWaitThreadsPtr);
vpl->nv.numWaitThreads = (int) vpl->waitingThreads.size();
if (Memory::IsValidAddress(numWaitThreadsPtr))
Memory::Write_U32(vpl->nv.numWaitThreads, numWaitThreadsPtr);
@@ -1217,7 +1481,10 @@ int sceKernelCancelVpl(SceUID uid, u32 numWaitThreadsPtr)
return 0;
}
else
{
DEBUG_LOG(HLE, "sceKernelCancelVpl(%i, %08x): invalid vpl", uid, numWaitThreadsPtr);
return error;
}
}
int sceKernelReferVplStatus(SceUID uid, u32 infoPtr)
@@ -1228,14 +1495,7 @@ int sceKernelReferVplStatus(SceUID uid, u32 infoPtr)
{
DEBUG_LOG(HLE, "sceKernelReferVplStatus(%i, %08x)", uid, infoPtr);
for (auto iter = vpl->waitingThreads.begin(); iter != vpl->waitingThreads.end(); ++iter)
{
SceUID waitID = __KernelGetWaitID(iter->threadID, WAITTYPE_VPL, error);
// The thread is no longer waiting for this, clean it up.
if (waitID != uid)
vpl->waitingThreads.erase(iter--);
}
__KernelSortFplThreads(vpl);
vpl->nv.numWaitThreads = (int) vpl->waitingThreads.size();
vpl->nv.freeSize = vpl->alloc.GetTotalFreeBytes();
if (Memory::IsValidAddress(infoPtr) && Memory::Read_U32(infoPtr))
@@ -1441,9 +1701,13 @@ SceUID sceKernelCreateTls(const char *name, u32 partition, u32 attr, u32 blockSi
// TODO: just alignment?
if (optionsPtr != 0)
WARN_LOG(HLE, "sceKernelCreateTls(%s) unsupported options parameter: %08x", name, optionsPtr);
{
u32 size = Memory::Read_U32(optionsPtr);
if (size > 4)
WARN_LOG_REPORT(HLE, "sceKernelCreateTls(%s) unsupported options parameter, size = %d", name, size);
}
if ((attr & PSP_TLS_ATTR_PRIORITY) != 0)
WARN_LOG(HLE, "sceKernelCreateTls(%s) unsupported attr parameter: %08x", name, attr);
WARN_LOG_REPORT(HLE, "sceKernelCreateTls(%s) unsupported attr parameter: %08x", name, attr);
return id;
}
@@ -1468,6 +1732,10 @@ int sceKernelAllocateTls(SceUID uid)
{
// TODO: Allocate downward if PSP_TLS_ATTR_HIGHMEM?
DEBUG_LOG(HLE, "sceKernelAllocateTls(%08x)", uid);
if (!__KernelIsDispatchEnabled() || __IsInInterrupt())
return 0;
u32 error;
TLS *tls = kernelObjects.Get<TLS>(uid, error);
if (tls)
+8 -8
View File
@@ -46,14 +46,14 @@ int sceKernelFreeVpl(SceUID uid, u32 addr);
int sceKernelCancelVpl(SceUID uid, u32 numWaitThreadsPtr);
int sceKernelReferVplStatus(SceUID uid, u32 infoPtr);
void sceKernelCreateFpl();
void sceKernelDeleteFpl();
void sceKernelAllocateFpl();
void sceKernelAllocateFplCB();
void sceKernelTryAllocateFpl();
void sceKernelFreeFpl();
void sceKernelCancelFpl();
void sceKernelReferFplStatus();
int sceKernelCreateFpl(const char *name, u32 mpid, u32 attr, u32 blocksize, u32 numBlocks, u32 optPtr);
int sceKernelDeleteFpl(SceUID uid);
int sceKernelAllocateFpl(SceUID uid, u32 blockPtrAddr, u32 timeoutPtr);
int sceKernelAllocateFplCB(SceUID uid, u32 blockPtrAddr, u32 timeoutPtr);
int sceKernelTryAllocateFpl(SceUID uid, u32 blockPtrAddr);
int sceKernelFreeFpl(SceUID uid, u32 blockPtr);
int sceKernelCancelFpl(SceUID uid, u32 numWaitThreadsPtr);
int sceKernelReferFplStatus(SceUID uid, u32 statusPtr);
int sceKernelGetCompiledSdkVersion();
+383 -92
View File
@@ -17,33 +17,34 @@
#include <fstream>
#include <algorithm>
#include <set>
#include "native/base/stringutil.h"
#include "Common/FileUtil.h"
#include "Core/HLE/HLE.h"
#include "Core/HLE/HLETables.h"
#include "Core/Reporting.h"
#include "Common/FileUtil.h"
#include "../Host.h"
#include "Core/Host.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/MIPSAnalyst.h"
#include "Core/ELF/ElfReader.h"
#include "Core/ELF/PBPReader.h"
#include "Core/ELF/PrxDecrypter.h"
#include "../Debugger/SymbolMap.h"
#include "../FileSystems/FileSystem.h"
#include "../FileSystems/MetaFileSystem.h"
#include "../Util/BlockAllocator.h"
#include "Core/FileSystems/FileSystem.h"
#include "Core/FileSystems/MetaFileSystem.h"
#include "Core/Util/BlockAllocator.h"
#include "Core/CoreTiming.h"
#include "Core/PSPLoaders.h"
#include "Core/System.h"
#include "Core/MemMap.h"
#include "Core/Debugger/SymbolMap.h"
#include "Core/MIPS/MIPS.h"
#include "sceKernel.h"
#include "sceKernelModule.h"
#include "sceKernelThread.h"
#include "sceKernelMemory.h"
#include "sceIo.h"
#include "Core/HLE/sceKernel.h"
#include "Core/HLE/sceKernelModule.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernelMemory.h"
#include "Core/HLE/sceIo.h"
enum {
PSP_THREAD_ATTR_USER = 0x80000000
@@ -69,6 +70,7 @@ enum {
static const char *lieAboutSuccessModules[] = {
"flash0:/kd/audiocodec.prx",
"flash0:/kd/libatrac3plus.prx",
"disc0:/PSP_GAME/SYSDIR/UPDATE/EBOOT.BIN",
};
static const char *blacklistedModules[] = {
@@ -89,13 +91,47 @@ static const char *blacklistedModules[] = {
"sceSsl_Module",
};
struct VarSymbol {
char moduleName[32];
u32 symAddr;
struct VarSymbolImport {
char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
u32 nid;
u32 stubAddr;
u8 type;
};
struct VarSymbolExport {
bool Matches(const VarSymbolImport &other) const {
return !strncmp(moduleName, other.moduleName, KERNELOBJECT_MAX_NAME_LENGTH) && nid == other.nid;
}
char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
u32 nid;
u32 symAddr;
};
struct FuncSymbolImport {
char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
u32 stubAddr;
u32 nid;
};
struct FuncSymbolExport {
bool Matches(const FuncSymbolImport &other) const {
return !strncmp(moduleName, other.moduleName, KERNELOBJECT_MAX_NAME_LENGTH) && nid == other.nid;
}
char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
u32 symAddr;
u32 nid;
};
void ImportVarSymbol(const VarSymbolImport &var);
void ExportVarSymbol(const VarSymbolExport &var);
void UnexportVarSymbol(const VarSymbolExport &var);
void ImportFuncSymbol(const FuncSymbolImport &func);
void ExportFuncSymbol(const FuncSymbolExport &func);
void UnexportFuncSymbol(const FuncSymbolExport &func);
struct NativeModule {
u32_le next;
u16_le attribute;
@@ -191,12 +227,87 @@ public:
p.Do(isStarted);
ModuleWaitingThread mwt = {0};
p.Do(waitingThreads, mwt);
FuncSymbolExport fsx = {0};
p.Do(exportedFuncs, fsx);
FuncSymbolImport fsi = {0};
p.Do(importedFuncs, fsi);
VarSymbolExport vsx = {0};
p.Do(exportedVars, vsx);
VarSymbolImport vsi = {0};
p.Do(importedVars, vsi);
RebuildImpExpModuleNames();
p.DoMarker("Module");
}
// We don't do this in the destructor to avoid annoying messages on game shutdown.
void Cleanup();
void ImportFunc(const FuncSymbolImport &func) {
if (!Memory::IsValidAddress(func.stubAddr)) {
WARN_LOG_REPORT(LOADER, "Invalid address for syscall stub %s %08x", func.moduleName, func.nid);
return;
}
DEBUG_LOG(LOADER, "Importing %s : %08x", GetFuncName(func.moduleName, func.nid), func.stubAddr);
// Add the symbol to the symbol map for debugging.
char temp[256];
sprintf(temp,"zz_%s", GetFuncName(func.moduleName, func.nid));
symbolMap.AddSymbol(temp, func.stubAddr, 8, ST_FUNCTION);
// Keep track and actually hook it up if possible.
importedFuncs.push_back(func);
impExpModuleNames.insert(func.moduleName);
ImportFuncSymbol(func);
}
void ImportVar(const VarSymbolImport &var) {
// Keep track and actually hook it up if possible.
importedVars.push_back(var);
impExpModuleNames.insert(var.moduleName);
ImportVarSymbol(var);
}
void ExportFunc(const FuncSymbolExport &func) {
exportedFuncs.push_back(func);
impExpModuleNames.insert(func.moduleName);
ExportFuncSymbol(func);
}
void ExportVar(const VarSymbolExport &var) {
exportedVars.push_back(var);
impExpModuleNames.insert(var.moduleName);
ExportVarSymbol(var);
}
template <typename T>
void RebuildImpExpList(const std::vector<T> &list) {
for (size_t i = 0; i < list.size(); ++i) {
impExpModuleNames.insert(list[i].moduleName);
}
}
void RebuildImpExpModuleNames() {
impExpModuleNames.clear();
RebuildImpExpList(exportedFuncs);
RebuildImpExpList(importedFuncs);
RebuildImpExpList(exportedVars);
RebuildImpExpList(importedVars);
}
bool ImportsOrExportsModuleName(const std::string &moduleName) {
return impExpModuleNames.find(moduleName) != impExpModuleNames.end();
}
NativeModule nm;
std::vector<ModuleWaitingThread> waitingThreads;
std::vector<FuncSymbolExport> exportedFuncs;
std::vector<FuncSymbolImport> importedFuncs;
std::vector<VarSymbolExport> exportedVars;
std::vector<VarSymbolImport> importedVars;
std::set<std::string> impExpModuleNames;
u32 memoryBlockAddr;
u32 memoryBlockSize;
bool isFake;
@@ -263,8 +374,7 @@ struct SceKernelSMOption {
// STATE BEGIN
static int actionAfterModule;
static std::vector<VarSymbol> unresolvedVars;
static std::vector<VarSymbol> exportedVars;
static std::set<SceUID> loadedModules;
// STATE END
//////////////////////////////////////////////////////////////////////////
@@ -277,16 +387,12 @@ void __KernelModuleDoState(PointerWrap &p)
{
p.Do(actionAfterModule);
__KernelRestoreActionType(actionAfterModule, AfterModuleEntryCall::Create);
VarSymbol vs = {""};
p.Do(unresolvedVars, vs);
p.Do(exportedVars, vs);
p.DoMarker("sceKernelModule");
}
void __KernelModuleShutdown()
{
unresolvedVars.clear();
exportedVars.clear();
loadedModules.clear();
MIPSAnalyst::Shutdown();
}
@@ -298,14 +404,14 @@ struct HI16RelocInfo
u32 addr;
u32 data;
};
void WriteVarSymbol(u32 exportAddress, u32 relocAddress, u8 type)
void WriteVarSymbol(u32 exportAddress, u32 relocAddress, u8 type, bool reverse = false)
{
// We have to post-process the HI16 part, since it might be +1 or not depending on the LO16 value.
static u32 lastHI16ExportAddress = 0;
static std::vector<HI16RelocInfo> lastHI16Relocs;
static bool lastHI16Processed = true;
u32 relocData = Memory::Read_Instruction(relocAddress);
u32 relocData = Memory::Read_Instruction(relocAddress).encoding;
switch (type)
{
@@ -314,24 +420,33 @@ void WriteVarSymbol(u32 exportAddress, u32 relocAddress, u8 type)
break;
case R_MIPS_32:
relocData += exportAddress;
if (!reverse) {
relocData += exportAddress;
} else {
relocData -= exportAddress;
}
break;
// Not really tested, but should work...
/*
case R_MIPS_26:
if (exportAddress % 4 || (exportAddress >> 28) != ((relocAddress + 4) >> 28))
if (exportAddress % 4 || (exportAddress >> 28) != ((relocAddress + 4) >> 28)) {
WARN_LOG_REPORT(LOADER, "Bad var relocation addresses for type 26 - %08x => %08x", exportAddress, relocAddress)
else
relocData = (relocData & ~0x03ffffff) | ((relocData + (exportAddress >> 2)) & 0x03ffffff);
} else {
if (!reverse) {
relocData = (relocData & ~0x03ffffff) | ((relocData + (exportAddress >> 2)) & 0x03ffffff);
} else {
relocData = (relocData & ~0x03ffffff) | ((relocData - (exportAddress >> 2)) & 0x03ffffff);
}
}
break;
*/
case R_MIPS_HI16:
if (lastHI16ExportAddress != exportAddress)
{
if (!lastHI16Processed && lastHI16Relocs.size() >= 1)
if (lastHI16ExportAddress != exportAddress) {
if (!lastHI16Processed && lastHI16Relocs.size() >= 1) {
WARN_LOG_REPORT(LOADER, "Unsafe unpaired HI16 variable relocation @ %08x / %08x", lastHI16Relocs[lastHI16Relocs.size() - 1].addr, relocAddress);
}
lastHI16ExportAddress = exportAddress;
lastHI16Relocs.clear();
@@ -341,7 +456,7 @@ void WriteVarSymbol(u32 exportAddress, u32 relocAddress, u8 type)
// The R_MIPS_LO16 and R_MIPS_HI16 will often be *different* relocAddress values.
HI16RelocInfo reloc;
reloc.addr = relocAddress;
reloc.data = Memory::Read_Instruction(relocAddress);
reloc.data = Memory::Read_Instruction(relocAddress).encoding;
lastHI16Relocs.push_back(reloc);
lastHI16Processed = false;
break;
@@ -353,17 +468,20 @@ void WriteVarSymbol(u32 exportAddress, u32 relocAddress, u8 type)
u32 full = exportOffsetLo;
// The ABI requires that these come in pairs, at least.
if (lastHI16Relocs.empty())
if (lastHI16Relocs.empty()) {
ERROR_LOG_REPORT(LOADER, "LO16 without any HI16 variable import at %08x for %08x", relocAddress, exportAddress)
// Try to process at least the low relocation...
else if (lastHI16ExportAddress != exportAddress)
} else if (lastHI16ExportAddress != exportAddress) {
ERROR_LOG_REPORT(LOADER, "HI16 and LO16 imports do not match at %08x for %08x (should be %08x)", relocAddress, lastHI16ExportAddress, exportAddress)
else
{
} else {
// Process each of the HI16. Usually there's only one.
for (auto it = lastHI16Relocs.begin(), end = lastHI16Relocs.end(); it != end; ++it)
{
full = (it->data << 16) + exportOffsetLo;
if (!reverse) {
full = (it->data << 16) + exportOffsetLo;
} else {
full = (it->data << 16) - exportOffsetLo;
}
// The low instruction will be a signed add, which means (full & 0x8000) will subtract.
// We add 1 in that case so that it ends up the right value.
u16 high = (full >> 16) + ((full & 0x8000) ? 1 : 0);
@@ -382,64 +500,177 @@ void WriteVarSymbol(u32 exportAddress, u32 relocAddress, u8 type)
}
Memory::Write_U32(relocData, relocAddress);
currentMIPS->InvalidateICache(relocAddress, 4);
}
void ImportVarSymbol(const char *moduleName, u32 nid, u32 address, u8 type)
{
_dbg_assert_msg_(HLE, moduleName != NULL, "Invalid module name.");
if (nid == 0)
{
void ImportVarSymbol(const VarSymbolImport &var) {
if (var.nid == 0) {
// TODO: What's the right thing for this?
ERROR_LOG_REPORT(LOADER, "Var import with nid = 0, type = %d", type);
ERROR_LOG_REPORT(LOADER, "Var import with nid = 0, type = %d", var.type);
return;
}
if (!Memory::IsValidAddress(address))
{
ERROR_LOG_REPORT(LOADER, "Invalid address for var import nid = %08x, type = %d, addr = %08x", nid, type, address);
if (!Memory::IsValidAddress(var.stubAddr)) {
ERROR_LOG_REPORT(LOADER, "Invalid address for var import nid = %08x, type = %d, addr = %08x", var.nid, var.type, var.stubAddr);
return;
}
for (auto it = exportedVars.begin(), end = exportedVars.end(); it != end; ++it)
{
if (!strncmp(it->moduleName, moduleName, KERNELOBJECT_MAX_NAME_LENGTH) && it->nid == nid)
{
WriteVarSymbol(it->symAddr, address, type);
return;
u32 error;
for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) {
Module *module = kernelObjects.Get<Module>(*mod, error);
if (!module || !module->ImportsOrExportsModuleName(var.moduleName)) {
continue;
}
// Look for exports currently loaded modules already have. Maybe it's available?
for (auto it = module->exportedVars.begin(), end = module->exportedVars.end(); it != end; ++it) {
if (it->Matches(var)) {
WriteVarSymbol(it->symAddr, var.stubAddr, var.type);
return;
}
}
}
// It hasn't been exported yet, but hopefully it will later.
INFO_LOG(LOADER, "Variable (%s,%08x) unresolved, storing for later resolving", moduleName, nid);
VarSymbol vs = {"", address, nid, type};
strncpy(vs.moduleName, moduleName, KERNELOBJECT_MAX_NAME_LENGTH);
vs.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
unresolvedVars.push_back(vs);
INFO_LOG(LOADER, "Variable (%s,%08x) unresolved, storing for later resolving", var.moduleName, var.nid);
}
void ExportVarSymbol(const char *moduleName, u32 nid, u32 address)
{
_dbg_assert_msg_(HLE, moduleName != NULL, "Invalid module name.");
VarSymbol ex = {"", address, nid};
strncpy(ex.moduleName, moduleName, KERNELOBJECT_MAX_NAME_LENGTH);
ex.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
exportedVars.push_back(ex);
for (auto it = unresolvedVars.begin(), end = unresolvedVars.end(); it != end; ++it)
{
if (strncmp(it->moduleName, moduleName, KERNELOBJECT_MAX_NAME_LENGTH) == 0 && it->nid == nid)
{
INFO_LOG(HLE,"Resolving var %s/%08x", moduleName, nid);
WriteVarSymbol(address, it->symAddr, it->type);
void ExportVarSymbol(const VarSymbolExport &var) {
u32 error;
for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) {
Module *module = kernelObjects.Get<Module>(*mod, error);
if (!module || !module->ImportsOrExportsModuleName(var.moduleName)) {
continue;
}
// Look for imports currently loaded modules already have, hook it up right away.
for (auto it = module->importedVars.begin(), end = module->importedVars.end(); it != end; ++it) {
if (var.Matches(*it)) {
INFO_LOG(LOADER, "Resolving var %s/%08x", var.moduleName, var.nid);
WriteVarSymbol(var.symAddr, it->stubAddr, it->type);
}
}
}
}
void UnexportVarSymbol(const VarSymbolExport &var) {
u32 error;
for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) {
Module *module = kernelObjects.Get<Module>(*mod, error);
if (!module || !module->ImportsOrExportsModuleName(var.moduleName)) {
continue;
}
// Look for imports modules that are *still* loaded have, and reverse them.
for (auto it = module->importedVars.begin(), end = module->importedVars.end(); it != end; ++it) {
if (var.Matches(*it)) {
INFO_LOG(LOADER, "Unresolving var %s/%08x", var.moduleName, var.nid);
WriteVarSymbol(var.symAddr, it->stubAddr, it->type, true);
}
}
}
}
void ImportFuncSymbol(const FuncSymbolImport &func) {
// Prioritize HLE implementations.
// TODO: Or not?
if (FuncImportIsSyscall(func.moduleName, func.nid)) {
WriteSyscall(func.moduleName, func.nid, func.stubAddr);
currentMIPS->InvalidateICache(func.stubAddr, 8);
return;
}
u32 error;
for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) {
Module *module = kernelObjects.Get<Module>(*mod, error);
if (!module || !module->ImportsOrExportsModuleName(func.moduleName)) {
continue;
}
// Look for exports currently loaded modules already have. Maybe it's available?
for (auto it = module->exportedFuncs.begin(), end = module->exportedFuncs.end(); it != end; ++it) {
if (it->Matches(func)) {
WriteFuncStub(func.stubAddr, it->symAddr);
currentMIPS->InvalidateICache(func.stubAddr, 8);
return;
}
}
}
// It hasn't been exported yet, but hopefully it will later.
if (GetModuleIndex(func.moduleName) != -1) {
WARN_LOG_REPORT(LOADER, "Unknown syscall in known module: %s 0x%08x", func.moduleName, func.nid);
} else {
INFO_LOG(LOADER, "Function (%s,%08x) unresolved, storing for later resolving", func.moduleName, func.nid);
}
WriteFuncMissingStub(func.stubAddr, func.nid);
currentMIPS->InvalidateICache(func.stubAddr, 8);
}
void ExportFuncSymbol(const FuncSymbolExport &func) {
if (FuncImportIsSyscall(func.moduleName, func.nid)) {
// Oops, HLE covers this.
WARN_LOG_REPORT(LOADER, "Ignoring func export %s/%08x, already implemented in HLE.", func.moduleName, func.nid);
return;
}
u32 error;
for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) {
Module *module = kernelObjects.Get<Module>(*mod, error);
if (!module || !module->ImportsOrExportsModuleName(func.moduleName)) {
continue;
}
// Look for imports currently loaded modules already have, hook it up right away.
for (auto it = module->importedFuncs.begin(), end = module->importedFuncs.end(); it != end; ++it) {
if (func.Matches(*it)) {
INFO_LOG(LOADER, "Resolving function %s/%08x", func.moduleName, func.nid);
WriteFuncStub(it->stubAddr, func.symAddr);
currentMIPS->InvalidateICache(it->stubAddr, 8);
}
}
}
}
void UnexportFuncSymbol(const FuncSymbolExport &func) {
if (FuncImportIsSyscall(func.moduleName, func.nid)) {
// Oops, HLE covers this.
return;
}
u32 error;
for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) {
Module *module = kernelObjects.Get<Module>(*mod, error);
if (!module || !module->ImportsOrExportsModuleName(func.moduleName)) {
continue;
}
// Look for imports modules that are *still* loaded have, and write back stubs.
for (auto it = module->importedFuncs.begin(), end = module->importedFuncs.end(); it != end; ++it) {
if (func.Matches(*it)) {
INFO_LOG(LOADER, "Unresolving function %s/%08x", func.moduleName, func.nid);
WriteFuncMissingStub(it->stubAddr, it->nid);
currentMIPS->InvalidateICache(it->stubAddr, 8);
}
}
}
}
void Module::Cleanup() {
loadedModules.erase(GetUID());
for (auto it = exportedVars.begin(), end = exportedVars.end(); it != end; ++it) {
UnexportVarSymbol(*it);
}
for (auto it = exportedFuncs.begin(), end = exportedFuncs.end(); it != end; ++it) {
UnexportFuncSymbol(*it);
}
}
Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *error_string, u32 *magic) {
Module *module = new Module;
kernelObjects.Create(module);
loadedModules.insert(module->GetUID());
memset(&module->nm, 0, sizeof(module->nm));
u8 *newptr = 0;
@@ -488,6 +719,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
*error_string = "File corrupt";
if (newptr)
delete [] newptr;
module->Cleanup();
kernelObjects.Destroy<Module>(module->GetUID());
return 0;
}
@@ -498,6 +730,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
ERROR_LOG(HLE, "LoadInto failed");
if (newptr)
delete [] newptr;
module->Cleanup();
kernelObjects.Destroy<Module>(module->GetUID());
return 0;
}
@@ -622,20 +855,17 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
continue;
}
FuncSymbolImport func;
strncpy(func.moduleName, modulename, KERNELOBJECT_MAX_NAME_LENGTH);
func.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
u32_le *nidDataPtr = (u32_le *)Memory::GetPointer(entry->nidData);
for (int i = 0; i < entry->numFuncs; ++i) {
u32 addrToWriteSyscall = entry->firstSymAddr + i * 8;
DEBUG_LOG(LOADER, "%s : %08x", GetFuncName(modulename, nidDataPtr[i]), addrToWriteSyscall);
//write a syscall here
if (Memory::IsValidAddress(addrToWriteSyscall)) {
WriteSyscall(modulename, nidDataPtr[i], addrToWriteSyscall);
} else {
WARN_LOG_REPORT(LOADER, "Invalid address for syscall stub %s %08x", modulename, nidDataPtr[i]);
}
char temp[256];
sprintf(temp,"zz_%s", GetFuncName(modulename, nidDataPtr[i]));
symbolMap.AddSymbol(temp, addrToWriteSyscall, 8, ST_FUNCTION);
// This is the id of the import.
func.nid = nidDataPtr[i];
// This is the address to write the j abnd delay slot to.
func.stubAddr = entry->firstSymAddr + i * 8;
module->ImportFunc(func);
}
} else if (entry->numFuncs > 0) {
WARN_LOG_REPORT(LOADER, "Module entry with %d imports but no valid address", entry->numFuncs);
@@ -649,6 +879,10 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
continue;
}
VarSymbolImport var;
strncpy(var.moduleName, modulename, KERNELOBJECT_MAX_NAME_LENGTH);
var.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
for (int i = 0; i < entry->numVars; ++i) {
u32 varRefsPtr = Memory::Read_U32(entry->varData + i * 8);
u32 nid = Memory::Read_U32(entry->varData + i * 8 + 4);
@@ -659,7 +893,10 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
u32_le *varRef = (u32_le *)Memory::GetPointer(varRefsPtr);
for (; *varRef != 0; ++varRef) {
ImportVarSymbol(modulename, nid, (*varRef & 0x03FFFFFF) << 2, *varRef >> 26);
var.nid = nid;
var.stubAddr = (*varRef & 0x03FFFFFF) << 2;
var.type = *varRef >> 26;
module->ImportVar(var);
}
}
} else if (entry->numVars > 0) {
@@ -733,7 +970,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
INFO_LOG(HLE, "Exporting ent %d named %s, %d funcs, %d vars, resident %08x", m, name, ent->fcount, ent->vcount, ent->resident);
if (!Memory::IsValidAddress(ent->resident)) {
if (ent->fcount + ent->vcount > 0) {
if (ent->fcount + variableCount > 0) {
WARN_LOG_REPORT(LOADER, "Invalid export resident address %08x", ent->resident);
}
continue;
@@ -746,6 +983,10 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
WARN_LOG_REPORT(LOADER, "Unexpected export module entry size %d, vcountNew=%08x, unknown1=%08x, unknown2=%08x", ent->size, ent->vcountNew, ent->unknown1, ent->unknown2);
}
FuncSymbolExport func;
strncpy(func.moduleName, name, KERNELOBJECT_MAX_NAME_LENGTH);
func.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
for (u32 j = 0; j < ent->fcount; j++) {
u32 nid = residentPtr[j];
u32 exportAddr = exportPtr[j];
@@ -767,10 +1008,16 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
module->nm.module_bootstart_func = exportAddr;
break;
default:
ResolveSyscall(name, nid, exportAddr);
func.nid = nid;
func.symAddr = exportAddr;
module->ExportFunc(func);
}
}
VarSymbolExport var;
strncpy(var.moduleName, name, KERNELOBJECT_MAX_NAME_LENGTH);
var.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
for (u32 j = 0; j < variableCount; j++) {
u32 nid = residentPtr[ent->fcount + j];
u32 exportAddr = exportPtr[ent->fcount + j];
@@ -813,7 +1060,9 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
DEBUG_LOG(LOADER, "Module SDK: %08x", Memory::Read_U32(exportAddr));
break;
default:
ExportVarSymbol(name, nid, exportAddr);
var.nid = nid;
var.symAddr = exportAddr;
module->ExportVar(var);
break;
}
}
@@ -971,8 +1220,10 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str
Module *module = __KernelLoadModule(temp, 0, error_string);
if (!module || module->isFake) {
if (module)
if (module) {
module->Cleanup();
kernelObjects.Destroy<Module>(module->GetUID());
}
ERROR_LOG(LOADER, "Failed to load module %s", filename);
*error_string = "Failed to load executable: " + *error_string;
delete [] temp;
@@ -1068,6 +1319,7 @@ u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr)
Module *module = new Module;
kernelObjects.Create(module);
loadedModules.insert(module->GetUID());
memset(&module->nm, 0, sizeof(module->nm));
module->isFake = true;
return module->GetUID();
@@ -1143,7 +1395,7 @@ void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 returnValu
u32 stacksize = 0x40000;
u32 attr = 0;
int stackPartition = 0;
SceKernelSMOption smoption;
SceKernelSMOption smoption = {0};
if (optionAddr) {
Memory::ReadStruct(optionAddr, &smoption);
}
@@ -1320,6 +1572,7 @@ u32 sceKernelUnloadModule(u32 moduleId)
if (!module)
return error;
module->Cleanup();
kernelObjects.Destroy<Module>(moduleId);
return moduleId;
}
@@ -1409,6 +1662,12 @@ u32 sceKernelGetModuleId()
u32 sceKernelFindModuleByName(const char *name)
{
ERROR_LOG_REPORT(HLE, "UNIMPL sceKernelFindModuleByName(%s)", name);
int index = GetModuleIndex(name);
if (index == -1)
return 0;
return 1;
}
@@ -1496,13 +1755,32 @@ u32 sceKernelQueryModuleInfo(u32 uid, u32 infoAddr)
return 0;
}
u32 ModuleMgrForKernel_977de386(const char *name, u32 flags, u32 optionAddr)
{
WARN_LOG(HLE,"Not support this patcher");
return sceKernelLoadModule(name, flags, optionAddr);
}
void ModuleMgrForKernel_50f0c1ec(u32 moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, u32 optionAddr)
{
WARN_LOG(HLE,"Not support this patcher");
sceKernelStartModule(moduleId, argsize, argAddr, returnValueAddr, optionAddr);
}
//fix for tiger x dragon
u32 ModuleMgrForKernel_a1a78c58(const char *name, u32 flags, u32 optionAddr)
{
WARN_LOG(HLE,"Not support this patcher");
return sceKernelLoadModule(name, flags, optionAddr);
}
const HLEFunction ModuleMgrForUser[] =
{
{0x977DE386,&WrapU_CUU<sceKernelLoadModule>,"sceKernelLoadModule"},
{0xb7f46618,&WrapU_UUU<sceKernelLoadModuleByID>,"sceKernelLoadModuleByID"},
{0x50F0C1EC,&WrapV_UUUUU<sceKernelStartModule>,"sceKernelStartModule"},
{0x50F0C1EC,&WrapV_UUUUU<sceKernelStartModule>,"sceKernelStartModule", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0xD675EBB8,&sceKernelExitGame,"sceKernelSelfStopUnloadModule"}, //HACK
{0xd1ff982a,&WrapU_UUUUU<sceKernelStopModule>,"sceKernelStopModule"},
{0xd1ff982a,&WrapU_UUUUU<sceKernelStopModule>,"sceKernelStopModule", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x2e0911aa,WrapU_U<sceKernelUnloadModule>,"sceKernelUnloadModule"},
{0x710F61B5,0,"sceKernelLoadModuleMs"},
{0xF9275D98,0,"sceKernelLoadModuleBufferUsbWlan"}, ///???
@@ -1519,7 +1797,20 @@ const HLEFunction ModuleMgrForUser[] =
};
const HLEFunction ModuleMgrForKernel[] =
{
{0x50f0c1ec,&WrapV_UUUUU<ModuleMgrForKernel_50f0c1ec>, "ModuleMgrForKernel_50f0c1ec"},//Not sure right
{0x977de386, &WrapU_CUU<ModuleMgrForKernel_977de386>, "ModuleMgrForKernel_977de386"},//Not sure right
{0xa1a78c58, &WrapU_CUU<ModuleMgrForKernel_a1a78c58>, "ModuleMgrForKernel_a1a78c58"}, //fix for tiger x dragon
};
void Register_ModuleMgrForUser()
{
RegisterModule("ModuleMgrForUser", ARRAY_SIZE(ModuleMgrForUser), ModuleMgrForUser);
}
void Register_ModuleMgrForKernel()
{
RegisterModule("ModuleMgrForKernel", ARRAY_SIZE(ModuleMgrForKernel), ModuleMgrForKernel);
};
+1
View File
@@ -29,3 +29,4 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str
void __KernelReturnFromModuleFunc();
void Register_ModuleMgrForUser();
void Register_ModuleMgrForKernel();
+79 -18
View File
@@ -23,6 +23,7 @@
#include "Core/HLE/sceKernel.h"
#include "Core/HLE/sceKernelMsgPipe.h"
#include "Core/HLE/sceKernelMemory.h"
#include "Core/HLE/sceKernelInterrupt.h"
#include "Core/HLE/sceKernelThread.h"
#include "Common/ChunkFile.h"
@@ -140,7 +141,7 @@ struct MsgPipe : public KernelObject
void AddWaitingThread(std::vector<MsgPipeWaitingThread> &list, SceUID id, u32 addr, u32 size, int waitMode, u32 transferredBytesAddr)
{
MsgPipeWaitingThread thread = { id, addr, size, size, waitMode, transferredBytesAddr };
MsgPipeWaitingThread thread = { id, addr, size, size, waitMode, { transferredBytesAddr } };
// Start out with 0 transferred bytes while waiting.
// TODO: for receive, it might be a different (partial) number.
if (thread.transferredBytes.IsValid())
@@ -399,7 +400,11 @@ int sceKernelCreateMsgPipe(const char *name, int partition, u32 attr, u32 size,
DEBUG_LOG(HLE, "%d=sceKernelCreateMsgPipe(%s, part=%d, attr=%08x, size=%d, opt=%08x)", id, name, partition, attr, size, optionsPtr);
if (optionsPtr != 0)
WARN_LOG_REPORT(HLE, "sceKernelCreateMsgPipe(%s) unsupported options parameter: %08x", name, optionsPtr);
{
u32 size = Memory::Read_U32(optionsPtr);
if (size > 4)
WARN_LOG_REPORT(HLE, "sceKernelCreateMsgPipe(%s) unsupported options parameter, size = %d", name, size);
}
return id;
}
@@ -423,11 +428,8 @@ int sceKernelDeleteMsgPipe(SceUID uid)
return kernelObjects.Destroy<MsgPipe>(uid);
}
int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll)
int __KernelValidateSendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, bool tryMode = false)
{
u32 curSendAddr = sendBufAddr;
SceUID uid = m->GetUID();
if (sendSize & 0x80000000)
{
ERROR_LOG(HLE, "__KernelSendMsgPipe(%d): illegal size %d", uid, sendSize);
@@ -442,10 +444,32 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode,
if (waitMode != SCE_KERNEL_MPW_ASAP && waitMode != SCE_KERNEL_MPW_FULL)
{
ERROR_LOG(HLE, "__KernelSendMsgPipe(%d): invalid wait mode", uid, waitMode);
ERROR_LOG(HLE, "__KernelSendMsgPipe(%d): invalid wait mode %d", uid, waitMode);
return SCE_KERNEL_ERROR_ILLEGAL_MODE;
}
if (!tryMode)
{
if (!__KernelIsDispatchEnabled())
{
WARN_LOG(HLE, "__KernelSendMsgPipe(%d): dispatch disabled", uid);
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
}
if (__IsInInterrupt())
{
WARN_LOG(HLE, "__KernelSendMsgPipe(%d): in interrupt", uid);
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
}
}
return 0;
}
int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll)
{
u32 curSendAddr = sendBufAddr;
SceUID uid = m->GetUID();
// If the buffer size is 0, nothing is buffered and all operations wait.
if (m->nmp.bufSize == 0)
{
@@ -547,7 +571,10 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode,
int sceKernelSendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr)
{
u32 error;
u32 error = __KernelValidateSendMsgPipe(uid, sendBufAddr, sendSize, waitMode, resultAddr);
if (error != 0) {
return error;
}
MsgPipe *m = kernelObjects.Get<MsgPipe>(uid, error);
if (!m) {
ERROR_LOG(HLE, "sceKernelSendMsgPipe(%i) - ERROR %08x", uid, error);
@@ -560,7 +587,10 @@ int sceKernelSendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode
int sceKernelSendMsgPipeCB(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr)
{
u32 error;
u32 error = __KernelValidateSendMsgPipe(uid, sendBufAddr, sendSize, waitMode, resultAddr);
if (error != 0) {
return error;
}
MsgPipe *m = kernelObjects.Get<MsgPipe>(uid, error);
if (!m) {
ERROR_LOG(HLE, "sceKernelSendMsgPipeCB(%i) - ERROR %08x", uid, error);
@@ -575,7 +605,10 @@ int sceKernelSendMsgPipeCB(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMo
int sceKernelTrySendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr)
{
u32 error;
u32 error = __KernelValidateSendMsgPipe(uid, sendBufAddr, sendSize, waitMode, resultAddr, true);
if (error != 0) {
return error;
}
MsgPipe *m = kernelObjects.Get<MsgPipe>(uid, error);
if (!m) {
ERROR_LOG(HLE, "sceKernelTrySendMsgPipe(%i) - ERROR %08x", uid, error);
@@ -586,11 +619,8 @@ int sceKernelTrySendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitM
return __KernelSendMsgPipe(m, sendBufAddr, sendSize, waitMode, resultAddr, 0, false, true);
}
int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll)
int __KernelValidateReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, int waitMode, u32 resultAddr, bool tryMode = false)
{
u32 curReceiveAddr = receiveBufAddr;
SceUID uid = m->GetUID();
if (receiveSize & 0x80000000)
{
ERROR_LOG(HLE, "__KernelReceiveMsgPipe(%d): illegal size %d", uid, receiveSize);
@@ -605,10 +635,32 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int
if (waitMode != SCE_KERNEL_MPW_ASAP && waitMode != SCE_KERNEL_MPW_FULL)
{
ERROR_LOG(HLE, "__KernelReceiveMsgPipe(%d): invalid wait mode", uid, waitMode);
ERROR_LOG(HLE, "__KernelReceiveMsgPipe(%d): invalid wait mode %d", uid, waitMode);
return SCE_KERNEL_ERROR_ILLEGAL_MODE;
}
if (!tryMode)
{
if (!__KernelIsDispatchEnabled())
{
WARN_LOG(HLE, "__KernelReceiveMsgPipe(%d): dispatch disabled", uid);
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
}
if (__IsInInterrupt())
{
WARN_LOG(HLE, "__KernelReceiveMsgPipe(%d): in interrupt", uid);
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
}
}
return 0;
}
int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll)
{
u32 curReceiveAddr = receiveBufAddr;
SceUID uid = m->GetUID();
// MsgPipe buffer size is 0, receiving directly from waiting send threads
if (m->nmp.bufSize == 0)
{
@@ -708,7 +760,10 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int
int sceKernelReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr)
{
u32 error;
u32 error = __KernelValidateReceiveMsgPipe(uid, receiveBufAddr, receiveSize, waitMode, resultAddr);
if (error != 0) {
return error;
}
MsgPipe *m = kernelObjects.Get<MsgPipe>(uid, error);
if (!m) {
ERROR_LOG(HLE, "sceKernelReceiveMsgPipe(%i) - ERROR %08x", uid, error);
@@ -721,7 +776,10 @@ int sceKernelReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32
int sceKernelReceiveMsgPipeCB(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr)
{
u32 error;
u32 error = __KernelValidateReceiveMsgPipe(uid, receiveBufAddr, receiveSize, waitMode, resultAddr);
if (error != 0) {
return error;
}
MsgPipe *m = kernelObjects.Get<MsgPipe>(uid, error);
if (!m) {
ERROR_LOG(HLE, "sceKernelReceiveMsgPipeCB(%i) - ERROR %08x", uid, error);
@@ -736,7 +794,10 @@ int sceKernelReceiveMsgPipeCB(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u
int sceKernelTryReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr)
{
u32 error;
u32 error = __KernelValidateReceiveMsgPipe(uid, receiveBufAddr, receiveSize, waitMode, resultAddr, true);
if (error != 0) {
return error;
}
MsgPipe *m = kernelObjects.Get<MsgPipe>(uid, error);
if (!m) {
ERROR_LOG(HLE, "sceKernelTryReceiveMsgPipe(%i) - ERROR %08x", uid, error);
+63 -1
View File
@@ -405,11 +405,11 @@ int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optio
int sceKernelDeleteMutex(SceUID id)
{
DEBUG_LOG(HLE,"sceKernelDeleteMutex(%i)", id);
u32 error;
Mutex *mutex = kernelObjects.Get<Mutex>(id, error);
if (mutex)
{
DEBUG_LOG(HLE, "sceKernelDeleteMutex(%i)", id);
bool wokeThreads = false;
std::vector<SceUID>::iterator iter, end;
for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter)
@@ -425,7 +425,10 @@ int sceKernelDeleteMutex(SceUID id)
return kernelObjects.Destroy<Mutex>(id);
}
else
{
DEBUG_LOG(HLE, "sceKernelDeleteMutex(%i): invalid mutex", id);
return error;
}
}
bool __KernelLockMutexCheck(Mutex *mutex, int count, u32 &error)
@@ -567,6 +570,65 @@ void __KernelWaitMutex(Mutex *mutex, u32 timeoutPtr)
CoreTiming::ScheduleEvent(usToCycles(micro), mutexWaitTimer, __KernelGetCurThread());
}
int sceKernelCancelMutex(SceUID uid, int count, u32 numWaitThreadsPtr)
{
u32 error;
Mutex *mutex = kernelObjects.Get<Mutex>(uid, error);
if (mutex)
{
bool lockable = count <= 0 || __KernelLockMutexCheck(mutex, count, error);
if (!lockable)
{
// May still be okay. As long as the count/etc. are valid.
if (error != 0 && error != PSP_MUTEX_ERROR_LOCK_OVERFLOW && error != PSP_MUTEX_ERROR_ALREADY_LOCKED)
{
DEBUG_LOG(HLE, "sceKernelCancelMutex(%i, %d, %08x): invalid count", uid, count, numWaitThreadsPtr);
return error;
}
}
DEBUG_LOG(HLE, "sceKernelCancelMutex(%i, %d, %08x)", uid, count, numWaitThreadsPtr);
// Remove threads no longer waiting on this first (so the numWaitThreads value is correct.)
for (auto iter = mutex->waitingThreads.begin(); iter != mutex->waitingThreads.end(); ++iter)
{
SceUID waitID = __KernelGetWaitID(*iter, WAITTYPE_MUTEX, error);
// The thread is no longer waiting for this, clean it up.
if (waitID != uid)
mutex->waitingThreads.erase(iter--);
}
if (Memory::IsValidAddress(numWaitThreadsPtr))
Memory::Write_U32((u32)mutex->waitingThreads.size(), numWaitThreadsPtr);
bool wokeThreads = false;
for (auto iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter)
wokeThreads |= __KernelUnlockMutexForThread(mutex, *iter, error, SCE_KERNEL_ERROR_WAIT_CANCEL);
if (mutex->nm.lockThread != -1)
__KernelMutexEraseLock(mutex);
mutex->waitingThreads.clear();
if (count <= 0)
{
mutex->nm.lockLevel = 0;
mutex->nm.lockThread = -1;
}
else
__KernelMutexAcquireLock(mutex, count);
if (wokeThreads)
hleReSchedule("mutex canceled");
return 0;
}
else
{
DEBUG_LOG(HLE, "sceKernelCancelMutex(%i, %d, %08x)", uid, count, numWaitThreadsPtr);
return error;
}
}
// int sceKernelLockMutex(SceUID id, int count, int *timeout)
int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr)
{
+1
View File
@@ -17,6 +17,7 @@
#pragma once
int sceKernelCancelMutex(SceUID uid, int count, u32 numWaitThreadsPtr);
int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr);
int sceKernelDeleteMutex(SceUID id);
int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr);
+3 -3
View File
@@ -477,7 +477,7 @@ int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, bool processCal
int sceKernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr)
{
int result = __KernelWaitSema(id, wantedCount, timeoutPtr, false);
if (result == SCE_KERNEL_ERROR_ILLEGAL_COUNT)
if (result == (int)SCE_KERNEL_ERROR_ILLEGAL_COUNT)
DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_ILLEGAL_COUNT=sceKernelWaitSema(%i, %i, %i)", id, wantedCount, timeoutPtr)
else if (result == 0)
DEBUG_LOG(HLE, "0=sceKernelWaitSema(%i, %i, %i)", id, wantedCount, timeoutPtr)
@@ -489,7 +489,7 @@ int sceKernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr)
int sceKernelWaitSemaCB(SceUID id, int wantedCount, u32 timeoutPtr)
{
int result = __KernelWaitSema(id, wantedCount, timeoutPtr, true);
if (result == SCE_KERNEL_ERROR_ILLEGAL_COUNT)
if (result == (int)SCE_KERNEL_ERROR_ILLEGAL_COUNT)
DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_ILLEGAL_COUNT=sceKernelWaitSemaCB(%i, %i, %i)", id, wantedCount, timeoutPtr)
else if (result == 0)
DEBUG_LOG(HLE, "0=sceKernelWaitSemaCB(%i, %i, %i)", id, wantedCount, timeoutPtr)
@@ -504,7 +504,7 @@ int sceKernelPollSema(SceUID id, int wantedCount)
if (wantedCount <= 0)
{
DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_ILLEGAL_COUNT=sceKernelPollSema(%i, %i)", id, wantedCount);
return SCE_KERNEL_ERROR_ILLEGAL_COUNT;
return (int)SCE_KERNEL_ERROR_ILLEGAL_COUNT;
}
u32 error;
+51 -29
View File
@@ -68,6 +68,7 @@ const WaitTypeNames waitTypeNames[] = {
{ WAITTYPE_MODULE, "Module" },
{ WAITTYPE_HLEDELAY, "HleDelay" },
{ WAITTYPE_TLS, "TLS" },
{ WAITTYPE_VMEM, "Volatile Mem" },
};
const char *getWaitTypeName(WaitType type)
@@ -822,6 +823,9 @@ int actionAfterMipsCall;
// Doesn't need state saving.
WaitTypeFuncs waitTypeFuncs[NUM_WAITTYPES];
// Doesn't really need state saving, just for logging purposes.
static u64 lastSwitchCycles = 0;
//////////////////////////////////////////////////////////////////////////
//STATE END
//////////////////////////////////////////////////////////////////////////
@@ -971,6 +975,7 @@ void __KernelThreadingInit()
g_inCbCount = 0;
currentCallbackThreadID = 0;
readyCallbacksCount = 0;
lastSwitchCycles = 0;
idleThreadHackAddr = kernelMemory.Alloc(blockSize, false, "threadrethack");
Memory::Memcpy(idleThreadHackAddr, idleThreadCode, sizeof(idleThreadCode));
@@ -1025,6 +1030,7 @@ void __KernelThreadingDoState(PointerWrap &p)
__KernelRestoreActionType(actionAfterCallback, ActionAfterCallback::Create);
hleCurrentThreadName = __KernelGetThreadName(currentThread);
lastSwitchCycles = CoreTiming::GetTicks();
p.DoMarker("sceKernelThread");
}
@@ -2124,7 +2130,10 @@ void sceKernelExitDeleteThread(int exitStatus)
u32 sceKernelSuspendDispatchThread()
{
if (!__InterruptsEnabled())
{
DEBUG_LOG(HLE, "sceKernelSuspendDispatchThread(): interrupts disabled");
return SCE_KERNEL_ERROR_CPUDI;
}
u32 oldDispatchEnabled = dispatchEnabled;
dispatchEnabled = false;
@@ -2135,7 +2144,10 @@ u32 sceKernelSuspendDispatchThread()
u32 sceKernelResumeDispatchThread(u32 enabled)
{
if (!__InterruptsEnabled())
{
DEBUG_LOG(HLE, "sceKernelResumeDispatchThread(%i): interrupts disabled", enabled);
return SCE_KERNEL_ERROR_CPUDI;
}
u32 oldDispatchEnabled = dispatchEnabled;
dispatchEnabled = enabled != 0;
@@ -2404,44 +2416,42 @@ int sceKernelDelayThread(u32 usec)
return 0;
}
void sceKernelDelaySysClockThreadCB()
int sceKernelDelaySysClockThreadCB(u32 sysclockAddr)
{
u32 sysclockAddr = PARAM(0);
if (!Memory::IsValidAddress(sysclockAddr)) {
ERROR_LOG(HLE, "sceKernelDelaySysClockThread(%08x) - bad pointer", sysclockAddr);
RETURN(-1);
return;
PSPPointer<SceKernelSysClock> sysclock;
sysclock = sysclockAddr;
if (!sysclock.IsValid()) {
ERROR_LOG(HLE, "sceKernelDelaySysClockThreadCB(%08x) - bad pointer", sysclockAddr);
return -1;
}
SceKernelSysClock sysclock;
Memory::ReadStruct(sysclockAddr, &sysclock);
// TODO: Which unit?
u64 usec = sysclock.lo | ((u64)sysclock.hi << 32);
DEBUG_LOG(HLE, "sceKernelDelaySysClockThread(%08x (%llu))", sysclockAddr, usec);
u64 usec = sysclock->lo | ((u64)sysclock->hi << 32);
DEBUG_LOG(HLE, "sceKernelDelaySysClockThreadCB(%08x (%llu))", sysclockAddr, usec);
SceUID curThread = __KernelGetCurThread();
__KernelScheduleWakeup(curThread, __KernelDelayThreadUs(usec));
__KernelWaitCurThread(WAITTYPE_DELAY, curThread, 0, 0, true, "thread delayed");
return 0;
}
void sceKernelDelaySysClockThread()
int sceKernelDelaySysClockThread(u32 sysclockAddr)
{
u32 sysclockAddr = PARAM(0);
if (!Memory::IsValidAddress(sysclockAddr)) {
PSPPointer<SceKernelSysClock> sysclock;
sysclock = sysclockAddr;
if (!sysclock.IsValid()) {
ERROR_LOG(HLE, "sceKernelDelaySysClockThread(%08x) - bad pointer", sysclockAddr);
RETURN(-1);
return;
return -1;
}
SceKernelSysClock sysclock;
Memory::ReadStruct(sysclockAddr, &sysclock);
// TODO: Which unit?
u64 usec = sysclock.lo | ((u64)sysclock.hi << 32);
u64 usec = sysclock->lo | ((u64)sysclock->hi << 32);
DEBUG_LOG(HLE, "sceKernelDelaySysClockThread(%08x (%llu))", sysclockAddr, usec);
SceUID curThread = __KernelGetCurThread();
__KernelScheduleWakeup(curThread, __KernelDelayThreadUs(usec));
__KernelWaitCurThread(WAITTYPE_DELAY, curThread, 0, 0, false, "thread delayed");
return 0;
}
u32 __KernelGetThreadPrio(SceUID id)
@@ -2537,6 +2547,11 @@ int sceKernelWaitThreadEnd(SceUID threadID, u32 timeoutPtr)
if (threadID == 0 || threadID == currentThread)
return SCE_KERNEL_ERROR_ILLEGAL_THID;
if (!__KernelIsDispatchEnabled())
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
if (__IsInInterrupt())
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
u32 error;
Thread *t = kernelObjects.Get<Thread>(threadID, error);
if (t)
@@ -2563,6 +2578,11 @@ int sceKernelWaitThreadEndCB(SceUID threadID, u32 timeoutPtr)
if (threadID == 0 || threadID == currentThread)
return SCE_KERNEL_ERROR_ILLEGAL_THID;
if (!__KernelIsDispatchEnabled())
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
if (__IsInInterrupt())
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
u32 error;
Thread *t = kernelObjects.Get<Thread>(threadID, error);
if (t)
@@ -2945,8 +2965,7 @@ void Thread::resumeFromWait()
if (action)
{
action->status &= ~THREADSTATUS_WAIT;
// TODO: What if DORMANT or DEAD?
if (!(action->status & THREADSTATUS_WAITSUSPEND))
if (!(action->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD)))
action->status = THREADSTATUS_READY;
// Non-waiting threads do not process callbacks.
@@ -2955,8 +2974,7 @@ void Thread::resumeFromWait()
else
{
this->nt.status &= ~THREADSTATUS_WAIT;
// TODO: What if DORMANT or DEAD?
if (!(this->nt.status & THREADSTATUS_WAITSUSPEND))
if (!(this->nt.status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD)))
__KernelChangeReadyState(this, this->GetUID(), true);
// Non-waiting threads do not process callbacks.
@@ -3010,7 +3028,7 @@ void __KernelSwitchContext(Thread *target, const char *reason)
{
u32 oldPC = 0;
SceUID oldUID = 0;
const char *oldName = "(none)";
const char *oldName = hleCurrentThreadName != NULL ? hleCurrentThreadName : "(none)";
Thread *cur = __GetCurrentThread();
if (cur) // It might just have been deleted.
@@ -3019,10 +3037,6 @@ void __KernelSwitchContext(Thread *target, const char *reason)
oldPC = currentMIPS->pc;
oldUID = cur->GetUID();
// Profile on Windows shows this takes time, skip it.
if (DEBUG_LEVEL <= MAX_LOGLEVEL)
oldName = cur->GetName();
// Normally this is taken care of in __KernelNextThread().
if (cur->isRunning())
__KernelChangeReadyState(cur, oldUID, true);
@@ -3043,15 +3057,23 @@ void __KernelSwitchContext(Thread *target, const char *reason)
hleCurrentThreadName = NULL;
}
#if DEBUG_LEVEL <= MAX_LOGLEVEL || DEBUG_LOG == NOTICE_LOG
bool fromIdle = oldUID == threadIdleID[0] || oldUID == threadIdleID[1];
bool toIdle = currentThread == threadIdleID[0] || currentThread == threadIdleID[1];
if (!(fromIdle && toIdle))
{
DEBUG_LOG(HLE,"Context switched: %s -> %s (%s) (%i - pc: %08x -> %i - pc: %08x)",
u64 nowCycles = CoreTiming::GetTicks();
s64 consumedCycles = nowCycles - lastSwitchCycles;
lastSwitchCycles = nowCycles;
DEBUG_LOG(HLE, "Context switch: %s -> %s (%i->%i, pc: %08x->%08x, %s) +%lldus",
oldName, hleCurrentThreadName,
oldUID, currentThread,
oldPC, currentMIPS->pc,
reason,
oldUID, oldPC, currentThread, currentMIPS->pc);
cyclesToUs(consumedCycles));
}
#endif
if (target)
{
+4 -3
View File
@@ -29,8 +29,8 @@ int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32
int sceKernelCreateThread(const char *threadName, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr);
int sceKernelDelayThread(u32 usec);
int sceKernelDelayThreadCB(u32 usec);
void sceKernelDelaySysClockThread();
void sceKernelDelaySysClockThreadCB();
int sceKernelDelaySysClockThread(u32 sysclockAddr);
int sceKernelDelaySysClockThreadCB(u32 sysclockAddr);
int sceKernelDeleteThread(int threadHandle);
void sceKernelExitDeleteThread(int exitStatus);
void sceKernelExitThread(int exitStatus);
@@ -67,7 +67,7 @@ struct SceKernelSysClock {
};
// TODO: Map these to PSP wait types.
// TODO: Map these to PSP wait types. Most of these are wrong.
// remember to update the waitTypeNames array in sceKernelThread.cpp when changing these
enum WaitType
{
@@ -93,6 +93,7 @@ enum WaitType
WAITTYPE_MODULE = 19,
WAITTYPE_HLEDELAY = 20,
WAITTYPE_TLS = 21,
WAITTYPE_VMEM = 22,
NUM_WAITTYPES
};
+68 -15
View File
@@ -301,18 +301,71 @@ int sceNetAdhocTerm() {
return 0;
}
// Homebrew SDK claims it's a void function, but tests seem to indicate otherwise
int sceNetEtherNtostr(const char *mac, u32 bufferPtr) {
DEBUG_LOG(HLE, "UNTESTED sceNetEtherNtostr(%s, %x)", mac, bufferPtr);
if(Memory::IsValidAddress(bufferPtr)) {
int len = (int)strlen(mac);
for (int i = 0; i < len; i++)
Memory::Write_U8(mac[i], bufferPtr + i);
}
else
ERROR_LOG(HLE, "UNTESTED sceNetEtherNtostr(%s, %x): Tried to write to an invalid pointer", mac, bufferPtr);
// Probably a void function, but often returns a useful value.
int sceNetEtherNtostr(u32 macPtr, u32 bufferPtr) {
DEBUG_LOG(HLE, "sceNetEtherNtostr(%08x, %08x)", macPtr, bufferPtr);
return 0;
if (Memory::IsValidAddress(bufferPtr) && Memory::IsValidAddress(macPtr)) {
char *buffer = (char *)Memory::GetPointer(bufferPtr);
const u8 *mac = Memory::GetPointer(macPtr);
// MAC address is always 6 bytes / 48 bits.
return sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
} else {
// Possibly a void function, seems to return this on bad args.
return 0x09d40000;
}
}
static int hex_to_digit(int c) {
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}
// Probably a void function, but sometimes returns a useful-ish value.
int sceNetEtherStrton(u32 bufferPtr, u32 macPtr) {
DEBUG_LOG(HLE, "sceNetEtherStrton(%08x, %08x)", bufferPtr, macPtr);
if (Memory::IsValidAddress(bufferPtr) && Memory::IsValidAddress(macPtr)) {
const char *buffer = (char *)Memory::GetPointer(bufferPtr);
u8 *mac = Memory::GetPointer(macPtr);
// MAC address is always 6 pairs of hex digits.
// TODO: Funny stuff happens if it's too short.
u8 value = 0;
for (int i = 0; i < 6 && *buffer != 0; ++i) {
value = 0;
int c = hex_to_digit(*buffer++);
if (c != -1) {
value |= c << 4;
}
c = hex_to_digit(*buffer++);
if (c != -1) {
value |= c;
}
*mac++ = value;
// Skip a single character in between.
// TODO: Strange behavior on the PSP, let's just null check.
if (*buffer++ == 0) {
break;
}
}
// Seems to maybe kinda return the last value. Probably returns void.
return value;
} else {
// Possibly a void function, seems to return this on bad args (or crash.)
return 0;
}
}
// Seems to always return 0, and write 0 to the pointer..
@@ -534,10 +587,10 @@ int sceNetInetConnect(int socket, u32 sockAddrInternetPtr, int addressLength) {
const HLEFunction sceNet[] = {
{0x39AF39A6, sceNetInit, "sceNetInit"},
{0x281928A9, WrapU_V<sceNetTerm>, "sceNetTerm"},
{0x89360950, WrapI_CU<sceNetEtherNtostr>, "sceNetEtherNtostr"},
{0x0bf0a3ae, 0, "sceNetGetLocalEtherAddr"},
{0xd27961c9, 0, "sceNetEtherStrton"},
{0x50647530, 0, "sceNetFreeThreadinfo"},
{0x89360950, WrapI_UU<sceNetEtherNtostr>, "sceNetEtherNtostr"},
{0xd27961c9, WrapI_UU<sceNetEtherStrton>, "sceNetEtherStrton"},
{0x0bf0a3ae, 0, "sceNetGetLocalEtherAddr"},
{0x50647530, 0, "sceNetFreeThreadinfo"},
{0xcc393e48, WrapI_U<sceNetGetMallocStat>, "sceNetGetMallocStat"},
{0xad6844c6, 0, "sceNetThreadAbort"},
};
+94 -27
View File
@@ -15,6 +15,7 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <map>
#include <vector>
#include "Common/ChunkFile.h"
#include "Core/HLE/HLE.h"
#include "Core/CoreTiming.h"
@@ -24,6 +25,12 @@
#include "Core/HLE/scePower.h"
#include "Core/HLE/sceKernelThread.h"
struct VolatileWaitingThread {
SceUID threadID;
u32 addrPtr;
u32 sizePtr;
};
const int PSP_POWER_ERROR_TAKEN_SLOT = 0x80000020;
const int PSP_POWER_ERROR_SLOTS_FULL = 0x80000022;
const int PSP_POWER_ERROR_PRIVATE_SLOT = 0x80000023;
@@ -45,6 +52,7 @@ const int numberOfCBPowerSlotsPrivate = 32;
static bool volatileMemLocked;
static int powerCbSlots[numberOfCBPowerSlots];
static std::vector<VolatileWaitingThread> volatileWaitingThreads;
// this should belong here on in CoreTiming?
static int pllFreq = 222;
@@ -53,6 +61,7 @@ static int busFreq = 111;
void __PowerInit() {
memset(powerCbSlots, 0, sizeof(powerCbSlots));
volatileMemLocked = false;
volatileWaitingThreads.clear();
if(g_Config.iLockedCPUSpeed > 0) {
CoreTiming::SetClockFrequencyMHz(g_Config.iLockedCPUSpeed);
@@ -64,6 +73,7 @@ void __PowerInit() {
void __PowerDoState(PointerWrap &p) {
p.DoArray(powerCbSlots, ARRAY_SIZE(powerCbSlots));
p.Do(volatileMemLocked);
p.Do(volatileWaitingThreads);
p.DoMarker("scePower");
}
@@ -199,12 +209,11 @@ int sceKernelPowerTick(int flag) {
#define ERROR_POWER_VMEM_IN_USE 0x802b0200
int sceKernelVolatileMemTryLock(int type, int paddr, int psize) {
if (!volatileMemLocked) {
INFO_LOG(HLE,"sceKernelVolatileMemTryLock(%i, %08x, %i) - success", type, paddr, psize);
volatileMemLocked = true;
} else {
ERROR_LOG_REPORT(HLE, "sceKernelVolatileMemTryLock(%i, %08x, %i) - already locked!", type, paddr, psize);
int __KernelVolatileMemLock(int type, u32 paddr, u32 psize) {
if (type != 0) {
return SCE_KERNEL_ERROR_INVALID_MODE;
}
if (volatileMemLocked) {
return ERROR_POWER_VMEM_IN_USE;
}
@@ -213,22 +222,89 @@ int sceKernelVolatileMemTryLock(int type, int paddr, int psize) {
// TODO: Should really reserve this properly!
Memory::Write_U32(0x08400000, paddr);
Memory::Write_U32(0x00400000, psize);
volatileMemLocked = true;
return 0;
}
int sceKernelVolatileMemTryLock(int type, u32 paddr, u32 psize) {
u32 error = __KernelVolatileMemLock(type, paddr, psize);
switch (error) {
case 0:
INFO_LOG(HLE, "sceKernelVolatileMemTryLock(%i, %08x, %08x) - success", type, paddr, psize);
break;
case ERROR_POWER_VMEM_IN_USE:
ERROR_LOG(HLE, "sceKernelVolatileMemTryLock(%i, %08x, %08x) - already locked!", type, paddr, psize);
break;
default:
ERROR_LOG_REPORT(HLE, "%08x=sceKernelVolatileMemTryLock(%i, %08x, %08x) - error", type, paddr, psize, error);
break;
}
return error;
}
int sceKernelVolatileMemUnlock(int type) {
if (type != 0) {
ERROR_LOG_REPORT(HLE, "sceKernelVolatileMemUnlock(%i) - invalid mode", type);
return SCE_KERNEL_ERROR_INVALID_MODE;
}
if (volatileMemLocked) {
INFO_LOG(HLE,"sceKernelVolatileMemUnlock(%i)", type);
volatileMemLocked = false;
// Wake someone, always fifo.
bool wokeThreads = false;
u32 error;
while (!volatileWaitingThreads.empty() && !volatileMemLocked) {
VolatileWaitingThread waitInfo = volatileWaitingThreads.front();
volatileWaitingThreads.erase(volatileWaitingThreads.begin());
int waitID = __KernelGetWaitID(waitInfo.threadID, WAITTYPE_VMEM, error);
// If they were force-released, just skip.
if (waitID == 1 && __KernelVolatileMemLock(0, waitInfo.addrPtr, waitInfo.sizePtr) == 0) {
__KernelResumeThreadFromWait(waitInfo.threadID, 0);
wokeThreads = true;
}
}
if (wokeThreads) {
INFO_LOG(HLE, "sceKernelVolatileMemUnlock(%i) handed over to another thread", type);
hleReSchedule("volatile mem unlocked");
} else {
INFO_LOG(HLE, "sceKernelVolatileMemUnlock(%i)", type);
}
} else {
ERROR_LOG_REPORT(HLE, "sceKernelVolatileMemUnlock(%i) FAILED - not locked", type);
}
return 0;
}
int sceKernelVolatileMemLock(int type, int paddr, int psize) {
return sceKernelVolatileMemTryLock(type, paddr, psize);
int sceKernelVolatileMemLock(int type, u32 paddr, u32 psize) {
u32 error = __KernelVolatileMemLock(type, paddr, psize);
switch (error) {
case 0:
INFO_LOG(HLE, "sceKernelVolatileMemLock(%i, %08x, %08x) - success", type, paddr, psize);
break;
case ERROR_POWER_VMEM_IN_USE:
{
WARN_LOG(HLE, "sceKernelVolatileMemLock(%i, %08x, %08x) - already locked, waiting", type, paddr, psize);
const VolatileWaitingThread waitInfo = { __KernelGetCurThread(), paddr, psize };
volatileWaitingThreads.push_back(waitInfo);
__KernelWaitCurThread(WAITTYPE_VMEM, 1, 0, 0, false, "volatile mem waited");
}
break;
default:
ERROR_LOG_REPORT(HLE, "%08x=sceKernelVolatileMemLock(%i, %08x, %08x) - error", type, paddr, psize, error);
break;
}
return error;
}
@@ -267,17 +343,6 @@ u32 scePowerSetBusClockFrequency(u32 busfreq) {
return 0;
}
u32 scePowerGetCpuClockFrequency() {
int cpuFreq = CoreTiming::GetClockFrequencyMHz();
DEBUG_LOG(HLE,"%i=scePowerGetCpuClockFrequency()", cpuFreq);
return cpuFreq;
}
u32 scePowerGetBusClockFrequency() {
INFO_LOG(HLE,"%i=scePowerGetBusClockFrequency()", busFreq);
return busFreq;
}
u32 scePowerGetCpuClockFrequencyInt() {
int cpuFreq = CoreTiming::GetClockFrequencyMHz();
DEBUG_LOG(HLE,"%i=scePowerGetCpuClockFrequencyInt()", cpuFreq);
@@ -361,8 +426,8 @@ static const HLEFunction scePower[] = {
{0xDB9D28DD,WrapI_I<scePowerUnregisterCallback>,"scePowerUnregitserCallback"},
{0x843FBF43,WrapU_U<scePowerSetCpuClockFrequency>,"scePowerSetCpuClockFrequency"},
{0xB8D7B3FB,WrapU_U<scePowerSetBusClockFrequency>,"scePowerSetBusClockFrequency"},
{0xFEE03A2F,WrapU_V<scePowerGetCpuClockFrequency>,"scePowerGetCpuClockFrequency"},
{0x478FE6F5,WrapU_V<scePowerGetBusClockFrequency>,"scePowerGetBusClockFrequency"},
{0xFEE03A2F,WrapU_V<scePowerGetCpuClockFrequencyInt>,"scePowerGetCpuClockFrequency"},
{0x478FE6F5,WrapU_V<scePowerGetBusClockFrequencyInt>,"scePowerGetBusClockFrequency"},
{0xFDB5BFE9,WrapU_V<scePowerGetCpuClockFrequencyInt>,"scePowerGetCpuClockFrequencyInt"},
{0xBD681969,WrapU_V<scePowerGetBusClockFrequencyInt>,"scePowerGetBusClockFrequencyInt"},
{0xB1A52C83,WrapF_V<scePowerGetCpuClockFrequencyFloat>,"scePowerGetCpuClockFrequencyFloat"},
@@ -379,9 +444,11 @@ static const HLEFunction scePower[] = {
{0x0442d852,0,"scePowerRequestColdReset"},
{0xbafa3df0,0,"scePowerGetCallbackMode"},
{0xa9d22232,0,"scePowerSetCallbackMode"},
{0x23c31ffe,0,"scePowerVolatileMemLock"},
{0xfa97a599,0,"scePowerVolatileMemTryLock"},
{0xb3edd801,0,"scePowerVolatileMemUnlock"},
// These seem to be aliases.
{0x23c31ffe,&WrapI_IUU<sceKernelVolatileMemLock>,"scePowerVolatileMemLock", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0xfa97a599,&WrapI_IUU<sceKernelVolatileMemTryLock>,"scePowerVolatileMemTryLock"},
{0xb3edd801,&WrapI_I<sceKernelVolatileMemUnlock>,"scePowerVolatileMemUnlock"},
};
//890129c in tyshooter looks bogus
@@ -392,9 +459,9 @@ const HLEFunction sceSuspendForUser[] = {
// There's an extra 4MB that can be allocated, which seems to be "volatile". These functions
// let you grab it.
{0xa14f40b2,&WrapI_III<sceKernelVolatileMemTryLock>,"sceKernelVolatileMemTryLock"},
{0xa14f40b2,&WrapI_IUU<sceKernelVolatileMemTryLock>,"sceKernelVolatileMemTryLock"},
{0xa569e425,&WrapI_I<sceKernelVolatileMemUnlock>,"sceKernelVolatileMemUnlock"},
{0x3e0271d3,&WrapI_III<sceKernelVolatileMemLock>,"sceKernelVolatileMemLock"}, //when "acquiring mem pool" (fired up)
{0x3e0271d3,&WrapI_IUU<sceKernelVolatileMemLock>,"sceKernelVolatileMemLock", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED}, //when "acquiring mem pool" (fired up)
};
+9
View File
@@ -256,6 +256,15 @@ u32 sceSasSetPitch(u32 core, int voiceNum, int pitch) {
}
SasVoice &v = sas->voices[voiceNum];
// Clamp pitch
if (pitch < PSP_SAS_PITCH_MIN) {
WARN_LOG(SAS, "bad pitch %i, clamping to %i", pitch, PSP_SAS_PITCH_MIN);
pitch = PSP_SAS_PITCH_MIN;
} else if (pitch > PSP_SAS_PITCH_MAX) {
WARN_LOG(SAS, "bad pitch %i, clamping to %i", pitch, PSP_SAS_PITCH_MAX);
pitch = PSP_SAS_PITCH_MAX;
}
v.pitch = pitch;
v.ChangedParams(false);
return 0;
+65 -17
View File
@@ -15,12 +15,13 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "HLE.h"
#include "../MIPS/MIPS.h"
#include "Common/ChunkFile.h"
#include "Core/HLE/HLE.h"
#include "Core/MIPS/MIPS.h"
#include "Core/CoreTiming.h"
#include "ChunkFile.h"
#include "sceUmd.h"
#include "sceKernelThread.h"
#include "Core/HLE/sceUmd.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernelInterrupt.h"
const u64 MICRO_DELAY_ACTIVATE = 4000;
@@ -270,51 +271,98 @@ void __UmdWaitStat(u32 timeout)
*/
int sceUmdWaitDriveStat(u32 stat)
{
DEBUG_LOG(HLE,"0=sceUmdWaitDriveStat(stat = %08x)", stat);
if ((stat & __KernelUmdGetState()) == 0) {
umdWaitingThreads.push_back(UmdWaitingThread::Make(__KernelGetCurThread(), stat));
__KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, 0, "umd stat waited");
if (stat == 0) {
DEBUG_LOG(HLE, "sceUmdWaitDriveStat(stat = %08x): bad status", stat);
return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
}
if (!__KernelIsDispatchEnabled()) {
DEBUG_LOG(HLE, "sceUmdWaitDriveStat(stat = %08x): dispatch disabled", stat);
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
}
if (__IsInInterrupt()) {
DEBUG_LOG(HLE, "sceUmdWaitDriveStat(stat = %08x): inside interrupt", stat);
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
}
if ((stat & __KernelUmdGetState()) == 0) {
DEBUG_LOG(HLE, "sceUmdWaitDriveStat(stat = %08x): waiting", stat);
umdWaitingThreads.push_back(UmdWaitingThread::Make(__KernelGetCurThread(), stat));
__KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, 0, "umd stat waited");
return 0;
}
DEBUG_LOG(HLE, "0=sceUmdWaitDriveStat(stat = %08x)", stat);
return 0;
}
int sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout)
{
DEBUG_LOG(HLE,"0=sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d)", stat, timeout);
if (stat == 0) {
DEBUG_LOG(HLE, "sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d): bad status", stat, timeout);
return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
}
if (!__KernelIsDispatchEnabled()) {
DEBUG_LOG(HLE, "sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d): dispatch disabled", stat, timeout);
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
}
if (__IsInInterrupt()) {
DEBUG_LOG(HLE, "sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d): inside interrupt", stat, timeout);
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
}
if ((stat & __KernelUmdGetState()) == 0) {
DEBUG_LOG(HLE, "sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d): waiting", stat, timeout);
__UmdWaitStat(timeout);
umdWaitingThreads.push_back(UmdWaitingThread::Make(__KernelGetCurThread(), stat));
__KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, 0, "umd stat waited with timer");
} else
hleReSchedule("umd stat waited with timer");
return 0;
} else {
hleReSchedule("umd stat checked");
}
DEBUG_LOG(HLE, "0=sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d)", stat, timeout);
return 0;
}
int sceUmdWaitDriveStatCB(u32 stat, u32 timeout)
{
DEBUG_LOG(HLE,"0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d)", stat, timeout);
if (stat == 0) {
DEBUG_LOG(HLE, "sceUmdWaitDriveStatCB(stat = %08x, timeout = %d): bad status", stat, timeout);
return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
}
if (!__KernelIsDispatchEnabled()) {
DEBUG_LOG(HLE, "sceUmdWaitDriveStatCB(stat = %08x, timeout = %d): dispatch disabled", stat, timeout);
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
}
if (__IsInInterrupt()) {
DEBUG_LOG(HLE, "sceUmdWaitDriveStatCB(stat = %08x, timeout = %d): inside interrupt", stat, timeout);
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
}
hleCheckCurrentCallbacks();
if ((stat & __KernelUmdGetState()) == 0) {
if (timeout == 0)
DEBUG_LOG(HLE, "0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d): waiting", stat, timeout);
if (timeout == 0) {
timeout = 8000;
}
__UmdWaitStat(timeout);
umdWaitingThreads.push_back(UmdWaitingThread::Make(__KernelGetCurThread(), stat));
__KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, true, "umd stat waited");
} else
} else {
hleReSchedule("umd stat waited");
}
DEBUG_LOG(HLE, "0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d)", stat, timeout);
return 0;
}
u32 sceUmdCancelWaitDriveStat()
{
DEBUG_LOG(HLE,"0=sceUmdCancelWaitDriveStat()");
DEBUG_LOG(HLE, "0=sceUmdCancelWaitDriveStat()");
__KernelTriggerWait(WAITTYPE_UMD, 1, SCE_KERNEL_ERROR_WAIT_CANCEL, "umd stat ready", true);
// TODO: We should call UnscheduleEvent() event here?
+94 -14
View File
@@ -43,6 +43,8 @@ enum UtilityDialogType {
UTILITY_DIALOG_MSG,
UTILITY_DIALOG_OSK,
UTILITY_DIALOG_NET,
UTILITY_DIALOG_SCREENSHOT,
UTILITY_DIALOG_GAMESHARING,
};
// Only a single dialog is allowed at a time.
@@ -384,33 +386,60 @@ int sceUtilityNetconfGetStatus()
//but it requires more investigation
u32 sceUtilityScreenshotInitStart(u32 unknown1, u32 unknown2, u32 unknown3, u32 unknown4, u32 unknown5, u32 unknown6)
{
if (currentDialogActive && currentDialogType != UTILITY_DIALOG_SCREENSHOT)
{
WARN_LOG(HLE, "sceUtilityScreenshotInitStart(%x, %x, %x, %x, %x, %x): wrong dialog type", unknown1, unknown2, unknown3, unknown4, unknown5, unknown6);
return SCE_ERROR_UTILITY_WRONG_TYPE;
}
currentDialogType = UTILITY_DIALOG_SCREENSHOT;
currentDialogActive = true;
u32 retval = screenshotDialog.Init();
WARN_LOG(HLE, "UNIMPL %i=sceUtilityScreenshotInitStart(%x, %x, %x, %x, %x, %x)", retval, unknown1, unknown2, unknown3, unknown4, unknown5, unknown6);
WARN_LOG_REPORT(HLE, "UNIMPL %i=sceUtilityScreenshotInitStart(%x, %x, %x, %x, %x, %x)", retval, unknown1, unknown2, unknown3, unknown4, unknown5, unknown6);
return retval;
}
u32 sceUtilityScreenshotShutdownStart()
{
if (currentDialogType != UTILITY_DIALOG_SCREENSHOT)
{
WARN_LOG(HLE, "sceUtilityScreenshotShutdownStart(): wrong dialog type");
return SCE_ERROR_UTILITY_WRONG_TYPE;
}
currentDialogActive = false;
WARN_LOG(HLE, "UNTESTED sceUtilityScreenshotShutdownStart()");
return screenshotDialog.Shutdown();
}
u32 sceUtilityScreenshotUpdate(u32 unknown)
{
if (currentDialogType != UTILITY_DIALOG_SCREENSHOT)
{
WARN_LOG(HLE, "sceUtilityScreenshotUpdate(): wrong dialog type");
return SCE_ERROR_UTILITY_WRONG_TYPE;
}
ERROR_LOG(HLE, "UNIMPL sceUtilityScreenshotUpdate(%d)", unknown);
return screenshotDialog.Update();
}
int sceUtilityScreenshotGetStatus()
{
if (currentDialogType != UTILITY_DIALOG_SCREENSHOT)
{
DEBUG_LOG(HLE, "sceUtilityScreenshotGetStatus(): wrong dialog type");
return SCE_ERROR_UTILITY_WRONG_TYPE;
}
u32 retval = screenshotDialog.GetStatus();
WARN_LOG(HLE, "UNIMPL %i=sceUtilityScreenshotGetStatus()", retval);
return retval;
}
void sceUtilityGamedataInstallInitStart(u32 unkown)
void sceUtilityGamedataInstallInitStart(u32 unknown)
{
ERROR_LOG_REPORT(HLE, "UNIMPL sceUtilityGamedataInstallInitStart(%i)", unkown);
ERROR_LOG_REPORT(HLE, "UNIMPL sceUtilityGamedataInstallInitStart(%i)", unknown);
}
int sceUtilityGamedataInstallGetStatus()
@@ -423,7 +452,7 @@ int sceUtilityGamedataInstallGetStatus()
//TODO: should save to config file
u32 sceUtilitySetSystemParamString(u32 id, u32 strPtr)
{
WARN_LOG(HLE, "sceUtilitySetSystemParamString(%i, %08x)", id, strPtr);
WARN_LOG_REPORT(HLE, "sceUtilitySetSystemParamString(%i, %08x)", id, strPtr);
return 0;
}
@@ -459,15 +488,19 @@ u32 sceUtilityGetSystemParamInt(u32 id, u32 destaddr)
break;
case PSP_SYSTEMPARAM_ID_INT_DATE_FORMAT:
param = g_Config.iDateFormat;
INFO_LOG_REPORT(HLE, "sceUtilitySystemGetSystemParamInt: %s", "Date Format")
break;
case PSP_SYSTEMPARAM_ID_INT_TIME_FORMAT:
param = g_Config.iTimeFormat?PSP_SYSTEMPARAM_TIME_FORMAT_12HR:PSP_SYSTEMPARAM_TIME_FORMAT_24HR;
INFO_LOG_REPORT(HLE, "sceUtilitySystemGetSystemParamInt: %s", "Time Format")
break;
case PSP_SYSTEMPARAM_ID_INT_TIMEZONE:
param = g_Config.iTimeZone;
INFO_LOG_REPORT(HLE, "sceUtilitySystemGetSystemParamInt: %s", "Timezone")
break;
case PSP_SYSTEMPARAM_ID_INT_DAYLIGHTSAVINGS:
param = g_Config.bDayLightSavings?PSP_SYSTEMPARAM_DAYLIGHTSAVINGS_SAVING:PSP_SYSTEMPARAM_DAYLIGHTSAVINGS_STD;
INFO_LOG_REPORT(HLE, "sceUtilitySystemGetSystemParamInt: %s", "Daylight Savings");
break;
case PSP_SYSTEMPARAM_ID_INT_LANGUAGE:
param = g_Config.ilanguage;
@@ -477,6 +510,7 @@ u32 sceUtilityGetSystemParamInt(u32 id, u32 destaddr)
break;
case PSP_SYSTEMPARAM_ID_INT_LOCK_PARENTAL_LEVEL:
param = g_Config.iLockParentalLevel;
INFO_LOG_REPORT(HLE, "sceUtilitySystemGetSystemParamInt: %s", "Lock Parental Level");
break;
default:
return PSP_SYSTEMPARAM_RETVAL_FAIL;
@@ -501,7 +535,7 @@ u32 sceUtilityUnloadNetModule(u32 module)
void sceUtilityInstallInitStart(u32 unknown)
{
DEBUG_LOG(HLE,"FAKE sceUtilityInstallInitStart()");
WARN_LOG_REPORT(HLE, "UNIMPL sceUtilityInstallInitStart()");
}
int sceUtilityStoreCheckoutShutdownStart()
@@ -528,6 +562,57 @@ int sceUtilityStoreCheckoutGetStatus()
return 0;
}
int sceUtilityGameSharingShutdownStart()
{
if (currentDialogType != UTILITY_DIALOG_GAMESHARING)
{
WARN_LOG(HLE, "sceUtilityGameSharingShutdownStart(): wrong dialog type");
return SCE_ERROR_UTILITY_WRONG_TYPE;
}
currentDialogActive = false;
ERROR_LOG(HLE, "UNIMPL sceUtilityGameSharingShutdownStart()");
return 0;
}
int sceUtilityGameSharingInitStart(u32 paramsPtr)
{
if (currentDialogActive && currentDialogType != UTILITY_DIALOG_GAMESHARING)
{
WARN_LOG(HLE, "sceUtilityGameSharingInitStart(%08x)", paramsPtr);
return SCE_ERROR_UTILITY_WRONG_TYPE;
}
currentDialogType = UTILITY_DIALOG_GAMESHARING;
currentDialogActive = true;
ERROR_LOG_REPORT(HLE, "UNIMPL sceUtilityGameSharingInitStart(%08x)", paramsPtr);
return 0;
}
int sceUtilityGameSharingUpdate(int drawSpeed)
{
if (currentDialogType != UTILITY_DIALOG_GAMESHARING)
{
WARN_LOG(HLE, "sceUtilityScreenshotUpdate(): wrong dialog type");
return SCE_ERROR_UTILITY_WRONG_TYPE;
}
ERROR_LOG(HLE, "UNIMPL sceUtilityGameSharingUpdate(%d)", drawSpeed);
return 0;
}
int sceUtilityGameSharingGetStatus()
{
if (currentDialogType != UTILITY_DIALOG_GAMESHARING)
{
DEBUG_LOG(HLE, "sceUtilityGameSharingGetStatus(): wrong dialog type");
return SCE_ERROR_UTILITY_WRONG_TYPE;
}
ERROR_LOG(HLE, "UNIMPL sceUtilityGameSharingGetStatus()");
return 0;
}
const HLEFunction sceUtility[] =
{
{0x1579a159, &WrapU_U<sceUtilityLoadNetModule>, "sceUtilityLoadNetModule"},
@@ -564,10 +649,10 @@ const HLEFunction sceUtility[] =
{0xA5DA2406, &WrapU_UU<sceUtilityGetSystemParamInt>, "sceUtilityGetSystemParamInt"},
{0xc492f751, 0, "sceUtilityGameSharingInitStart"},
{0xefc6f80f, 0, "sceUtilityGameSharingShutdownStart"},
{0x7853182d, 0, "sceUtilityGameSharingUpdate"},
{0x946963f3, 0, "sceUtilityGameSharingGetStatus"},
{0xc492f751, &WrapI_U<sceUtilityGameSharingInitStart>, "sceUtilityGameSharingInitStart"},
{0xefc6f80f, &WrapI_V<sceUtilityGameSharingShutdownStart>, "sceUtilityGameSharingShutdownStart"},
{0x7853182d, &WrapI_I<sceUtilityGameSharingUpdate>, "sceUtilityGameSharingUpdate"},
{0x946963f3, &WrapI_V<sceUtilityGameSharingGetStatus>, "sceUtilityGameSharingGetStatus"},
{0x2995d020, 0, "sceUtilitySavedataErrInitStart"},
{0xb62a4061, 0, "sceUtilitySavedataErrShutdownStart"},
@@ -662,12 +747,7 @@ const HLEFunction sceUtility[] =
{0xb6cee597, 0, "sceNetplayDialogGetStatus"},
{0x28d35634, 0, "sceUtility_28D35634"},
{0x6f56f9cf, 0, "sceUtility_6F56F9CF"},
{0x70267adf, 0, "sceUtility_70267ADF"},
{0x81c44706, 0, "sceUtility_81C44706"},
{0x8326ab05, 0, "sceUtility_8326AB05"},
{0xb0fb7ff5, 0, "sceUtility_B0fB7FF5"},
{0xe7b778d8, 0, "sceUtility_E7B778D8"},
{0xece1d3e5, 0, "sceUtility_ECE1D3E5"},
{0xef3582b2, 0, "sceUtility_EF3582B2"},
+8 -2
View File
@@ -15,8 +15,9 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "MediaEngine.h"
#include "../MemMap.h"
#include "Core/HW/MediaEngine.h"
#include "Core/MemMap.h"
#include "Core/Reporting.h"
#include "GPU/GPUInterface.h"
#include "Core/HW/atrac3plus.h"
@@ -221,6 +222,11 @@ bool MediaEngine::openContext() {
if(avformat_find_stream_info(m_pFormatCtx, NULL) < 0)
return false;
if (m_videoStream >= (int)m_pFormatCtx->nb_streams) {
WARN_LOG_REPORT(ME, "Bad video stream %d", m_videoStream);
m_videoStream = -1;
}
if (m_videoStream == -1) {
// Find the first video stream
for(int i = 0; i < (int)m_pFormatCtx->nb_streams; i++) {
+1 -1
View File
@@ -250,7 +250,7 @@ static int getReleaseRate(int bitfield2) {
if (getReleaseType(bitfield2) == PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE) {
return (0x40000000 >> (n + 2));
}
return (0x08000000 >> n);
return (0x40000000 >> n);
}
static int getSustainLevel(int bitfield1) {
+5 -4
View File
@@ -21,16 +21,14 @@
struct InputState;
class PMixer
{
class PMixer {
public:
PMixer() {}
virtual ~PMixer() {}
virtual int Mix(short *stereoout, int numSamples) {memset(stereoout,0,numSamples*2*sizeof(short)); return numSamples;}
};
class Host
{
class Host {
public:
virtual ~Host() {}
//virtual void StartThread()
@@ -64,10 +62,13 @@ public:
virtual void SendGPUWait(u32 cmd, u32 addr, void* data) {}
virtual void SetGPUStep(bool value, int flag = 0, int data = 0) {}
virtual void NextGPUStep() {}
virtual bool CanCreateShortcut() {return false;}
virtual bool CreateDesktopShortcut(std::string argumentPath, std::string title) {return false;}
#ifdef _WIN32
// Implement this on your platform to grab text input from the user for whatever purpose.
virtual bool InputBoxGetString(char *title, const char *defaultValue, char *outValue, size_t outlength) { return false; }
virtual bool InputBoxGetWString(const wchar_t *title, const std::wstring &defaultvalue, std::wstring &outvalue) { return false; }
#endif
// Used for headless.
+10 -1
View File
@@ -16,6 +16,7 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "file/file_util.h"
#include "Common/FileUtil.h"
#include "MIPS/MIPS.h"
#include "MIPS/MIPSCodeUtils.h"
@@ -71,7 +72,7 @@ IdentifiedFileType Identify_File(std::string &filename)
return FILETYPE_NORMAL_DIRECTORY;
}
FILE *f = fopen(filename.c_str(), "rb");
FILE *f = File::OpenCFile(filename.c_str(), "rb");
if (!f) {
// File does not exists
return FILETYPE_ERROR;
@@ -161,6 +162,13 @@ bool LoadFile(std::string &filename, std::string *error_string) {
if (fileInfo.exists) {
INFO_LOG(LOADER, "File is a PBP in a directory!");
std::string ebootPath = filename + "/EBOOT.PBP";
IdentifiedFileType ebootType = Identify_File(ebootPath);
if(ebootType == FILETYPE_PSP_ISO_NP) {
InitMemoryForGameISO(ebootPath);
pspFileSystem.SetStartingDirectory("disc0:/PSP_GAME/USRDIR");
return Load_PSP_ISO(filename.c_str(), error_string);
}
std::string path = filename;
size_t pos = path.find("/PSP/GAME/");
if (pos != std::string::npos)
@@ -212,6 +220,7 @@ bool LoadFile(std::string &filename, std::string *error_string) {
case FILETYPE_NORMAL_DIRECTORY:
ERROR_LOG(LOADER, "Just a directory.");
*error_string = "Just a directory.";
break;
case FILETYPE_UNKNOWN_BIN:
+40 -35
View File
@@ -15,19 +15,24 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "ArmJit.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Core/MIPS/ARM/ArmJit.h"
#include "Common/CPUDetect.h"
using namespace MIPSAnalyst;
#define _RS ((op>>21) & 0x1F)
#define _RT ((op>>16) & 0x1F)
#define _RD ((op>>11) & 0x1F)
#define _FS ((op>>11) & 0x1F)
#define _FT ((op>>16) & 0x1F)
#define _FD ((op>>6 ) & 0x1F)
#define _SA ((op>>6 ) & 0x1F)
#define _POS ((op>>6 ) & 0x1F)
#define _SIZE ((op>>11 ) & 0x1F)
#define _RS MIPS_GET_RS(op)
#define _RT MIPS_GET_RT(op)
#define _RD MIPS_GET_RD(op)
#define _FS MIPS_GET_FS(op)
#define _FT MIPS_GET_FT(op)
#define _FD MIPS_GET_FD(op)
#define _SA MIPS_GET_SA(op)
#define _POS ((op>> 6) & 0x1F)
#define _SIZE ((op>>11) & 0x1F)
#define _IMM16 (signed short)(op & 0xFFFF)
#define _IMM26 (op & 0x03FFFFFF)
// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly.
// Currently known non working ones should have DISABLE.
@@ -61,15 +66,15 @@ namespace MIPSComp
}
}
void Jit::Comp_IType(u32 op)
void Jit::Comp_IType(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
s32 simm = (s32)(s16)(op & 0xFFFF); // sign extension
u32 uimm = op & 0xFFFF;
u32 suimm = (u32)(s32)simm;
int rt = _RT;
int rs = _RS;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
// noop, won't write to ZERO.
if (rt == 0)
@@ -127,10 +132,10 @@ namespace MIPSComp
}
}
void Jit::Comp_RType2(u32 op)
void Jit::Comp_RType2(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int rs = _RS;
MIPSGPReg rs = _RS;
int rd = _RD;
// Don't change $zr.
@@ -180,11 +185,11 @@ namespace MIPSComp
}
}
void Jit::Comp_RType3(u32 op)
void Jit::Comp_RType3(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int rt = _RT;
int rs = _RS;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
int rd = _RD;
// noop, won't write to ZERO.
@@ -325,21 +330,21 @@ namespace MIPSComp
}
}
void Jit::CompShiftImm(u32 op, ArmGen::ShiftType shiftType)
void Jit::CompShiftImm(MIPSOpcode op, ArmGen::ShiftType shiftType)
{
int rd = _RD;
int rt = _RT;
MIPSGPReg rt = _RT;
int sa = _SA;
gpr.MapDirtyIn(rd, rt);
MOV(gpr.R(rd), Operand2(gpr.R(rt), shiftType, sa));
}
void Jit::CompShiftVar(u32 op, ArmGen::ShiftType shiftType)
void Jit::CompShiftVar(MIPSOpcode op, ArmGen::ShiftType shiftType)
{
int rd = _RD;
int rt = _RT;
int rs = _RS;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
if (gpr.IsImm(rs))
{
int sa = gpr.GetImm(rs) & 0x1F;
@@ -352,10 +357,10 @@ namespace MIPSComp
MOV(gpr.R(rd), Operand2(gpr.R(rt), shiftType, R0));
}
void Jit::Comp_ShiftType(u32 op)
void Jit::Comp_ShiftType(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int rs = _RS;
MIPSGPReg rs = _RS;
int rd = _RD;
int fd = _FD;
@@ -379,12 +384,12 @@ namespace MIPSComp
}
}
void Jit::Comp_Special3(u32 op)
void Jit::Comp_Special3(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int rs = _RS;
int rt = _RT;
MIPSGPReg rs = _RS;
MIPSGPReg rt = _RT;
int pos = _POS;
int size = _SIZE + 1;
@@ -447,10 +452,10 @@ namespace MIPSComp
}
}
void Jit::Comp_Allegrex(u32 op)
void Jit::Comp_Allegrex(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int rt = _RT;
MIPSGPReg rt = _RT;
int rd = _RD;
// Don't change $zr.
if (rd == 0)
@@ -505,10 +510,10 @@ namespace MIPSComp
}
}
void Jit::Comp_Allegrex2(u32 op)
void Jit::Comp_Allegrex2(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int rt = _RT;
MIPSGPReg rt = _RT;
int rd = _RD;
// Don't change $zr.
if (rd == 0)
@@ -538,11 +543,11 @@ namespace MIPSComp
}
}
void Jit::Comp_MulDivType(u32 op)
void Jit::Comp_MulDivType(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int rt = _RT;
int rs = _RS;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
int rd = _RD;
switch (op & 63)
+32 -31
View File
@@ -31,15 +31,16 @@
#include "Common/ArmEmitter.h"
#define _RS ((op>>21) & 0x1F)
#define _RT ((op>>16) & 0x1F)
#define _RD ((op>>11) & 0x1F)
#define _FS ((op>>11) & 0x1F)
#define _FT ((op>>16) & 0x1F)
#define _FD ((op>>6 ) & 0x1F)
#define _POS ((op>>6 ) & 0x1F)
#define _SIZE ((op>>11 ) & 0x1F)
#define _IMM16 (signed short)(op&0xFFFF)
#define _RS MIPS_GET_RS(op)
#define _RT MIPS_GET_RT(op)
#define _RD MIPS_GET_RD(op)
#define _FS MIPS_GET_FS(op)
#define _FT MIPS_GET_FT(op)
#define _FD MIPS_GET_FD(op)
#define _SA MIPS_GET_SA(op)
#define _POS ((op>> 6) & 0x1F)
#define _SIZE ((op>>11) & 0x1F)
#define _IMM16 (signed short)(op & 0xFFFF)
#define _IMM26 (op & 0x03FFFFFF)
#define LOOPOPTIMIZATION 0
@@ -53,18 +54,18 @@ using namespace MIPSAnalyst;
namespace MIPSComp
{
void Jit::BranchRSRTComp(u32 op, ArmGen::CCFlags cc, bool likely)
void Jit::BranchRSRTComp(MIPSOpcode op, ArmGen::CCFlags cc, bool likely)
{
if (js.inDelaySlot) {
ERROR_LOG_REPORT(JIT, "Branch in RSRTComp delay slot at %08x in block starting at %08x", js.compilerPC, js.blockStart);
return;
}
int offset = _IMM16 << 2;
int rt = _RT;
int rs = _RS;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
u32 targetAddr = js.compilerPC + offset + 4;
u32 delaySlotOp = Memory::ReadUnchecked_U32(js.compilerPC+4);
MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC+4);
bool delaySlotIsNice = IsDelaySlotNiceReg(op, delaySlotOp, rt, rs);
CONDITIONAL_NICE_DELAYSLOT;
if (!likely && delaySlotIsNice)
@@ -113,17 +114,17 @@ void Jit::BranchRSRTComp(u32 op, ArmGen::CCFlags cc, bool likely)
}
void Jit::BranchRSZeroComp(u32 op, ArmGen::CCFlags cc, bool andLink, bool likely)
void Jit::BranchRSZeroComp(MIPSOpcode op, ArmGen::CCFlags cc, bool andLink, bool likely)
{
if (js.inDelaySlot) {
ERROR_LOG_REPORT(JIT, "Branch in RSZeroComp delay slot at %08x in block starting at %08x", js.compilerPC, js.blockStart);
return;
}
int offset = _IMM16 << 2;
int rs = _RS;
MIPSGPReg rs = _RS;
u32 targetAddr = js.compilerPC + offset + 4;
u32 delaySlotOp = Memory::ReadUnchecked_U32(js.compilerPC + 4);
MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4);
bool delaySlotIsNice = IsDelaySlotNiceReg(op, delaySlotOp, rs);
CONDITIONAL_NICE_DELAYSLOT;
if (!likely && delaySlotIsNice)
@@ -164,7 +165,7 @@ void Jit::BranchRSZeroComp(u32 op, ArmGen::CCFlags cc, bool andLink, bool likely
}
void Jit::Comp_RelBranch(u32 op)
void Jit::Comp_RelBranch(MIPSOpcode op)
{
// The CC flags here should be opposite of the actual branch becuase they skip the branching action.
switch (op>>26)
@@ -187,7 +188,7 @@ void Jit::Comp_RelBranch(u32 op)
}
}
void Jit::Comp_RelBranchRI(u32 op)
void Jit::Comp_RelBranchRI(MIPSOpcode op)
{
switch ((op >> 16) & 0x1F)
{
@@ -206,7 +207,7 @@ void Jit::Comp_RelBranchRI(u32 op)
}
// If likely is set, discard the branch slot if NOT taken.
void Jit::BranchFPFlag(u32 op, ArmGen::CCFlags cc, bool likely)
void Jit::BranchFPFlag(MIPSOpcode op, ArmGen::CCFlags cc, bool likely)
{
if (js.inDelaySlot) {
ERROR_LOG_REPORT(JIT, "Branch in FPFlag delay slot at %08x in block starting at %08x", js.compilerPC, js.blockStart);
@@ -215,7 +216,7 @@ void Jit::BranchFPFlag(u32 op, ArmGen::CCFlags cc, bool likely)
int offset = _IMM16 << 2;
u32 targetAddr = js.compilerPC + offset + 4;
u32 delaySlotOp = Memory::ReadUnchecked_U32(js.compilerPC + 4);
MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4);
bool delaySlotIsNice = IsDelaySlotNiceFPU(op, delaySlotOp);
CONDITIONAL_NICE_DELAYSLOT;
if (!likely && delaySlotIsNice)
@@ -249,7 +250,7 @@ void Jit::BranchFPFlag(u32 op, ArmGen::CCFlags cc, bool likely)
js.compiling = false;
}
void Jit::Comp_FPUBranch(u32 op)
void Jit::Comp_FPUBranch(MIPSOpcode op)
{
switch((op >> 16) & 0x1f)
{
@@ -264,7 +265,7 @@ void Jit::Comp_FPUBranch(u32 op)
}
// If likely is set, discard the branch slot if NOT taken.
void Jit::BranchVFPUFlag(u32 op, ArmGen::CCFlags cc, bool likely)
void Jit::BranchVFPUFlag(MIPSOpcode op, ArmGen::CCFlags cc, bool likely)
{
if (js.inDelaySlot) {
ERROR_LOG_REPORT(JIT, "Branch in VFPU delay slot at %08x in block starting at %08x", js.compilerPC, js.blockStart);
@@ -273,7 +274,7 @@ void Jit::BranchVFPUFlag(u32 op, ArmGen::CCFlags cc, bool likely)
int offset = _IMM16 << 2;
u32 targetAddr = js.compilerPC + offset + 4;
u32 delaySlotOp = Memory::ReadUnchecked_U32(js.compilerPC + 4);
MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4);
// Sometimes there's a VFPU branch in a delay slot (Disgaea 2: Dark Hero Days, Zettai Hero Project, La Pucelle)
// The behavior is undefined - the CPU may take the second branch even if the first one passes.
@@ -321,7 +322,7 @@ void Jit::BranchVFPUFlag(u32 op, ArmGen::CCFlags cc, bool likely)
js.compiling = false;
}
void Jit::Comp_VBranch(u32 op)
void Jit::Comp_VBranch(MIPSOpcode op)
{
switch ((op >> 16) & 3)
{
@@ -332,7 +333,7 @@ void Jit::Comp_VBranch(u32 op)
}
}
void Jit::Comp_Jump(u32 op)
void Jit::Comp_Jump(MIPSOpcode op)
{
if (js.inDelaySlot) {
ERROR_LOG_REPORT(JIT, "Branch in Jump delay slot at %08x in block starting at %08x", js.compilerPC, js.blockStart);
@@ -364,15 +365,15 @@ void Jit::Comp_Jump(u32 op)
js.compiling = false;
}
void Jit::Comp_JumpReg(u32 op)
void Jit::Comp_JumpReg(MIPSOpcode op)
{
if (js.inDelaySlot) {
ERROR_LOG_REPORT(JIT, "Branch in JumpReg delay slot at %08x in block starting at %08x", js.compilerPC, js.blockStart);
return;
}
int rs = _RS;
MIPSGPReg rs = _RS;
u32 delaySlotOp = Memory::ReadUnchecked_U32(js.compilerPC + 4);
MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4);
bool delaySlotIsNice = IsDelaySlotNiceReg(op, delaySlotOp, rs);
CONDITIONAL_NICE_DELAYSLOT;
@@ -413,7 +414,7 @@ void Jit::Comp_JumpReg(u32 op)
}
void Jit::Comp_Syscall(u32 op)
void Jit::Comp_Syscall(MIPSOpcode op)
{
FlushAll();
@@ -428,7 +429,7 @@ void Jit::Comp_Syscall(u32 op)
QuickCallFunction(R1, (void *)GetFunc("FakeSysCalls", NID_IDLE)->func);
else
{
MOVI2R(R0, op);
MOVI2R(R0, op.encoding);
QuickCallFunction(R1, (void *)&CallSyscall);
}
RestoreDowncount();
@@ -437,7 +438,7 @@ void Jit::Comp_Syscall(u32 op)
js.compiling = false;
}
void Jit::Comp_Break(u32 op)
void Jit::Comp_Break(MIPSOpcode op)
{
Comp_Generic(op);
WriteSyscallExit();
+22 -17
View File
@@ -14,21 +14,26 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Core/Config.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Core/MIPS/MIPSTables.h"
#include "ArmJit.h"
#include "ArmRegCache.h"
#include "Core/MIPS/ARM/ArmJit.h"
#include "Core/MIPS/ARM/ArmRegCache.h"
#define _RS ((op>>21) & 0x1F)
#define _RT ((op>>16) & 0x1F)
#define _RD ((op>>11) & 0x1F)
#define _FS ((op>>11) & 0x1F)
#define _FT ((op>>16) & 0x1F)
#define _FD ((op>>6 ) & 0x1F)
#define _POS ((op>>6 ) & 0x1F)
#define _RS MIPS_GET_RS(op)
#define _RT MIPS_GET_RT(op)
#define _RD MIPS_GET_RD(op)
#define _FS MIPS_GET_FS(op)
#define _FT MIPS_GET_FT(op)
#define _FD MIPS_GET_FD(op)
#define _SA MIPS_GET_SA(op)
#define _POS ((op>> 6) & 0x1F)
#define _SIZE ((op>>11) & 0x1F)
#define _IMM16 (signed short)(op & 0xFFFF)
#define _IMM26 (op & 0x03FFFFFF)
// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly.
// Currently known non working ones should have DISABLE.
@@ -40,7 +45,7 @@
namespace MIPSComp
{
void Jit::Comp_FPU3op(u32 op)
void Jit::Comp_FPU3op(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
@@ -54,7 +59,7 @@ void Jit::Comp_FPU3op(u32 op)
case 0: VADD(fpr.R(fd), fpr.R(fs), fpr.R(ft)); break; //F(fd) = F(fs) + F(ft); //add
case 1: VSUB(fpr.R(fd), fpr.R(fs), fpr.R(ft)); break; //F(fd) = F(fs) - F(ft); //sub
case 2: { //F(fd) = F(fs) * F(ft); //mul
u32 nextOp = Memory::Read_Instruction(js.compilerPC + 4);
MIPSOpcode nextOp = Memory::Read_Instruction(js.compilerPC + 4);
// Optimization possible if destination is the same
if (fd == (int)((nextOp>>6) & 0x1F)) {
// VMUL + VNEG -> VNMUL
@@ -78,13 +83,13 @@ void Jit::Comp_FPU3op(u32 op)
extern int logBlocks;
void Jit::Comp_FPULS(u32 op)
void Jit::Comp_FPULS(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
s32 offset = (s16)(op & 0xFFFF);
int ft = _FT;
int rs = _RS;
MIPSGPReg rs = _RS;
// u32 addr = R(rs) + offset;
// logBlocks = 1;
bool doCheck = false;
@@ -167,7 +172,7 @@ void Jit::Comp_FPULS(u32 op)
}
}
void Jit::Comp_FPUComp(u32 op) {
void Jit::Comp_FPUComp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
int opc = op & 0xF;
if (opc >= 8) opc -= 8; // alias
@@ -233,7 +238,7 @@ void Jit::Comp_FPUComp(u32 op) {
STR(R0, CTXREG, offsetof(MIPSState, fpcond));
}
void Jit::Comp_FPU2op(u32 op)
void Jit::Comp_FPU2op(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
@@ -307,12 +312,12 @@ void Jit::Comp_FPU2op(u32 op)
}
}
void Jit::Comp_mxc1(u32 op)
void Jit::Comp_mxc1(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int fs = _FS;
int rt = _RT;
MIPSGPReg rt = _RT;
switch ((op >> 21) & 0x1f)
{
+26 -21
View File
@@ -37,20 +37,25 @@
// (pointer or data), we could avoid many BIC instructions.
#include "../../MemMap.h"
#include "../MIPSAnalyst.h"
#include "../../Config.h"
#include "ArmJit.h"
#include "ArmRegCache.h"
#include "Core/MemMap.h"
#include "Core/Config.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/MIPSAnalyst.h"
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Core/MIPS/ARM/ArmJit.h"
#include "Core/MIPS/ARM/ArmRegCache.h"
#define _RS ((op>>21) & 0x1F)
#define _RT ((op>>16) & 0x1F)
#define _RD ((op>>11) & 0x1F)
#define _FS ((op>>11) & 0x1F)
#define _FT ((op>>16) & 0x1F)
#define _FD ((op>>6 ) & 0x1F)
#define _POS ((op>>6 ) & 0x1F)
#define _SIZE ((op>>11 ) & 0x1F)
#define _RS MIPS_GET_RS(op)
#define _RT MIPS_GET_RT(op)
#define _RD MIPS_GET_RD(op)
#define _FS MIPS_GET_FS(op)
#define _FT MIPS_GET_FT(op)
#define _FD MIPS_GET_FD(op)
#define _SA MIPS_GET_SA(op)
#define _POS ((op>> 6) & 0x1F)
#define _SIZE ((op>>11) & 0x1F)
#define _IMM16 (signed short)(op & 0xFFFF)
#define _IMM26 (op & 0x03FFFFFF)
// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly.
// Currently known non working ones should have DISABLE.
@@ -121,15 +126,15 @@ namespace MIPSComp
SetCC(CC_GT);
}
void Jit::Comp_ITypeMem(u32 op)
void Jit::Comp_ITypeMem(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int offset = (signed short)(op&0xFFFF);
bool load = false;
int rt = _RT;
int rs = _RS;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
int o = op>>26;
if (((op >> 29) & 1) == 0 && rt == 0) {
if (((op >> 29) & 1) == 0 && rt == MIPS_REG_ZERO) {
// Don't load anything into $zr
return;
}
@@ -194,13 +199,13 @@ namespace MIPSComp
if (!js.inDelaySlot) {
// Optimisation: Combine to single unaligned load/store
bool isLeft = (o == 34 || o == 42);
u32 nextOp = Memory::Read_Instruction(js.compilerPC + 4);
MIPSOpcode nextOp = Memory::Read_Instruction(js.compilerPC + 4);
// Find a matching shift in opposite direction with opposite offset.
if (nextOp == (isLeft ? (op + (4<<26) - 3)
: (op - (4<<26) + 3)))
if (nextOp == (isLeft ? (op.encoding + (4<<26) - 3)
: (op.encoding - (4<<26) + 3)))
{
EatInstruction(nextOp);
nextOp = ((load ? 35 : 43) << 26) | ((isLeft ? nextOp : op) & 0x03FFFFFF); //lw, sw
nextOp = MIPSOpcode(((load ? 35 : 43) << 26) | ((isLeft ? nextOp : op) & 0x03FFFFFF)); //lw, sw
Comp_ITypeMem(nextOp);
return;
}
+48 -44
View File
@@ -21,12 +21,13 @@
#include "Core/MemMap.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/MIPSAnalyst.h"
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Common/CPUDetect.h"
#include "Core/Config.h"
#include "Core/Reporting.h"
#include "ArmJit.h"
#include "ArmRegCache.h"
#include "Core/MIPS/ARM/ArmJit.h"
#include "Core/MIPS/ARM/ArmRegCache.h"
const bool disablePrefixes = false;
@@ -38,14 +39,17 @@ const bool disablePrefixes = false;
#define CONDITIONAL_DISABLE ;
#define DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
#define _RS ((op>>21) & 0x1F)
#define _RT ((op>>16) & 0x1F)
#define _RD ((op>>11) & 0x1F)
#define _FS ((op>>11) & 0x1F)
#define _FT ((op>>16) & 0x1F)
#define _FD ((op>>6 ) & 0x1F)
#define _POS ((op>>6 ) & 0x1F)
#define _SIZE ((op>>11 ) & 0x1F)
#define _RS MIPS_GET_RS(op)
#define _RT MIPS_GET_RT(op)
#define _RD MIPS_GET_RD(op)
#define _FS MIPS_GET_FS(op)
#define _FT MIPS_GET_FT(op)
#define _FD MIPS_GET_FD(op)
#define _SA MIPS_GET_SA(op)
#define _POS ((op>> 6) & 0x1F)
#define _SIZE ((op>>11) & 0x1F)
#define _IMM16 (signed short)(op & 0xFFFF)
#define _IMM26 (op & 0x03FFFFFF)
namespace MIPSComp
{
@@ -73,7 +77,7 @@ namespace MIPSComp
return IsOverlapSafeAllowS(dreg, di, sn, sregs, tn, tregs) && sregs[di] != dreg;
}
void Jit::Comp_VPFX(u32 op)
void Jit::Comp_VPFX(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int data = op & 0xFFFFF;
@@ -231,12 +235,12 @@ namespace MIPSComp
}
}
void Jit::Comp_SV(u32 op) {
void Jit::Comp_SV(MIPSOpcode op) {
CONDITIONAL_DISABLE;
s32 imm = (signed short)(op&0xFFFC);
int vt = ((op >> 16) & 0x1f) | ((op & 3) << 5);
int rs = _RS;
MIPSGPReg rs = _RS;
bool doCheck = false;
switch (op >> 26)
@@ -321,13 +325,13 @@ namespace MIPSComp
}
}
void Jit::Comp_SVQ(u32 op)
void Jit::Comp_SVQ(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int imm = (signed short)(op&0xFFFC);
int vt = (((op >> 16) & 0x1f)) | ((op&1) << 5);
int rs = _RS;
MIPSGPReg rs = _RS;
bool doCheck = false;
switch (op >> 26)
@@ -433,7 +437,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_VVectorInit(u32 op)
void Jit::Comp_VVectorInit(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
@@ -470,7 +474,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_VIdt(u32 op) {
void Jit::Comp_VIdt(MIPSOpcode op) {
CONDITIONAL_DISABLE
if (js.HasUnknownPrefix() || disablePrefixes) {
@@ -507,7 +511,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_VMatrixInit(u32 op)
void Jit::Comp_VMatrixInit(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
@@ -555,7 +559,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_VDot(u32 op) {
void Jit::Comp_VDot(MIPSOpcode op) {
CONDITIONAL_DISABLE;
if (js.HasUnknownPrefix() || disablePrefixes) {
DISABLE;
@@ -592,7 +596,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_Vhoriz(u32 op) {
void Jit::Comp_Vhoriz(MIPSOpcode op) {
DISABLE;
switch ((op >> 16) & 31) {
@@ -603,12 +607,12 @@ namespace MIPSComp
}
}
void Jit::Comp_VHdp(u32 op) {
void Jit::Comp_VHdp(MIPSOpcode op) {
// Similar to vdot
DISABLE;
}
void Jit::Comp_VecDo3(u32 op) {
void Jit::Comp_VecDo3(MIPSOpcode op) {
CONDITIONAL_DISABLE;
if (js.HasUnknownPrefix() || disablePrefixes) {
@@ -723,7 +727,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_VV2Op(u32 op) {
void Jit::Comp_VV2Op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
if (js.HasUnknownPrefix() || disablePrefixes) {
@@ -849,7 +853,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_Vi2f(u32 op) {
void Jit::Comp_Vi2f(MIPSOpcode op) {
CONDITIONAL_DISABLE;
if (js.HasUnknownPrefix() || disablePrefixes)
@@ -895,7 +899,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_Vf2i(u32 op) {
void Jit::Comp_Vf2i(MIPSOpcode op) {
CONDITIONAL_DISABLE;
DISABLE;
@@ -963,12 +967,12 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_Mftv(u32 op)
void Jit::Comp_Mftv(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int imm = op & 0xFF;
int rt = _RT;
MIPSGPReg rt = _RT;
switch ((op >> 21) & 0x1f)
{
case 3: //mfv / mfvc
@@ -1024,7 +1028,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_Vmtvc(u32 op) {
void Jit::Comp_Vmtvc(MIPSOpcode op) {
CONDITIONAL_DISABLE;
int vs = _VS;
@@ -1045,7 +1049,7 @@ namespace MIPSComp
}
}
void Jit::Comp_Vmmov(u32 op) {
void Jit::Comp_Vmmov(MIPSOpcode op) {
CONDITIONAL_DISABLE;
// TODO: This probably ignores prefixes?
@@ -1086,7 +1090,7 @@ namespace MIPSComp
}
}
void Jit::Comp_VScl(u32 op) {
void Jit::Comp_VScl(MIPSOpcode op) {
CONDITIONAL_DISABLE;
if (js.HasUnknownPrefix() || disablePrefixes) {
@@ -1135,7 +1139,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_Vmmul(u32 op) {
void Jit::Comp_Vmmul(MIPSOpcode op) {
CONDITIONAL_DISABLE;
// TODO: This probably ignores prefixes?
@@ -1177,11 +1181,11 @@ namespace MIPSComp
}
}
void Jit::Comp_Vmscl(u32 op) {
void Jit::Comp_Vmscl(MIPSOpcode op) {
DISABLE;
}
void Jit::Comp_Vtfm(u32 op) {
void Jit::Comp_Vtfm(MIPSOpcode op) {
CONDITIONAL_DISABLE;
// TODO: This probably ignores prefixes? Or maybe uses D?
@@ -1241,23 +1245,23 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_VCrs(u32 op) {
void Jit::Comp_VCrs(MIPSOpcode op) {
DISABLE;
}
void Jit::Comp_VDet(u32 op) {
void Jit::Comp_VDet(MIPSOpcode op) {
DISABLE;
}
void Jit::Comp_Vi2x(u32 op) {
void Jit::Comp_Vi2x(MIPSOpcode op) {
DISABLE;
}
void Jit::Comp_Vx2i(u32 op) {
void Jit::Comp_Vx2i(MIPSOpcode op) {
DISABLE;
}
void Jit::Comp_VCrossQuat(u32 op) {
void Jit::Comp_VCrossQuat(MIPSOpcode op) {
// This op does not support prefixes.
if (js.HasUnknownPrefix() || disablePrefixes)
DISABLE;
@@ -1303,7 +1307,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_Vcmp(u32 op) {
void Jit::Comp_Vcmp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
if (js.HasUnknownPrefix() || disablePrefixes)
@@ -1441,7 +1445,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_Vcmov(u32 op) {
void Jit::Comp_Vcmov(MIPSOpcode op) {
CONDITIONAL_DISABLE;
if (js.HasUnknownPrefix() || disablePrefixes)
@@ -1489,7 +1493,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_Viim(u32 op) {
void Jit::Comp_Viim(MIPSOpcode op) {
CONDITIONAL_DISABLE;
u8 dreg;
@@ -1503,7 +1507,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_Vfim(u32 op) {
void Jit::Comp_Vfim(MIPSOpcode op) {
CONDITIONAL_DISABLE;
if (js.HasUnknownPrefix() || disablePrefixes) {
@@ -1523,7 +1527,7 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}
void Jit::Comp_Vcst(u32 op) {
void Jit::Comp_Vcst(MIPSOpcode op) {
CONDITIONAL_DISABLE;
if (js.HasUnknownPrefix() || disablePrefixes) {
@@ -1572,7 +1576,7 @@ namespace MIPSComp
}
// Very heavily used by FF:CC
void Jit::Comp_VRot(u32 op) {
void Jit::Comp_VRot(MIPSOpcode op) {
// Not sure about the ABI so I disable on non-Android.
#if !defined(ARMV7) || !defined(ANDROID)
DISABLE;
+12 -13
View File
@@ -118,21 +118,20 @@ void Jit::ClearCache()
GenerateFixedCode();
}
void Jit::ClearCacheAt(u32 em_address)
void Jit::ClearCacheAt(u32 em_address, int length)
{
// TODO: Properly.
ClearCache();
blocks.InvalidateICache(em_address, length);
}
void Jit::CompileAt(u32 addr)
{
u32 op = Memory::Read_Instruction(addr);
MIPSOpcode op = Memory::Read_Instruction(addr);
MIPSCompileOp(op);
}
void Jit::EatInstruction(u32 op)
void Jit::EatInstruction(MIPSOpcode op)
{
u32 info = MIPSGetInfo(op);
MIPSInfo info = MIPSGetInfo(op);
_dbg_assert_msg_(JIT, !(info & DELAYSLOT), "Never eat a branch op.");
_dbg_assert_msg_(JIT, !js.inDelaySlot, "Never eat an instruction inside a delayslot.");
@@ -149,7 +148,7 @@ void Jit::CompileDelaySlot(int flags)
MRS(R8); // Save flags register. R8 is preserved through function calls and is not allocated.
js.inDelaySlot = true;
u32 op = Memory::Read_Instruction(js.compilerPC + 4);
MIPSOpcode op = Memory::Read_Instruction(js.compilerPC + 4);
MIPSCompileOp(op);
js.inDelaySlot = false;
@@ -224,7 +223,7 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b)
{
gpr.SetCompilerPC(js.compilerPC); // Let it know for log messages
fpr.SetCompilerPC(js.compilerPC);
u32 inst = Memory::Read_Instruction(js.compilerPC);
MIPSOpcode inst = Memory::Read_Instruction(js.compilerPC);
js.downcountAmount += MIPSGetInstructionCycleEstimate(inst);
MIPSCompileOp(inst);
@@ -266,13 +265,13 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b)
return b->normalEntry;
}
void Jit::Comp_RunBlock(u32 op)
void Jit::Comp_RunBlock(MIPSOpcode op)
{
// This shouldn't be necessary, the dispatcher should catch us before we get here.
ERROR_LOG(DYNA_REC, "Comp_RunBlock should never be reached!");
}
void Jit::Comp_Generic(u32 op)
void Jit::Comp_Generic(MIPSOpcode op)
{
FlushAll();
MIPSInterpretFunc func = MIPSGetInterpretFunc(op);
@@ -281,12 +280,12 @@ void Jit::Comp_Generic(u32 op)
SaveDowncount();
MOVI2R(R0, js.compilerPC);
MovToPC(R0);
MOVI2R(R0, op);
MOVI2R(R0, op.encoding);
QuickCallFunction(R1, (void *)func);
RestoreDowncount();
}
const int info = MIPSGetInfo(op);
const MIPSInfo info = MIPSGetInfo(op);
if ((info & IS_VFPU) != 0 && (info & VFPU_NO_PREFIX) == 0)
{
// If it does eat them, it'll happen in MIPSCompileOp().
@@ -383,7 +382,7 @@ void Jit::WriteSyscallExit()
B((const void *)dispatcherCheckCoreState);
}
void Jit::Comp_DoNothing(u32 op) { }
void Jit::Comp_DoNothing(MIPSOpcode op) { }
#define _RS ((op>>21) & 0x1F)
#define _RT ((op>>16) & 0x1F)
+67 -67
View File
@@ -152,7 +152,7 @@ public:
// Compiled ops should ignore delay slots
// the compiler will take care of them by itself
// OR NOT
void Comp_Generic(u32 op);
void Comp_Generic(MIPSOpcode op);
void RunLoopUntil(u64 globalticks);
@@ -161,76 +161,76 @@ public:
void CompileDelaySlot(int flags);
void CompileAt(u32 addr);
void EatInstruction(u32 op);
void Comp_RunBlock(u32 op);
void EatInstruction(MIPSOpcode op);
void Comp_RunBlock(MIPSOpcode op);
// Ops
void Comp_ITypeMem(u32 op);
void Comp_ITypeMem(MIPSOpcode op);
void Comp_RelBranch(u32 op);
void Comp_RelBranchRI(u32 op);
void Comp_FPUBranch(u32 op);
void Comp_FPULS(u32 op);
void Comp_FPUComp(u32 op);
void Comp_Jump(u32 op);
void Comp_JumpReg(u32 op);
void Comp_Syscall(u32 op);
void Comp_Break(u32 op);
void Comp_RelBranch(MIPSOpcode op);
void Comp_RelBranchRI(MIPSOpcode op);
void Comp_FPUBranch(MIPSOpcode op);
void Comp_FPULS(MIPSOpcode op);
void Comp_FPUComp(MIPSOpcode op);
void Comp_Jump(MIPSOpcode op);
void Comp_JumpReg(MIPSOpcode op);
void Comp_Syscall(MIPSOpcode op);
void Comp_Break(MIPSOpcode op);
void Comp_IType(u32 op);
void Comp_RType2(u32 op);
void Comp_RType3(u32 op);
void Comp_ShiftType(u32 op);
void Comp_Allegrex(u32 op);
void Comp_Allegrex2(u32 op);
void Comp_VBranch(u32 op);
void Comp_MulDivType(u32 op);
void Comp_Special3(u32 op);
void Comp_IType(MIPSOpcode op);
void Comp_RType2(MIPSOpcode op);
void Comp_RType3(MIPSOpcode op);
void Comp_ShiftType(MIPSOpcode op);
void Comp_Allegrex(MIPSOpcode op);
void Comp_Allegrex2(MIPSOpcode op);
void Comp_VBranch(MIPSOpcode op);
void Comp_MulDivType(MIPSOpcode op);
void Comp_Special3(MIPSOpcode op);
void Comp_FPU3op(u32 op);
void Comp_FPU2op(u32 op);
void Comp_mxc1(u32 op);
void Comp_FPU3op(MIPSOpcode op);
void Comp_FPU2op(MIPSOpcode op);
void Comp_mxc1(MIPSOpcode op);
void Comp_DoNothing(u32 op);
void Comp_DoNothing(MIPSOpcode op);
void Comp_SV(u32 op);
void Comp_SVQ(u32 op);
void Comp_VPFX(u32 op);
void Comp_VVectorInit(u32 op);
void Comp_VMatrixInit(u32 op);
void Comp_VDot(u32 op);
void Comp_VecDo3(u32 op);
void Comp_VV2Op(u32 op);
void Comp_Mftv(u32 op);
void Comp_Vmtvc(u32 op);
void Comp_Vmmov(u32 op);
void Comp_VScl(u32 op);
void Comp_Vmmul(u32 op);
void Comp_Vmscl(u32 op);
void Comp_Vtfm(u32 op);
void Comp_VHdp(u32 op);
void Comp_VCrs(u32 op);
void Comp_VDet(u32 op);
void Comp_Vi2x(u32 op);
void Comp_Vx2i(u32 op);
void Comp_Vf2i(u32 op);
void Comp_Vi2f(u32 op);
void Comp_Vcst(u32 op);
void Comp_Vhoriz(u32 op);
void Comp_VRot(u32 op);
void Comp_VIdt(u32 op);
void Comp_Vcmp(u32 op);
void Comp_Vcmov(u32 op);
void Comp_Viim(u32 op);
void Comp_Vfim(u32 op);
void Comp_VCrossQuat(u32 op);
void Comp_Vsge(u32 op);
void Comp_Vslt(u32 op);
void Comp_SV(MIPSOpcode op);
void Comp_SVQ(MIPSOpcode op);
void Comp_VPFX(MIPSOpcode op);
void Comp_VVectorInit(MIPSOpcode op);
void Comp_VMatrixInit(MIPSOpcode op);
void Comp_VDot(MIPSOpcode op);
void Comp_VecDo3(MIPSOpcode op);
void Comp_VV2Op(MIPSOpcode op);
void Comp_Mftv(MIPSOpcode op);
void Comp_Vmtvc(MIPSOpcode op);
void Comp_Vmmov(MIPSOpcode op);
void Comp_VScl(MIPSOpcode op);
void Comp_Vmmul(MIPSOpcode op);
void Comp_Vmscl(MIPSOpcode op);
void Comp_Vtfm(MIPSOpcode op);
void Comp_VHdp(MIPSOpcode op);
void Comp_VCrs(MIPSOpcode op);
void Comp_VDet(MIPSOpcode op);
void Comp_Vi2x(MIPSOpcode op);
void Comp_Vx2i(MIPSOpcode op);
void Comp_Vf2i(MIPSOpcode op);
void Comp_Vi2f(MIPSOpcode op);
void Comp_Vcst(MIPSOpcode op);
void Comp_Vhoriz(MIPSOpcode op);
void Comp_VRot(MIPSOpcode op);
void Comp_VIdt(MIPSOpcode op);
void Comp_Vcmp(MIPSOpcode op);
void Comp_Vcmov(MIPSOpcode op);
void Comp_Viim(MIPSOpcode op);
void Comp_Vfim(MIPSOpcode op);
void Comp_VCrossQuat(MIPSOpcode op);
void Comp_Vsge(MIPSOpcode op);
void Comp_Vslt(MIPSOpcode op);
JitBlockCache *GetBlockCache() { return &blocks; }
void ClearCache();
void ClearCacheAt(u32 em_address);
void ClearCacheAt(u32 em_address, int length = 4);
void EatPrefix() { js.EatPrefix(); }
@@ -251,17 +251,17 @@ private:
void WriteSyscallExit();
// Utility compilation functions
void BranchFPFlag(u32 op, ArmGen::CCFlags cc, bool likely);
void BranchVFPUFlag(u32 op, ArmGen::CCFlags cc, bool likely);
void BranchRSZeroComp(u32 op, ArmGen::CCFlags cc, bool andLink, bool likely);
void BranchRSRTComp(u32 op, ArmGen::CCFlags cc, bool likely);
void BranchFPFlag(MIPSOpcode op, ArmGen::CCFlags cc, bool likely);
void BranchVFPUFlag(MIPSOpcode op, ArmGen::CCFlags cc, bool likely);
void BranchRSZeroComp(MIPSOpcode op, ArmGen::CCFlags cc, bool andLink, bool likely);
void BranchRSRTComp(MIPSOpcode op, ArmGen::CCFlags cc, bool likely);
// Utilities to reduce duplicated code
void CompImmLogic(int rs, int rt, u32 uimm, void (ARMXEmitter::*arith)(ARMReg dst, ARMReg src, Operand2 op2), u32 (*eval)(u32 a, u32 b));
void CompType3(int rd, int rs, int rt, void (ARMXEmitter::*arithOp2)(ARMReg dst, ARMReg rm, Operand2 rn), u32 (*eval)(u32 a, u32 b), bool isSub = false);
void CompShiftImm(u32 op, ArmGen::ShiftType shiftType);
void CompShiftVar(u32 op, ArmGen::ShiftType shiftType);
void CompShiftImm(MIPSOpcode op, ArmGen::ShiftType shiftType);
void CompShiftVar(MIPSOpcode op, ArmGen::ShiftType shiftType);
void ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz);
void ApplyPrefixD(const u8 *vregs, VectorSize sz);
@@ -307,7 +307,7 @@ public:
const u8 *breakpointBailout;
};
typedef void (Jit::*MIPSCompileFunc)(u32 opcode);
typedef void (Jit::*MIPSCompileFunc)(MIPSOpcode opcode);
} // namespace MIPSComp
+17 -12
View File
@@ -31,6 +31,7 @@
#include "Core/Core.h"
#include "Core/MemMap.h"
#include "Core/CoreTiming.h"
#include "Core/Reporting.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/MIPSTables.h"
@@ -157,7 +158,7 @@ void JitBlockCache::FinalizeBlock(int block_num, bool block_link)
JitBlock &b = blocks[block_num];
b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress);
u32 opcode = GetEmuHackOpForBlock(block_num);
MIPSOpcode opcode = GetEmuHackOpForBlock(block_num);
Memory::Write_Opcode_JIT(b.originalAddress, opcode);
// Convert the logical address to a physical address for the block map
@@ -215,25 +216,28 @@ int binary_search(JitBlock blocks[], const u8 *baseoff, int imin, int imax)
return -1;
}
int JitBlockCache::GetBlockNumberFromEmuHackOp(u32 inst) const {
int JitBlockCache::GetBlockNumberFromEmuHackOp(MIPSOpcode inst) const {
if (!num_blocks || !MIPS_IS_EMUHACK(inst)) // definitely not a JIT block
return -1;
int off = (inst & MIPS_EMUHACK_VALUE_MASK);
const u8 *baseoff = codeBlock_->GetBasePtr() + off;
return binary_search(blocks, baseoff, 0, num_blocks-1);
int bl = binary_search(blocks, baseoff, 0, num_blocks-1);
if (blocks[bl].invalid)
return -1;
return bl;
}
u32 JitBlockCache::GetEmuHackOpForBlock(int blockNum) const {
MIPSOpcode JitBlockCache::GetEmuHackOpForBlock(int blockNum) const {
int off = (int)(blocks[blockNum].normalEntry - codeBlock_->GetBasePtr());
return (MIPS_EMUHACK_OPCODE | off);
return MIPSOpcode(MIPS_EMUHACK_OPCODE | off);
}
int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr)
{
if (!blocks)
return -1;
u32 inst = Memory::Read_U32(addr);
MIPSOpcode inst = MIPSOpcode(Memory::Read_U32(addr));
int bl = GetBlockNumberFromEmuHackOp(inst);
if (bl < 0)
return -1;
@@ -249,12 +253,12 @@ void JitBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector<int>
block_numbers->push_back(i);
}
u32 JitBlockCache::GetOriginalFirstOp(int block_num)
MIPSOpcode JitBlockCache::GetOriginalFirstOp(int block_num)
{
if (block_num >= num_blocks || block_num < 0)
{
//PanicAlert("JitBlockCache::GetOriginalFirstOp - block_num = %u is out of range", block_num);
return block_num;
return MIPSOpcode(block_num);
}
return blocks[block_num].originalFirstOpcode;
}
@@ -327,7 +331,7 @@ void JitBlockCache::UnlinkBlock(int i)
void JitBlockCache::DestroyBlock(int block_num, bool invalidate)
{
if (block_num < 0 || block_num >= num_blocks) {
ERROR_LOG(JIT, "DestroyBlock: Invalid block number %d", block_num);
ERROR_LOG_REPORT(JIT, "DestroyBlock: Invalid block number %d", block_num);
return;
}
JitBlock &b = blocks[block_num];
@@ -337,9 +341,9 @@ void JitBlockCache::DestroyBlock(int block_num, bool invalidate)
return;
}
b.invalid = true;
if (Memory::ReadUnchecked_U32(b.originalAddress) == GetEmuHackOpForBlock(block_num))
Memory::WriteUnchecked_U32(b.originalFirstOpcode, b.originalAddress);
b.normalEntry = 0;
if (Memory::ReadUnchecked_U32(b.originalAddress) == GetEmuHackOpForBlock(block_num).encoding)
Memory::Write_Opcode_JIT(b.originalAddress, b.originalFirstOpcode);
// It's not safe to set normalEntry to 0 here, since we use a binary search.
UnlinkBlock(block_num);
@@ -380,6 +384,7 @@ void JitBlockCache::InvalidateICache(u32 address, const u32 length)
// destroy JIT blocks
// !! this works correctly under assumption that any two overlapping blocks end at the same address
// TODO: This may not be a safe assumption with jit continuing enabled.
std::map<pair<u32,u32>, u32>::iterator it1 = block_map.lower_bound(std::make_pair(pAddr, 0)), it2 = it1;
while (it2 != block_map.end() && it2->first.second < pAddr + length) {
DestroyBlock(it2->second, true);
+4 -4
View File
@@ -65,7 +65,7 @@ struct JitBlock {
u32 exitAddress[MAX_JIT_BLOCK_EXITS]; // 0xFFFFFFFF == unknown
u32 originalAddress;
u32 originalFirstOpcode; //to be able to restore
MIPSOpcode originalFirstOpcode; //to be able to restore
u16 codeSize;
u16 originalSize;
u16 blockNum;
@@ -107,9 +107,9 @@ public:
// Returns a list of block numbers - only one block can start at a particular address, but they CAN overlap.
// This one is slow so should only be used for one-shots from the debugger UI, not for anything during runtime.
void GetBlockNumbersFromAddress(u32 em_address, std::vector<int> *block_numbers);
int GetBlockNumberFromEmuHackOp(u32 inst) const;
int GetBlockNumberFromEmuHackOp(MIPSOpcode inst) const;
u32 GetOriginalFirstOp(int block_num);
MIPSOpcode GetOriginalFirstOp(int block_num);
// DOES NOT WORK CORRECTLY WITH JIT INLINING
void InvalidateICache(u32 address, const u32 length);
@@ -120,7 +120,7 @@ private:
void LinkBlock(int i);
void UnlinkBlock(int i);
u32 GetEmuHackOpForBlock(int block_num) const;
MIPSOpcode GetEmuHackOpForBlock(int block_num) const;
MIPSState *mips;
CodeBlock *codeBlock_;
-1
View File
@@ -44,5 +44,4 @@
namespace MIPSComp {
extern Jit *jit;
extern const float cst_constants[32];
}
+8 -1
View File
@@ -60,7 +60,7 @@ MIPSDebugInterface *currentDebugMIPS = &debugr4k;
#define M_SQRT1_2 0.707106781186547524401f
#endif
extern const float cst_constants[32] = {
const float cst_constants[32] = {
0,
std::numeric_limits<float>::max(), // all these are verified on real PSP
sqrtf(2.0f),
@@ -230,6 +230,13 @@ u32 MIPSState::ReadFCR(int reg)
return 0;
}
void MIPSState::InvalidateICache(u32 address, int length)
{
// Only really applies to jit.
if (MIPSComp::jit)
MIPSComp::jit->ClearCacheAt(address, length);
}
// Interrupts should be served directly on the running thread.
void MIPSState::Irq()
+9 -9
View File
@@ -17,11 +17,14 @@
#pragma once
#include "../../Globals.h"
#include "../CPU.h"
#include "Globals.h"
#include "Core/MemMap.h"
#include "Core/CPU.h"
#include "util/random/rng.h"
enum
typedef Memory::Opcode MIPSOpcode;
enum MIPSGPReg
{
MIPS_REG_ZERO=0,
MIPS_REG_COMPILER_SCRATCH=1,
@@ -53,6 +56,7 @@ enum
// ID for mipscall "callback" is stored here - from JPCSP
MIPS_REG_CALL_ID=MIPS_REG_S0,
MIPS_REG_INVALID=-1,
};
enum
@@ -164,6 +168,8 @@ public:
void SingleStep();
int RunLoopUntil(u64 globalTicks);
// To clear jit caches, etc.
void InvalidateICache(u32 address, int length = 4);
// for logging messages only.
const char *DisasmAt(u32 compilerPC);
@@ -177,12 +183,6 @@ extern MIPSState *currentMIPS;
extern MIPSDebugInterface *currentDebugMIPS;
extern MIPSState mipsr4k;
void MIPS_Init();
int MIPS_SingleStep();
void MIPS_Shutdown();
void MIPS_Irq();
void MIPS_SWI();
extern const float cst_constants[32];
+100 -151
View File
@@ -16,186 +16,135 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <map>
#include "../../Globals.h"
#include "Globals.h"
#include "MIPS.h"
#include "MIPSTables.h"
#include "MIPSAnalyst.h"
#include "MIPSCodeUtils.h"
#include "../Debugger/SymbolMap.h"
#include "../Debugger/DebugInterface.h"
#include "Common/FileUtil.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/MIPSTables.h"
#include "Core/MIPS/MIPSAnalyst.h"
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Core/Debugger/SymbolMap.h"
#include "Core/Debugger/DebugInterface.h"
using namespace MIPSCodeUtils;
using namespace std;
namespace MIPSAnalyst
{
RegisterAnalysisResults regAnal[32];
RegisterAnalysisResults total[32];
int numAnalysisDone=0;
int GetOutReg(u32 op)
{
u32 opinfo = MIPSGetInfo(op);
if (opinfo & OUT_RT)
return MIPS_GET_RT(op);
if (opinfo & OUT_RD)
return MIPS_GET_RD(op);
if (opinfo & OUT_RA)
return MIPS_REG_RA;
return -1;
}
bool ReadsFromReg(u32 op, u32 reg)
{
u32 opinfo = MIPSGetInfo(op);
if (opinfo & IN_RT)
{
if (MIPS_GET_RT(opinfo) == reg)
return true;
}
if (opinfo & IN_RS)
{
if (MIPS_GET_RS(opinfo) == reg)
return true;
}
return false; //TODO: there are more cases!
}
// TODO: Remove me?
bool IsDelaySlotNice(u32 branch, u32 delayslot)
{
int outReg = GetOutReg(delayslot);
if (outReg != -1)
{
if (ReadsFromReg(branch, outReg))
{
return false; //evil :(
// Only can ever output a single reg.
MIPSGPReg GetOutGPReg(MIPSOpcode op) {
MIPSInfo opinfo = MIPSGetInfo(op);
if ((opinfo & IS_VFPU) == 0) {
if (opinfo & OUT_RT) {
return MIPS_GET_RT(op);
}
else
{
return false; //aggh this should be true but doesn't work
if (opinfo & OUT_RD) {
return MIPS_GET_RD(op);
}
if (opinfo & OUT_RA) {
return MIPS_REG_RA;
}
}
else
{
// Check for FPU flag
if ((MIPSGetInfo(delayslot) & OUT_FPUFLAG) && (MIPSGetInfo(branch) & IN_FPUFLAG))
return false;
return true; //nice :)
}
return MIPS_REG_INVALID;
}
bool IsDelaySlotNiceReg(u32 branchOp, u32 op, int reg1, int reg2)
{
bool ReadsFromGPReg(MIPSOpcode op, MIPSGPReg reg) {
MIPSInfo info = MIPSGetInfo(op);
if ((info & IS_VFPU) == 0) {
if ((info & IN_RS) != 0 && MIPS_GET_RS(op) == reg) {
return true;
}
if ((info & IN_RT) != 0 && MIPS_GET_RT(op) == reg) {
return true;
}
}
return false;
}
bool IsDelaySlotNiceReg(MIPSOpcode branchOp, MIPSOpcode op, MIPSGPReg reg1, MIPSGPReg reg2) {
// $0 is never an out reg, it's always 0.
if (reg1 != 0 && GetOutReg(op) == reg1)
if (reg1 != MIPS_REG_ZERO && GetOutGPReg(op) == reg1) {
return false;
if (reg2 != 0 && GetOutReg(op) == reg2)
}
if (reg2 != MIPS_REG_ZERO && GetOutGPReg(op) == reg2) {
return false;
}
return true;
}
bool IsDelaySlotNiceVFPU(u32 branchOp, u32 op)
{
bool IsDelaySlotNiceVFPU(MIPSOpcode branchOp, MIPSOpcode op) {
// TODO: There may be IS_VFPU cases which are safe...
return (MIPSGetInfo(op) & IS_VFPU) == 0;
}
bool IsDelaySlotNiceFPU(u32 branchOp, u32 op)
{
bool IsDelaySlotNiceFPU(MIPSOpcode branchOp, MIPSOpcode op) {
return (MIPSGetInfo(op) & OUT_FPUFLAG) == 0;
}
bool IsSyscall(u32 op)
{
bool IsSyscall(MIPSOpcode op) {
// Syscalls look like this: 0000 00-- ---- ---- ---- --00 1100
return (op >> 26) == 0 && (op & 0x3f) == 12;
}
void Analyze(u32 address)
{
AnalysisResults Analyze(u32 address) {
const int MAX_ANALYZE = 10000;
AnalysisResults results;
//set everything to -1 (FF)
memset(regAnal, 255, sizeof(AnalysisResults)*32);
for (int i=0; i<32; i++)
{
regAnal[i].used=false;
regAnal[i].readCount=0;
regAnal[i].writeCount=0;
regAnal[i].readAsAddrCount=0;
memset(&results, 255, sizeof(AnalysisResults));
for (int i = 0; i < MIPS_NUM_GPRS; i++) {
results.r[i].used = false;
results.r[i].readCount = 0;
results.r[i].writeCount = 0;
results.r[i].readAsAddrCount = 0;
}
u32 addr = address;
bool exitFlag = false;
while (true)
{
u32 op = Memory::Read_Instruction(addr);
u32 info = MIPSGetInfo(op);
for (u32 addr = address, endAddr = address + MAX_ANALYZE; addr <= endAddr; addr += 4) {
MIPSOpcode op = Memory::Read_Instruction(addr);
MIPSInfo info = MIPSGetInfo(op);
for (int reg=0; reg < 32; reg++)
{
int rs = MIPS_GET_RS(op);
int rt = MIPS_GET_RT(op);
int rd = MIPS_GET_RD(op);
MIPSGPReg rs = MIPS_GET_RS(op);
MIPSGPReg rt = MIPS_GET_RT(op);
if (
((info & IN_RS) && (info & IN_RS_ADDR) == IN_RS && (rs == reg)) ||
((info & IN_RT) && (rt == reg)))
{
if (regAnal[reg].firstRead == -1)
regAnal[reg].firstRead = addr;
regAnal[reg].lastRead = addr;
regAnal[reg].readCount++;
regAnal[reg].used=true;
}
if (
((info & IN_RS_ADDR) && (rs == reg))
)
{
if (regAnal[reg].firstReadAsAddr == -1)
regAnal[reg].firstReadAsAddr = addr;
regAnal[reg].lastReadAsAddr = addr;
regAnal[reg].readAsAddrCount++;
regAnal[reg].used=true;
}
if (
((info & OUT_RT) && (rt == reg)) ||
((info & OUT_RD) && (rd == reg)) ||
((info & OUT_RA) && (reg == MIPS_REG_RA))
)
{
if (regAnal[reg].firstWrite == -1)
regAnal[reg].firstWrite = addr;
regAnal[reg].lastWrite = addr;
regAnal[reg].writeCount++;
regAnal[reg].used=true;
if (info & IN_RS) {
if ((info & IN_RS_ADDR) == IN_RS_ADDR) {
results.r[rs].MarkReadAsAddr(addr);
} else {
results.r[rs].MarkRead(addr);
}
}
if (exitFlag) //delay slot done, let's quit!
break;
if ((info & IS_JUMP) || (info & IS_CONDBRANCH))
{
exitFlag = true; // now do the delay slot
if (info & IN_RT) {
results.r[rt].MarkRead(addr);
}
addr += 4;
MIPSGPReg outReg = GetOutGPReg(op);
if (outReg != MIPS_REG_INVALID) {
results.r[outReg].MarkWrite(addr);
}
if (info & DELAYSLOT)
{
// Let's just finish the delay slot before bailing.
endAddr = addr + 4;
}
}
int numUsedRegs=0;
static int totalUsedRegs=0;
static int numAnalyzings=0;
for (int i=0; i<32; i++)
{
if (regAnal[i].used)
for (int i = 0; i < MIPS_NUM_GPRS; i++) {
if (results.r[i].used) {
numUsedRegs++;
}
}
totalUsedRegs+=numUsedRegs;
numAnalyzings++;
DEBUG_LOG(CPU,"[ %08x ] Used regs: %i Average: %f",address,numUsedRegs,(float)totalUsedRegs/(float)numAnalyzings);
return results;
}
@@ -236,12 +185,12 @@ namespace MIPSAnalyst
}
bool IsRegisterUsed(u32 reg, u32 addr)
bool IsRegisterUsed(MIPSGPReg reg, u32 addr)
{
while (true)
{
u32 op = Memory::Read_Instruction(addr);
u32 info = MIPSGetInfo(op);
MIPSOpcode op = Memory::Read_Instruction(addr);
MIPSInfo info = MIPSGetInfo(op);
if ((info & IN_RS) && (MIPS_GET_RS(op) == reg))
return true;
@@ -271,8 +220,8 @@ namespace MIPSAnalyst
for (u32 addr = f.start; addr <= f.end; addr += 4)
{
u32 validbits = 0xFFFFFFFF;
u32 instr = Memory::Read_Instruction(addr);
u32 flags = MIPSGetInfo(instr);
MIPSOpcode instr = Memory::Read_Instruction(addr);
MIPSInfo flags = MIPSGetInfo(instr);
if (flags & IN_IMM16)
validbits&=~0xFFFF;
if (flags & IN_IMM26)
@@ -303,7 +252,7 @@ namespace MIPSAnalyst
continue;
}
u32 op = Memory::Read_Instruction(addr);
MIPSOpcode op = Memory::Read_Instruction(addr);
u32 target = GetBranchTargetNoRA(addr);
if (target != INVALIDTARGET)
{
@@ -378,7 +327,7 @@ namespace MIPSAnalyst
void StoreHashMap(const char *filename)
{
FILE *file = fopen(filename,"wb");
FILE *file = File::OpenCFile(filename,"wb");
u32 num = 0;
if(fwrite(&num,4,1,file) != 1) //fill in later
WARN_LOG(CPU, "Could not store hash map %s", filename);
@@ -412,7 +361,7 @@ namespace MIPSAnalyst
HashFunctions();
UpdateHashToFunctionMap();
FILE *file = fopen(filename, "rb");
FILE *file = File::OpenCFile(filename, "rb");
int num;
if(fread(&num,4,1,file) == 1) {
for (int i=0; i<num; i++)
@@ -452,10 +401,10 @@ namespace MIPSAnalyst
LOG(CPU,"Precompiled %i straight leaf functions",count);*/
}
std::vector<int> GetInputRegs(u32 op)
std::vector<MIPSGPReg> GetInputRegs(MIPSOpcode op)
{
std::vector<int> vec;
u32 info = MIPSGetInfo(op);
std::vector<MIPSGPReg> vec;
MIPSInfo info = MIPSGetInfo(op);
if ((info & IS_VFPU) == 0)
{
if (info & IN_RS) vec.push_back(MIPS_GET_RS(op));
@@ -463,10 +412,10 @@ namespace MIPSAnalyst
}
return vec;
}
std::vector<int> GetOutputRegs(u32 op)
std::vector<MIPSGPReg> GetOutputRegs(MIPSOpcode op)
{
std::vector<int> vec;
u32 info = MIPSGetInfo(op);
std::vector<MIPSGPReg> vec;
MIPSInfo info = MIPSGetInfo(op);
if ((info & IS_VFPU) == 0)
{
if (info & OUT_RD) vec.push_back(MIPS_GET_RD(op));
@@ -489,8 +438,8 @@ namespace MIPSAnalyst
info.opcodeAddress = address;
info.encodedOpcode = Memory::Read_Instruction(address);
u32 op = info.encodedOpcode;
u32 opInfo = MIPSGetInfo(op);
MIPSOpcode op = info.encodedOpcode;
MIPSInfo opInfo = MIPSGetInfo(op);
info.isLikelyBranch = (opInfo & LIKELY) != 0;
//j , jal, ...
@@ -505,7 +454,7 @@ namespace MIPSAnalyst
if (opInfo & IN_RS) // to register
{
info.isBranchToRegister = true;
info.branchRegisterNum = MIPS_GET_RS(op);
info.branchRegisterNum = (int)MIPS_GET_RS(op);
info.branchTarget = cpu->GetRegValue(0,info.branchRegisterNum);
} else { // to immediate
info.branchTarget = GetJumpTarget(address);
@@ -517,7 +466,7 @@ namespace MIPSAnalyst
{
info.isConditional = true;
u32 rt = cpu->GetRegValue(0,MIPS_GET_RT(op));
u32 rt = cpu->GetRegValue(0, (int)MIPS_GET_RT(op));
switch (opInfo & CONDTYPE_MASK)
{
case CONDTYPE_EQ:
@@ -541,8 +490,8 @@ namespace MIPSAnalyst
info.isLinkedBranch = true;
}
u32 rt = cpu->GetRegValue(0,MIPS_GET_RT(op));
u32 rs = cpu->GetRegValue(0,MIPS_GET_RS(op));
u32 rt = cpu->GetRegValue(0, (int)MIPS_GET_RT(op));
u32 rs = cpu->GetRegValue(0, (int)MIPS_GET_RS(op));
switch (opInfo & CONDTYPE_MASK)
{
case CONDTYPE_EQ:
@@ -596,7 +545,7 @@ namespace MIPSAnalyst
info.dataSize = 16;
}
u32 rs = cpu->GetRegValue(0,MIPS_GET_RS(op));
u32 rs = cpu->GetRegValue(0, (int)MIPS_GET_RS(op));
s16 imm16 = op & 0xFFFF;
info.dataAddress = rs + imm16;
}
+46 -21
View File
@@ -17,15 +17,16 @@
#pragma once
#include "../../Globals.h"
#include "Globals.h"
#include "Core/MIPS/MIPS.h"
class DebugInterface;
namespace MIPSAnalyst
{
void Analyze(u32 address);
struct RegisterAnalysisResults
{
const int MIPS_NUM_GPRS = 32;
struct RegisterAnalysisResults {
bool used;
int firstRead;
int lastRead;
@@ -37,32 +38,56 @@ namespace MIPSAnalyst
int readCount;
int writeCount;
int readAsAddrCount;
bool usesVFPU;
int TotalReadCount() {return readCount + readAsAddrCount;}
int FirstRead() {return firstReadAsAddr < firstRead ? firstReadAsAddr : firstRead;}
int LastRead() {return lastReadAsAddr > lastRead ? lastReadAsAddr : lastRead;}
int TotalReadCount() const { return readCount + readAsAddrCount; }
int FirstRead() const { return firstReadAsAddr < firstRead ? firstReadAsAddr : firstRead; }
int LastRead() const { return lastReadAsAddr > lastRead ? lastReadAsAddr : lastRead; }
void MarkRead(u32 addr) {
if (firstRead == -1)
firstRead = addr;
lastRead = addr;
readCount++;
used = true;
}
void MarkReadAsAddr(u32 addr) {
if (firstReadAsAddr == -1)
firstReadAsAddr = addr;
lastReadAsAddr = addr;
readAsAddrCount++;
used = true;
}
void MarkWrite(u32 addr) {
if (firstWrite == -1)
firstWrite = addr;
lastWrite = addr;
writeCount++;
used = true;
}
};
struct AnalysisResults
{
int x;
struct AnalysisResults {
RegisterAnalysisResults r[MIPS_NUM_GPRS];
};
AnalysisResults Analyze(u32 address);
bool IsRegisterUsed(u32 reg, u32 addr);
void ScanForFunctions(u32 startAddr, u32 endAddr);
void CompileLeafs();
std::vector<int> GetInputRegs(u32 op);
std::vector<int> GetOutputRegs(u32 op);
std::vector<MIPSGPReg> GetInputRegs(MIPSOpcode op);
std::vector<MIPSGPReg> GetOutputRegs(MIPSOpcode op);
int GetOutReg(u32 op);
bool ReadsFromReg(u32 op, u32 reg);
bool IsDelaySlotNice(u32 branch, u32 delayslot);
bool IsDelaySlotNiceReg(u32 branchOp, u32 op, int reg1, int reg2 = 0);
bool IsDelaySlotNiceVFPU(u32 branchOp, u32 op);
bool IsDelaySlotNiceFPU(u32 branchOp, u32 op);
bool IsSyscall(u32 op);
MIPSGPReg GetOutGPReg(MIPSOpcode op);
bool ReadsFromGPReg(MIPSOpcode op, MIPSGPReg reg);
bool IsDelaySlotNiceReg(MIPSOpcode branchOp, MIPSOpcode op, MIPSGPReg reg1, MIPSGPReg reg2 = MIPS_REG_ZERO);
bool IsDelaySlotNiceVFPU(MIPSOpcode branchOp, MIPSOpcode op);
bool IsDelaySlotNiceFPU(MIPSOpcode branchOp, MIPSOpcode op);
bool IsSyscall(MIPSOpcode op);
void Shutdown();
@@ -70,7 +95,7 @@ namespace MIPSAnalyst
{
DebugInterface* cpu;
u32 opcodeAddress;
u32 encodedOpcode;
MIPSOpcode encodedOpcode;
// shared between branches and conditional moves
bool isConditional;
+29 -12
View File
@@ -2,10 +2,27 @@
#include "stdafx.h"
#endif
#include "MIPSAsm.h"
#include <cstdarg>
namespace MIPSAsm
{
char errorMessage[512];
void SetAssembleError(const char* format, ...)
{
va_list args;
va_start(args,format);
vsprintf(errorMessage,format,args);
va_end (args);
}
char* GetAssembleError()
{
return errorMessage;
}
void SplitLine(const char* Line, char* Name, char* Arguments)
{
while (*Line == ' ' || *Line == '\t') Line++;
@@ -30,7 +47,7 @@ void SplitLine(const char* Line, char* Name, char* Arguments)
*Arguments = 0;
}
bool MipsAssembleOpcode(char* line, DebugInterface* cpu, u32 address, u32& dest)
bool MipsAssembleOpcode(const char* line, DebugInterface* cpu, u32 address, u32& dest)
{
char name[64],args[256];
SplitLine(line,name,args);
@@ -51,7 +68,7 @@ bool MipsAssembleOpcode(char* line, DebugInterface* cpu, u32 address, u32& dest)
return true;
}
int MipsGetRegister(char* source, int& RetLen)
int MipsGetRegister(const char* source, int& RetLen)
{
for (int z = 0; MipsRegister[z].name != NULL; z++)
{
@@ -69,7 +86,7 @@ int MipsGetRegister(char* source, int& RetLen)
return -1;
}
int MipsGetFloatRegister(char* source, int& RetLen)
int MipsGetFloatRegister(const char* source, int& RetLen)
{
for (int z = 0; MipsFloatRegister[z].name != NULL; z++)
{
@@ -87,7 +104,7 @@ int MipsGetFloatRegister(char* source, int& RetLen)
return -1;
}
bool MipsCheckImmediate(char* Source, char* Dest, int& RetLen)
bool MipsCheckImmediate(const char* Source, char* Dest, int& RetLen)
{
int BufferPos = 0;
int l;
@@ -166,9 +183,9 @@ bool CMipsInstruction::Load(char* Name, char* Params, int RamPos)
{
if (paramfail == true)
{
// PrintError(ERROR_ERROR,"Parameter failure \"%s\"",Params);
SetAssembleError("Parameter failure \"%s\"",Params);
} else {
// PrintError(ERROR_ERROR,"Invalid opcode \"%s\"",Name);
SetAssembleError("Invalid opcode \"%s\"",Name);
}
}
return false;
@@ -181,7 +198,7 @@ bool CMipsInstruction::LoadEncoding(const tMipsOpcode& SourceOpcode, char* Line)
int RetLen;
bool Immediate = false;
char* SourceEncoding = SourceOpcode.encoding;
const char *SourceEncoding = SourceOpcode.encoding;
char* OriginalLine = Line;
while (*Line == ' ' || *Line == '\t') Line++;
@@ -301,7 +318,7 @@ bool CMipsInstruction::Validate()
if (num > 0x20000 || num < (-0x20000))
{
//QueueError(ERROR_ERROR,"Branch target %08X out of range",Vars.Immediate);
SetAssembleError("Branch target %08X out of range",Vars.Immediate);
return false;
}
Vars.Immediate = num >> 2;
@@ -312,7 +329,7 @@ bool CMipsInstruction::Validate()
case MIPS_IMMEDIATE5:
if (Vars.Immediate > 0x1F)
{
// QueueError(ERROR_ERROR,"Immediate value %02X out of range",Vars.OriginalImmediate);
SetAssembleError("Immediate value %02X out of range",Vars.OriginalImmediate);
return false;
}
break;
@@ -321,7 +338,7 @@ bool CMipsInstruction::Validate()
case MIPS_IMMEDIATE16:
if (abs(Vars.Immediate) > 0x0000FFFF)
{
// QueueError(ERROR_ERROR,"Immediate value %04X out of range",Vars.OriginalImmediate);
SetAssembleError("Immediate value %04X out of range",Vars.OriginalImmediate);
return false;
}
Vars.Immediate &= 0x0000FFFF;
@@ -329,7 +346,7 @@ bool CMipsInstruction::Validate()
case MIPS_IMMEDIATE20:
if (abs(Vars.Immediate) > 0x000FFFFF)
{
// QueueError(ERROR_ERROR,"Immediate value %08X out of range",Vars.OriginalImmediate);
SetAssembleError("Immediate value %08X out of range",Vars.OriginalImmediate);
return false;
}
Vars.Immediate &= 0x000FFFFF;
@@ -337,7 +354,7 @@ bool CMipsInstruction::Validate()
case MIPS_IMMEDIATE26:
if (abs(Vars.Immediate) > 0x03FFFFFF)
{
// QueueError(ERROR_ERROR,"Immediate value %08X out of range",Vars.OriginalImmediate);
SetAssembleError("Immediate value %08X out of range",Vars.OriginalImmediate);
return false;
}
Vars.Immediate &= 0x03FFFFFF;
+4 -2
View File
@@ -6,9 +6,9 @@
namespace MIPSAsm
{
bool MipsAssembleOpcode(char* line, DebugInterface* cpu, u32 address, u32& dest);
bool MipsAssembleOpcode(const char* line, DebugInterface* cpu, u32 address, u32& dest);
typedef enum eMipsImmediateType { MIPS_NOIMMEDIATE, MIPS_IMMEDIATE5,
enum eMipsImmediateType { MIPS_NOIMMEDIATE, MIPS_IMMEDIATE5,
MIPS_IMMEDIATE16, MIPS_IMMEDIATE20, MIPS_IMMEDIATE26 };
typedef struct {
@@ -39,4 +39,6 @@ private:
u32 encoding;
};
char* GetAssembleError();
}
+3 -3
View File
@@ -4,14 +4,14 @@ namespace MIPSAsm
{
typedef struct {
char* name;
char* encoding;
const char *name;
const char *encoding;
unsigned int destencoding;
unsigned int flags;
} tMipsOpcode;
typedef struct {
char* name;
const char *name;
short num;
short len;
} tMipsRegister;
+13 -13
View File
@@ -31,10 +31,10 @@ namespace MIPSCodeUtils
u32 GetJumpTarget(u32 addr)
{
u32 op = Memory::Read_Instruction(addr);
if (op)
MIPSOpcode op = Memory::Read_Instruction(addr);
if (op != 0)
{
u32 info = MIPSGetInfo(op);
MIPSInfo info = MIPSGetInfo(op);
if ((info & IS_JUMP) && (info & IN_IMM26))
{
u32 target = (addr & 0xF0000000) | ((op&0x03FFFFFF) << 2);
@@ -49,10 +49,10 @@ namespace MIPSCodeUtils
u32 GetBranchTarget(u32 addr)
{
u32 op = Memory::Read_Instruction(addr);
if (op)
MIPSOpcode op = Memory::Read_Instruction(addr);
if (op != 0)
{
u32 info = MIPSGetInfo(op);
MIPSInfo info = MIPSGetInfo(op);
if (info & IS_CONDBRANCH)
{
return addr + 4 + ((signed short)(op&0xFFFF)<<2);
@@ -66,10 +66,10 @@ namespace MIPSCodeUtils
u32 GetBranchTargetNoRA(u32 addr)
{
u32 op = Memory::Read_Instruction(addr);
if (op)
MIPSOpcode op = Memory::Read_Instruction(addr);
if (op != 0)
{
u32 info = MIPSGetInfo(op);
MIPSInfo info = MIPSGetInfo(op);
if ((info & IS_CONDBRANCH) && !(info & OUT_RA))
{
return addr + 4 + ((signed short)(op&0xFFFF)<<2);
@@ -83,10 +83,10 @@ namespace MIPSCodeUtils
u32 GetSureBranchTarget(u32 addr)
{
u32 op = Memory::Read_Instruction(addr);
if (op)
MIPSOpcode op = Memory::Read_Instruction(addr);
if (op != 0)
{
u32 info = MIPSGetInfo(op);
MIPSInfo info = MIPSGetInfo(op);
if (info & IS_CONDBRANCH)
{
bool sure;
@@ -133,7 +133,7 @@ namespace MIPSCodeUtils
return INVALIDTARGET;
}
bool IsVFPUBranch(u32 op) {
bool IsVFPUBranch(MIPSOpcode op) {
return (MIPSGetInfo(op) & (IS_VFPU | IS_CONDBRANCH)) == (IS_VFPU | IS_CONDBRANCH);
}
}
+5 -5
View File
@@ -38,11 +38,11 @@
#define MIPS_GET_OP(op) ((op>>26) & 0x3F)
#define MIPS_GET_FUNC(op) (op & 0x3F)
#define MIPS_GET_SA(op) (op>>6 & 0x1F)
#define MIPS_GET_SA(op) ((op>>6) & 0x1F)
#define MIPS_GET_RS(op) ((op>>21) & 0x1F)
#define MIPS_GET_RT(op) ((op>>16) & 0x1F)
#define MIPS_GET_RD(op) ((op>>11) & 0x1F)
#define MIPS_GET_RS(op) MIPSGPReg((op>>21) & 0x1F)
#define MIPS_GET_RT(op) MIPSGPReg((op>>16) & 0x1F)
#define MIPS_GET_RD(op) MIPSGPReg((op>>11) & 0x1F)
#define MIPS_GET_FS(op) ((op>>11) & 0x1F)
#define MIPS_GET_FT(op) ((op>>16) & 0x1F)
@@ -57,5 +57,5 @@ namespace MIPSCodeUtils
u32 GetBranchTargetNoRA(u32 addr);
u32 GetJumpTarget(u32 addr);
u32 GetSureBranchTarget(u32 addr);
bool IsVFPUBranch(u32 op);
bool IsVFPUBranch(MIPSOpcode op);
}
+2 -2
View File
@@ -121,7 +121,7 @@ const char *MIPSDebugInterface::disasm(unsigned int address, unsigned int align)
}
unsigned int MIPSDebugInterface::readMemory(unsigned int address)
{
return Memory::Read_U32(address);
return Memory::Read_Instruction(address).encoding;
}
bool MIPSDebugInterface::isAlive()
@@ -171,7 +171,7 @@ bool MIPSDebugInterface::getSymbolValue(char* symbol, u32& dest)
return symbolMap.getSymbolValue(symbol,dest);
}
bool MIPSDebugInterface::initExpression(char* exp, PostfixExpression& dest)
bool MIPSDebugInterface::initExpression(const char* exp, PostfixExpression& dest)
{
MipsExpressionFunctions funcs(this);
return initPostfixExpression(exp,&funcs,dest);
+1 -1
View File
@@ -42,7 +42,7 @@ public:
virtual const char *getDescription(unsigned int address);
virtual const char *findSymbolForAddress(unsigned int address);
virtual bool getSymbolValue(char* symbol, u32& dest);
virtual bool initExpression(char* exp, PostfixExpression& dest);
virtual bool initExpression(const char* exp, PostfixExpression& dest);
virtual bool parseExpression(PostfixExpression& exp, u32& dest);
//overridden functions
+33 -33
View File
@@ -56,12 +56,12 @@ namespace MIPSDis
return temp;
}
void Dis_Generic(u32 op, char *out)
void Dis_Generic(MIPSOpcode op, char *out)
{
sprintf(out, "%s\t --- unknown ---", MIPSGetName(op));
}
void Dis_mxc1(u32 op, char *out)
void Dis_mxc1(MIPSOpcode op, char *out)
{
int fs = _FS;
int rt = _RT;
@@ -69,24 +69,24 @@ namespace MIPSDis
sprintf(out, "%s\t%s, %s",name,RN(rt),FN(fs));
}
void Dis_FPU3op(u32 op, char *out)
void Dis_FPU3op(MIPSOpcode op, char *out)
{
int ft = _FT;
int fs = _FS;
int fd = _FD;;
int fd = _FD;
const char *name = MIPSGetName(op);
sprintf(out, "%s\t%s, %s, %s",name,FN(fd),FN(fs),FN(ft));
}
void Dis_FPU2op(u32 op, char *out)
void Dis_FPU2op(MIPSOpcode op, char *out)
{
int fs = _FS;
int fd = _FD;;
int fd = _FD;
const char *name = MIPSGetName(op);
sprintf(out, "%s\t%s, %s",name,FN(fd),FN(fs));
}
void Dis_FPULS(u32 op, char *out)
void Dis_FPULS(MIPSOpcode op, char *out)
{
int offset = (signed short)(op&0xFFFF);
int ft = _FT;
@@ -94,7 +94,7 @@ namespace MIPSDis
const char *name = MIPSGetName(op);
sprintf(out, "%s\t%s, %s(%s)",name,FN(ft),SignedHex(offset),RN(rs));
}
void Dis_FPUComp(u32 op, char *out)
void Dis_FPUComp(MIPSOpcode op, char *out)
{
int fs = _FS;
int ft = _FT;
@@ -102,7 +102,7 @@ namespace MIPSDis
sprintf(out, "%s\t%s, %s",name,FN(fs),FN(ft));
}
void Dis_FPUBranch(u32 op, char *out)
void Dis_FPUBranch(MIPSOpcode op, char *out)
{
u32 off = disPC;
int imm = (signed short)(op&0xFFFF)<<2;
@@ -111,7 +111,7 @@ namespace MIPSDis
sprintf(out, "%s\t->$%08x",name,off);
}
void Dis_RelBranch(u32 op, char *out)
void Dis_RelBranch(MIPSOpcode op, char *out)
{
u32 off = disPC;
int imm = (signed short)(op&0xFFFF)<<2;
@@ -122,7 +122,7 @@ namespace MIPSDis
sprintf(out, "%s\t%s, ->$%08x",name,RN(rs),off);
}
void Dis_Syscall(u32 op, char *out)
void Dis_Syscall(MIPSOpcode op, char *out)
{
u32 callno = (op>>6) & 0xFFFFF; //20 bits
int funcnum = callno & 0xFFF;
@@ -130,20 +130,20 @@ namespace MIPSDis
sprintf(out, "syscall\t %s",/*PSPHLE::GetModuleName(modulenum),*/GetFuncName(modulenum, funcnum));
}
void Dis_ToHiloTransfer(u32 op, char *out)
void Dis_ToHiloTransfer(MIPSOpcode op, char *out)
{
int rs = _RS;
const char *name = MIPSGetName(op);
sprintf(out, "%s\t%s",name,RN(rs));
}
void Dis_FromHiloTransfer(u32 op, char *out)
void Dis_FromHiloTransfer(MIPSOpcode op, char *out)
{
int rd = _RD;
const char *name = MIPSGetName(op);
sprintf(out, "%s\t%s",name,RN(rd));
}
void Dis_RelBranch2(u32 op, char *out)
void Dis_RelBranch2(MIPSOpcode op, char *out)
{
u32 off = disPC;
int imm = (signed short)(op&0xFFFF)<<2;
@@ -161,7 +161,7 @@ namespace MIPSDis
sprintf(out, "%s\t%s, %s, ->$%08x",name,RN(rt),RN(rs),off);
}
void Dis_IType(u32 op, char *out)
void Dis_IType(MIPSOpcode op, char *out)
{
s32 simm = (s32)(s16)(op & 0xFFFF);
u32 uimm = (u32)(u16)(op & 0xFFFF);
@@ -185,7 +185,7 @@ namespace MIPSDis
break;
}
}
void Dis_ori(u32 op, char *out)
void Dis_ori(MIPSOpcode op, char *out)
{
s32 simm = (s32)(s16)(op & 0xFFFF);
u32 uimm = (u32)(u16)(op & 0xFFFF);
@@ -198,7 +198,7 @@ namespace MIPSDis
sprintf(out, "%s\t%s, %s, 0x%X",name,RN(rt),RN(rs),uimm);
}
void Dis_IType1(u32 op, char *out)
void Dis_IType1(MIPSOpcode op, char *out)
{
u32 uimm = (u32)(u16)(op & 0xFFFF);
int rt = _RT;
@@ -206,7 +206,7 @@ namespace MIPSDis
sprintf(out, "%s\t%s, 0x%X",name,RN(rt),uimm);
}
void Dis_addi(u32 op, char *out)
void Dis_addi(MIPSOpcode op, char *out)
{
int imm = (signed short)(op&0xFFFF);
int rt = _RT;
@@ -217,7 +217,7 @@ namespace MIPSDis
Dis_IType(op,out);
}
void Dis_ITypeMem(u32 op, char *out)
void Dis_ITypeMem(MIPSOpcode op, char *out)
{
int imm = (signed short)(op&0xFFFF);
int rt = _RT;
@@ -226,7 +226,7 @@ namespace MIPSDis
sprintf(out, "%s\t%s, %s(%s)",name,RN(rt),SignedHex(imm),RN(rs));
}
void Dis_RType2(u32 op, char *out)
void Dis_RType2(MIPSOpcode op, char *out)
{
int rs = _RS;
int rd = _RD;
@@ -234,7 +234,7 @@ namespace MIPSDis
sprintf(out, "%s\t%s, %s",name,RN(rd),RN(rs));
}
void Dis_RType3(u32 op, char *out)
void Dis_RType3(MIPSOpcode op, char *out)
{
int rt = _RT;
int rs = _RS;
@@ -243,7 +243,7 @@ namespace MIPSDis
sprintf(out, "%s\t%s, %s, %s",name,RN(rd),RN(rs),RN(rt));
}
void Dis_addu(u32 op, char *out)
void Dis_addu(MIPSOpcode op, char *out)
{
int rt = _RT;
int rs = _RS;
@@ -252,14 +252,14 @@ namespace MIPSDis
if (rs==0 && rt==0)
sprintf(out,"li\t%s, 0",RN(rd));
else if (rs == 0)
sprintf(out,"mov\t%s, %s",RN(rd),RN(rt));
sprintf(out,"move\t%s, %s",RN(rd),RN(rt));
else if (rt == 0)
sprintf(out,"mov\t%s, %s",RN(rd),RN(rs));
sprintf(out,"move\t%s, %s",RN(rd),RN(rs));
else
sprintf(out, "%s\t%s, %s, %s",name,RN(rd),RN(rs),RN(rt));
}
void Dis_ShiftType(u32 op, char *out)
void Dis_ShiftType(MIPSOpcode op, char *out)
{
int rt = _RT;
int rs = _RS;
@@ -273,7 +273,7 @@ namespace MIPSDis
sprintf(out, "%s\t%s, %s, 0x%X",name,RN(rd),RN(rt),sa);
}
void Dis_VarShiftType(u32 op, char *out)
void Dis_VarShiftType(MIPSOpcode op, char *out)
{
int rt = _RT;
int rs = _RS;
@@ -283,7 +283,7 @@ namespace MIPSDis
}
void Dis_MulDivType(u32 op, char *out)
void Dis_MulDivType(MIPSOpcode op, char *out)
{
int rt = _RT;
int rs = _RS;
@@ -292,7 +292,7 @@ namespace MIPSDis
}
void Dis_Special3(u32 op, char *out)
void Dis_Special3(MIPSOpcode op, char *out)
{
int rs = _RS;
int Rt = _RT;
@@ -316,14 +316,14 @@ namespace MIPSDis
}
}
void Dis_JumpType(u32 op, char *out)
void Dis_JumpType(MIPSOpcode op, char *out)
{
u32 off = ((op & 0x03FFFFFF) << 2);
u32 addr = (disPC & 0xF0000000) | off;
const char *name = MIPSGetName(op);
sprintf(out, "%s\t->$%08x",name,addr);
}
void Dis_JumpRegType(u32 op, char *out)
void Dis_JumpRegType(MIPSOpcode op, char *out)
{
int rs = (op>>21)&0x1f;
const char *name = MIPSGetName(op);
@@ -331,7 +331,7 @@ namespace MIPSDis
}
void Dis_Allegrex(u32 op, char *out)
void Dis_Allegrex(MIPSOpcode op, char *out)
{
int rt = _RT;
int rd = _RD;
@@ -339,7 +339,7 @@ namespace MIPSDis
sprintf(out,"%s\t%s,%s",name,RN(rd),RN(rt));
}
void Dis_Allegrex2(u32 op, char *out)
void Dis_Allegrex2(MIPSOpcode op, char *out)
{
int rt = _RT;
int rd = _RD;
@@ -347,7 +347,7 @@ namespace MIPSDis
sprintf(out,"%s\t%s,%s",name,RN(rd),RN(rt));
}
void Dis_Emuhack(u32 op, char *out)
void Dis_Emuhack(MIPSOpcode op, char *out)
{
//const char *name = MIPSGetName(op);
//sprintf(out,"%s\t-",name);
+33 -32
View File
@@ -17,45 +17,46 @@
#pragma once
#include "../../Globals.h"
#include "Globals.h"
#include "Core/MIPS/MIPS.h"
extern u32 disPC;
namespace MIPSDis
{
void Dis_Unknown(u32 op, char *out);
void Dis_Unimpl(u32 op, char *out);
void Dis_Syscall(u32 op, char *out);
void Dis_Unknown(MIPSOpcode op, char *out);
void Dis_Unimpl(MIPSOpcode op, char *out);
void Dis_Syscall(MIPSOpcode op, char *out);
void Dis_mxc1(u32 op, char *out);
void Dis_addi(u32 op, char *out);
void Dis_addu(u32 op, char *out);
void Dis_RelBranch2(u32 op, char *out);
void Dis_RelBranch(u32 op, char *out);
void Dis_Generic(u32 op, char *out);
void Dis_IType(u32 op, char *out);
void Dis_IType1(u32 op, char *out);
void Dis_ITypeMem(u32 op, char *out);
void Dis_RType2(u32 op, char *out);
void Dis_RType3(u32 op, char *out);
void Dis_MulDivType(u32 op, char *out);
void Dis_ShiftType(u32 op, char *out);
void Dis_VarShiftType(u32 op, char *out);
void Dis_FPU3op(u32 op, char *out);
void Dis_FPU2op(u32 op, char *out);
void Dis_FPULS(u32 op, char *out);
void Dis_FPUComp(u32 op, char *out);
void Dis_FPUBranch(u32 op, char *out);
void Dis_ori(u32 op, char *out);
void Dis_Special3(u32 op, char *out);
void Dis_mxc1(MIPSOpcode op, char *out);
void Dis_addi(MIPSOpcode op, char *out);
void Dis_addu(MIPSOpcode op, char *out);
void Dis_RelBranch2(MIPSOpcode op, char *out);
void Dis_RelBranch(MIPSOpcode op, char *out);
void Dis_Generic(MIPSOpcode op, char *out);
void Dis_IType(MIPSOpcode op, char *out);
void Dis_IType1(MIPSOpcode op, char *out);
void Dis_ITypeMem(MIPSOpcode op, char *out);
void Dis_RType2(MIPSOpcode op, char *out);
void Dis_RType3(MIPSOpcode op, char *out);
void Dis_MulDivType(MIPSOpcode op, char *out);
void Dis_ShiftType(MIPSOpcode op, char *out);
void Dis_VarShiftType(MIPSOpcode op, char *out);
void Dis_FPU3op(MIPSOpcode op, char *out);
void Dis_FPU2op(MIPSOpcode op, char *out);
void Dis_FPULS(MIPSOpcode op, char *out);
void Dis_FPUComp(MIPSOpcode op, char *out);
void Dis_FPUBranch(MIPSOpcode op, char *out);
void Dis_ori(MIPSOpcode op, char *out);
void Dis_Special3(MIPSOpcode op, char *out);
void Dis_ToHiloTransfer(u32 op, char *out);
void Dis_FromHiloTransfer(u32 op, char *out);
void Dis_JumpType(u32 op, char *out);
void Dis_JumpRegType(u32 op, char *out);
void Dis_ToHiloTransfer(MIPSOpcode op, char *out);
void Dis_FromHiloTransfer(MIPSOpcode op, char *out);
void Dis_JumpType(MIPSOpcode op, char *out);
void Dis_JumpRegType(MIPSOpcode op, char *out);
void Dis_Allegrex(u32 op, char *out);
void Dis_Allegrex2(u32 op, char *out);
void Dis_Allegrex(MIPSOpcode op, char *out);
void Dis_Allegrex2(MIPSOpcode op, char *out);
void Dis_Emuhack(u32 op, char *out);
void Dis_Emuhack(MIPSOpcode op, char *out);
}
+31 -31
View File
@@ -82,7 +82,7 @@ inline const char *MN(int v, MatrixSize size)
return GetMatrixNotation(v, size);
}
inline const char *VSuff(u32 op)
inline const char *VSuff(MIPSOpcode op)
{
int a = (op>>7)&1;
int b = (op>>15)&1;
@@ -99,7 +99,7 @@ inline const char *VSuff(u32 op)
namespace MIPSDis
{
void Dis_SV(u32 op, char *out)
void Dis_SV(MIPSOpcode op, char *out)
{
int offset = (signed short)(op&0xFFFC);
int vt = ((op>>16)&0x1f)|((op&3)<<5);
@@ -108,7 +108,7 @@ namespace MIPSDis
sprintf(out, "%s\t%s, %d(%s)",name,VN(vt, V_Single),offset,RN(rs));
}
void Dis_SVQ(u32 op, char *out)
void Dis_SVQ(MIPSOpcode op, char *out)
{
int offset = (signed short)(op&0xFFFC);
int vt = (((op>>16)&0x1f))|((op&1)<<5);
@@ -119,7 +119,7 @@ namespace MIPSDis
strcat(out, ", wb");
}
void Dis_SVLRQ(u32 op, char *out)
void Dis_SVLRQ(MIPSOpcode op, char *out)
{
int offset = (signed short)(op&0xFFFC);
int vt = (((op>>16)&0x1f))|((op&1)<<5);
@@ -129,7 +129,7 @@ namespace MIPSDis
sprintf(out, "%s%s.q\t%s, %d(%s)",name,lr?"r":"l",VN(vt,V_Quad),offset,RN(rs));
}
void Dis_Mftv(u32 op, char *out)
void Dis_Mftv(MIPSOpcode op, char *out)
{
int vr = op & 0xFF;
int rt = _RT;
@@ -137,7 +137,7 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s",name,vr>127?"c":"", RN(rt), VN(vr, V_Single));
}
void Dis_VPFXST(u32 op, char *out)
void Dis_VPFXST(MIPSOpcode op, char *out)
{
int data = op & 0xFFFFF;
const char *name = MIPSGetName(op);
@@ -170,7 +170,7 @@ namespace MIPSDis
}
}
void Dis_VPFXD(u32 op, char *out)
void Dis_VPFXD(MIPSOpcode op, char *out)
{
int data = op & 0xFFFFF;
const char *name = MIPSGetName(op);
@@ -189,7 +189,7 @@ namespace MIPSDis
}
void Dis_Viim(u32 op, char *out)
void Dis_Viim(MIPSOpcode op, char *out)
{
int vt = _VT;
int imm = op&0xFFFF;
@@ -205,7 +205,7 @@ namespace MIPSDis
sprintf(out, "ARGH");
}
void Dis_Vcst(u32 op, char *out)
void Dis_Vcst(MIPSOpcode op, char *out)
{
int conNum = (op>>16) & 0x1f;
int vd = _VD;
@@ -239,14 +239,14 @@ namespace MIPSDis
}
void Dis_MatrixSet1(u32 op, char *out)
void Dis_MatrixSet1(MIPSOpcode op, char *out)
{
const char *name = MIPSGetName(op);
int vd = _VD;
MatrixSize sz = GetMtxSize(op);
sprintf(out, "%s%s\t%s",name,VSuff(op),MN(vd, sz));
}
void Dis_MatrixSet2(u32 op, char *out)
void Dis_MatrixSet2(MIPSOpcode op, char *out)
{
const char *name = MIPSGetName(op);
int vd = _VD;
@@ -254,7 +254,7 @@ namespace MIPSDis
MatrixSize sz = GetMtxSize(op);
sprintf(out, "%s%s\t%s, %s",name,VSuff(op),MN(vd, sz),MN(vs,sz));
}
void Dis_MatrixSet3(u32 op, char *out)
void Dis_MatrixSet3(MIPSOpcode op, char *out)
{
const char *name = MIPSGetName(op);
int vd = _VD;
@@ -264,7 +264,7 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s, %s",name,VSuff(op),MN(vd, sz),MN(vs,sz),MN(vt,sz));
}
void Dis_MatrixMult(u32 op, char *out)
void Dis_MatrixMult(MIPSOpcode op, char *out)
{
const char *name = MIPSGetName(op);
int vd = _VD;
@@ -274,7 +274,7 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s, %s",name,VSuff(op),MN(vd, sz),MN(Xpose(vs),sz),MN(vt,sz));
}
void Dis_VectorDot(u32 op, char *out)
void Dis_VectorDot(MIPSOpcode op, char *out)
{
const char *name = MIPSGetName(op);
int vd = _VD;
@@ -284,7 +284,7 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, V_Single), VN(vs,sz), VN(vt, sz));
}
void Dis_Vtfm(u32 op, char *out)
void Dis_Vtfm(MIPSOpcode op, char *out)
{
int vd = _VD;
int vs = _VS;
@@ -309,12 +309,12 @@ namespace MIPSDis
}
}
void Dis_Vflush(u32 op, char *out)
void Dis_Vflush(MIPSOpcode op, char *out)
{
sprintf(out,"vflush");
}
void Dis_Vcrs(u32 op, char *out)
void Dis_Vcrs(MIPSOpcode op, char *out)
{
const char *name = MIPSGetName(op);
int vt = _VT;
@@ -330,7 +330,7 @@ namespace MIPSDis
}
void Dis_Vcmp(u32 op, char *out)
void Dis_Vcmp(MIPSOpcode op, char *out)
{
const char *name = MIPSGetName(op);
int vt = _VT;
@@ -341,7 +341,7 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s, %s", name, VSuff(op), condNames[cond], VN(vs, sz), VN(vt,sz));
}
void Dis_Vcmov(u32 op, char *out)
void Dis_Vcmov(MIPSOpcode op, char *out)
{
const char *name = MIPSGetName(op);
VectorSize sz = GetVecSize(op);
@@ -361,7 +361,7 @@ namespace MIPSDis
}
void Dis_Vfad(u32 op, char *out)
void Dis_Vfad(MIPSOpcode op, char *out)
{
const char *name = MIPSGetName(op);
int vd = _VD;
@@ -370,7 +370,7 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s", name, VSuff(op), VN(vd, V_Single), VN(vs,sz));
}
void Dis_VScl(u32 op, char *out)
void Dis_VScl(MIPSOpcode op, char *out)
{
const char *name = MIPSGetName(op);
int vd = _VD;
@@ -380,14 +380,14 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs,sz), VN(vt, V_Single));
}
void Dis_VectorSet1(u32 op, char *out)
void Dis_VectorSet1(MIPSOpcode op, char *out)
{
const char *name = MIPSGetName(op);
int vd = _VD;
VectorSize sz = GetVecSize(op);
sprintf(out, "%s%s\t%s",name,VSuff(op),VN(vd, sz));
}
void Dis_VectorSet2(u32 op, char *out)
void Dis_VectorSet2(MIPSOpcode op, char *out)
{
const char *name = MIPSGetName(op);
int vd = _VD;
@@ -395,7 +395,7 @@ namespace MIPSDis
VectorSize sz = GetVecSize(op);
sprintf(out, "%s%s\t%s, %s",name,VSuff(op),VN(vd, sz),VN(vs, sz));
}
void Dis_VectorSet3(u32 op, char *out)
void Dis_VectorSet3(MIPSOpcode op, char *out)
{
const char *name = MIPSGetName(op);
int vd = _VD;
@@ -405,7 +405,7 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs,sz), VN(vt, sz));
}
void Dis_VRot(u32 op, char *out)
void Dis_VRot(MIPSOpcode op, char *out)
{
int vd = _VD;
int vs = _VS;
@@ -439,7 +439,7 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s, %s",name,VSuff(op),VN(vd, sz),VN(vs, V_Single),temp);
}
void Dis_CrossQuat(u32 op, char *out)
void Dis_CrossQuat(MIPSOpcode op, char *out)
{
VectorSize sz = GetVecSize(op);
const char *name;
@@ -464,7 +464,7 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs,sz), VN(vt, sz));
}
void Dis_Vbfy(u32 op, char *out)
void Dis_Vbfy(MIPSOpcode op, char *out)
{
VectorSize sz = GetVecSize(op);
int vd = _VD;
@@ -473,7 +473,7 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s",name,VSuff(op),VN(vd, sz),VN(vs, sz));
}
void Dis_Vf2i(u32 op, char *out)
void Dis_Vf2i(MIPSOpcode op, char *out)
{
VectorSize sz = GetVecSize(op);
int vd = _VD;
@@ -483,7 +483,7 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s, %i",name,VSuff(op),VN(vd, sz),VN(vs, sz),imm);
}
void Dis_Vs2i(u32 op, char *out)
void Dis_Vs2i(MIPSOpcode op, char *out)
{
VectorSize sz = GetVecSize(op);
int vd = _VD;
@@ -492,7 +492,7 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s",name,VSuff(op),VN(vd, sz),VN(vs, sz));
}
void Dis_Vi2x(u32 op, char *out)
void Dis_Vi2x(MIPSOpcode op, char *out)
{
VectorSize sz = GetVecSize(op);
VectorSize dsz = GetHalfVectorSize(sz);
@@ -505,7 +505,7 @@ namespace MIPSDis
sprintf(out, "%s%s\t%s, %s",name,VSuff(op),VN(vd, dsz),VN(vs, sz));
}
void Dis_VBranch(u32 op, char *out)
void Dis_VBranch(MIPSOpcode op, char *out)
{
u32 off = disPC;
int imm = (signed short)(op&0xFFFF)<<2;
+30 -30
View File
@@ -23,38 +23,38 @@ extern u32 disPC;
namespace MIPSDis
{
void Dis_Mftv(u32 op, char *out);
void Dis_Mftv(MIPSOpcode op, char *out);
void Dis_SV(u32 op, char *out);
void Dis_SVQ(u32 op, char *out);
void Dis_SVLRQ(u32 op, char *out);
void Dis_SV(MIPSOpcode op, char *out);
void Dis_SVQ(MIPSOpcode op, char *out);
void Dis_SVLRQ(MIPSOpcode op, char *out);
void Dis_MatrixSet1(u32 op, char *out);
void Dis_MatrixSet2(u32 op, char *out);
void Dis_MatrixSet3(u32 op, char *out);
void Dis_MatrixMult(u32 op, char *out);
void Dis_MatrixSet1(MIPSOpcode op, char *out);
void Dis_MatrixSet2(MIPSOpcode op, char *out);
void Dis_MatrixSet3(MIPSOpcode op, char *out);
void Dis_MatrixMult(MIPSOpcode op, char *out);
void Dis_VectorDot(u32 op, char *out);
void Dis_Vfad(u32 op, char *out);
void Dis_VectorSet1(u32 op, char *out);
void Dis_VectorSet2(u32 op, char *out);
void Dis_VectorSet3(u32 op, char *out);
void Dis_VRot(u32 op, char *out);
void Dis_VScl(u32 op, char *out);
void Dis_VectorDot(MIPSOpcode op, char *out);
void Dis_Vfad(MIPSOpcode op, char *out);
void Dis_VectorSet1(MIPSOpcode op, char *out);
void Dis_VectorSet2(MIPSOpcode op, char *out);
void Dis_VectorSet3(MIPSOpcode op, char *out);
void Dis_VRot(MIPSOpcode op, char *out);
void Dis_VScl(MIPSOpcode op, char *out);
void Dis_VPFXST(u32 op, char *out);
void Dis_VPFXD(u32 op, char *out);
void Dis_Vcrs(u32 op, char *out);
void Dis_Viim(u32 op, char *out);
void Dis_Vcst(u32 op, char *out);
void Dis_CrossQuat(u32 op, char *out);
void Dis_Vtfm(u32 op, char *out);
void Dis_Vcmp(u32 op, char *out);
void Dis_Vcmov(u32 op, char *out);
void Dis_Vflush(u32 op, char *out);
void Dis_Vbfy(u32 op, char *out);
void Dis_Vf2i(u32 op, char *out);
void Dis_Vi2x(u32 op, char *out);
void Dis_Vs2i(u32 op, char *out);
void Dis_VBranch(u32 op, char *out);
void Dis_VPFXST(MIPSOpcode op, char *out);
void Dis_VPFXD(MIPSOpcode op, char *out);
void Dis_Vcrs(MIPSOpcode op, char *out);
void Dis_Viim(MIPSOpcode op, char *out);
void Dis_Vcst(MIPSOpcode op, char *out);
void Dis_CrossQuat(MIPSOpcode op, char *out);
void Dis_Vtfm(MIPSOpcode op, char *out);
void Dis_Vcmp(MIPSOpcode op, char *out);
void Dis_Vcmov(MIPSOpcode op, char *out);
void Dis_Vflush(MIPSOpcode op, char *out);
void Dis_Vbfy(MIPSOpcode op, char *out);
void Dis_Vf2i(MIPSOpcode op, char *out);
void Dis_Vi2x(MIPSOpcode op, char *out);
void Dis_Vs2i(MIPSOpcode op, char *out);
void Dis_VBranch(MIPSOpcode op, char *out);
}
+53 -30
View File
@@ -66,13 +66,13 @@ static inline void SkipLikely()
int MIPS_SingleStep()
{
#if defined(ARM)
u32 op = Memory::ReadUnchecked_U32(mipsr4k.pc);
MIPSOpcode op = MIPSOpcode(Memory::ReadUnchecked_U32(mipsr4k.pc));
#else
u32 op = Memory::Read_Opcode_JIT(mipsr4k.pc);
MIPSOpcode op = Memory::Read_Opcode_JIT(mipsr4k.pc);
#endif
/*
// Choke on VFPU
u32 info = MIPSGetInfo(op);
MIPSInfo info = MIPSGetInfo(op);
if (info & IS_VFPU)
{
if (!Core_IsStepping() && !GetAsyncKeyState(VK_LSHIFT))
@@ -117,7 +117,7 @@ void MIPS_ClearDelaySlot()
namespace MIPSInt
{
void Int_Cache(u32 op)
void Int_Cache(MIPSOpcode op)
{
int imm = (s16)(op & 0xFFFF);
int rs = _RS;
@@ -145,7 +145,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Syscall(u32 op)
void Int_Syscall(MIPSOpcode op)
{
// Need to pre-move PC, as CallSyscall may result in a rescheduling!
// To do this neater, we'll need a little generated kernel loop that syscall can jump to and then RFI from
@@ -162,13 +162,13 @@ namespace MIPSInt
CallSyscall(op);
}
void Int_Sync(u32 op)
void Int_Sync(MIPSOpcode op)
{
//DEBUG_LOG(CPU, "sync");
PC += 4;
}
void Int_Break(u32 op)
void Int_Break(MIPSOpcode op)
{
Reporting::ReportMessage("BREAK instruction hit");
ERROR_LOG(CPU, "BREAK!");
@@ -177,7 +177,7 @@ namespace MIPSInt
PC += 4;
}
void Int_RelBranch(u32 op)
void Int_RelBranch(MIPSOpcode op)
{
int imm = (signed short)(op&0xFFFF)<<2;
int rs = _RS;
@@ -202,7 +202,7 @@ namespace MIPSInt
}
}
void Int_RelBranchRI(u32 op)
void Int_RelBranchRI(MIPSOpcode op)
{
int imm = (signed short)(op&0xFFFF)<<2;
int rs = _RS;
@@ -225,7 +225,7 @@ namespace MIPSInt
}
void Int_VBranch(u32 op)
void Int_VBranch(MIPSOpcode op)
{
int imm = (signed short)(op&0xFFFF)<<2;
u32 addr = PC + imm + 4;
@@ -243,7 +243,7 @@ namespace MIPSInt
}
}
void Int_FPUBranch(u32 op)
void Int_FPUBranch(MIPSOpcode op)
{
int imm = (signed short)(op&0xFFFF)<<2;
u32 addr = PC + imm + 4;
@@ -259,7 +259,7 @@ namespace MIPSInt
}
}
void Int_JumpType(u32 op)
void Int_JumpType(MIPSOpcode op)
{
if (mipsr4k.inDelaySlot)
_dbg_assert_msg_(CPU,0,"Jump in delay slot :(");
@@ -280,7 +280,7 @@ namespace MIPSInt
}
}
void Int_JumpRegType(u32 op)
void Int_JumpRegType(MIPSOpcode op)
{
if (mipsr4k.inDelaySlot)
{
@@ -306,7 +306,7 @@ namespace MIPSInt
}
}
void Int_IType(u32 op)
void Int_IType(MIPSOpcode op)
{
s32 simm = (s32)(s16)(op & 0xFFFF);
u32 uimm = (u32)(u16)(op & 0xFFFF);
@@ -338,7 +338,7 @@ namespace MIPSInt
PC += 4;
}
void Int_StoreSync(u32 op)
void Int_StoreSync(MIPSOpcode op)
{
int imm = (signed short)(op&0xFFFF);
int rt = _RT;
@@ -371,7 +371,7 @@ namespace MIPSInt
}
void Int_RType3(u32 op)
void Int_RType3(MIPSOpcode op)
{
int rt = _RT;
int rs = _RS;
@@ -419,7 +419,7 @@ namespace MIPSInt
}
void Int_ITypeMem(u32 op)
void Int_ITypeMem(MIPSOpcode op)
{
int imm = (signed short)(op&0xFFFF);
int rt = _RT;
@@ -489,7 +489,7 @@ namespace MIPSInt
PC += 4;
}
void Int_FPULS(u32 op)
void Int_FPULS(MIPSOpcode op)
{
s32 offset = (s16)(op&0xFFFF);
int ft = _FT;
@@ -507,7 +507,7 @@ namespace MIPSInt
PC += 4;
}
void Int_mxc1(u32 op)
void Int_mxc1(MIPSOpcode op)
{
int fs = _FS;
int rt = _RT;
@@ -526,7 +526,7 @@ namespace MIPSInt
PC += 4;
}
void Int_RType2(u32 op)
void Int_RType2(MIPSOpcode op)
{
int rs = _RS;
int rd = _RD;
@@ -571,7 +571,7 @@ namespace MIPSInt
PC += 4;
}
void Int_MulDivType(u32 op)
void Int_MulDivType(MIPSOpcode op)
{
int rt = _RT;
int rs = _RS;
@@ -674,7 +674,7 @@ namespace MIPSInt
}
void Int_ShiftType(u32 op)
void Int_ShiftType(MIPSOpcode op)
{
int rt = _RT;
int rs = _RS;
@@ -728,7 +728,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Allegrex(u32 op)
void Int_Allegrex(MIPSOpcode op)
{
int rt = _RT;
int rd = _RD;
@@ -771,7 +771,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Allegrex2(u32 op)
void Int_Allegrex2(MIPSOpcode op)
{
int rt = _RT;
int rd = _RD;
@@ -798,7 +798,30 @@ namespace MIPSInt
PC += 4;
}
void Int_Special3(u32 op)
void Int_Special2(MIPSOpcode op)
{
static int reported = 0;
switch (op & 0x3F)
{
case 36:
if (!reported) {
Reporting::ReportMessage("MFIC instruction hit (%08x) at %08x", op, currentMIPS->pc);
WARN_LOG(CPU,"MFIC Disable/Enable Interrupt CPU instruction");
reported = 1;
}
break;
case 38:
if (!reported) {
Reporting::ReportMessage("MTIC instruction hit (%08x) at %08x", op, currentMIPS->pc);
WARN_LOG(CPU,"MTIC Disable/Enable Interrupt CPU instruction");
reported = 1;
}
break;
}
PC += 4;
}
void Int_Special3(MIPSOpcode op)
{
int rs = _RS;
int rt = _RT;
@@ -832,7 +855,7 @@ namespace MIPSInt
PC += 4;
}
void Int_FPU2op(u32 op)
void Int_FPU2op(MIPSOpcode op)
{
int fs = _FS;
int fd = _FD;
@@ -865,7 +888,7 @@ namespace MIPSInt
PC += 4;
}
void Int_FPUComp(u32 op)
void Int_FPUComp(MIPSOpcode op)
{
int fs = _FS;
int ft = _FT;
@@ -921,7 +944,7 @@ namespace MIPSInt
PC += 4;
}
void Int_FPU3op(u32 op)
void Int_FPU3op(MIPSOpcode op)
{
int ft = _FT;
int fs = _FS;
@@ -940,7 +963,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Interrupt(u32 op)
void Int_Interrupt(MIPSOpcode op)
{
static int reported = 0;
switch (op & 1)
@@ -957,7 +980,7 @@ namespace MIPSInt
}
void Int_Emuhack(u32 op)
void Int_Emuhack(MIPSOpcode op)
{
_dbg_assert_msg_(CPU,0,"Trying to interpret emuhack instruction that can't be interpreted");
}
+29 -28
View File
@@ -25,33 +25,34 @@ int MIPS_SingleStep();
namespace MIPSInt
{
void Int_Unknown(u32 op);
void Int_Unimpl(u32 op);
void Int_Syscall(u32 op);
void Int_Unknown(MIPSOpcode op);
void Int_Unimpl(MIPSOpcode op);
void Int_Syscall(MIPSOpcode op);
void Int_mxc1(u32 op);
void Int_RelBranch(u32 op);
void Int_RelBranchRI(u32 op);
void Int_IType(u32 op);
void Int_ITypeMem(u32 op);
void Int_RType2(u32 op);
void Int_RType3(u32 op);
void Int_ShiftType(u32 op);
void Int_MulDivType(u32 op);
void Int_JumpType(u32 op);
void Int_JumpRegType(u32 op);
void Int_Allegrex2(u32 op);
void Int_FPULS(u32 op);
void Int_FPU3op(u32 op);
void Int_FPU2op(u32 op);
void Int_Allegrex(u32 op);
void Int_FPUComp(u32 op);
void Int_FPUBranch(u32 op);
void Int_Emuhack(u32 op);
void Int_Special3(u32 op);
void Int_Interrupt(u32 op);
void Int_Cache(u32 op);
void Int_Sync(u32 op);
void Int_Break(u32 op);
void Int_StoreSync(u32 op);
void Int_mxc1(MIPSOpcode op);
void Int_RelBranch(MIPSOpcode op);
void Int_RelBranchRI(MIPSOpcode op);
void Int_IType(MIPSOpcode op);
void Int_ITypeMem(MIPSOpcode op);
void Int_RType2(MIPSOpcode op);
void Int_RType3(MIPSOpcode op);
void Int_ShiftType(MIPSOpcode op);
void Int_MulDivType(MIPSOpcode op);
void Int_JumpType(MIPSOpcode op);
void Int_JumpRegType(MIPSOpcode op);
void Int_Allegrex2(MIPSOpcode op);
void Int_FPULS(MIPSOpcode op);
void Int_FPU3op(MIPSOpcode op);
void Int_FPU2op(MIPSOpcode op);
void Int_Allegrex(MIPSOpcode op);
void Int_FPUComp(MIPSOpcode op);
void Int_FPUBranch(MIPSOpcode op);
void Int_Emuhack(MIPSOpcode op);
void Int_Special2(MIPSOpcode op);
void Int_Special3(MIPSOpcode op);
void Int_Interrupt(MIPSOpcode op);
void Int_Cache(MIPSOpcode op);
void Int_Sync(MIPSOpcode op);
void Int_Break(MIPSOpcode op);
void Int_StoreSync(MIPSOpcode op);
}
+54 -54
View File
@@ -196,7 +196,7 @@ void EatPrefixes()
namespace MIPSInt
{
void Int_VPFX(u32 op)
void Int_VPFX(MIPSOpcode op)
{
int data = op & 0xFFFFF;
int regnum = (op >> 24) & 3;
@@ -204,7 +204,7 @@ namespace MIPSInt
PC += 4;
}
void Int_SVQ(u32 op)
void Int_SVQ(MIPSOpcode op)
{
int imm = (signed short)(op&0xFFFC);
int rs = _RS;
@@ -315,7 +315,7 @@ namespace MIPSInt
PC += 4;
}
void Int_VMatrixInit(u32 op)
void Int_VMatrixInit(MIPSOpcode op)
{
static const float idt[16] =
{
@@ -359,7 +359,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_VVectorInit(u32 op)
void Int_VVectorInit(MIPSOpcode op)
{
int vd = _VD;
VectorSize sz = GetVecSize(op);
@@ -387,7 +387,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Viim(u32 op)
void Int_Viim(MIPSOpcode op)
{
int vt = _VT;
s32 imm = (s16)(op&0xFFFF);
@@ -408,7 +408,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vidt(u32 op)
void Int_Vidt(MIPSOpcode op)
{
int vd = _VD;
VectorSize sz = GetVecSize(op);
@@ -435,7 +435,7 @@ namespace MIPSInt
EatPrefixes();
}
// The test really needs some work.
void Int_Vmmul(u32 op)
void Int_Vmmul(MIPSOpcode op)
{
float s[16];
float t[16];
@@ -468,7 +468,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vmscl(u32 op)
void Int_Vmscl(MIPSOpcode op)
{
float d[16];
float s[16];
@@ -496,7 +496,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vmmov(u32 op)
void Int_Vmmov(MIPSOpcode op)
{
float s[16];
int vd = _VD;
@@ -509,13 +509,13 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vflush(u32 op)
void Int_Vflush(MIPSOpcode op)
{
// DEBUG_LOG(CPU,"vflush");
PC += 4;
}
void Int_VV2Op(u32 op)
void Int_VV2Op(MIPSOpcode op)
{
float s[4], d[4];
int vd = _VD;
@@ -555,7 +555,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vocp(u32 op)
void Int_Vocp(MIPSOpcode op)
{
float s[4], d[4];
int vd = _VD;
@@ -573,7 +573,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vsocp(u32 op)
void Int_Vsocp(MIPSOpcode op)
{
float s[4], d[4];
int vd = _VD;
@@ -596,7 +596,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vsgn(u32 op)
void Int_Vsgn(MIPSOpcode op)
{
float s[4], d[4];
int vd = _VD;
@@ -627,7 +627,7 @@ namespace MIPSInt
return (int)round_ieee_754(param);
}
void Int_Vf2i(u32 op) {
void Int_Vf2i(MIPSOpcode op) {
float s[4];
int d[4];
int vd = _VD;
@@ -665,7 +665,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vi2f(u32 op)
void Int_Vi2f(MIPSOpcode op)
{
int s[4];
float d[4];
@@ -686,7 +686,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vh2f(u32 op)
void Int_Vh2f(MIPSOpcode op)
{
u32 s[4];
float d[4];
@@ -721,7 +721,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vf2h(u32 op)
void Int_Vf2h(MIPSOpcode op)
{
float s[4];
u32 d[4];
@@ -753,7 +753,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vx2i(u32 op)
void Int_Vx2i(MIPSOpcode op)
{
u32 s[4];
u32 d[4] = {0};
@@ -845,7 +845,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vi2x(u32 op)
void Int_Vi2x(MIPSOpcode op)
{
int s[4];
u32 d[2] = {0};
@@ -920,7 +920,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_ColorConv(u32 op)
void Int_ColorConv(MIPSOpcode op)
{
int vd = _VD;
int vs = _VS;
@@ -969,7 +969,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_VDot(u32 op)
void Int_VDot(MIPSOpcode op)
{
float s[4], t[4];
float d;
@@ -994,7 +994,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_VHdp(u32 op)
void Int_VHdp(MIPSOpcode op)
{
float s[4], t[4];
float d;
@@ -1019,7 +1019,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vbfy(u32 op)
void Int_Vbfy(MIPSOpcode op)
{
float s[4];
float d[4];
@@ -1051,7 +1051,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vsrt1(u32 op)
void Int_Vsrt1(MIPSOpcode op)
{
float s[4];
float d[4];
@@ -1074,7 +1074,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vsrt2(u32 op)
void Int_Vsrt2(MIPSOpcode op)
{
float s[4];
float d[4];
@@ -1097,7 +1097,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vsrt3(u32 op)
void Int_Vsrt3(MIPSOpcode op)
{
float s[4];
float d[4];
@@ -1120,7 +1120,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vsrt4(u32 op)
void Int_Vsrt4(MIPSOpcode op)
{
float s[4];
float d[4];
@@ -1143,7 +1143,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vcrs(u32 op)
void Int_Vcrs(MIPSOpcode op)
{
//half a cross product
float s[4], t[4];
@@ -1167,7 +1167,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vdet(u32 op)
void Int_Vdet(MIPSOpcode op)
{
float s[4], t[4];
float d[4];
@@ -1187,7 +1187,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vfad(u32 op)
void Int_Vfad(MIPSOpcode op)
{
float s[4];
float d;
@@ -1209,7 +1209,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vavg(u32 op)
void Int_Vavg(MIPSOpcode op)
{
float s[4];
float d;
@@ -1231,7 +1231,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_VScl(u32 op)
void Int_VScl(MIPSOpcode op)
{
float s[4];
float d[4];
@@ -1258,7 +1258,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vrnds(u32 op)
void Int_Vrnds(MIPSOpcode op)
{
int vd = _VD;
int seed = VI(vd);
@@ -1267,7 +1267,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_VrndX(u32 op)
void Int_VrndX(MIPSOpcode op)
{
float d[4];
int vd = _VD;
@@ -1290,7 +1290,7 @@ namespace MIPSInt
}
// Generates one line of a rotation matrix around one of the three axes
void Int_Vrot(u32 op)
void Int_Vrot(MIPSOpcode op)
{
int vd = _VD;
int vs = _VS;
@@ -1315,7 +1315,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vtfm(u32 op)
void Int_Vtfm(MIPSOpcode op)
{
int vd = _VD;
int vs = _VS;
@@ -1372,7 +1372,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_SV(u32 op)
void Int_SV(MIPSOpcode op)
{
s32 imm = (signed short)(op&0xFFFC);
int vt = ((op >> 16) & 0x1f) | ((op & 3) << 5);
@@ -1395,7 +1395,7 @@ namespace MIPSInt
}
void Int_Mftv(u32 op)
void Int_Mftv(MIPSOpcode op)
{
int imm = op & 0xFF;
int rt = _RT;
@@ -1433,7 +1433,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Vmfvc(u32 op) {
void Int_Vmfvc(MIPSOpcode op) {
int vs = _VS;
int imm = op & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
@@ -1442,7 +1442,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Vmtvc(u32 op) {
void Int_Vmtvc(MIPSOpcode op) {
int vs = _VS;
int imm = op & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
@@ -1451,7 +1451,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Vcst(u32 op)
void Int_Vcst(MIPSOpcode op)
{
int conNum = (op >> 16) & 0x1f;
int vd = _VD;
@@ -1465,7 +1465,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vcmp(u32 op)
void Int_Vcmp(MIPSOpcode op)
{
int vs = _VS;
int vt = _VT;
@@ -1527,7 +1527,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vminmax(u32 op) {
void Int_Vminmax(MIPSOpcode op) {
int vt = _VT;
int vs = _VS;
int vd = _VD;
@@ -1565,7 +1565,7 @@ namespace MIPSInt
}
// This doesn't quite pass all the tests :/
void Int_Vscmp(u32 op) {
void Int_Vscmp(MIPSOpcode op) {
int vt = _VT;
int vs = _VS;
int vd = _VD;
@@ -1588,7 +1588,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vsge(u32 op) {
void Int_Vsge(MIPSOpcode op) {
int vt = _VT;
int vs = _VS;
int vd = _VD;
@@ -1614,7 +1614,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vslt(u32 op) {
void Int_Vslt(MIPSOpcode op) {
int vt = _VT;
int vs = _VS;
int vd = _VD;
@@ -1641,7 +1641,7 @@ namespace MIPSInt
}
void Int_Vcmov(u32 op)
void Int_Vcmov(MIPSOpcode op)
{
int vs = _VS;
int vd = _VD;
@@ -1683,7 +1683,7 @@ namespace MIPSInt
EatPrefixes();
}
void Int_VecDo3(u32 op)
void Int_VecDo3(MIPSOpcode op)
{
int vd = _VD;
int vs = _VS;
@@ -1729,7 +1729,7 @@ bad:
}
void Int_CrossQuat(u32 op)
void Int_CrossQuat(MIPSOpcode op)
{
int vd = _VD;
int vs = _VS;
@@ -1764,7 +1764,7 @@ bad:
EatPrefixes();
}
void Int_Vlgb(u32 op)
void Int_Vlgb(MIPSOpcode op)
{
// S & D valid
Reporting::ReportMessage("vlgb not implemented");
@@ -1775,7 +1775,7 @@ bad:
// There has to be a concise way of expressing this in terms of
// bit manipulation on the raw floats.
void Int_Vwbn(u32 op) {
void Int_Vwbn(MIPSOpcode op) {
Reporting::ReportMessage("vwbn not implemented");
_dbg_assert_msg_(CPU,0,"vwbn not implemented");
PC += 4;
@@ -1807,7 +1807,7 @@ bad:
EatPrefixes();*/
}
void Int_Vsbn(u32 op)
void Int_Vsbn(MIPSOpcode op)
{
Reporting::ReportMessage("vsbn not implemented");
_dbg_assert_msg_(CPU,0,"vsbn not implemented");
@@ -1815,7 +1815,7 @@ bad:
EatPrefixes();
}
void Int_Vsbz(u32 op)
void Int_Vsbz(MIPSOpcode op)
{
Reporting::ReportMessage("vsbz not implemented");
_dbg_assert_msg_(CPU,0,"vsbz not implemented");
+56 -56
View File
@@ -25,60 +25,60 @@ int MIPS_SingleStep();
namespace MIPSInt
{
void Int_SV(u32 op);
void Int_SVQ(u32 op);
void Int_Mftv(u32 op);
void Int_MatrixSet(u32 op);
void Int_VecDo3(u32 op);
void Int_Vcst(u32 op);
void Int_VMatrixInit(u32 op);
void Int_VVectorInit(u32 op);
void Int_Vmmul(u32 op);
void Int_Vmscl(u32 op);
void Int_Vmmov(u32 op);
void Int_VV2Op(u32 op);
void Int_Vrot(u32 op);
void Int_VDot(u32 op);
void Int_VHdp(u32 op);
void Int_Vavg(u32 op);
void Int_Vfad(u32 op);
void Int_Vocp(u32 op);
void Int_Vsocp(u32 op);
void Int_Vsgn(u32 op);
void Int_Vtfm(u32 op);
void Int_Viim(u32 op);
void Int_VScl(u32 op);
void Int_Vidt(u32 op);
void Int_Vcmp(u32 op);
void Int_Vminmax(u32 op);
void Int_Vscmp(u32 op);
void Int_Vcrs(u32 op);
void Int_Vdet(u32 op);
void Int_Vcmov(u32 op);
void Int_CrossQuat(u32 op);
void Int_VPFX(u32 op);
void Int_Vflush(u32 op);
void Int_Vbfy(u32 op);
void Int_Vsrt1(u32 op);
void Int_Vsrt2(u32 op);
void Int_Vsrt3(u32 op);
void Int_Vsrt4(u32 op);
void Int_Vf2i(u32 op);
void Int_Vi2f(u32 op);
void Int_Vi2x(u32 op);
void Int_Vx2i(u32 op);
void Int_VBranch(u32 op);
void Int_Vrnds(u32 op);
void Int_VrndX(u32 op);
void Int_ColorConv(u32 op);
void Int_Vh2f(u32 op);
void Int_Vf2h(u32 op);
void Int_Vsge(u32 op);
void Int_Vslt(u32 op);
void Int_Vmfvc(u32 op);
void Int_Vmtvc(u32 op);
void Int_Vlgb(u32 op);
void Int_Vwbn(u32 op);
void Int_Vsbn(u32 op);
void Int_Vsbz(u32 op);
void Int_SV(MIPSOpcode op);
void Int_SVQ(MIPSOpcode op);
void Int_Mftv(MIPSOpcode op);
void Int_MatrixSet(MIPSOpcode op);
void Int_VecDo3(MIPSOpcode op);
void Int_Vcst(MIPSOpcode op);
void Int_VMatrixInit(MIPSOpcode op);
void Int_VVectorInit(MIPSOpcode op);
void Int_Vmmul(MIPSOpcode op);
void Int_Vmscl(MIPSOpcode op);
void Int_Vmmov(MIPSOpcode op);
void Int_VV2Op(MIPSOpcode op);
void Int_Vrot(MIPSOpcode op);
void Int_VDot(MIPSOpcode op);
void Int_VHdp(MIPSOpcode op);
void Int_Vavg(MIPSOpcode op);
void Int_Vfad(MIPSOpcode op);
void Int_Vocp(MIPSOpcode op);
void Int_Vsocp(MIPSOpcode op);
void Int_Vsgn(MIPSOpcode op);
void Int_Vtfm(MIPSOpcode op);
void Int_Viim(MIPSOpcode op);
void Int_VScl(MIPSOpcode op);
void Int_Vidt(MIPSOpcode op);
void Int_Vcmp(MIPSOpcode op);
void Int_Vminmax(MIPSOpcode op);
void Int_Vscmp(MIPSOpcode op);
void Int_Vcrs(MIPSOpcode op);
void Int_Vdet(MIPSOpcode op);
void Int_Vcmov(MIPSOpcode op);
void Int_CrossQuat(MIPSOpcode op);
void Int_VPFX(MIPSOpcode op);
void Int_Vflush(MIPSOpcode op);
void Int_Vbfy(MIPSOpcode op);
void Int_Vsrt1(MIPSOpcode op);
void Int_Vsrt2(MIPSOpcode op);
void Int_Vsrt3(MIPSOpcode op);
void Int_Vsrt4(MIPSOpcode op);
void Int_Vf2i(MIPSOpcode op);
void Int_Vi2f(MIPSOpcode op);
void Int_Vi2x(MIPSOpcode op);
void Int_Vx2i(MIPSOpcode op);
void Int_VBranch(MIPSOpcode op);
void Int_Vrnds(MIPSOpcode op);
void Int_VrndX(MIPSOpcode op);
void Int_ColorConv(MIPSOpcode op);
void Int_Vh2f(MIPSOpcode op);
void Int_Vf2h(MIPSOpcode op);
void Int_Vsge(MIPSOpcode op);
void Int_Vslt(MIPSOpcode op);
void Int_Vmfvc(MIPSOpcode op);
void Int_Vmtvc(MIPSOpcode op);
void Int_Vlgb(MIPSOpcode op);
void Int_Vwbn(MIPSOpcode op);
void Int_Vsbn(MIPSOpcode op);
void Int_Vsbz(MIPSOpcode op);
}
+5 -5
View File
@@ -44,15 +44,15 @@ namespace MIPSStackWalk {
return INVALIDTARGET;
}
bool IsSWInstr(u32 op) {
bool IsSWInstr(MIPSOpcode op) {
return (op & MIPSTABLE_IMM_MASK) == 0xAC000000;
}
bool IsAddImmInstr(u32 op) {
bool IsAddImmInstr(MIPSOpcode op) {
return (op & MIPSTABLE_IMM_MASK) == 0x20000000 || (op & MIPSTABLE_IMM_MASK) == 0x24000000;
}
bool IsMovRegsInstr(u32 op) {
bool IsMovRegsInstr(MIPSOpcode op) {
// TODO: There are more options here. Let's assume addu for now.
if ((op & MIPSTABLE_SPECIAL_MASK) == 0x00000021) {
return _RS == 0 || _RT == 0;
@@ -67,7 +67,7 @@ namespace MIPSStackWalk {
// It ought to be pretty close.
u32 stop = pc - 32 * 4;
for (; Memory::IsValidAddress(pc) && pc >= stop; pc -= 4) {
u32 op = Memory::Read_Instruction(pc);
MIPSOpcode op = Memory::Read_Instruction(pc);
// We're looking for a "mov fp, sp" close by a "addiu sp, sp, -N".
if (IsMovRegsInstr(op) && _RD == MIPS_REG_FP && (_RS == MIPS_REG_SP || _RT == MIPS_REG_SP)) {
@@ -83,7 +83,7 @@ namespace MIPSStackWalk {
int ra_offset = -1;
u32 stop = entry == INVALIDTARGET ? 0 : entry;
for (u32 pc = frame.pc; Memory::IsValidAddress(pc) && pc >= stop; pc -= 4) {
u32 op = Memory::Read_Instruction(pc);
MIPSOpcode op = Memory::Read_Instruction(pc);
// Here's where they store the ra address.
if (IsSWInstr(op) && _RT == MIPS_REG_RA && _RS == MIPS_REG_SP) {
+21 -21
View File
@@ -71,7 +71,7 @@ struct MIPSInstruction
#endif
MIPSInterpretFunc interpret;
//MIPSInstructionInfo information;
u32 flags;
MIPSInfo flags;
};
#define INVALID {-2}
@@ -80,7 +80,7 @@ struct MIPSInstruction
#ifndef FINAL
#define ENCODING(a) {a}
#define INSTR(name, comp, dis, inter, flags) {-1, N(name), comp, dis, inter, flags}
#define INSTR(name, comp, dis, inter, flags) {-1, N(name), comp, dis, inter, MIPSInfo(flags)}
#else
#define ENCODING(a) {a}
#define INSTR(name, comp, dis, inter, flags) {-1, comp, inter, flags}
@@ -257,9 +257,9 @@ const MIPSInstruction tableSpecial2[64] = // 011100 ..... ..... ..... ..... xxxx
INVALID_X_8,
//32
INVALID, INVALID, INVALID, INVALID,
INSTR("mfic", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("mfic", &Jit::Comp_Generic, Dis_Generic, Int_Special2, 0),
INVALID,
INSTR("mtic", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("mtic", &Jit::Comp_Generic, Dis_Generic, Int_Special2, 0),
INVALID,
//40
INVALID_X_8,
@@ -891,7 +891,7 @@ const MIPSInstruction *mipsTables[NumEncodings] =
//Todo : generate dispatcher functions from above tables
//instead of this horribly slow abomination
const MIPSInstruction *MIPSGetInstruction(u32 op)
const MIPSInstruction *MIPSGetInstruction(MIPSOpcode op)
{
MipsEncoding encoding = Imme;
const MIPSInstruction *instr = &tableImmediate[op>>26];
@@ -919,19 +919,19 @@ const MIPSInstruction *MIPSGetInstruction(u32 op)
void MIPSCompileOp(u32 op)
void MIPSCompileOp(MIPSOpcode op)
{
if (op==0)
return;
const MIPSInstruction *instr = MIPSGetInstruction(op);
const int info = MIPSGetInfo(op);
const MIPSInfo info = MIPSGetInfo(op);
if (instr)
{
if (instr->compile)
(MIPSComp::jit->*(instr->compile))(op); // woohoo, member functions pointers!
else
{
ERROR_LOG_REPORT(CPU,"MIPSCompileOp %08x failed",op);
ERROR_LOG_REPORT(CPU,"MIPSCompileOp %08x failed",op.encoding);
//MessageBox(0,"ARGH2",0,0);//compile an interpreter call
}
@@ -940,12 +940,12 @@ void MIPSCompileOp(u32 op)
}
else
{
ERROR_LOG_REPORT(CPU, "MIPSCompileOp: Invalid instruction %08x", op);
ERROR_LOG_REPORT(CPU, "MIPSCompileOp: Invalid instruction %08x", op.encoding);
}
}
void MIPSDisAsm(u32 op, u32 pc, char *out, bool tabsToSpaces)
void MIPSDisAsm(MIPSOpcode op, u32 pc, char *out, bool tabsToSpaces)
{
if (op == 0)
{
@@ -973,7 +973,7 @@ void MIPSDisAsm(u32 op, u32 pc, char *out, bool tabsToSpaces)
}
void MIPSInterpret(u32 op) //only for those rare ones
void MIPSInterpret(MIPSOpcode op) //only for those rare ones
{
//if ((op&0xFFFFF000) == 0xd0110000)
// Crash();
@@ -986,7 +986,7 @@ void MIPSInterpret(u32 op) //only for those rare ones
instr->interpret(op);
else
{
ERROR_LOG_REPORT(CPU, "Unknown instruction %08x at %08x", op, currentMIPS->pc);
ERROR_LOG_REPORT(CPU, "Unknown instruction %08x at %08x", op.encoding, currentMIPS->pc);
// Try to disassemble it
char disasm[256];
MIPSDisAsm(op, currentMIPS->pc, disasm);
@@ -1014,11 +1014,11 @@ int MIPSInterpret_RunUntil(u64 globalTicks)
// int cycles = 0;
{
again:
u32 op = Memory::Read_U32(curMips->pc);
//u32 op = Memory::Read_Opcode_JIT(mipsr4k.pc);
MIPSOpcode op = MIPSOpcode(Memory::Read_U32(curMips->pc));
//MIPSOpcode op = Memory::Read_Opcode_JIT(mipsr4k.pc);
/*
// Choke on VFPU
u32 info = MIPSGetInfo(op);
MIPSInfo info = MIPSGetInfo(op);
if (info & IS_VFPU)
{
if (!Core_IsStepping() && !GetAsyncKeyState(VK_LSHIFT))
@@ -1079,7 +1079,7 @@ static inline void DelayBranchTo(MIPSState *curMips, u32 where)
curMips->inDelaySlot = true;
}
const char *MIPSGetName(u32 op)
const char *MIPSGetName(MIPSOpcode op)
{
static const char *noname = "unk";
const MIPSInstruction *instr = MIPSGetInstruction(op);
@@ -1089,17 +1089,17 @@ const char *MIPSGetName(u32 op)
return instr->name;
}
u32 MIPSGetInfo(u32 op)
MIPSInfo MIPSGetInfo(MIPSOpcode op)
{
// int crunch = CRUNCH_MIPS_OP(op);
const MIPSInstruction *instr = MIPSGetInstruction(op);
if (instr)
return instr->flags;
else
return 0;
return MIPSInfo(BAD_INSTRUCTION);
}
MIPSInterpretFunc MIPSGetInterpretFunc(u32 op)
MIPSInterpretFunc MIPSGetInterpretFunc(MIPSOpcode op)
{
const MIPSInstruction *instr = MIPSGetInstruction(op);
if (instr->interpret)
@@ -1109,9 +1109,9 @@ MIPSInterpretFunc MIPSGetInterpretFunc(u32 op)
}
// TODO: Do something that makes sense here.
int MIPSGetInstructionCycleEstimate(u32 op)
int MIPSGetInstructionCycleEstimate(MIPSOpcode op)
{
u32 info = MIPSGetInfo(op);
MIPSInfo info = MIPSGetInfo(op);
if (info & DELAYSLOT)
return 2;
else
+48 -33
View File
@@ -17,7 +17,23 @@
#pragma once
#include "../../Globals.h"
#include "Globals.h"
#include "Core/MIPS/MIPS.h"
struct MIPSInfo {
MIPSInfo() {
value = 0;
}
explicit MIPSInfo(u32 v) : value(v) {
}
u32 operator & (const u32 &arg) const {
return value & arg;
}
u32 value;
};
#define CONDTYPE_MASK 0x00000007
#define CONDTYPE_EQ 0x00000001
@@ -40,50 +56,49 @@
#define IS_CONDMOVE 0x00000008
#define DELAYSLOT 0x00000010
#define BAD_INSTRUCTION 0x00000020
#define UNCONDITIONAL 0x00000040
#define LIKELY 0x00000080
#define IS_CONDBRANCH 0x00000100
#define IS_JUMP 0x00000200
#define LIKELY 0x00000040
#define IS_CONDBRANCH 0x00000080
#define IS_JUMP 0x00000100
#define IN_RS 0x00000400
#define IN_RS_ADDR (0x00000800 | IN_RS)
#define IN_RS_SHIFT (0x00001000 | IN_RS)
#define IN_RT 0x00002000
#define IN_SA 0x00004000
#define IN_IMM16 0x00008000
#define IN_IMM26 0x00010000
#define IN_MEM 0x00020000
#define IN_OTHER 0x00040000
#define IN_FPUFLAG 0x00080000
#define IN_RS 0x00000200
#define IN_RS_ADDR (0x00000400 | IN_RS)
#define IN_RS_SHIFT (0x00000800 | IN_RS)
#define IN_RT 0x00001000
#define IN_SA 0x00002000
#define IN_IMM16 0x00004000
#define IN_IMM26 0x00008000
#define IN_MEM 0x00010000
#define IN_OTHER 0x00020000
#define IN_FPUFLAG 0x00040000
#define OUT_RT 0x00100000
#define OUT_RD 0x00200000
#define OUT_RA 0x00400000
#define OUT_MEM 0x00800000
#define OUT_OTHER 0x01000000
#define OUT_FPUFLAG 0x02000000
#define OUT_EAT_PREFIX 0x04000000
#define OUT_RT 0x00080000
#define OUT_RD 0x00100000
#define OUT_RA 0x00200000
#define OUT_MEM 0x00400000
#define OUT_OTHER 0x00800000
#define OUT_FPUFLAG 0x01000000
#define OUT_EAT_PREFIX 0x02000000
#define VFPU_NO_PREFIX 0x08000000
#define IS_VFPU 0x80000000
#define VFPU_NO_PREFIX 0x04000000
#define IS_VFPU 0x08000000
#ifndef CDECL
#define CDECL
#endif
typedef void (CDECL *MIPSDisFunc)(u32 opcode, char *out);
typedef void (CDECL *MIPSInterpretFunc)(u32 opcode);
typedef void (CDECL *MIPSDisFunc)(MIPSOpcode opcode, char *out);
typedef void (CDECL *MIPSInterpretFunc)(MIPSOpcode opcode);
void MIPSCompileOp(u32 op);
void MIPSDisAsm(u32 op, u32 pc, char *out, bool tabsToSpaces = false);
u32 MIPSGetInfo(u32 op);
void MIPSInterpret(u32 op); //only for those rare ones
void MIPSCompileOp(MIPSOpcode op);
void MIPSDisAsm(MIPSOpcode op, u32 pc, char *out, bool tabsToSpaces = false);
MIPSInfo MIPSGetInfo(MIPSOpcode op);
void MIPSInterpret(MIPSOpcode op); //only for those rare ones
int MIPSInterpret_RunUntil(u64 globalTicks);
MIPSInterpretFunc MIPSGetInterpretFunc(u32 op);
MIPSInterpretFunc MIPSGetInterpretFunc(MIPSOpcode op);
int MIPSGetInstructionCycleEstimate(u32 op);
const char *MIPSGetName(u32 op);
int MIPSGetInstructionCycleEstimate(MIPSOpcode op);
const char *MIPSGetName(MIPSOpcode op);
void FillMIPSTables();
+2 -2
View File
@@ -226,7 +226,7 @@ VectorSize GetHalfVectorSize(VectorSize sz)
}
}
VectorSize GetVecSize(u32 op)
VectorSize GetVecSize(MIPSOpcode op)
{
int a = (op>>7)&1;
int b = (op>>15)&1;
@@ -241,7 +241,7 @@ VectorSize GetVecSize(u32 op)
}
}
MatrixSize GetMtxSize(u32 op)
MatrixSize GetMtxSize(MIPSOpcode op)
{
int a = (op>>7)&1;
int b = (op>>15)&1;
+2 -2
View File
@@ -65,8 +65,8 @@ inline int GetMtx(int matrixReg) {
return (matrixReg >> 2) & 7;
}
VectorSize GetVecSize(u32 op);
MatrixSize GetMtxSize(u32 op);
VectorSize GetVecSize(MIPSOpcode op);
MatrixSize GetMtxSize(MIPSOpcode op);
VectorSize GetHalfVectorSize(VectorSize sz);
int GetNumVectorElements(VectorSize sz);
int GetMatrixSide(MatrixSize sz);
+2 -2
View File
@@ -169,8 +169,8 @@ void Jit::ClearCache() {
GenerateFixedCode();
}
void Jit::ClearCacheAt(u32 em_address) {
ClearCache();
void Jit::ClearCacheAt(u32 em_address, int length) {
blocks.InvalidateICache(em_address, length);
}
Jit::Jit(MIPSState *mips) : blocks(mips, this), gpr(mips, &jo),mips_(mips)
+1 -1
View File
@@ -242,7 +242,7 @@ namespace MIPSComp
void WriteSyscallExit();
void ClearCache();
void ClearCacheAt(u32 em_address);
void ClearCacheAt(u32 em_address, int length = 4);
void RunLoopUntil(u64 globalticks);
void GenerateFixedCode();
+70 -66
View File
@@ -15,20 +15,24 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Jit.h"
#include "RegCache.h"
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Core/MIPS/x86/Jit.h"
#include "Core/MIPS/x86/RegCache.h"
#include <algorithm>
using namespace MIPSAnalyst;
#define _RS ((op>>21) & 0x1F)
#define _RT ((op>>16) & 0x1F)
#define _RD ((op>>11) & 0x1F)
#define _FS ((op>>11) & 0x1F)
#define _FT ((op>>16) & 0x1F)
#define _FD ((op>>6 ) & 0x1F)
#define _SA ((op>>6 ) & 0x1F)
#define _POS ((op>>6 ) & 0x1F)
#define _SIZE ((op>>11 ) & 0x1F)
#define _RS MIPS_GET_RS(op)
#define _RT MIPS_GET_RT(op)
#define _RD MIPS_GET_RD(op)
#define _FS MIPS_GET_FS(op)
#define _FT MIPS_GET_FT(op)
#define _FD MIPS_GET_FD(op)
#define _SA MIPS_GET_SA(op)
#define _POS ((op>> 6) & 0x1F)
#define _SIZE ((op>>11) & 0x1F)
#define _IMM16 (signed short)(op & 0xFFFF)
#define _IMM26 (op & 0x03FFFFFF)
// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly.
// Currently known non working ones should have DISABLE.
@@ -39,11 +43,11 @@ using namespace MIPSAnalyst;
namespace MIPSComp
{
void Jit::CompImmLogic(u32 op, void (XEmitter::*arith)(int, const OpArg &, const OpArg &))
void Jit::CompImmLogic(MIPSOpcode op, void (XEmitter::*arith)(int, const OpArg &, const OpArg &))
{
u32 uimm = (u16)(op & 0xFFFF);
int rt = _RT;
int rs = _RS;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
gpr.Lock(rt, rs);
gpr.BindToRegister(rt, rt == rs, true);
if (rt != rs)
@@ -52,18 +56,18 @@ namespace MIPSComp
gpr.UnlockAll();
}
void Jit::Comp_IType(u32 op)
void Jit::Comp_IType(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
s32 simm = (s32)(s16)(op & 0xFFFF); // sign extension
s32 simm = (s32)_IMM16; // sign extension
u32 uimm = op & 0xFFFF;
u32 suimm = (u32)(s32)simm;
int rt = _RT;
int rs = _RS;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
// noop, won't write to ZERO.
if (rt == 0)
if (rt == MIPS_REG_ZERO)
return;
switch (op >> 26)
@@ -159,14 +163,14 @@ namespace MIPSComp
}
}
void Jit::Comp_RType2(u32 op)
void Jit::Comp_RType2(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int rs = _RS;
int rd = _RD;
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
// Don't change $zr.
if (rd == 0)
if (rd == MIPS_REG_ZERO)
return;
switch (op & 63)
@@ -266,11 +270,11 @@ namespace MIPSComp
}
//rd = rs X rt
void Jit::CompTriArith(u32 op, void (XEmitter::*arith)(int, const OpArg &, const OpArg &), u32 (*doImm)(const u32, const u32))
void Jit::CompTriArith(MIPSOpcode op, void (XEmitter::*arith)(int, const OpArg &, const OpArg &), u32 (*doImm)(const u32, const u32))
{
int rt = _RT;
int rs = _RS;
int rd = _RD;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
// Yes, this happens. Let's make it fast.
if (doImm && gpr.IsImmediate(rs) && gpr.IsImmediate(rt))
@@ -281,19 +285,19 @@ namespace MIPSComp
// Act like zero was used if the operand is equivalent. This happens.
if (gpr.IsImmediate(rs) && gpr.GetImmediate32(rs) == 0)
rs = 0;
rs = MIPS_REG_ZERO;
if (gpr.IsImmediate(rt) && gpr.GetImmediate32(rt) == 0)
rt = 0;
rt = MIPS_REG_ZERO;
gpr.Lock(rt, rs, rd);
// Optimize out operations against 0... and is the only one that isn't a MOV.
if (rt == 0 || (rs == 0 && doImm != &RType3_ImmSub))
if (rt == MIPS_REG_ZERO || (rs == MIPS_REG_ZERO && doImm != &RType3_ImmSub))
{
if (doImm == &RType3_ImmAnd)
gpr.SetImmediate32(rd, 0);
else
{
int rsource = rt == 0 ? rs : rt;
MIPSGPReg rsource = rt == MIPS_REG_ZERO ? rs : rt;
if (rsource != rd)
{
gpr.BindToRegister(rd, false, true);
@@ -323,16 +327,16 @@ namespace MIPSComp
gpr.UnlockAll();
}
void Jit::Comp_RType3(u32 op)
void Jit::Comp_RType3(MIPSOpcode op)
{
CONDITIONAL_DISABLE
int rt = _RT;
int rs = _RS;
int rd = _RD;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
// noop, won't write to ZERO.
if (rd == 0)
if (rd == MIPS_REG_ZERO)
return;
switch (op & 63)
@@ -451,7 +455,7 @@ namespace MIPSComp
gpr.SetImmediate32(rd, std::max((s32)gpr.GetImmediate32(rs), (s32)gpr.GetImmediate32(rt)));
else
{
int rsrc = rd == rt ? rs : rt;
MIPSGPReg rsrc = rd == rt ? rs : rt;
gpr.Lock(rd, rs, rt);
gpr.KillImmediate(rsrc, true, false);
gpr.BindToRegister(rd, rd == rs || rd == rt, true);
@@ -468,7 +472,7 @@ namespace MIPSComp
gpr.SetImmediate32(rd, std::min((s32)gpr.GetImmediate32(rs), (s32)gpr.GetImmediate32(rt)));
else
{
int rsrc = rd == rt ? rs : rt;
MIPSGPReg rsrc = rd == rt ? rs : rt;
gpr.Lock(rd, rs, rt);
gpr.KillImmediate(rsrc, true, false);
gpr.BindToRegister(rd, rd == rs || rd == rt, true);
@@ -507,10 +511,10 @@ namespace MIPSComp
return (a >> sa) | (a << (32 - sa));
}
void Jit::CompShiftImm(u32 op, void (XEmitter::*shift)(int, OpArg, OpArg), u32 (*doImm)(const u32, const u32))
void Jit::CompShiftImm(MIPSOpcode op, void (XEmitter::*shift)(int, OpArg, OpArg), u32 (*doImm)(const u32, const u32))
{
int rd = _RD;
int rt = _RT;
MIPSGPReg rd = _RD;
MIPSGPReg rt = _RT;
int sa = _SA;
if (doImm && gpr.IsImmediate(rt))
@@ -528,11 +532,11 @@ namespace MIPSComp
}
// "over-shifts" work the same as on x86 - only bottom 5 bits are used to get the shift value
void Jit::CompShiftVar(u32 op, void (XEmitter::*shift)(int, OpArg, OpArg), u32 (*doImm)(const u32, const u32))
void Jit::CompShiftVar(MIPSOpcode op, void (XEmitter::*shift)(int, OpArg, OpArg), u32 (*doImm)(const u32, const u32))
{
int rd = _RD;
int rt = _RT;
int rs = _RS;
MIPSGPReg rd = _RD;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
if (doImm && gpr.IsImmediate(rs) && gpr.IsImmediate(rt))
{
@@ -563,15 +567,15 @@ namespace MIPSComp
gpr.UnlockAll();
}
void Jit::Comp_ShiftType(u32 op)
void Jit::Comp_ShiftType(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int rs = _RS;
int rd = _RD;
int fd = _FD;
int rs = (op>>21) & 0x1F;
MIPSGPReg rd = _RD;
int fd = (op>>6) & 0x1F;
// noop, won't write to ZERO.
if (rd == 0)
if (rd == MIPS_REG_ZERO)
return;
// WARNING : ROTR
@@ -591,18 +595,18 @@ namespace MIPSComp
}
}
void Jit::Comp_Special3(u32 op)
void Jit::Comp_Special3(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int rs = _RS;
int rt = _RT;
MIPSGPReg rs = _RS;
MIPSGPReg rt = _RT;
int pos = _POS;
int size = _SIZE + 1;
u32 mask = 0xFFFFFFFFUL >> (32 - size);
// Don't change $zr.
if (rt == 0)
if (rt == MIPS_REG_ZERO)
return;
switch (op & 0x3f)
@@ -659,13 +663,13 @@ namespace MIPSComp
}
void Jit::Comp_Allegrex(u32 op)
void Jit::Comp_Allegrex(MIPSOpcode op)
{
CONDITIONAL_DISABLE
int rt = _RT;
int rd = _RD;
MIPSGPReg rt = _RT;
MIPSGPReg rd = _RD;
// Don't change $zr.
if (rd == 0)
if (rd == MIPS_REG_ZERO)
return;
switch ((op >> 6) & 31)
@@ -769,13 +773,13 @@ namespace MIPSComp
}
}
void Jit::Comp_Allegrex2(u32 op)
void Jit::Comp_Allegrex2(MIPSOpcode op)
{
CONDITIONAL_DISABLE
int rt = _RT;
int rd = _RD;
MIPSGPReg rt = _RT;
MIPSGPReg rd = _RD;
// Don't change $zr.
if (rd == 0)
if (rd == MIPS_REG_ZERO)
return;
DISABLE;
@@ -799,12 +803,12 @@ namespace MIPSComp
}
}
void Jit::Comp_MulDivType(u32 op)
void Jit::Comp_MulDivType(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
int rt = _RT;
int rs = _RS;
int rd = _RD;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
switch (op & 63)
{
Loaded 100 of 202 files, more files were not shown because too many files have changed in this diff. Show more