Fixed conflicts

This commit is contained in:
O1L 2014-09-07 15:13:29 +04:00
commit 339e40d423
458 changed files with 52441 additions and 34033 deletions

10
.gitignore vendored
View file

@ -30,6 +30,8 @@
*.dump
*.wav
/build
/libs
/ipch
/rpcs3/Debug
@ -61,4 +63,10 @@ rpcs3/git-version.h
!/bin/dev_hdd0/game/TEST12345/
# Ignore other system generated files
bin/dev_hdd0/log.txt
bin/dev_hdd0/*.txt
x64/Debug/emucore.lib
x64/Release/emucore.lib
rpcs3/x64/*
.DS_Store
rpcs3/Emu/SysCalls/Modules/prx_*.h

View file

@ -8,28 +8,30 @@ branches:
only:
- master
git:
submodules: false
before_install:
- echo "yes" | sudo apt-key adv --fetch-keys http://repos.codelite.org/CodeLite.asc
- echo "yes" | sudo apt-add-repository 'deb http://repos.codelite.org/wx3.0/ubuntu/ precise universe'
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
- sudo apt-get update
- sudo apt-get install libwxgtk3.0-dev libopenal-dev freeglut3-dev libglew-dev
- sudo apt-get install libwxgtk3.0-dev libopenal-dev freeglut3-dev libglew-dev libc6-dev
- sudo apt-get install aria2 -qq
- download_extract() { aria2c -x 16 $1 -o $2 && tar -xf $2; }
- if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.8; export CXX="g++-4.8" CC="gcc-4.8"; else sudo apt-get install libstdc++-4.8-dev; fi
# Travis uses CMake 2.8.7. We require 2.8.8. Grab latest
- sudo apt-get install -qq g++-4.8
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
- sudo apt-get install lib32stdc++6 -qq &&
aria2c -x 16 http://www.cmake.org/files/v2.8/cmake-2.8.12.1-Linux-i386.sh &&
chmod a+x cmake-2.8.12.1-Linux-i386.sh &&
sudo ./cmake-2.8.12.1-Linux-i386.sh --skip-license --prefix=/usr;
aria2c -x 16 http://www.cmake.org/files/v3.0/cmake-3.0.0-Linux-i386.sh &&
chmod a+x cmake-3.0.0-Linux-i386.sh &&
sudo ./cmake-3.0.0-Linux-i386.sh --skip-license --prefix=/usr;
before_script:
- git submodule update --init --recursive
- git submodule update --init asmjit ffmpeg
- mkdir build
- cd build
- cmake ..
script:
- make
- make -j 4

View file

@ -2,5 +2,14 @@ cmake_minimum_required(VERSION 2.8)
set(ASMJIT_STATIC TRUE)
if (NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type selected, default to Release")
set(CMAKE_BUILD_TYPE "Release")
endif()
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
message( FATAL_ERROR "RPCS3 can only be compiled on 64-bit platforms." )
endif()
add_subdirectory( asmjit )
add_subdirectory( rpcs3 )

Binary file not shown.

View file

@ -17,7 +17,6 @@ If you want to contribute please take a took at the [Coding Style](https://githu
__Windows__
* [Visual C++ Redistributable Packages for Visual Studio 2013](http://www.microsoft.com/en-us/download/details.aspx?id=40784)
* [OpenAL binaries](http://kcat.strangesoft.net/openal.html): download and copy `Win64\soft_oal.dll` to `rpcs3\bin\`
__Linux__
* Debian & Ubuntu: `sudo apt-get install libopenal-dev libwxgtk3.0-dev build-essential`

View file

@ -1,88 +0,0 @@
#pragma once
template<typename T, size_t size> class SizedStack
{
T m_ptr[size];
uint m_count;
public:
SizedStack()
{
Clear();
}
~SizedStack()
{
Clear();
}
void Clear()
{
m_count = 0;
}
bool Pop(T& dst)
{
if(!m_count)
return false;
dst = m_ptr[--m_count];
return true;
}
bool Push(const T& src)
{
if(m_count + 1 > size)
return false;
m_ptr[m_count++] = src;
return true;
}
size_t GetFreeCount() const
{
return size - m_count;
}
size_t GetCount() const
{
return m_count;
}
size_t GetMaxCount() const
{
return size;
}
};
template<typename T> struct ScopedPtr
{
private:
T* m_ptr;
public:
ScopedPtr() : m_ptr(nullptr)
{
}
ScopedPtr(T* ptr) : m_ptr(ptr)
{
}
~ScopedPtr()
{
Swap(nullptr);
}
operator T*() { return m_ptr; }
operator const T*() const { return m_ptr; }
T* operator ->() { return m_ptr; }
const T* operator ->() const { return m_ptr; }
void Swap(T* ptr)
{
delete m_ptr;
m_ptr = ptr;
}
};

128
Utilities/AutoPause.cpp Normal file
View file

@ -0,0 +1,128 @@
#include "stdafx.h"
#include "rpcs3/Ini.h"
#include "AutoPause.h"
#include "Utilities/Log.h"
#include "Utilities/rFile.h"
#include "Emu/System.h"
using namespace Debug;
//Even different from those tutorials on webpages, i use the method similiar from Log.h
//TODO:: Question: Does such a Singleton struct get fully deallocated after its pointer?
AutoPause* gAutoPause = nullptr;
AutoPause& AutoPause::getInstance(void)
{
if (!gAutoPause)
{
gAutoPause = new AutoPause();
}
return *gAutoPause;
}
//Still use binary format. Default Setting should be "disable all auto pause".
AutoPause::AutoPause(void)
{
m_pause_function.reserve(16);
m_pause_syscall.reserve(16);
initialized = false;
//Reload(false, false);
Reload();
}
//Notice: I would not allow to write the binary to file in this command.
AutoPause::~AutoPause(void)
{
initialized = false;
m_pause_function.clear();
m_pause_syscall.clear();
m_pause_function_enable = false;
m_pause_syscall_enable = false;
}
//Load Auto Pause Configuration from file "pause.bin"
//This would be able to create in a GUI window.
void AutoPause::Reload(void)
{
if (rExists("pause.bin"))
{
m_pause_function.clear();
m_pause_function.reserve(16);
m_pause_syscall.clear();
m_pause_syscall.reserve(16);
rFile list;
list.Open("pause.bin", rFile::read);
//System calls ID and Function calls ID are all u32 iirc.
u32 num;
size_t fmax = list.Length();
size_t fcur = 0;
list.Seek(0);
while (fcur <= fmax - sizeof(u32))
{
list.Read(&num, sizeof(u32));
fcur += sizeof(u32);
if (num == 0xFFFFFFFF) break;
if (num < 1024)
{
//Less than 1024 - be regarded as a system call.
//emplace_back may not cause reductant move/copy operation.
m_pause_syscall.emplace_back(num);
LOG_WARNING(HLE, "Auto Pause: Find System Call ID %x", num);
}
else
{
m_pause_function.emplace_back(num);
LOG_WARNING(HLE, "Auto Pause: Find Function Call ID %x", num);
}
}
list.Close();
}
else
{
LOG_WARNING(HLE, "No pause.bin found, Auto Pause will not work.");
}
m_pause_syscall_enable = Ini.DBGAutoPauseSystemCall.GetValue();
m_pause_function_enable = Ini.DBGAutoPauseFunctionCall.GetValue();
initialized = true;
}
void AutoPause::TryPause(u32 code) {
if (code < 1024)
{
//Would first check Enable setting. Then the list length.
if ((!m_pause_syscall_enable)
|| (m_pause_syscall.size() <= 0))
{
return;
}
for (u32 i = 0; i < m_pause_syscall.size(); ++i)
{
if (code == m_pause_syscall[i])
{
Emu.Pause();
LOG_ERROR(HLE, "Auto Pause Triggered: System call %x", code); //Used Error
}
}
}
else
{
//Well similiar.. Seperate the list caused by possible setting difference.
if ((!m_pause_function_enable)
|| (m_pause_function.size() <= 0))
{
return;
}
for (u32 i = 0; i < m_pause_function.size(); ++i)
{
if (code == m_pause_function[i])
{
Emu.Pause();
LOG_ERROR(HLE, "Auto Pause Triggered: Function call %x", code); //Used Error
}
}
}
}

24
Utilities/AutoPause.h Normal file
View file

@ -0,0 +1,24 @@
#pragma once
//Regarded as a Debugger Enchantment
namespace Debug {
//To store the pause function/call id, and let those pause there.
//Would be with a GUI to configure those.
struct AutoPause
{
std::vector<u32> m_pause_syscall;
std::vector<u32> m_pause_function;
bool initialized;
bool m_pause_syscall_enable;
bool m_pause_function_enable;
AutoPause();
~AutoPause();
public:
static AutoPause& getInstance(void);
void Reload(void);
void TryPause(u32 code);
};
}

View file

@ -1,26 +1,242 @@
#pragma once
#include "Utilities/GNU.h"
#include <emmintrin.h>
union u128
{
struct
{
u64 hi;
u64 lo;
};
u64 _u64[2];
s64 _s64[2];
u32 _u32[4];
s32 _s32[4];
u16 _u16[8];
s16 _s16[8];
u8 _u8[16];
s8 _s8[16];
float _f[4];
double _d[2];
__m128 xmm;
class bit_array_128
{
u64 data[2];
public:
class bit_element
{
u64& data;
const u64 mask;
public:
bit_element(u64& data, const u64 mask)
: data(data)
, mask(mask)
{
}
__forceinline operator bool() const
{
return (data & mask) != 0;
}
__forceinline bit_element& operator = (const bool right)
{
if (right)
{
data |= mask;
}
else
{
data &= ~mask;
}
return *this;
}
__forceinline bit_element& operator = (const bit_element& right)
{
if (right)
{
data |= mask;
}
else
{
data &= ~mask;
}
return *this;
}
};
bit_element operator [] (u32 index)
{
assert(index < 128);
return bit_element(data[index / 64], 1ull << (index % 64));
}
const bool operator [] (u32 index) const
{
assert(index < 128);
return (data[index / 64] & (1ull << (index % 64))) != 0;
}
} _bit;
//operator u64() const { return _u64[0]; }
//operator u32() const { return _u32[0]; }
//operator u16() const { return _u16[0]; }
//operator u8() const { return _u8[0]; }
//operator bool() const { return _u64[0] != 0 || _u64[1] != 0; }
static u128 from128(u64 hi, u64 lo)
{
u128 ret = { hi, lo };
return ret;
}
static u128 from64(u64 src)
{
u128 ret = { 0, src };
return ret;
}
static u128 from32(u32 src)
{
u128 ret;
ret._u32[0] = src;
ret._u32[1] = 0;
ret._u32[2] = 0;
ret._u32[3] = 0;
return ret;
}
static u128 fromBit(u32 bit)
{
u128 ret;
ret._bit[bit] = true;
return ret;
}
void setBit(u32 bit)
{
_bit[bit] = true;
}
bool operator == (const u128& right) const
{
return (lo == right.lo) && (hi == right.hi);
}
bool operator != (const u128& right) const
{
return (lo != right.lo) || (hi != right.hi);
}
u128 operator | (const u128& right) const
{
return from128(hi | right.hi, lo | right.lo);
}
u128 operator & (const u128& right) const
{
return from128(hi & right.hi, lo & right.lo);
}
u128 operator ^ (const u128& right) const
{
return from128(hi ^ right.hi, lo ^ right.lo);
}
u128 operator ~ () const
{
return from128(~hi, ~lo);
}
void clear()
{
hi = lo = 0;
}
std::string to_hex() const
{
return fmt::Format("%08x%08x%08x%08x", _u32[3], _u32[2], _u32[1], _u32[0]);
}
std::string to_xyzw() const
{
return fmt::Format("x: %g y: %g z: %g w: %g", _f[3], _f[2], _f[1], _f[0]);
}
static __forceinline u128 byteswap(const u128 val)
{
u128 ret;
ret.lo = _byteswap_uint64(val.hi);
ret.hi = _byteswap_uint64(val.lo);
return ret;
}
};
#define re16(val) _byteswap_ushort(val)
#define re32(val) _byteswap_ulong(val)
#define re64(val) _byteswap_uint64(val)
#define re128(val) u128::byteswap(val)
template<typename T, int size = sizeof(T)> struct se_t;
template<typename T> struct se_t<T, 1> { static __forceinline void func(T& dst, const T src) { (u8&)dst = (u8&)src; } };
template<typename T> struct se_t<T, 2> { static __forceinline void func(T& dst, const T src) { (u16&)dst = _byteswap_ushort((u16&)src); } };
template<typename T> struct se_t<T, 4> { static __forceinline void func(T& dst, const T src) { (u32&)dst = _byteswap_ulong((u32&)src); } };
template<typename T> struct se_t<T, 8> { static __forceinline void func(T& dst, const T src) { (u64&)dst = _byteswap_uint64((u64&)src); } };
template<typename T> struct se_t<T, 1>
{
static __forceinline T func(const T src)
{
return src;
}
};
template<typename T, s64 _value, int size = sizeof(T)> struct const_se_t;
template<typename T, s64 _value> struct const_se_t<T, _value, 1>
template<typename T> struct se_t<T, 2>
{
static __forceinline T func(const T src)
{
const u16 res = _byteswap_ushort((u16&)src);
return (T&)res;
}
};
template<typename T> struct se_t<T, 4>
{
static __forceinline T func(const T src)
{
const u32 res = _byteswap_ulong((u32&)src);
return (T&)res;
}
};
template<typename T> struct se_t<T, 8>
{
static __forceinline T func(const T src)
{
const u64 res = _byteswap_uint64((u64&)src);
return (T&)res;
}
};
//template<typename T> T re(const T val) { T res; se_t<T>::func(res, val); return res; }
//template<typename T1, typename T2> void re(T1& dst, const T2 val) { se_t<T1>::func(dst, val); }
template<typename T, u64 _value, int size = sizeof(T)> struct const_se_t;
template<typename T, u64 _value> struct const_se_t<T, _value, 1>
{
static const T value = (T)_value;
};
template<typename T, s64 _value> struct const_se_t<T, _value, 2>
template<typename T, u64 _value> struct const_se_t<T, _value, 2>
{
static const T value = ((_value >> 8) & 0xff) | ((_value << 8) & 0xff00);
};
template<typename T, s64 _value> struct const_se_t<T, _value, 4>
template<typename T, u64 _value> struct const_se_t<T, _value, 4>
{
static const T value =
((_value >> 24) & 0x000000ff) |
@ -29,7 +245,7 @@ template<typename T, s64 _value> struct const_se_t<T, _value, 4>
((_value << 24) & 0xff000000);
};
template<typename T, s64 _value> struct const_se_t<T, _value, 8>
template<typename T, u64 _value> struct const_se_t<T, _value, 8>
{
static const T value =
((_value >> 56) & 0x00000000000000ff) |
@ -42,32 +258,14 @@ template<typename T, s64 _value> struct const_se_t<T, _value, 8>
((_value << 56) & 0xff00000000000000);
};
template<typename T, int size=sizeof(T)>
template<typename T, typename T2 = T>
class be_t
{
static_assert(size == 1 || size == 2 || size == 4 || size == 8, "Bad be_t type");
static_assert(sizeof(T2) == 1 || sizeof(T2) == 2 || sizeof(T2) == 4 || sizeof(T2) == 8, "Bad be_t type");
T m_data;
public:
typedef T type;
#ifdef _WIN32
be_t(){}
#else
be_t() noexcept = default;
#endif
be_t(const be_t<T,size>& value) = default;
be_t(const T& value)
{
FromLE(value);
}
template<typename T1>
explicit be_t(const be_t<T1>& value)
{
FromBE(value.ToBE());
}
const T& ToBE() const
{
@ -76,11 +274,7 @@ public:
T ToLE() const
{
T res;
se_t<T>::func(res, m_data);
return res;
return se_t<T, sizeof(T2)>::func(m_data);
}
void FromBE(const T& value)
@ -90,21 +284,18 @@ public:
void FromLE(const T& value)
{
se_t<T>::func(m_data, value);
m_data = se_t<T, sizeof(T2)>::func(value);
}
static be_t MakeFromLE(const T value)
{
be_t res;
res.FromLE(value);
return res;
T data = se_t<T, sizeof(T2)>::func(value);
return (be_t&)data;
}
static be_t MakeFromBE(const T value)
{
be_t res;
res.FromBE(value);
return res;
return (be_t&)value;
}
//template<typename T1>
@ -116,18 +307,36 @@ public:
template<typename T1>
operator const be_t<T1>() const
{
be_t<T1> res;
res.FromBE(ToBE());
return res;
if (sizeof(T1) > sizeof(T) || std::is_floating_point<T>::value || std::is_floating_point<T1>::value)
{
T1 res = se_t<T1, sizeof(T1)>::func(ToLE());
return (be_t<T1>&)res;
}
else if (sizeof(T1) < sizeof(T))
{
T1 res = ToBE() >> ((sizeof(T) - sizeof(T1)) * 8);
return (be_t<T1>&)res;
}
else
{
T1 res = ToBE();
return (be_t<T1>&)res;
}
}
be_t& operator = (const T& right)
{
FromLE(right);
m_data = se_t<T, sizeof(T2)>::func(right);
return *this;
}
be_t<T,size>& operator = (const be_t<T,size>& right) = default;
be_t& operator = (const be_t& right) = default;
be_t& operator = (const be_t<const T, const T2>& right)
{
m_data = right.ToBE();
return *this;
}
template<typename T1> be_t& operator += (T1 right) { return *this = T(*this) + right; }
template<typename T1> be_t& operator -= (T1 right) { return *this = T(*this) - right; }
@ -173,10 +382,244 @@ public:
be_t& operator-- () { *this -= 1; return *this; }
};
template<typename T, typename T2>
class be_t<const T, T2>
{
static_assert(sizeof(T2) == 1 || sizeof(T2) == 2 || sizeof(T2) == 4 || sizeof(T2) == 8, "Bad be_t type");
const T m_data;
public:
typedef const T type;
const T& ToBE() const
{
return m_data;
}
const T ToLE() const
{
return se_t<const T, sizeof(T2)>::func(m_data);
}
static be_t MakeFromLE(const T value)
{
const T data = se_t<const T, sizeof(T2)>::func(value);
return (be_t&)data;
}
static be_t MakeFromBE(const T value)
{
return (be_t&)value;
}
//template<typename T1>
operator const T() const
{
return ToLE();
}
template<typename T1>
operator const be_t<T1>() const
{
if (sizeof(T1) > sizeof(T) || std::is_floating_point<T>::value || std::is_floating_point<T1>::value)
{
T1 res = se_t<T1, sizeof(T1)>::func(ToLE());
return (be_t<T1>&)res;
}
else if (sizeof(T1) < sizeof(T))
{
T1 res = ToBE() >> ((sizeof(T) - sizeof(T1)) * 8);
return (be_t<T1>&)res;
}
else
{
T1 res = ToBE();
return (be_t<T1>&)res;
}
}
template<typename T1> be_t operator & (const be_t<T1>& right) const { const T res; res = ToBE() & right.ToBE(); return (be_t&)res; }
template<typename T1> be_t operator | (const be_t<T1>& right) const { const T res; res = ToBE() | right.ToBE(); return (be_t&)res; }
template<typename T1> be_t operator ^ (const be_t<T1>& right) const { const T res; res = ToBE() ^ right.ToBE(); return (be_t&)res; }
template<typename T1> bool operator == (T1 right) const { return (T1)ToLE() == right; }
template<typename T1> bool operator != (T1 right) const { return !(*this == right); }
template<typename T1> bool operator > (T1 right) const { return (T1)ToLE() > right; }
template<typename T1> bool operator < (T1 right) const { return (T1)ToLE() < right; }
template<typename T1> bool operator >= (T1 right) const { return (T1)ToLE() >= right; }
template<typename T1> bool operator <= (T1 right) const { return (T1)ToLE() <= right; }
template<typename T1> bool operator == (const be_t<T1>& right) const { return ToBE() == right.ToBE(); }
template<typename T1> bool operator != (const be_t<T1>& right) const { return !(*this == right); }
template<typename T1> bool operator > (const be_t<T1>& right) const { return (T1)ToLE() > right.ToLE(); }
template<typename T1> bool operator < (const be_t<T1>& right) const { return (T1)ToLE() < right.ToLE(); }
template<typename T1> bool operator >= (const be_t<T1>& right) const { return (T1)ToLE() >= right.ToLE(); }
template<typename T1> bool operator <= (const be_t<T1>& right) const { return (T1)ToLE() <= right.ToLE(); }
};
template<typename T, typename T2 = T>
struct is_be_t : public std::integral_constant<bool, false> {};
template<typename T, typename T2>
struct is_be_t<be_t<T, T2>, T2> : public std::integral_constant<bool, true> {};
template<typename T, typename T2 = T>
struct remove_be_t
{
typedef T type;
};
template<typename T, typename T2>
struct remove_be_t<be_t<T, T2>>
{
typedef T type;
};
template<typename T, typename T2 = T>
class to_be_t
{
template<typename TT, typename TT2, bool is_need_swap>
struct _be_type_selector
{
typedef TT type;
};
template<typename TT, typename TT2>
struct _be_type_selector<TT, TT2, true>
{
typedef be_t<TT, TT2> type;
};
public:
//true if need swap endianes for be
static const bool value = (sizeof(T2) > 1) && std::is_arithmetic<T>::value;
//be_t<T, size> if need swap endianes, T otherwise
typedef typename _be_type_selector< T, T2, value >::type type;
};
template<typename T>
class to_be_t<T, void>
{
public:
//true if need swap endianes for be
static const bool value = false;
//be_t<T, size> if need swap endianes, T otherwise
typedef void type;
};
template<typename T>
class to_be_t<T, const void>
{
public:
//true if need swap endianes for be
static const bool value = false;
//be_t<T, size> if need swap endianes, T otherwise
typedef const void type;
};
template<typename T, typename T2 = T>
struct invert_be_t
{
typedef typename to_be_t<T, T2>::type type;
};
template<typename T, typename T2>
struct invert_be_t<be_t<T, T2>>
{
typedef T type;
};
template<typename T, typename T1, T1 value> struct _se : public const_se_t<T, value> {};
template<typename T, typename T1, T1 value> struct _se<be_t<T>, T1, value> : public const_se_t<T, value> {};
#define se(t, x) _se<decltype(t), decltype(x), x>::value
//#define se(t, x) _se<decltype(t), decltype(x), x>::value
#define se16(x) _se<u16, decltype(x), x>::value
#define se32(x) _se<u32, decltype(x), x>::value
#define se64(x) _se<u64, decltype(x), x>::value
template<typename T> __forceinline static u8 Read8(T& f)
{
u8 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static u16 Read16(T& f)
{
be_t<u16> ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static u32 Read32(T& f)
{
be_t<u32> ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static u64 Read64(T& f)
{
be_t<u64> ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static u16 Read16LE(T& f)
{
u16 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static u32 Read32LE(T& f)
{
u32 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static u64 Read64LE(T& f)
{
u64 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static void Write8(T& f, const u8 data)
{
f.Write(&data, sizeof(data));
}
template<typename T> __forceinline static void Write16LE(T& f, const u16 data)
{
f.Write(&data, sizeof(data));
}
template<typename T> __forceinline static void Write32LE(T& f, const u32 data)
{
f.Write(&data, sizeof(data));
}
template<typename T> __forceinline static void Write64LE(T& f, const u64 data)
{
f.Write(&data, sizeof(data));
}
template<typename T> __forceinline static void Write16(T& f, const u16 data)
{
Write16LE(f, re16(data));
}
template<typename T> __forceinline static void Write32(T& f, const u32 data)
{
Write32LE(f, re32(data));
}
template<typename T> __forceinline static void Write64(T& f, const u64 data)
{
Write64LE(f, re64(data));
}

View file

@ -1,20 +1,23 @@
#include <time.h>
#include <sys/time.h>
#include "GNU.h"
#ifdef __APPLE__
void * _aligned_malloc(size_t size, size_t alignment) {
void *buffer;
posix_memalign(&buffer, alignment, size);
return buffer;
}
#include <time.h>
#include <sys/time.h>
int clock_gettime(int foo, struct timespec *ts) {
struct timeval tv;
struct timeval tv;
gettimeofday(&tv, NULL);
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec * 1000;
return(0);
gettimeofday(&tv, NULL);
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec * 1000;
return(0);
}
#endif /* !__APPLE__ */
#endif /* __APPLE__ */
#if defined(__GNUG__)
void * _aligned_malloc(size_t size, size_t alignment) {
void *buffer;
return (posix_memalign(&buffer, alignment, size) == 0) ? buffer : 0;
}
#endif

View file

@ -1,5 +1,25 @@
#pragma once
#ifdef _WIN32
#define thread_local __declspec(thread)
#elif __APPLE__
#define thread_local __thread
#endif
#ifdef _WIN32
#define __noinline __declspec(noinline)
#else
#define __noinline __attribute__((noinline))
#endif
template<size_t size>
void strcpy_trunc(char (&dst)[size], const std::string& src)
{
const size_t count = (src.size() >= size) ? size - 1 /* truncation */ : src.size();
memcpy(dst, src.c_str(), count);
dst[count] = 0;
}
#if defined(__GNUG__)
#include <cmath>
#include <stdlib.h>
@ -14,8 +34,6 @@
#define _byteswap_ushort(x) __builtin_bswap16(x)
#define _byteswap_ulong(x) __builtin_bswap32(x)
#define _byteswap_uint64(x) __builtin_bswap64(x)
#define Sleep(x) usleep(x * 1000)
#define mkdir(x) mkdir(x, 0777)
#define INFINITE 0xFFFFFFFF
#define _CRT_ALIGN(x) __attribute__((aligned(x)))
#define InterlockedCompareExchange(ptr,new_val,old_val) __sync_val_compare_and_swap(ptr,old_val,new_val)
@ -47,10 +65,10 @@ inline int64_t __mulh(int64_t a, int64_t b)
return result;
}
#ifndef __APPLE__
#define _aligned_malloc(size,alignment) memalign(alignment,size)
#else
void * _aligned_malloc(size_t size, size_t alignment);
#ifdef __APPLE__
int clock_gettime(int foo, struct timespec *ts);
#define wxIsNaN(x) ((x) != (x))
@ -58,9 +76,20 @@ int clock_gettime(int foo, struct timespec *ts);
#define CLOCK_MONOTONIC 0
#endif /* !CLOCK_MONOTONIC */
#endif /* !__APPLE__ */
#endif /* __APPLE__ */
#define _aligned_free free
#define DWORD int32_t
#endif
#ifndef InterlockedCompareExchange
static __forceinline uint32_t InterlockedCompareExchange(volatile uint32_t* dest, uint32_t exch, uint32_t comp)
{
return _InterlockedCompareExchange((volatile long*)dest, exch, comp);
}
static __forceinline uint64_t InterlockedCompareExchange(volatile uint64_t* dest, uint64_t exch, uint64_t comp)
{
return _InterlockedCompareExchange64((volatile long long*)dest, exch, comp);
}
#endif

42
Utilities/Interval.h Normal file
View file

@ -0,0 +1,42 @@
#pragma once
template<typename T>
struct BaseInterval
{
static const uint64_t zero = 0ull;
static const uint64_t notz = 0xffffffffffffffffull;
T m_min, m_max;
static BaseInterval<T> make(T min_value, T max_value)
{
BaseInterval<T> res = { min_value, max_value };
return res;
}
static BaseInterval<T> make()
{
return make((T&)zero, (T&)notz);
}
bool getconst(T& result)
{
if (m_min == m_max)
{
result = m_min;
return true;
}
else
{
return false;
}
}
bool isindef()
{
if (T == float)
{
}
}
};

235
Utilities/Log.cpp Normal file
View file

@ -0,0 +1,235 @@
#include "stdafx.h"
#include "rPlatform.h"
#include "Log.h"
#include "rMsgBox.h"
#include <iostream>
#include <cinttypes>
#include "Thread.h"
#include "rFile.h"
using namespace Log;
LogManager *gLogManager = nullptr;
u32 LogMessage::size()
{
//1 byte for NULL terminator
return (u32)(sizeof(LogMessage::size_type) + sizeof(LogType) + sizeof(LogSeverity) + sizeof(std::string::value_type) * mText.size() + 1);
}
void LogMessage::serialize(char *output)
{
LogMessage::size_type size = this->size();
memcpy(output, &size, sizeof(LogMessage::size_type));
output += sizeof(LogMessage::size_type);
memcpy(output, &mType, sizeof(LogType));
output += sizeof(LogType);
memcpy(output, &mServerity, sizeof(LogSeverity));
output += sizeof(LogSeverity);
memcpy(output, mText.c_str(), mText.size() );
output += sizeof(std::string::value_type)*mText.size();
*output = '\0';
}
LogMessage LogMessage::deserialize(char *input, u32* size_out)
{
LogMessage msg;
LogMessage::size_type msgSize = *(reinterpret_cast<LogMessage::size_type*>(input));
input += sizeof(LogMessage::size_type);
msg.mType = *(reinterpret_cast<LogType*>(input));
input += sizeof(LogType);
msg.mServerity = *(reinterpret_cast<LogSeverity*>(input));
input += sizeof(LogSeverity);
if (msgSize > 9000)
{
int wtf = 6;
}
msg.mText.append(input, msgSize - 1 - sizeof(LogSeverity) - sizeof(LogType));
if (size_out){(*size_out) = msgSize;}
return msg;
}
LogChannel::LogChannel() : LogChannel("unknown")
{}
LogChannel::LogChannel(const std::string& name) :
name(name)
, mEnabled(true)
, mLogLevel(Warning)
{}
void LogChannel::log(LogMessage msg)
{
std::lock_guard<std::mutex> lock(mListenerLock);
for (auto &listener : mListeners)
{
listener->log(msg);
}
}
void LogChannel::addListener(std::shared_ptr<LogListener> listener)
{
std::lock_guard<std::mutex> lock(mListenerLock);
mListeners.insert(listener);
}
void LogChannel::removeListener(std::shared_ptr<LogListener> listener)
{
std::lock_guard<std::mutex> lock(mListenerLock);
mListeners.erase(listener);
}
struct CoutListener : LogListener
{
void log(LogMessage msg)
{
std::cerr << msg.mText << std::endl;
}
};
struct FileListener : LogListener
{
rFile mFile;
bool mPrependChannelName;
FileListener(const std::string& name = _PRGNAME_, bool prependChannel = true)
: mFile(std::string(rPlatform::getConfigDir() + name + ".log").c_str(), rFile::write),
mPrependChannelName(prependChannel)
{
if (!mFile.IsOpened())
{
rMessageBox("Can't create log file! (" + name + ".log)", "Error", rICON_ERROR);
}
}
void log(LogMessage msg)
{
if (mPrependChannelName)
{
msg.mText.insert(0, gTypeNameTable[static_cast<u32>(msg.mType)].mName);
}
mFile.Write(msg.mText);
}
};
LogManager::LogManager()
#ifdef BUFFERED_LOGGING
: mExiting(false), mLogConsumer()
#endif
{
auto it = mChannels.begin();
std::shared_ptr<LogListener> listener(new FileListener());
for (const LogTypeName& name : gTypeNameTable)
{
it->name = name.mName;
it->addListener(listener);
it++;
}
std::shared_ptr<LogListener> TTYListener(new FileListener("TTY",false));
getChannel(TTY).addListener(TTYListener);
#ifdef BUFFERED_LOGGING
mLogConsumer = std::thread(&LogManager::consumeLog, this);
#endif
}
LogManager::~LogManager()
{
#ifdef BUFFERED_LOGGING
mExiting = true;
mBufferReady.notify_all();
mLogConsumer.join();
}
void LogManager::consumeLog()
{
std::unique_lock<std::mutex> lock(mStatusMut);
while (!mExiting)
{
mBufferReady.wait(lock);
mBuffer.lockGet();
size_t size = mBuffer.size();
std::vector<char> local_messages(size);
mBuffer.popN(&local_messages.front(), size);
mBuffer.unlockGet();
u32 cursor = 0;
u32 removed = 0;
while (cursor < size)
{
Log::LogMessage msg = Log::LogMessage::deserialize(local_messages.data() + cursor, &removed);
cursor += removed;
getChannel(msg.mType).log(msg);
}
}
#endif
}
void LogManager::log(LogMessage msg)
{
//don't do any formatting changes or filtering to the TTY output since we
//use the raw output to do diffs with the output of a real PS3 and some
//programs write text in single bytes to the console
if (msg.mType != TTY)
{
std::string prefix;
switch (msg.mServerity)
{
case Success:
prefix = "S ";
break;
case Notice:
prefix = "! ";
break;
case Warning:
prefix = "W ";
break;
case Error:
prefix = "E ";
break;
}
if (NamedThreadBase* thr = GetCurrentNamedThread())
{
prefix += "{" + thr->GetThreadName() + "} ";
}
msg.mText.insert(0, prefix);
msg.mText.append(1,'\n');
}
#ifdef BUFFERED_LOGGING
size_t size = msg.size();
std::vector<char> temp_buffer(size);
msg.serialize(temp_buffer.data());
mBuffer.pushRange(temp_buffer.begin(), temp_buffer.end());
mBufferReady.notify_one();
#else
mChannels[static_cast<u32>(msg.mType)].log(msg);
#endif
}
void LogManager::addListener(std::shared_ptr<LogListener> listener)
{
for (auto& channel : mChannels)
{
channel.addListener(listener);
}
}
void LogManager::removeListener(std::shared_ptr<LogListener> listener)
{
for (auto& channel : mChannels)
{
channel.removeListener(listener);
}
}
LogManager& LogManager::getInstance()
{
if (!gLogManager)
{
gLogManager = new LogManager();
}
return *gLogManager;
}
LogChannel &LogManager::getChannel(LogType type)
{
return mChannels[static_cast<u32>(type)];
}

141
Utilities/Log.h Normal file
View file

@ -0,0 +1,141 @@
#pragma once
#include <array>
#include "Utilities/MTRingbuffer.h"
//#define BUFFERED_LOGGING 1
//first parameter is of type Log::LogType and text is of type std::string
#define LOG_SUCCESS(logType, text, ...) log_message(logType, Log::Success, text, ##__VA_ARGS__)
#define LOG_NOTICE(logType, text, ...) log_message(logType, Log::Notice, text, ##__VA_ARGS__)
#define LOG_WARNING(logType, text, ...) log_message(logType, Log::Warning, text, ##__VA_ARGS__)
#define LOG_ERROR(logType, text, ...) log_message(logType, Log::Error, text, ##__VA_ARGS__)
namespace Log
{
const unsigned int MAX_LOG_BUFFER_LENGTH = 1024*1024;
const unsigned int gBuffSize = 1000;
enum LogType : u32
{
GENERAL = 0,
LOADER,
MEMORY,
RSX,
HLE,
PPU,
SPU,
TTY,
};
struct LogTypeName
{
LogType mType;
std::string mName;
};
//well I'd love make_array() but alas manually counting is not the end of the world
static const std::array<LogTypeName, 8> gTypeNameTable = { {
{ GENERAL, "G: " },
{ LOADER, "LDR: " },
{ MEMORY, "MEM: " },
{ RSX, "RSX: " },
{ HLE, "HLE: " },
{ PPU, "PPU: " },
{ SPU, "SPU: " },
{ TTY, "TTY: " }
} };
enum LogSeverity : u32
{
Success = 0,
Notice,
Warning,
Error,
};
struct LogMessage
{
using size_type = u32;
LogType mType;
LogSeverity mServerity;
std::string mText;
u32 size();
void serialize(char *output);
static LogMessage deserialize(char *input, u32* size_out=nullptr);
};
struct LogListener
{
virtual ~LogListener() {};
virtual void log(LogMessage msg) = 0;
};
struct LogChannel
{
LogChannel();
LogChannel(const std::string& name);
LogChannel(LogChannel& other) = delete;
LogChannel& operator = (LogChannel& other) = delete;
void log(LogMessage msg);
void addListener(std::shared_ptr<LogListener> listener);
void removeListener(std::shared_ptr<LogListener> listener);
std::string name;
private:
bool mEnabled;
LogSeverity mLogLevel;
std::mutex mListenerLock;
std::set<std::shared_ptr<LogListener>> mListeners;
};
struct LogManager
{
LogManager();
~LogManager();
static LogManager& getInstance();
LogChannel& getChannel(LogType type);
void log(LogMessage msg);
void addListener(std::shared_ptr<LogListener> listener);
void removeListener(std::shared_ptr<LogListener> listener);
#ifdef BUFFERED_LOGGING
void consumeLog();
#endif
private:
#ifdef BUFFERED_LOGGING
MTRingbuffer<char, MAX_LOG_BUFFER_LENGTH> mBuffer;
std::condition_variable mBufferReady;
std::mutex mStatusMut;
std::atomic<bool> mExiting;
std::thread mLogConsumer;
#endif
std::array<LogChannel, std::tuple_size<decltype(gTypeNameTable)>::value> mChannels;
//std::array<LogChannel,gTypeNameTable.size()> mChannels; //TODO: use this once Microsoft sorts their shit out
};
}
static struct { inline operator Log::LogType() { return Log::LogType::GENERAL; } } GENERAL;
static struct { inline operator Log::LogType() { return Log::LogType::LOADER; } } LOADER;
static struct { inline operator Log::LogType() { return Log::LogType::MEMORY; } } MEMORY;
static struct { inline operator Log::LogType() { return Log::LogType::RSX; } } RSX;
static struct { inline operator Log::LogType() { return Log::LogType::HLE; } } HLE;
static struct { inline operator Log::LogType() { return Log::LogType::PPU; } } PPU;
static struct { inline operator Log::LogType() { return Log::LogType::SPU; } } SPU;
static struct { inline operator Log::LogType() { return Log::LogType::TTY; } } TTY;
inline void log_message(Log::LogType type, Log::LogSeverity sev, std::string text)
{
//another msvc bug makes this not work, uncomment this and delete everything else in this function when it's fixed
//Log::LogManager::getInstance().log({logType, severity, text})
Log::LogMessage msg{type, sev, text};
Log::LogManager::getInstance().log(msg);
}
template<typename T, typename ...Ts>
inline void log_message(Log::LogType type, Log::LogSeverity sev, std::string text, T arg, Ts... args)
{
Log::LogMessage msg{type, sev, fmt::Format(text,arg,args...)};
Log::LogManager::getInstance().log(msg);
}

155
Utilities/MTRingbuffer.h Normal file
View file

@ -0,0 +1,155 @@
#pragma once
//Simple non-resizable FIFO Ringbuffer that can be simultaneously be read from and written to
//if we ever get to use boost please replace this with boost::circular_buffer, there's no reason
//why we would have to keep this amateur attempt at such a fundamental data-structure around
template< typename T, unsigned int MAX_MTRINGBUFFER_BUFFER_SIZE>
class MTRingbuffer{
std::array<T, MAX_MTRINGBUFFER_BUFFER_SIZE> mBuffer;
//this is a recursive mutex because the get methods lock it but the only
//way to be sure that they do not block is to check the size and the only
//way to check the size and use get atomically is to lock this mutex,
//so it goes:
//lock get mutex-->check size-->call get-->lock get mutex-->unlock get mutex-->return from get-->unlock get mutex
std::recursive_mutex mMutGet;
std::mutex mMutPut;
size_t mGet;
size_t mPut;
size_t moveGet(size_t by = 1){ return (mGet + by) % MAX_MTRINGBUFFER_BUFFER_SIZE; }
size_t movePut(size_t by = 1){ return (mPut + by) % MAX_MTRINGBUFFER_BUFFER_SIZE; }
public:
MTRingbuffer() : mGet(0), mPut(0){}
//blocks until there's something to get, so check "spaceLeft()" if you want to avoid blocking
//also lock the get mutex around the spaceLeft() check and the pop if you want to avoid racing
T pop()
{
std::lock_guard<std::recursive_mutex> lock(mMutGet);
while (mGet == mPut)
{
//wait until there's actually something to get
//throwing an exception might be better, blocking here is a little awkward
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
size_t ret = mGet;
mGet = moveGet();
return mBuffer[ret];
}
//blocks if the buffer is full until there's enough room
void push(T &putEle)
{
std::lock_guard<std::mutex> lock(mMutPut);
while (movePut() == mGet)
{
//if this is reached a lot it's time to increase the buffer size
//or implement dynamic re-sizing
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
mBuffer[mPut] = std::forward(putEle);
mPut = movePut();
}
bool empty()
{
return mGet == mPut;
}
//returns the amount of free places, this is the amount of actual free spaces-1
//since mGet==mPut signals an empty buffer we can't actually use the last free
//space, so we shouldn't report it as free.
size_t spaceLeft() //apparently free() is a macro definition in msvc in some conditions
{
if (mGet < mPut)
{
return mBuffer.size() - (mPut - mGet) - 1;
}
else if (mGet > mPut)
{
return mGet - mPut - 1;
}
else
{
return mBuffer.size() - 1;
}
}
size_t size()
{
//the magic -1 is the same magic 1 that is explained in the spaceLeft() function
return mBuffer.size() - spaceLeft() - 1;
}
//takes random access iterator to T
template<typename IteratorType>
void pushRange(IteratorType from, IteratorType until)
{
std::lock_guard<std::mutex> lock(mMutPut);
size_t length = until - from;
//if whatever we're trying to store is greater than the entire buffer the following loop will be infinite
assert(mBuffer.size() > length);
while (spaceLeft() < length)
{
//if this is reached a lot it's time to increase the buffer size
//or implement dynamic re-sizing
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
if (mPut + length <= mBuffer.size())
{
std::copy(from, until, mBuffer.begin() + mPut);
}
else
{
size_t tillEnd = mBuffer.size() - mPut;
std::copy(from, from + tillEnd, mBuffer.begin() + mPut);
std::copy(from + tillEnd, until, mBuffer.begin());
}
mPut = movePut(length);
}
//takes output iterator to T
template<typename IteratorType>
void popN(IteratorType output, size_t n)
{
std::lock_guard<std::recursive_mutex> lock(mMutGet);
//make sure we're not trying to retrieve more than is in
assert(n <= size());
peekN<IteratorType>(output, n);
mGet = moveGet(n);
}
//takes output iterator to T
template<typename IteratorType>
void peekN(IteratorType output, size_t n)
{
size_t lGet = mGet;
if (lGet + n <= mBuffer.size())
{
std::copy_n(mBuffer.begin() + lGet, n, output);
}
else
{
auto next = std::copy(mBuffer.begin() + lGet, mBuffer.end(), output);
std::copy_n(mBuffer.begin(), n - (mBuffer.size() - lGet), next);
}
}
//well this is just asking for trouble
//but the comment above the declaration of mMutGet explains why it's there
//if there's a better way please remove this
void lockGet()
{
mMutGet.lock();
}
//well this is just asking for trouble
//but the comment above the declaration of mMutGet explains why it's there
//if there's a better way please remove this
void unlockGet()
{
mMutGet.unlock();
}
};

View file

@ -1,26 +1,34 @@
#include <stdafx.h>
#include <Utilities/SMutex.h>
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/CPU/CPUThread.h"
__forceinline void SM_Sleep()
#include "Utilities/SMutex.h"
bool SM_IsAborted()
{
Sleep(1);
return Emu.IsStopped();
}
#ifdef _WIN32
__declspec(thread)
#elif __APPLE__
__thread
#else
thread_local
#endif
size_t g_this_thread_id = 0;
void SM_Sleep()
{
if (NamedThreadBase* t = GetCurrentNamedThread())
{
t->WaitForAnySignal();
}
else
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
__forceinline size_t SM_GetCurrentThreadId()
thread_local size_t g_this_thread_id = 0;
size_t SM_GetCurrentThreadId()
{
return g_this_thread_id ? g_this_thread_id : g_this_thread_id = std::hash<std::thread::id>()(std::this_thread::get_id());
}
__forceinline u32 SM_GetCurrentCPUThreadId()
u32 SM_GetCurrentCPUThreadId()
{
if (CPUThread* t = GetCurrentCPUThread())
{
@ -29,7 +37,7 @@ __forceinline u32 SM_GetCurrentCPUThreadId()
return 0;
}
__forceinline be_t<u32> SM_GetCurrentCPUThreadIdBE()
be_t<u32> SM_GetCurrentCPUThreadIdBE()
{
return SM_GetCurrentCPUThreadId();
return be_t<u32>::MakeFromLE(SM_GetCurrentCPUThreadId());
}

View file

@ -1,9 +1,10 @@
#pragma once
extern void SM_Sleep();
extern size_t SM_GetCurrentThreadId();
extern u32 SM_GetCurrentCPUThreadId();
extern be_t<u32> SM_GetCurrentCPUThreadIdBE();
bool SM_IsAborted();
void SM_Sleep();
size_t SM_GetCurrentThreadId();
u32 SM_GetCurrentCPUThreadId();
be_t<u32> SM_GetCurrentCPUThreadIdBE();
enum SMutexResult
{
@ -20,8 +21,8 @@ enum SMutexResult
template
<
typename T,
u64 free_value = 0,
u64 dead_value = 0xffffffff,
const u64 free_value = 0,
const u64 dead_value = 0xffffffffffffffffull,
void (*wait)() = SM_Sleep
>
class SMutexBase
@ -30,20 +31,31 @@ class SMutexBase
std::atomic<T> owner;
public:
SMutexBase()
: owner((T)free_value)
static const T GetFreeValue()
{
static const u64 value = free_value;
return (const T&)value;
}
static const T GetDeadValue()
{
static const u64 value = dead_value;
return (const T&)value;
}
void initialize()
{
(T&)owner = free_value;
owner = GetFreeValue();
}
~SMutexBase()
SMutexBase()
{
lock((T)dead_value);
owner = (T)dead_value;
initialize();
}
void finalize()
{
owner = GetDeadValue();
}
__forceinline T GetOwner() const
@ -51,23 +63,13 @@ public:
return (T&)owner;
}
__forceinline T GetFreeValue() const
{
return (T)free_value;
}
__forceinline T GetDeadValue() const
{
return (T)dead_value;
}
SMutexResult trylock(T tid)
{
if (Emu.IsStopped())
if (SM_IsAborted())
{
return SMR_ABORT;
}
T old = (T)free_value;
T old = GetFreeValue();
if (!owner.compare_exchange_strong(old, tid))
{
@ -75,7 +77,7 @@ public:
{
return SMR_DEADLOCK;
}
if (old == (T)dead_value)
if (old == GetDeadValue())
{
return SMR_DESTROYED;
}
@ -85,9 +87,9 @@ public:
return SMR_OK;
}
SMutexResult unlock(T tid, T to = (T)free_value)
SMutexResult unlock(T tid, T to = GetFreeValue())
{
if (Emu.IsStopped())
if (SM_IsAborted())
{
return SMR_ABORT;
}
@ -95,11 +97,11 @@ public:
if (!owner.compare_exchange_strong(old, to))
{
if (old == (T)free_value)
if (old == GetFreeValue())
{
return SMR_FAILED;
}
if (old == (T)dead_value)
if (old == GetDeadValue())
{
return SMR_DESTROYED;
}
@ -122,7 +124,7 @@ public:
default: return res;
}
wait();
if (wait != nullptr) wait();
if (timeout && counter++ > timeout)
{
@ -132,23 +134,22 @@ public:
}
};
template<typename T, T (get_tid)()>
template<typename T, typename Tid, Tid (get_tid)()>
class SMutexLockerBase
{
SMutexBase<T>& sm;
T& sm;
public:
const T tid;
const Tid tid;
__forceinline SMutexLockerBase(SMutexBase<T>& _sm)
__forceinline SMutexLockerBase(T& _sm)
: sm(_sm)
, tid(get_tid())
{
if (!tid)
{
if (!Emu.IsStopped())
if (!SM_IsAborted())
{
ConLog.Error("SMutexLockerBase: thread id == 0");
Emu.Pause();
assert(!"SMutexLockerBase: thread id == 0");
}
return;
}
@ -168,9 +169,9 @@ typedef SMutexBase<u32>
typedef SMutexBase<be_t<u32>>
SMutexBE;
typedef SMutexLockerBase<size_t, SM_GetCurrentThreadId>
typedef SMutexLockerBase<SMutexGeneral, size_t, SM_GetCurrentThreadId>
SMutexGeneralLocker;
typedef SMutexLockerBase<u32, SM_GetCurrentCPUThreadId>
typedef SMutexLockerBase<SMutex, u32, SM_GetCurrentCPUThreadId>
SMutexLocker;
typedef SMutexLockerBase<be_t<u32>, SM_GetCurrentCPUThreadIdBE>
typedef SMutexLockerBase<SMutexBE, be_t<u32>, SM_GetCurrentCPUThreadIdBE>
SMutexBELocker;

View file

@ -1,9 +1,11 @@
#pragma once
#include "Utilities/SMutex.h"
template<typename T, u32 SQSize = 666>
class SQueue
{
SMutexGeneral m_mutex;
std::mutex m_mutex;
u32 m_pos;
u32 m_count;
T m_data[SQSize];
@ -24,23 +26,19 @@ public:
{
while (true)
{
if (m_mutex.GetOwner() == m_mutex.GetDeadValue())
{
return false;
}
if (m_count >= SQSize)
{
if (Emu.IsStopped())
{
return false;
}
Sleep(1);
SM_Sleep();
continue;
}
{
SMutexGeneralLocker lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
if (m_count >= SQSize) continue;
@ -55,23 +53,19 @@ public:
{
while (true)
{
if (m_mutex.GetOwner() == m_mutex.GetDeadValue())
{
return false;
}
if (!m_count)
{
if (Emu.IsStopped())
{
return false;
}
Sleep(1);
SM_Sleep();
continue;
}
{
SMutexGeneralLocker lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
if (!m_count) continue;
@ -84,19 +78,26 @@ public:
}
}
volatile u32 GetCount() // may be not safe
u32 GetCount()
{
std::lock_guard<std::mutex> lock(m_mutex);
return m_count;
}
u32 GetCountUnsafe()
{
return m_count;
}
volatile bool IsEmpty() // may be not safe
bool IsEmpty()
{
std::lock_guard<std::mutex> lock(m_mutex);
return !m_count;
}
void Clear()
{
SMutexGeneralLocker lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
m_count = 0;
}
@ -104,26 +105,40 @@ public:
{
while (true)
{
if (m_mutex.GetOwner() == m_mutex.GetDeadValue())
{
break;
}
if (!m_count)
if (m_count <= pos)
{
if (Emu.IsStopped())
{
break;
}
Sleep(1);
SM_Sleep();
continue;
}
{
SMutexGeneralLocker lock(m_mutex);
if (m_count) break;
std::lock_guard<std::mutex> lock(m_mutex);
if (m_count > pos)
{
break;
}
}
}
return m_data[(m_pos + pos) % SQSize];
}
T& PeekIfExist(u32 pos = 0)
{
static T def_value;
std::lock_guard<std::mutex> lock(m_mutex);
if (m_count <= pos)
{
return def_value;
}
else
{
return m_data[(m_pos + pos) % SQSize];
}
}
};

88
Utilities/SSemaphore.cpp Normal file
View file

@ -0,0 +1,88 @@
#include "stdafx.h"
#include "Utilities/SSemaphore.h"
#include "Emu/System.h"
void SSemaphore::wait()
{
u32 order;
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_count && m_out_order == m_in_order)
{
m_count--;
return;
}
order = m_in_order++;
}
std::unique_lock<std::mutex> cv_lock(m_cv_mutex);
while (true)
{
if (Emu.IsStopped())
{
return;
}
m_cond.wait_for(cv_lock, std::chrono::milliseconds(1));
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_count)
{
if (m_out_order == order)
{
m_count--;
m_out_order++;
return;
}
else
{
m_cond.notify_one();
}
}
}
}
}
bool SSemaphore::try_wait()
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_count && m_in_order == m_out_order)
{
m_count--;
return true;
}
else
{
return false;
}
}
void SSemaphore::post()
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_count < m_max)
{
m_count++;
}
else
{
return;
}
m_cond.notify_one();
}
bool SSemaphore::post_and_wait()
{
// TODO: merge these functions? Probably has a race condition.
if (try_wait()) return false;
post();
wait();
return true;
}

41
Utilities/SSemaphore.h Normal file
View file

@ -0,0 +1,41 @@
#pragma once
class SSemaphore
{
const u32 m_max;
u32 m_count;
u32 m_in_order;
u32 m_out_order;
std::mutex m_cv_mutex;
std::mutex m_mutex;
std::condition_variable m_cond;
public:
SSemaphore(u32 value, u32 max = 1)
: m_max(max > 0 ? max : 0xffffffff)
, m_count(value > m_max ? m_max : value)
, m_in_order(0)
, m_out_order(0)
{
}
SSemaphore()
: m_max(0xffffffff)
, m_count(0)
, m_in_order(0)
, m_out_order(0)
{
}
~SSemaphore()
{
}
void wait();
bool try_wait();
void post();
bool post_and_wait();
};

View file

@ -1,5 +1,6 @@
#include "stdafx.h"
#include "StrFmt.h"
#include <wx/string.h>
extern const std::string fmt::placeholder = "???";
@ -14,7 +15,11 @@ std::string fmt::FormatV(const char *fmt, va_list args)
for (;;)
{
std::vector<char> buffptr(length);
#if !defined(_MSC_VER)
size_t printlen = vsnprintf(buffptr.data(), length, fmt, args);
#else
size_t printlen = vsnprintf_s(buffptr.data(), length, length - 1, fmt, args);
#endif
if (printlen < length)
{
str = std::string(buffptr.data(), printlen);
@ -31,11 +36,35 @@ std::string fmt::FormatV(std::string fmt, va_list args)
return str;
}
std::string replace_first(const std::string& src, const std::string& from, const std::string& to)
{
auto pos = src.find(from);
if (pos == std::string::npos)
{
return src;
}
return (pos ? src.substr(0, pos) + to : to) + std::string(src.c_str() + pos + from.length());
}
std::string replace_all(std::string src, const std::string& from, const std::string& to)
{
for (auto pos = src.find(from); pos != std::string::npos; src.find(from, pos + 1))
{
src = (pos ? src.substr(0, pos) + to : to) + std::string(src.c_str() + pos + from.length());
pos += to.length();
}
return src;
}
//TODO: move this wx Stuff somewhere else
//convert a wxString to a std::string encoded in utf8
//CAUTION, only use this to interface with wxWidgets classes
std::string fmt::ToUTF8(const wxString& right)
{
auto ret = std::string(((const char *) right.utf8_str()));
auto ret = std::string(((const char *)right.utf8_str()));
return ret;
}
@ -63,4 +92,46 @@ int fmt::CmpNoCase(const std::string& a, const std::string& b)
[](const char& a, const char& b){return tolower(a) == tolower(b); })
? 0 : -1;
}
}
//TODO: remove this after every snippet that uses it is gone
//WARNING: not fully compatible with CmpNoCase from wxString
void fmt::Replace(std::string &str, const std::string &searchterm, const std::string& replaceterm)
{
size_t cursor = 0;
do
{
cursor = str.find(searchterm, cursor);
if (cursor != std::string::npos)
{
str.replace(cursor, searchterm.size(), replaceterm);
cursor += replaceterm.size();
}
else
{
break;
}
} while (true);
}
std::vector<std::string> fmt::rSplit(const std::string& source, const std::string& delim)
{
std::vector<std::string> ret;
size_t cursor = 0;
do
{
size_t prevcurs = cursor;
cursor = source.find(delim, cursor);
if (cursor != std::string::npos)
{
ret.push_back(source.substr(prevcurs,cursor-prevcurs));
cursor += delim.size();
}
else
{
ret.push_back(source.substr(prevcurs));
break;
}
} while (true);
return ret;
}

View file

@ -1,9 +1,5 @@
#pragma once
#include <string>
#include <vector>
#include <ostream>
#include <sstream>
#include <cstdio>
class wxString;
#if defined(_MSC_VER)
#define snprintf _snprintf
@ -18,6 +14,38 @@ namespace fmt{
extern const string placeholder;
template <typename T>
std::string AfterLast(const std::string& source, T searchstr)
{
size_t search_pos = source.rfind(searchstr);
search_pos = search_pos == std::string::npos ? 0 : search_pos;
return source.substr(search_pos);
}
template <typename T>
std::string BeforeLast(const std::string& source, T searchstr)
{
size_t search_pos = source.rfind(searchstr);
search_pos = search_pos == std::string::npos ? 0 : search_pos;
return source.substr(0, search_pos);
}
template <typename T>
std::string AfterFirst(const std::string& source, T searchstr)
{
size_t search_pos = source.find(searchstr);
search_pos = search_pos == std::string::npos ? 0 : search_pos;
return source.substr(search_pos);
}
template <typename T>
std::string BeforeFirst(const std::string& source, T searchstr)
{
size_t search_pos = source.find(searchstr);
search_pos = search_pos == std::string::npos ? 0 : search_pos;
return source.substr(0, search_pos);
}
// write `fmt` from `pos` to the first occurence of `fmt::placeholder` to
// the stream `os`. Then write `arg` to to the stream. If there's no
// `fmt::placeholder` after `pos` everything in `fmt` after pos is written
@ -76,7 +104,7 @@ namespace fmt{
//wrapper to deal with advance sprintf formating options with automatic length finding
template<typename ... Args>
string Format(const string &fmt, Args&& ... parameters)
string Format(const string &fmt, Args ... parameters)
{
size_t length = 256;
string str;
@ -84,10 +112,14 @@ namespace fmt{
for (;;)
{
std::vector<char> buffptr(length);
#if !defined(_MSC_VER)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-security"
size_t printlen = snprintf(buffptr.data(), length, fmt.c_str(), std::forward<Args>(parameters)...);
#pragma clang diagnostic pop
#else
size_t printlen = _snprintf_s(buffptr.data(), length, length - 1, fmt.c_str(), std::forward<Args>(parameters)...);
#endif
if (printlen < length)
{
str = string(buffptr.data(), printlen);
@ -98,6 +130,57 @@ namespace fmt{
return str;
}
std::string replace_first(const std::string& src, const std::string& from, const std::string& to);
std::string replace_all(std::string src, const std::string& from, const std::string& to);
template<size_t list_size>
std::string replace_all(std::string src, const std::pair<std::string, std::string>(&list)[list_size])
{
for (size_t pos = 0; pos < src.length(); ++pos)
{
for (size_t i = 0; i < list_size; ++i)
{
const size_t comp_length = list[i].first.length();
if (src.length() - pos < comp_length)
continue;
if (src.substr(pos, comp_length) == list[i].first)
{
src = (pos ? src.substr(0, pos) + list[i].second : list[i].second) + std::string(src.c_str() + pos + comp_length);
pos += list[i].second.length() - 1;
break;
}
}
}
return src;
}
template<size_t list_size>
std::string replace_all(std::string src, const std::pair<std::string, std::function<std::string()>>(&list)[list_size])
{
for (size_t pos = 0; pos < src.length(); ++pos)
{
for (size_t i = 0; i < list_size; ++i)
{
const size_t comp_length = list[i].first.length();
if (src.length() - pos < comp_length)
continue;
if (src.substr(pos, comp_length) == list[i].first)
{
src = (pos ? src.substr(0, pos) + list[i].second() : list[i].second()) + std::string(src.c_str() + pos + comp_length);
pos += list[i].second().length() - 1;
break;
}
}
}
return src;
}
//convert a wxString to a std::string encoded in utf8
//CAUTION, only use this to interface with wxWidgets classes
std::string ToUTF8(const wxString& right);
@ -110,4 +193,9 @@ namespace fmt{
//WARNING: not fully compatible with CmpNoCase from wxString
int CmpNoCase(const std::string& a, const std::string& b);
//TODO: remove this after every snippet that uses it is gone
//WARNING: not fully compatible with Replace from wxString
void Replace(std::string &str, const std::string &searchterm, const std::string& replaceterm);
std::vector<std::string> rSplit(const std::string& source, const std::string& delim);
}

View file

@ -1,20 +1,19 @@
#include "stdafx.h"
#include "Thread.h"
#ifdef _WIN32
__declspec(thread)
#elif __APPLE__
__thread
#else
thread_local
#endif
NamedThreadBase* g_tls_this_thread = nullptr;
thread_local NamedThreadBase* g_tls_this_thread = nullptr;
std::atomic<u32> g_thread_count(0);
NamedThreadBase* GetCurrentNamedThread()
{
return g_tls_this_thread;
}
void SetCurrentNamedThread(NamedThreadBase* value)
{
g_tls_this_thread = value;
}
std::string NamedThreadBase::GetThreadName() const
{
return m_name;
@ -25,6 +24,17 @@ void NamedThreadBase::SetThreadName(const std::string& name)
m_name = name;
}
void NamedThreadBase::WaitForAnySignal() // wait 1 ms for something
{
std::unique_lock<std::mutex> lock(m_signal_mtx);
m_signal_cv.wait_for(lock, std::chrono::milliseconds(1));
}
void NamedThreadBase::Notify() // wake up waiting thread or nothing
{
m_signal_cv.notify_one();
}
ThreadBase::ThreadBase(const std::string& name)
: NamedThreadBase(name)
, m_executor(nullptr)
@ -38,7 +48,8 @@ ThreadBase::~ThreadBase()
if(IsAlive())
Stop(false);
safe_delete(m_executor);
delete m_executor;
m_executor = nullptr;
}
void ThreadBase::Start()
@ -50,15 +61,16 @@ void ThreadBase::Start()
m_destroy = false;
m_alive = true;
m_executor = new std::thread(
[this]()
{
g_tls_this_thread = this;
m_executor = new std::thread([this]()
{
SetCurrentNamedThread(this);
g_thread_count++;
Task();
Task();
m_alive = false;
});
m_alive = false;
g_thread_count--;
});
}
void ThreadBase::Stop(bool wait, bool send_destroy)
@ -127,17 +139,12 @@ void thread::start(std::function<void()> func)
m_thr = std::thread([func, name]()
{
NamedThreadBase info(name);
g_tls_this_thread = &info;
SetCurrentNamedThread(&info);
g_thread_count++;
try
{
func();
}
catch(...)
{
ConLog.Error("Crash :(");
//std::terminate();
}
func();
g_thread_count--;
});
}

View file

@ -1,18 +1,14 @@
#pragma once
#include "Array.h"
#include <functional>
#include <thread>
#include <vector>
#include <mutex>
#include <atomic>
#include <condition_variable>
class ThreadExec;
static std::thread::id main_thread;
class NamedThreadBase
{
std::string m_name;
std::condition_variable m_signal_cv;
std::mutex m_signal_mtx;
public:
NamedThreadBase(const std::string& name) : m_name(name)
{
@ -24,9 +20,14 @@ public:
virtual std::string GetThreadName() const;
virtual void SetThreadName(const std::string& name);
void WaitForAnySignal();
void Notify();
};
NamedThreadBase* GetCurrentNamedThread();
void SetCurrentNamedThread(NamedThreadBase* value);
class ThreadBase : public NamedThreadBase
{
@ -67,142 +68,4 @@ public:
void detach();
void join();
bool joinable() const;
};
template<typename T> class MTPacketBuffer
{
protected:
volatile bool m_busy;
volatile u32 m_put, m_get;
std::vector<u8> m_buffer;
u32 m_max_buffer_size;
mutable std::recursive_mutex m_cs_main;
void CheckBusy()
{
m_busy = m_put >= m_max_buffer_size;
}
public:
MTPacketBuffer(u32 max_buffer_size)
: m_max_buffer_size(max_buffer_size)
{
Flush();
}
~MTPacketBuffer()
{
Flush();
}
void Flush()
{
std::lock_guard<std::recursive_mutex> lock(m_cs_main);
m_put = m_get = 0;
m_buffer.clear();
m_busy = false;
}
private:
virtual void _push(const T& v) = 0;
virtual T _pop() = 0;
public:
void Push(const T& v)
{
std::lock_guard<std::recursive_mutex> lock(m_cs_main);
_push(v);
}
T Pop()
{
std::lock_guard<std::recursive_mutex> lock(m_cs_main);
return _pop();
}
bool HasNewPacket() const { std::lock_guard<std::recursive_mutex> lock(m_cs_main); return m_put != m_get; }
bool IsBusy() const { return m_busy; }
};
static __forceinline bool SemaphorePostAndWait(wxSemaphore& sem)
{
if(sem.TryWait() != wxSEMA_BUSY) return false;
sem.Post();
sem.Wait();
return true;
}
/*
class StepThread : public ThreadBase
{
wxSemaphore m_main_sem;
wxSemaphore m_destroy_sem;
volatile bool m_exit;
protected:
StepThread(const std::string& name = "Unknown StepThread")
: ThreadBase(true, name)
, m_exit(false)
{
}
virtual ~StepThread() throw()
{
}
private:
virtual void Task()
{
m_exit = false;
while(!TestDestroy())
{
m_main_sem.Wait();
if(TestDestroy() || m_exit) break;
Step();
}
while(!TestDestroy()) Sleep(0);
if(m_destroy_sem.TryWait() != wxSEMA_NO_ERROR) m_destroy_sem.Post();
}
virtual void Step()=0;
public:
void DoStep()
{
if(IsRunning()) m_main_sem.Post();
}
void WaitForExit()
{
if(TestDestroy()) m_destroy_sem.Wait();
}
void WaitForNextStep()
{
if(!IsRunning()) return;
while(m_main_sem.TryWait() != wxSEMA_NO_ERROR) Sleep(0);
}
void Exit(bool wait = false)
{
if(!IsAlive()) return;
if(m_main_sem.TryWait() != wxSEMA_NO_ERROR)
{
m_exit = true;
m_main_sem.Post();
}
Delete();
if(wait) WaitForExit();
}
};
*/
};

403
Utilities/rFile.cpp Normal file
View file

@ -0,0 +1,403 @@
#include "stdafx.h"
#include "Log.h"
#include <wx/dir.h>
#include <wx/file.h>
#include <wx/filename.h>
#include "rFile.h"
#ifdef _WIN32
#include <Windows.h>
// Maybe in StrFmt?
std::wstring ConvertUTF8ToWString(const std::string &source) {
int len = (int)source.size();
int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0);
std::wstring str;
str.resize(size);
if (size > 0) {
MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, &str[0], size);
}
return str;
}
#endif
bool getFileInfo(const char *path, FileInfo *fileInfo) {
// TODO: Expand relative paths?
fileInfo->fullName = path;
#ifdef _WIN32
WIN32_FILE_ATTRIBUTE_DATA attrs;
if (!GetFileAttributesExW(ConvertUTF8ToWString(path).c_str(), GetFileExInfoStandard, &attrs)) {
fileInfo->size = 0;
fileInfo->isDirectory = false;
fileInfo->exists = false;
return false;
}
fileInfo->size = (uint64_t)attrs.nFileSizeLow | ((uint64_t)attrs.nFileSizeHigh << 32);
fileInfo->isDirectory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
fileInfo->isWritable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
fileInfo->exists = true;
#else
struct stat64 file_info;
int result = stat64(path, &file_info);
if (result < 0) {
LOG_NOTICE(GENERAL, "IsDirectory: stat failed on %s", path);
fileInfo->exists = false;
return false;
}
fileInfo->isDirectory = S_ISDIR(file_info.st_mode);
fileInfo->isWritable = false;
fileInfo->size = file_info.st_size;
fileInfo->exists = true;
// HACK: approximation
if (file_info.st_mode & 0200)
fileInfo->isWritable = true;
#endif
return true;
}
bool rIsDir(const std::string &filename) {
FileInfo info;
getFileInfo(filename.c_str(), &info);
return info.isDirectory;
}
bool rMkdir(const std::string &dir)
{
#ifdef _WIN32
return !_mkdir(dir.c_str());
#else
return !mkdir(dir.c_str(), 0777);
#endif
}
bool rMkpath(const std::string &path)
{
size_t start=0, pos;
std::string dir;
bool ret;
while (true) {
if ((pos = path.find_first_of("/\\", start)) == std::string::npos)
pos = path.length();
dir = path.substr(0,pos++);
start = pos;
if(dir.size() == 0)
continue;
#ifdef _WIN32
if((ret = _mkdir(dir.c_str())) && errno != EEXIST){
#else
if((ret = mkdir(dir.c_str(), 0777)) && errno != EEXIST){
#endif
return !ret;
}
if (pos >= path.length())
return true;
}
return true;
}
bool rRmdir(const std::string &dir)
{
#ifdef _WIN32
if (!RemoveDirectory(ConvertUTF8ToWString(dir).c_str())) {
LOG_ERROR(GENERAL, "Error deleting directory %s: %i", dir.c_str(), GetLastError());
return false;
}
return true;
#else
rmdir(dir.c_str());
#endif
}
bool rRename(const std::string &from, const std::string &to)
{
// TODO: Deal with case-sensitivity
#ifdef _WIN32
return (MoveFile(ConvertUTF8ToWString(from).c_str(), ConvertUTF8ToWString(to).c_str()) == TRUE);
#else
return (0 == rename(from.c_str(), to.c_str()));
#endif
}
bool rExists(const std::string &file)
{
#ifdef _WIN32
std::wstring wstr = ConvertUTF8ToWString(file);
return GetFileAttributes(wstr.c_str()) != 0xFFFFFFFF;
#else
struct stat buffer;
return (stat (file.c_str(), &buffer) == 0);
#endif
}
bool rRemoveFile(const std::string &file)
{
#ifdef _WIN32
if (!DeleteFile(ConvertUTF8ToWString(file).c_str())) {
LOG_ERROR(GENERAL, "Error deleting %s: %i", file.c_str(), GetLastError());
return false;
}
#else
int err = unlink(file.c_str());
if (err) {
LOG_ERROR(GENERAL, "Error unlinking %s: %i", file.c_str(), err);
return false;
}
#endif
return true;
}
wxFile::OpenMode convertOpenMode(rFile::OpenMode open)
{
wxFile::OpenMode mode;
switch (open)
{
case rFile::read:
mode = wxFile::read;
break;
case rFile::write:
mode = wxFile::write;
break;
case rFile::read_write:
mode = wxFile::read_write;
break;
case rFile::write_append:
mode = wxFile::write_append;
break;
case rFile::write_excl:
mode = wxFile::write_excl;
break;
}
return mode;
}
rFile::OpenMode rConvertOpenMode(wxFile::OpenMode open)
{
rFile::OpenMode mode;
switch (open)
{
case wxFile::read:
mode = rFile::read;
break;
case wxFile::write:
mode = rFile::write;
break;
case wxFile::read_write:
mode = rFile::read_write;
break;
case wxFile::write_append:
mode = rFile::write_append;
break;
case wxFile::write_excl:
mode = rFile::write_excl;
break;
}
return mode;
}
wxSeekMode convertSeekMode(rSeekMode mode)
{
wxSeekMode ret;
switch (mode)
{
case rFromStart:
ret = wxFromStart;
break;
case rFromCurrent:
ret = wxFromCurrent;
break;
case rFromEnd:
ret = wxFromEnd;
break;
}
return ret;
}
rSeekMode rConvertSeekMode(wxSeekMode mode)
{
rSeekMode ret;
switch (mode)
{
case wxFromStart:
ret = rFromStart;
break;
case wxFromCurrent:
ret = rFromCurrent;
break;
case wxFromEnd:
ret = rFromEnd;
break;
}
return ret;
}
rFile::rFile()
{
handle = reinterpret_cast<void*>(new wxFile());
}
rFile::rFile(const std::string& filename, rFile::OpenMode open)
{
handle = reinterpret_cast<void*>(new wxFile(fmt::FromUTF8(filename), convertOpenMode(open)));
}
rFile::rFile(int fd)
{
handle = reinterpret_cast<void*>(new wxFile(fd));
}
rFile::~rFile()
{
delete reinterpret_cast<wxFile*>(handle);
}
bool rFile::Access(const std::string &filename, rFile::OpenMode mode)
{
return wxFile::Access(fmt::FromUTF8(filename), convertOpenMode(mode));
}
size_t rFile::Write(const void *buffer, size_t count)
{
return reinterpret_cast<wxFile*>(handle)->Write(buffer,count);
}
bool rFile::Write(const std::string &text)
{
return reinterpret_cast<wxFile*>(handle)->Write(reinterpret_cast<const void*>(text.c_str()),text.size());
}
bool rFile::Close()
{
return reinterpret_cast<wxFile*>(handle)->Close();
}
bool rFile::Create(const std::string &filename, bool overwrite, int access)
{
return reinterpret_cast<wxFile*>(handle)->Create(fmt::FromUTF8(filename), overwrite, access);
}
bool rFile::Open(const std::string &filename, rFile::OpenMode mode, int access)
{
return reinterpret_cast<wxFile*>(handle)->Open(fmt::FromUTF8(filename), convertOpenMode(mode), access);
}
bool rFile::IsOpened() const
{
return reinterpret_cast<wxFile*>(handle)->IsOpened();
}
size_t rFile::Length() const
{
return reinterpret_cast<wxFile*>(handle)->Length();
}
size_t rFile::Read(void *buffer, size_t count)
{
return reinterpret_cast<wxFile*>(handle)->Read(buffer,count);
}
size_t rFile::Seek(size_t ofs, rSeekMode mode)
{
return reinterpret_cast<wxFile*>(handle)->Seek(ofs, convertSeekMode(mode));
}
size_t rFile::Tell() const
{
return reinterpret_cast<wxFile*>(handle)->Tell();
}
rDir::rDir()
{
handle = reinterpret_cast<void*>(new wxDir());
}
rDir::~rDir()
{
delete reinterpret_cast<wxDir*>(handle);
}
rDir::rDir(const std::string &path)
{
handle = reinterpret_cast<void*>(new wxDir(fmt::FromUTF8(path)));
}
bool rDir::Open(const std::string& path)
{
return reinterpret_cast<wxDir*>(handle)->Open(fmt::FromUTF8(path));
}
bool rDir::IsOpened() const
{
return reinterpret_cast<wxDir*>(handle)->IsOpened();
}
bool rDir::GetFirst(std::string *filename) const
{
wxString str;
bool res;
res = reinterpret_cast<wxDir*>(handle)->GetFirst(&str);
*filename = str.ToStdString();
return res;
}
bool rDir::GetNext(std::string *filename) const
{
wxString str;
bool res;
res = reinterpret_cast<wxDir*>(handle)->GetNext(&str);
*filename = str.ToStdString();
return res;
}
rFileName::rFileName()
{
handle = reinterpret_cast<void*>(new wxFileName());
}
rFileName::~rFileName()
{
delete reinterpret_cast<wxFileName*>(handle);
}
rFileName::rFileName(const rFileName& filename)
{
handle = reinterpret_cast<void*>(new wxFileName(*reinterpret_cast<wxFileName*>(filename.handle)));
}
rFileName::rFileName(const std::string& name)
{
handle = reinterpret_cast<void*>(new wxFileName(fmt::FromUTF8(name)));
}
std::string rFileName::GetFullPath()
{
return fmt::ToUTF8(reinterpret_cast<wxFileName*>(handle)->GetFullPath());
}
std::string rFileName::GetPath()
{
return fmt::ToUTF8(reinterpret_cast<wxFileName*>(handle)->GetPath());
}
std::string rFileName::GetName()
{
return fmt::ToUTF8(reinterpret_cast<wxFileName*>(handle)->GetName());
}
std::string rFileName::GetFullName()
{
return fmt::ToUTF8(reinterpret_cast<wxFileName*>(handle)->GetFullName());
}
bool rFileName::Normalize()
{
return reinterpret_cast<wxFileName*>(handle)->Normalize();
}

87
Utilities/rFile.h Normal file
View file

@ -0,0 +1,87 @@
#pragma once
struct FileInfo {
std::string name;
std::string fullName;
bool exists;
bool isDirectory;
bool isWritable;
uint64_t size;
};
bool getFileInfo(const char *path, FileInfo *fileInfo);
bool rIsDir(const std::string& filename);
bool rRmdir(const std::string& dir);
bool rMkdir(const std::string& dir);
bool rMkpath(const std::string& path);
bool rRename(const std::string &from, const std::string &to);
bool rExists(const std::string &path);
bool rRemoveFile(const std::string &path);
enum rSeekMode
{
rFromStart,
rFromCurrent,
rFromEnd
};
class rFile
{
public:
enum OpenMode
{
read,
write,
read_write,
write_append,
write_excl
};
rFile();
rFile(const rFile& other) = delete;
~rFile();
rFile(const std::string& filename, rFile::OpenMode open = rFile::read);
rFile(int fd);
static bool Access(const std::string &filename, rFile::OpenMode mode);
size_t Write(const void *buffer, size_t count);
bool Write(const std::string &text);
bool Close();
bool Create(const std::string &filename, bool overwrite = false, int access = 0666);
bool Open(const std::string &filename, rFile::OpenMode mode = rFile::read, int access = 0666);
static bool Exists(const std::string&);
bool IsOpened() const;
size_t Length() const;
size_t Read(void *buffer, size_t count);
size_t Seek(size_t ofs, rSeekMode mode = rFromStart);
size_t Tell() const;
void *handle;
};
struct rDir
{
rDir();
~rDir();
rDir(const rDir& other) = delete;
rDir(const std::string &path);
bool Open(const std::string& path);
bool IsOpened() const;
static bool Exists(const std::string &path);
bool GetFirst(std::string *filename) const;
bool GetNext(std::string *filename) const;
void *handle;
};
struct rFileName
{
rFileName();
rFileName(const rFileName& other);
~rFileName();
rFileName(const std::string& name);
std::string GetFullPath();
std::string GetPath();
std::string GetName();
std::string GetFullName();
bool Normalize();
void *handle;
};

34
Utilities/rMsgBox.cpp Normal file
View file

@ -0,0 +1,34 @@
#include "stdafx.h"
#include "restore_new.h"
#include <wx/msgdlg.h>
#include "define_new_memleakdetect.h"
#include "rMsgBox.h"
#ifndef QT_UI
rMessageDialog::rMessageDialog(void *parent, const std::string& msg, const std::string& title , long style )
{
handle = reinterpret_cast<void*>(new wxMessageDialog(
reinterpret_cast<wxWindow*>(parent)
, fmt::FromUTF8(msg)
, fmt::FromUTF8(title)
, style
));
}
rMessageDialog::~rMessageDialog()
{
delete reinterpret_cast<wxMessageDialog*>(handle);
}
long rMessageDialog::ShowModal()
{
return reinterpret_cast<wxMessageDialog*>(handle)->ShowModal();
}
long rMessageBox(const std::string& message, const std::string& title, long style)
{
return wxMessageBox(fmt::FromUTF8(message), fmt::FromUTF8(title),style);
}
#endif

38
Utilities/rMsgBox.h Normal file
View file

@ -0,0 +1,38 @@
#pragma once
enum MsgBoxParams : unsigned long
{
rYES_DEFAULT = 0x0,
rOK_DEFAULT = 0x0,
rCENTRE = 0x1,
rYES = 0x2, //res
rOK = 0x4,
rNO = 0x8, //res
rCANCEL = 0x10,
rYES_NO = 0xA,
rNO_DEFAULT = 0x80,
rICON_EXCLAMATION = 0x100,
rICON_ERROR = 0x200,
rICON_HAND = 0x200,
rICON_QUESTION = 0x400,
rICON_INFORMATION = 0x800,
rHELP = 0x1000,
rID_CANCEL = 0x13ED,
rID_YES = 0x13EF, //resDialog
rSTAY_ON_TOP = 0x8000,
rICON_NONE = 0x40000,
rICON_AUTH_NEEDED = 0x80000,
rCANCEL_DEFAULT = 0x80000000,
};
struct rMessageDialog
{
rMessageDialog(void *parent, const std::string& msg, const std::string& title = "RPCS3", long style = rOK | rCENTRE);
rMessageDialog(const rMessageDialog& other) = delete;
~rMessageDialog();
long ShowModal();
void *handle;
};
long rMessageBox(const std::string& message, const std::string& title,long style);

57
Utilities/rPlatform.cpp Normal file
View file

@ -0,0 +1,57 @@
#include "stdafx.h"
#include "restore_new.h"
#include <wx/image.h>
#include "define_new_memleakdetect.h"
#ifndef _WIN32
#include <dirent.h>
#endif
#include "rPlatform.h"
rImage::rImage()
{
handle = static_cast<void*>(new wxImage());
}
rImage::~rImage()
{
delete static_cast<wxImage*>(handle);
}
void rImage::Create(int width, int height, void *data, void *alpha)
{
static_cast<wxImage*>(handle)->Create(width, height, static_cast<unsigned char*>(data), static_cast<unsigned char*>(alpha));
}
void rImage::SaveFile(const std::string& name, rImageType type)
{
if (type == rBITMAP_TYPE_PNG)
{
static_cast<wxImage*>(handle)->SaveFile(fmt::FromUTF8(name),wxBITMAP_TYPE_PNG);
}
else
{
throw std::string("unsupported type");
}
}
std::string rPlatform::getConfigDir()
{
static std::string dir = ".";
if (dir == ".") {
#ifdef _WIN32
dir = "";
//mkdir(dir.c_str());
#else
if (getenv("XDG_CONFIG_HOME") != NULL)
dir = getenv("XDG_CONFIG_HOME");
else if (getenv("HOME") != NULL)
dir = getenv("HOME") + std::string("/.config");
else // Just in case
dir = "./config";
dir = dir + "/rpcs3/";
mkdir(dir.c_str(), 0777);
#endif
}
return dir;
}

45
Utilities/rPlatform.h Normal file
View file

@ -0,0 +1,45 @@
#pragma once
struct rPlatform
{
static std::string getConfigDir();
};
/**********************************************************************
*********** RSX Debugger
************************************************************************/
struct RSXDebuggerProgram
{
u32 id;
u32 vp_id;
u32 fp_id;
std::string vp_shader;
std::string fp_shader;
bool modified;
RSXDebuggerProgram()
: modified(false)
{
}
};
extern std::vector<RSXDebuggerProgram> m_debug_programs;
/**********************************************************************
*********** Image stuff
************************************************************************/
enum rImageType
{
rBITMAP_TYPE_PNG
};
struct rImage
{
rImage();
rImage(const rImage &) = delete;
~rImage();
void Create(int width , int height, void *data, void *alpha);
void SaveFile(const std::string& name, rImageType type);
void *handle;
};

232
Utilities/rTime.cpp Normal file
View file

@ -0,0 +1,232 @@
#include "stdafx.h"
#include "rTime.h"
#include <wx/datetime.h>
std::string rDefaultDateTimeFormat = "%c";
rTimeSpan::rTimeSpan()
{
handle = static_cast<void *>(new wxTimeSpan());
}
rTimeSpan::~rTimeSpan()
{
delete static_cast<wxTimeSpan*>(handle);
}
rTimeSpan::rTimeSpan(const rTimeSpan& other)
{
handle = static_cast<void *>(new wxTimeSpan(*static_cast<wxTimeSpan*>(other.handle)));
}
rTimeSpan::rTimeSpan(int a, int b , int c, int d)
{
handle = static_cast<void *>(new wxTimeSpan(a,b,c,d));
}
rDateSpan::rDateSpan()
{
handle = static_cast<void *>(new wxDateSpan());
}
rDateSpan::~rDateSpan()
{
delete static_cast<wxDateSpan*>(handle);
}
rDateSpan::rDateSpan(const rDateSpan& other)
{
handle = static_cast<void *>(new wxDateSpan(*static_cast<wxDateSpan*>(other.handle)));
}
rDateSpan::rDateSpan(int a, int b, int c, int d)
{
handle = static_cast<void *>(new wxDateSpan(a,b,c,d));
}
rDateTime::rDateTime()
{
handle = static_cast<void *>(new wxDateTime());
}
rDateTime::~rDateTime()
{
delete static_cast<wxDateTime*>(handle);
}
rDateTime::rDateTime(const rDateTime& other)
{
handle = static_cast<void *>(new wxDateTime(*static_cast<wxDateTime*>(other.handle)));
}
rDateTime::rDateTime(const time_t& time)
{
handle = static_cast<void *>(new wxDateTime(time));
}
rDateTime::rDateTime(u16 day, rDateTime::Month month, u16 year, u16 hour, u16 minute, u16 second, u32 millisecond)
{
handle = static_cast<void *>(new wxDateTime(day,(wxDateTime::Month)month,year,hour,minute,second,millisecond));
}
rDateTime rDateTime::UNow()
{
rDateTime time;
delete static_cast<wxDateTime*>(time.handle);
time.handle = static_cast<void *>(new wxDateTime(wxDateTime::UNow()));
return time;
}
rDateTime rDateTime::FromUTC(bool val)
{
rDateTime time(*this);
void *temp = time.handle;
time.handle = static_cast<void *>(new wxDateTime(static_cast<wxDateTime*>(temp)->FromTimezone(wxDateTime::GMT0, val)));
delete static_cast<wxDateTime*>(temp);
return time;
}
rDateTime rDateTime::ToUTC(bool val)
{
rDateTime time(*this);
void *temp = time.handle;
time.handle = static_cast<void *>(new wxDateTime(static_cast<wxDateTime*>(temp)->ToTimezone(wxDateTime::GMT0, val)));
delete static_cast<wxDateTime*>(temp);
return time;
}
time_t rDateTime::GetTicks()
{
return static_cast<wxDateTime*>(handle)->GetTicks();
}
void rDateTime::Add(const rTimeSpan& span)
{
static_cast<wxDateTime*>(handle)->Add(*static_cast<wxTimeSpan*>(span.handle));
}
void rDateTime::Add(const rDateSpan& span)
{
static_cast<wxDateTime*>(handle)->Add(*static_cast<wxDateSpan*>(span.handle));
}
wxDateTime::TimeZone convertTZ(rDateTime::rTimeZone tz)
{
switch (tz)
{
case rDateTime::Local:
return wxDateTime::Local;
case rDateTime::GMT0:
return wxDateTime::GMT0;
case rDateTime::UTC:
return wxDateTime::UTC;
default:
throw std::string("WRONG DATETIME");
}
}
std::string rDateTime::Format(const std::string &format, const rTimeZone &tz) const
{
return fmt::ToUTF8(static_cast<wxDateTime*>(handle)->Format(fmt::FromUTF8(format),convertTZ(tz)));
}
void rDateTime::ParseDateTime(const char* format)
{
static_cast<wxDateTime*>(handle)->ParseDateTime(format);
}
u32 rDateTime::GetAsDOS()
{
return static_cast<wxDateTime*>(handle)->GetAsDOS();
}
rDateTime &rDateTime::SetFromDOS(u32 fromdos)
{
static_cast<wxDateTime*>(handle)->SetFromDOS(fromdos);
return *this;
}
bool rDateTime::IsLeapYear(int year, rDateTime::Calender cal)
{
if (cal == Gregorian)
{
return wxDateTime::IsLeapYear(year, wxDateTime::Gregorian);
}
else
{
return wxDateTime::IsLeapYear(year, wxDateTime::Julian);
}
}
int rDateTime::GetNumberOfDays(rDateTime::Month month, int year, rDateTime::Calender cal)
{
if (cal == Gregorian)
{
return wxDateTime::GetNumberOfDays(static_cast<wxDateTime::Month>(month), year, wxDateTime::Gregorian);
}
else
{
return wxDateTime::GetNumberOfDays(static_cast<wxDateTime::Month>(month), year, wxDateTime::Julian);
}
}
void rDateTime::SetToWeekDay(rDateTime::WeekDay day, int n, rDateTime::Month month, int year)
{
static_cast<wxDateTime*>(handle)->SetToWeekDay(
static_cast<wxDateTime::WeekDay>(day)
, n
, static_cast<wxDateTime::Month>(month)
, year
);
}
int rDateTime::GetWeekDay()
{
return static_cast<wxDateTime*>(handle)->GetWeekDay();
}
u16 rDateTime::GetYear(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetYear(convertTZ(timezone));
}
u16 rDateTime::GetMonth(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetMonth(convertTZ(timezone));
}
u16 rDateTime::GetDay(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetDay(convertTZ(timezone));
}
u16 rDateTime::GetHour(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetHour(convertTZ(timezone));
}
u16 rDateTime::GetMinute(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetMinute(convertTZ(timezone));
}
u16 rDateTime::GetSecond(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetSecond(convertTZ(timezone));
}
u32 rDateTime::GetMillisecond(rDateTime::TZ timezone)
{
return static_cast<wxDateTime*>(handle)->GetMillisecond(convertTZ(timezone));
}

102
Utilities/rTime.h Normal file
View file

@ -0,0 +1,102 @@
#pragma once
extern std::string rDefaultDateTimeFormat;
struct rTimeSpan
{
rTimeSpan();
~rTimeSpan();
rTimeSpan(const rTimeSpan& other);
rTimeSpan(int, int, int, int);
void *handle;
};
struct rDateSpan
{
rDateSpan();
~rDateSpan();
rDateSpan(const rDateSpan& other);
rDateSpan(int, int, int, int);
void *handle;
};
struct rDateTime
{
enum TZ
{
Local, GMT0,UTC
};
enum Calender
{
Gregorian, Julian
};
using rTimeZone = TZ;
enum WeekDay
{
Sun = 0,
Mon,
Tue,
Wed,
Thu,
Fri,
Sat,
Inv_WeekDay
};
enum Month {
Jan = 0,
Feb = 1,
Mar = 2,
Apr = 3,
May = 4,
Jun = 5,
Jul = 6,
Aug = 7,
Sep = 8,
Oct = 9,
Nov = 10,
Dec = 11,
Inv_Month = 12
};
rDateTime();
~rDateTime();
rDateTime(const rDateTime& other);
rDateTime(const time_t &time);
rDateTime(u16 day, rDateTime::Month month, u16 year, u16 hour, u16 minute, u16 second, u32 millisecond);
static rDateTime UNow();
rDateTime FromUTC(bool val);
rDateTime ToUTC(bool val);
time_t GetTicks();
void Add(const rTimeSpan& span);
void Add(const rDateSpan& span);
void Close();
std::string Format(const std::string &format = rDefaultDateTimeFormat, const rTimeZone &tz = Local) const;
void ParseDateTime(const char* format);
u32 GetAsDOS();
rDateTime &SetFromDOS(u32 fromdos);
static bool IsLeapYear(int year, rDateTime::Calender cal);
static int GetNumberOfDays(rDateTime::Month month, int year, rDateTime::Calender cal);
void SetToWeekDay(rDateTime::WeekDay day, int n, rDateTime::Month month, int year);
int GetWeekDay();
u16 GetYear( rDateTime::TZ timezone);
u16 GetMonth(rDateTime::TZ timezone);
u16 GetDay(rDateTime::TZ timezone);
u16 GetHour(rDateTime::TZ timezone);
u16 GetMinute(rDateTime::TZ timezone);
u16 GetSecond(rDateTime::TZ timezone);
u32 GetMillisecond(rDateTime::TZ timezone);
void *handle;
};

113
Utilities/rXml.cpp Normal file
View file

@ -0,0 +1,113 @@
#include "stdafx.h"
#include "Utilities/rXml.h"
#include <wx/xml/xml.h>
rXmlNode::rXmlNode()
{
ownPtr = true;
handle = reinterpret_cast<void *>(new wxXmlNode());
}
rXmlNode::rXmlNode(void *ptr)
{
ownPtr = false;
handle = ptr;
}
rXmlNode::rXmlNode(const rXmlNode& other)
{
ownPtr = true;
handle = reinterpret_cast<void *>(new wxXmlNode(*reinterpret_cast<wxXmlNode*>(other.handle)));
}
rXmlNode &rXmlNode::operator=(const rXmlNode& other)
{
if (ownPtr)
{
delete reinterpret_cast<wxXmlNode*>(handle);
}
handle = reinterpret_cast<void *>(new wxXmlNode(*reinterpret_cast<wxXmlNode*>(other.handle)));
ownPtr = true;
return *this;
}
rXmlNode::~rXmlNode()
{
if (ownPtr)
{
delete reinterpret_cast<wxXmlNode*>(handle);
}
}
std::shared_ptr<rXmlNode> rXmlNode::GetChildren()
{
wxXmlNode* result = reinterpret_cast<wxXmlNode*>(handle)->GetChildren();
if (result)
{
return std::make_shared<rXmlNode>(reinterpret_cast<void*>(result));
}
else
{
return std::shared_ptr<rXmlNode>(nullptr);
}
}
std::shared_ptr<rXmlNode> rXmlNode::GetNext()
{
wxXmlNode* result = reinterpret_cast<wxXmlNode*>(handle)->GetNext();
if (result)
{
return std::make_shared<rXmlNode>(reinterpret_cast<void*>(result));
}
else
{
return std::shared_ptr<rXmlNode>(nullptr);
}
}
std::string rXmlNode::GetName()
{
return fmt::ToUTF8(reinterpret_cast<wxXmlNode*>(handle)->GetName());
}
std::string rXmlNode::GetAttribute(const std::string &name)
{
return fmt::ToUTF8(reinterpret_cast<wxXmlNode*>(handle)->GetAttribute(fmt::FromUTF8(name)));
}
std::string rXmlNode::GetNodeContent()
{
return fmt::ToUTF8(reinterpret_cast<wxXmlNode*>(handle)->GetNodeContent());
}
rXmlDocument::rXmlDocument()
{
handle = reinterpret_cast<void *>(new wxXmlDocument());
}
rXmlDocument::rXmlDocument(const rXmlDocument& other)
{
handle = reinterpret_cast<void *>(new wxXmlDocument(*reinterpret_cast<wxXmlDocument*>(other.handle)));
}
rXmlDocument &rXmlDocument::operator = (const rXmlDocument& other)
{
delete reinterpret_cast<wxXmlDocument*>(handle);
handle = reinterpret_cast<void *>(new wxXmlDocument(*reinterpret_cast<wxXmlDocument*>(other.handle)));
return *this;
}
rXmlDocument::~rXmlDocument()
{
delete reinterpret_cast<wxXmlDocument*>(handle);
}
void rXmlDocument::Load(const std::string & path)
{
reinterpret_cast<wxXmlDocument*>(handle)->Load(fmt::FromUTF8(path));
}
std::shared_ptr<rXmlNode> rXmlDocument::GetRoot()
{
return std::make_shared<rXmlNode>(reinterpret_cast<void*>(reinterpret_cast<wxXmlDocument*>(handle)->GetRoot()));
}

30
Utilities/rXml.h Normal file
View file

@ -0,0 +1,30 @@
#pragma once
struct rXmlNode
{
rXmlNode();
rXmlNode(void *);
rXmlNode(const rXmlNode& other);
rXmlNode &operator=(const rXmlNode& other);
~rXmlNode();
std::shared_ptr<rXmlNode> GetChildren();
std::shared_ptr<rXmlNode> GetNext();
std::string GetName();
std::string GetAttribute( const std::string &name);
std::string GetNodeContent();
void *handle;
bool ownPtr;
};
struct rXmlDocument
{
rXmlDocument();
rXmlDocument(const rXmlDocument& other);
rXmlDocument &operator=(const rXmlDocument& other);
~rXmlDocument();
void Load(const std::string & path);
std::shared_ptr<rXmlNode> GetRoot();
void *handle;
};

View file

@ -1,3 +1,5 @@
#pragma once
/*
* Copyright 2001-2004 Unicode, Inc.
*

56
appveyor.yml Normal file
View file

@ -0,0 +1,56 @@
# version format
version: 0.1.{build}
branches:
only:
- appveyorbuild
# blacklist
#except:
# - gh-pages
#---------------------------------#
# environment configuration #
#---------------------------------#
# clone directory
clone_folder: c:\projects\rpcs3
platform:
- x64
configuration:
- Release
install:
- cmd: cinst wget -x86
- cmd: cinst 7zip.commandline -x86
- cmd: git submodule update --init --recursive .\ffmpeg .\asmjit
- cmd: wget -q --no-check-certificate https://googledrive.com/host/0B3tDmChwjRbRTTdhaTFOeGN1eEU/wxWidgets.7z -O c:\projects\rpcs3\wxwidgets.7z
- cmd: 7z x C:\projects\rpcs3\wxwidgets.7z -oc:\projects\rpcs3\wxWidgets
build:
build_script:
- msbuild /m /p:Configuration=Release rpcs3_buildbot.sln
after_build:
- cmd: package.bat
artifacts:
- path: .\rpcs3*.7z
deploy: OFF
# - provider: FTP
# server:
# secure: kZT7rsbEPGQ0fC2GFRBGfL2vPwUgih2JkwjbSuw00T8=
# username:
# secure: YJzwsi4wfSezFLqaB9uiww==
# password:
# secure: EQ3xa2LoRgelAdE57+qakQ==
# folder: .\rpcs3\
# enable_ssl: false
test: OFF

2
asmjit

@ -1 +1 @@
Subproject commit b76922fde96232030be302b3bdd9673e9bcec568
Subproject commit d7fc62d9e905859579f5965eee6f7f99b65c2246

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@ -23,30 +23,55 @@
<ClCompile Include="..\asmjit\src\asmjit\base\codegen.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\compiler.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\constpool.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\containers.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\context.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\cpuinfo.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\cputicks.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\defs.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\error.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\func.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\globals.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\intutil.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\logger.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\memorymanager.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\podvector.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\operand.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\runtime.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\string.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\vmem.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\zone.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\contrib\winremoteruntime.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86assembler.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86compiler.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86context.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86cpuinfo.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86defs.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86func.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86inst.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86operand.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86operand_regs.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86scheduler.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\asmjit\src\asmjit\base\assembler.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\codegen.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\compiler.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\constpool.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\containers.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\context_p.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\cpuinfo.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\cputicks.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\error.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\globals.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\intutil.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\lock.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\logger.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\operand.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\runtime.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\string.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\vectypes.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\vmem.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\zone.h" />
<ClInclude Include="..\asmjit\src\asmjit\x86\x86assembler.h" />
<ClInclude Include="..\asmjit\src\asmjit\x86\x86compiler.h" />
<ClInclude Include="..\asmjit\src\asmjit\x86\x86context_p.h" />
<ClInclude Include="..\asmjit\src\asmjit\x86\x86cpuinfo.h" />
<ClInclude Include="..\asmjit\src\asmjit\x86\x86inst.h" />
<ClInclude Include="..\asmjit\src\asmjit\x86\x86operand.h" />
<ClInclude Include="..\asmjit\src\asmjit\x86\x86scheduler_p.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{AC40FF01-426E-4838-A317-66354CEFAE88}</ProjectGuid>

View file

@ -1,33 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="..\asmjit\src\asmjit\x86\x86assembler.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86compiler.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86context.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86cpuinfo.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86defs.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86func.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\contrib\winremoteruntime.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\assembler.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\codegen.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\compiler.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\constpool.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\containers.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\context.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\cpuinfo.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\cputicks.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\defs.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\error.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\func.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\globals.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\intutil.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\logger.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\memorymanager.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\podvector.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\operand.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\runtime.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\string.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\vmem.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\zone.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\base\constpool.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86assembler.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86compiler.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86context.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86cpuinfo.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86inst.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86operand.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86operand_regs.cpp" />
<ClCompile Include="..\asmjit\src\asmjit\x86\x86scheduler.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\asmjit\src\asmjit\x86\x86assembler.h" />
<ClInclude Include="..\asmjit\src\asmjit\x86\x86compiler.h" />
<ClInclude Include="..\asmjit\src\asmjit\x86\x86context_p.h" />
<ClInclude Include="..\asmjit\src\asmjit\x86\x86cpuinfo.h" />
<ClInclude Include="..\asmjit\src\asmjit\x86\x86inst.h" />
<ClInclude Include="..\asmjit\src\asmjit\x86\x86operand.h" />
<ClInclude Include="..\asmjit\src\asmjit\x86\x86scheduler_p.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\assembler.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\codegen.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\compiler.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\constpool.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\containers.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\context_p.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\cpuinfo.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\cputicks.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\error.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\globals.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\intutil.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\lock.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\logger.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\operand.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\runtime.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\string.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\vectypes.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\vmem.h" />
<ClInclude Include="..\asmjit\src\asmjit\base\zone.h" />
</ItemGroup>
</Project>

BIN
bin/soft_oal.dll Normal file

Binary file not shown.

23
package.bat Normal file
View file

@ -0,0 +1,23 @@
mkdir build
mkdir build\rpcs3
copy bin\rpcs3-*.exe build\rpcs3
copy bin\soft_oal.dll build\rpcs3
copy bin\make_fself.cmd build\rpcs3
mkdir build\rpcs3\dev_hdd1
xcopy /Y /e bin\dev_hdd1 build\rpcs3\dev_hdd1
mkdir build\rpcs3\dev_hdd0
xcopy /Y /e bin\dev_hdd0 build\rpcs3\dev_hdd0
mkdir build\rpcs3\dev_flash
xcopy /Y /e bin\dev_flash build\rpcs3\dev_flash
mkdir build\rpcs3\dev_usb000
xcopy /Y /e bin\dev_usb000 build\rpcs3\dev_usb000
for /f "delims=" %%a in ('git describe') do @set gitrev=%%a
cd build
7z a -mx9 ..\rpcs3-%gitrev%-windows-x86_64.7z rpcs3
cd ..

View file

@ -4,8 +4,10 @@ VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxproj", "{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}"
ProjectSection(ProjectDependencies) = postProject
{AC40FF01-426E-4838-A317-66354CEFAE88} = {AC40FF01-426E-4838-A317-66354CEFAE88}
{CD478F02-7550-58A5-E085-CE4BC0C0AD23} = {CD478F02-7550-58A5-E085-CE4BC0C0AD23}
{067D9406-2A93-DACA-9449-93A2D356357D} = {067D9406-2A93-DACA-9449-93A2D356357D}
{C4A10229-4712-4BD2-B63E-50D93C67A038} = {C4A10229-4712-4BD2-B63E-50D93C67A038}
{5C363C34-4741-7036-861C-2E2279CF552E} = {5C363C34-4741-7036-861C-2E2279CF552E}
{23E1C437-A951-5943-8639-A17F3CF2E606} = {23E1C437-A951-5943-8639-A17F3CF2E606}
{22B14659-C5B6-B775-868D-A49198FEAD4A} = {22B14659-C5B6-B775-868D-A49198FEAD4A}
@ -135,6 +137,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "asmjit", "asmjitsrc\asmjit.
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "asmjit", "asmjit", "{E2A982F2-4B1A-48B1-8D77-A17A589C58D7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "emucore", "rpcs3\emucore.vcxproj", "{C4A10229-4712-4BD2-B63E-50D93C67A038}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug - MemLeak|x64 = Debug - MemLeak|x64
@ -186,6 +190,7 @@ Global
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Release|x64.Build.0 = Release|x64
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug - MemLeak|x64.Build.0 = Debug|x64
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug - MemLeak|x64.Deploy.0 = Debug|x64
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug|x64.ActiveCfg = Debug|x64
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug|x64.Build.0 = Debug|x64
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Release|x64.ActiveCfg = Release|x64
@ -281,10 +286,17 @@ Global
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Release|x64.ActiveCfg = Release|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Release|x64.Build.0 = Release|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - MemLeak|x64.Build.0 = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug|x64.ActiveCfg = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug|x64.Build.0 = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release|x64.ActiveCfg = Release|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release|x64.Build.0 = Release|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug - MemLeak|x64.ActiveCfg = Debug - MemLeak|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug|x64.ActiveCfg = Debug|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug|x64.Build.0 = Debug|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release|x64.ActiveCfg = Release|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -1,22 +1,38 @@
cmake_minimum_required(VERSION 2.8)
set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake_modules")
include(cotire)
project(rpcs3)
if (CMAKE_COMPILER_IS_GNUCXX)
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7.0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
message(FATAL_ERROR "GCC ${CMAKE_CXX_COMPILER_VERSION} is too old.")
endif()
#add_definitions(-D__WXGTK__)
#add_definitions(-Wfatal-errors)
add_definitions(-w) # TODO: remove me
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
add_definitions(-fpermissive) # TODO: remove me
add_definitions(-g) # Debugging!!
add_definitions(-msse2)
# Warnings
add_definitions(-Wno-attributes -Wno-enum-compare)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
# TODO: stdlib?
endif()
if (NOT MSVC)
add_definitions(-DwxGUI)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fexceptions")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -D_DEBUG")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -Os -D_NDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O1 -D_NDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O1 -g -D_NDEBUG")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -D_DEBUG")
set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -Os -D_NDEBUG")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O1 -D_NDEBUG")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O1 -g -D_NDEBUG")
add_definitions(-msse2)
endif()
if (APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/opt/X11/include")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I/opt/X11/include")
endif()
If( NOT RPCS3_SRC_DIR)
@ -27,7 +43,8 @@ Else()
EndIf()
set(CMAKE_MODULE_PATH "${RPCS3_SRC_DIR}/cmake_modules")
set(EXECUTABLE_OUTPUT_PATH "${RPCS3_SRC_DIR}/../bin") # TODO: do real installation, including copying directory structure
# TODO: do real installation, including copying directory structure
set(EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}/../bin")
#include(cotire)
add_definitions(-DGL_GLEXT_PROTOTYPES)
@ -41,11 +58,6 @@ find_package(OpenAL REQUIRED)
include("${wxWidgets_USE_FILE}")
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
message( FATAL_ERROR "RPCS3 can only be compiled on 64-bit platforms." )
endif()
if(APPLE)
set(PLATFORM_ARCH "macosx/x86_64")
elseif(WIN32)
@ -59,8 +71,6 @@ ${wxWidgets_INCLUDE_DIRS}
${OPENAL_INCLUDE_DIR}
"${RPCS3_SRC_DIR}/../ffmpeg/${PLATFORM_ARCH}/include"
"${RPCS3_SRC_DIR}"
"${RPCS3_SRC_DIR}/Emu"
"${RPCS3_SRC_DIR}/Gui"
"${RPCS3_SRC_DIR}/Loader"
"${RPCS3_SRC_DIR}/Crypto"
"${RPCS3_SRC_DIR}/.."
@ -92,5 +102,6 @@ add_executable(rpcs3 ${RPCS3_SRC})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_BINARY_DIR}/../asmjit/") #hack because the asmjit cmake file force fno exceptions
target_link_libraries(rpcs3 asmjit.a ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES} libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a ${ZLIB_LIBRARIES})
#set_target_properties(rpcs3 PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${RPCS3_SRC_DIR}/stdafx.h")
#cotire(rpcs3)
set_target_properties(rpcs3 PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${RPCS3_SRC_DIR}/stdafx.h")
cotire(rpcs3)

View file

@ -1,3 +1,5 @@
#pragma once
/**
* \file aes.h
*
@ -174,4 +176,4 @@ void aes_cmac(aes_context *ctx, int length, unsigned char *input, unsigned char
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,6 +1,20 @@
#include "stdafx.h"
#include "utils.h"
#include "aes.h"
#include "key_vault.h"
SELF_KEY::SELF_KEY(u64 ver, u16 rev, u32 type, const std::string& e, const std::string& r, const std::string& pb, const std::string& pr, u32 ct)
{
version = ver;
revision = rev;
self_type = type;
hex_to_bytes(erk, e.c_str());
hex_to_bytes(riv, r.c_str());
hex_to_bytes(pub, pb.c_str());
hex_to_bytes(priv, pr.c_str());
curve_type = ct;
}
KeyVault::KeyVault()
{
}
@ -579,17 +593,17 @@ void KeyVault::LoadSelfUNK7Keys()
0x0F);
}
SELF_KEY KeyVault::GetSelfLV0Key()
SELF_KEY KeyVault::GetSelfLV0Key() const
{
return sk_LV0_arr[0];
}
SELF_KEY KeyVault::GetSelfLDRKey()
SELF_KEY KeyVault::GetSelfLDRKey() const
{
return sk_LDR_arr[0];
}
SELF_KEY KeyVault::GetSelfLV1Key(u64 version)
SELF_KEY KeyVault::GetSelfLV1Key(u64 version) const
{
SELF_KEY key(0, 0, 0, "", "", "", "", 0);
@ -605,7 +619,7 @@ SELF_KEY KeyVault::GetSelfLV1Key(u64 version)
return key;
}
SELF_KEY KeyVault::GetSelfLV2Key(u64 version)
SELF_KEY KeyVault::GetSelfLV2Key(u64 version) const
{
SELF_KEY key(0, 0, 0, "", "", "", "", 0);
@ -621,7 +635,7 @@ SELF_KEY KeyVault::GetSelfLV2Key(u64 version)
return key;
}
SELF_KEY KeyVault::GetSelfISOKey(u16 revision, u64 version)
SELF_KEY KeyVault::GetSelfISOKey(u16 revision, u64 version) const
{
SELF_KEY key(0, 0, 0, "", "", "", "", 0);
@ -638,7 +652,7 @@ SELF_KEY KeyVault::GetSelfISOKey(u16 revision, u64 version)
return key;
}
SELF_KEY KeyVault::GetSelfAPPKey(u16 revision)
SELF_KEY KeyVault::GetSelfAPPKey(u16 revision) const
{
SELF_KEY key(0, 0, 0, "", "", "", "", 0);
@ -654,7 +668,7 @@ SELF_KEY KeyVault::GetSelfAPPKey(u16 revision)
return key;
}
SELF_KEY KeyVault::GetSelfUNK7Key(u64 version)
SELF_KEY KeyVault::GetSelfUNK7Key(u64 version) const
{
SELF_KEY key(0, 0, 0, "", "", "", "", 0);
@ -670,7 +684,7 @@ SELF_KEY KeyVault::GetSelfUNK7Key(u64 version)
return key;
}
SELF_KEY KeyVault::GetSelfNPDRMKey(u16 revision)
SELF_KEY KeyVault::GetSelfNPDRMKey(u16 revision) const
{
SELF_KEY key(0, 0, 0, "", "", "", "", 0);

View file

@ -1,5 +1,4 @@
#pragma once
#include "utils.h"
enum SELF_KEY_TYPE {
KEY_LV0 = 1,
@ -22,17 +21,7 @@ struct SELF_KEY {
u8 priv[0x15];
u32 curve_type;
SELF_KEY(u64 ver, u16 rev, u32 type, const std::string& e, const std::string& r, const std::string& pb, const std::string& pr, u32 ct)
{
version = ver;
revision = rev;
self_type = type;
hex_to_bytes(erk, e.c_str());
hex_to_bytes(riv, r.c_str());
hex_to_bytes(pub, pb.c_str());
hex_to_bytes(priv, pr.c_str());
curve_type = ct;
}
SELF_KEY(u64 ver, u16 rev, u32 type, const std::string& e, const std::string& r, const std::string& pb, const std::string& pr, u32 ct);
};
static u8 PKG_AES_KEY[0x10] = {
@ -142,14 +131,14 @@ private:
void LoadSelfAPPKeys();
void LoadSelfUNK7Keys();
void LoadSelfNPDRMKeys();
SELF_KEY GetSelfLV0Key();
SELF_KEY GetSelfLDRKey();
SELF_KEY GetSelfLV1Key(u64 version);
SELF_KEY GetSelfLV2Key(u64 version);
SELF_KEY GetSelfISOKey(u16 revision, u64 version);
SELF_KEY GetSelfAPPKey(u16 revision);
SELF_KEY GetSelfUNK7Key(u64 version);
SELF_KEY GetSelfNPDRMKey(u16 revision);
SELF_KEY GetSelfLV0Key() const;
SELF_KEY GetSelfLDRKey() const;
SELF_KEY GetSelfLV1Key(u64 version) const;
SELF_KEY GetSelfLV2Key(u64 version) const;
SELF_KEY GetSelfISOKey(u16 revision, u64 version) const;
SELF_KEY GetSelfAPPKey(u16 revision) const;
SELF_KEY GetSelfUNK7Key(u64 version) const;
SELF_KEY GetSelfNPDRMKey(u16 revision) const;
};
// RAP to RIF function.

View file

@ -1,3 +1,4 @@
#pragma once
#include <string.h>
int decode_range(unsigned int *range, unsigned int *code, unsigned char **src);

View file

@ -1,3 +1,4 @@
#pragma once
/**
* \file sha1.h
*
@ -158,4 +159,4 @@ void sha1_hmac( const unsigned char *key, size_t keylen,
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,5 +1,9 @@
#include "stdafx.h"
#include "utils.h"
#include "key_vault.h"
#include "unedat.h"
#include "Utilities/Log.h"
#include "Utilities/rFile.h"
void generate_key(int crypto_mode, int version, unsigned char *key_final, unsigned char *iv_final, unsigned char *key, unsigned char *iv)
{
@ -73,7 +77,7 @@ bool crypto(int hash_mode, int crypto_mode, int version, unsigned char *in, unsi
}
else
{
ConLog.Error("EDAT: Unknown crypto algorithm!\n");
LOG_ERROR(LOADER, "EDAT: Unknown crypto algorithm!\n");
return false;
}
@ -91,7 +95,7 @@ bool crypto(int hash_mode, int crypto_mode, int version, unsigned char *in, unsi
}
else
{
ConLog.Error("EDAT: Unknown hashing algorithm!\n");
LOG_ERROR(LOADER, "EDAT: Unknown hashing algorithm!\n");
return false;
}
}
@ -132,7 +136,7 @@ unsigned char* get_block_key(int block, NPD_HEADER *npd)
}
// EDAT/SDAT functions.
int decrypt_data(wxFile *in, wxFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, unsigned char* crypt_key, bool verbose)
int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, unsigned char* crypt_key, bool verbose)
{
// Get metadata info and setup buffers.
int block_num = (int) ((edat->file_size + edat->block_size - 1) / edat->block_size);
@ -155,6 +159,12 @@ int decrypt_data(wxFile *in, wxFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *np
int length = 0;
int compression_end = 0;
if ((edat->flags & EDAT_FLAG_0x04) != 0)
{
LOG_ERROR(LOADER, "EDAT: Flag 0x04 is not yet supported");
return -1;
}
if ((edat->flags & EDAT_COMPRESSED_FLAG) != 0)
{
unsigned char metadata[0x20];
@ -261,15 +271,15 @@ int decrypt_data(wxFile *in, wxFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *np
memset(decomp_data, 0, decomp_size);
if (verbose)
ConLog.Write("EDAT: Decompressing...\n");
LOG_NOTICE(LOADER, "EDAT: Decompressing...\n");
int res = lz_decompress(decomp_data, dec_data, decomp_size);
out->Write(decomp_data, res);
if (verbose)
{
ConLog.Write("EDAT: Compressed block size: %d\n", pad_length);
ConLog.Write("EDAT: Decompressed block size: %d\n", res);
LOG_NOTICE(LOADER, "EDAT: Compressed block size: %d\n", pad_length);
LOG_NOTICE(LOADER, "EDAT: Decompressed block size: %d\n", res);
}
edat->file_size -= res;
@ -278,11 +288,11 @@ int decrypt_data(wxFile *in, wxFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *np
{
if (res < 0)
{
ConLog.Error("EDAT: Decompression failed!\n");
LOG_ERROR(LOADER, "EDAT: Decompression failed!\n");
return 1;
}
else
ConLog.Success("EDAT: Data successfully decompressed!\n");
LOG_SUCCESS(LOADER, "EDAT: Data successfully decompressed!\n");
}
delete[] decomp_data;
@ -308,7 +318,7 @@ static bool check_flags(EDAT_SDAT_HEADER *edat, NPD_HEADER *npd)
{
if (edat->flags & 0x7EFFFFFE)
{
ConLog.Error("EDAT: Bad header flags!\n");
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n");
return false;
}
}
@ -316,7 +326,7 @@ static bool check_flags(EDAT_SDAT_HEADER *edat, NPD_HEADER *npd)
{
if (edat->flags & 0x7EFFFFE0)
{
ConLog.Error("EDAT: Bad header flags!\n");
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n");
return false;
}
}
@ -324,20 +334,20 @@ static bool check_flags(EDAT_SDAT_HEADER *edat, NPD_HEADER *npd)
{
if (edat->flags & 0x7EFFFFC0)
{
ConLog.Error("EDAT: Bad header flags!\n");
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n");
return false;
}
}
else if (npd->version > 4)
{
ConLog.Error("EDAT: Unknown version - %d\n", npd->version);
LOG_ERROR(LOADER, "EDAT: Unknown version - %d\n", npd->version);
return false;
}
return true;
}
int check_data(unsigned char *key, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, wxFile *f, bool verbose)
int check_data(unsigned char *key, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, rFile *f, bool verbose)
{
f->Seek(0);
unsigned char *header = new unsigned char[0xA0];
@ -363,7 +373,7 @@ int check_data(unsigned char *key, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, wxFi
int hash_mode = ((edat->flags & EDAT_ENCRYPTED_KEY_FLAG) == 0) ? 0x00000002 : 0x10000002;
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != 0)
{
ConLog.Warning("EDAT: DEBUG data detected!\n");
LOG_ERROR(LOADER, "EDAT: DEBUG data detected!\n");
hash_mode |= 0x01000000;
}
@ -375,14 +385,14 @@ int check_data(unsigned char *key, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, wxFi
if (!crypto(hash_mode, crypto_mode, (npd->version == 4), header, tmp, 0xA0, header_key, header_iv, key, hash_result))
{
if (verbose)
ConLog.Warning("EDAT: Header hash is invalid!\n");
LOG_WARNING(LOADER, "EDAT: Header hash is invalid!\n");
}
// Parse the metadata info.
int metadata_section_size = 0x10;
if (((edat->flags & EDAT_COMPRESSED_FLAG) != 0))
{
ConLog.Warning("EDAT: COMPRESSED data detected!\n");
LOG_WARNING(LOADER, "EDAT: COMPRESSED data detected!\n");
metadata_section_size = 0x20;
}
@ -411,7 +421,7 @@ int check_data(unsigned char *key, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, wxFi
if (!crypto(hash_mode, crypto_mode, (npd->version == 4), data, tmp, block_size, header_key, header_iv, key, hash_result))
{
if (verbose)
ConLog.Warning("EDAT: Metadata hash from block 0x%08x is invalid!\n", metadata_offset + bytes_read);
LOG_WARNING(LOADER, "EDAT: Metadata hash from block 0x%08x is invalid!\n", metadata_offset + bytes_read);
}
// Adjust sizes.
@ -448,9 +458,9 @@ void validate_data(const char* file_name, unsigned char *klicensee, NPD_HEADER *
if (verbose)
{
if (title_hash_result)
ConLog.Success("EDAT: NPD title hash is valid!\n");
LOG_SUCCESS(LOADER, "EDAT: NPD title hash is valid!\n");
else
ConLog.Warning("EDAT: NPD title hash is invalid!\n");
LOG_WARNING(LOADER, "EDAT: NPD title hash is invalid!\n");
}
// Check for an empty dev_hash (can't validate if devklic is NULL);
@ -467,7 +477,7 @@ void validate_data(const char* file_name, unsigned char *klicensee, NPD_HEADER *
if (isDevklicEmpty)
{
if (verbose)
ConLog.Warning("EDAT: NPD dev hash is empty!\n");
LOG_WARNING(LOADER, "EDAT: NPD dev hash is empty!\n");
}
else
{
@ -480,16 +490,16 @@ void validate_data(const char* file_name, unsigned char *klicensee, NPD_HEADER *
if (verbose)
{
if (dev_hash_result)
ConLog.Success("EDAT: NPD dev hash is valid!\n");
LOG_SUCCESS(LOADER, "EDAT: NPD dev hash is valid!\n");
else
ConLog.Warning("EDAT: NPD dev hash is invalid!\n");
LOG_WARNING(LOADER, "EDAT: NPD dev hash is invalid!\n");
}
}
delete[] buf;
}
bool extract_data(wxFile *input, wxFile *output, const char* input_file_name, unsigned char* devklic, unsigned char* rifkey, bool verbose)
bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsigned char* devklic, unsigned char* rifkey, bool verbose)
{
// Setup NPD and EDAT/SDAT structs.
NPD_HEADER *NPD = new NPD_HEADER();
@ -515,7 +525,7 @@ bool extract_data(wxFile *input, wxFile *output, const char* input_file_name, un
unsigned char npd_magic[4] = {0x4E, 0x50, 0x44, 0x00}; //NPD0
if(memcmp(NPD->magic, npd_magic, 4))
{
ConLog.Error("EDAT: File has invalid NPD header.");
LOG_ERROR(LOADER, "EDAT: %s has invalid NPD header or already decrypted.", input_file_name);
delete NPD;
delete EDAT;
return 1;
@ -527,16 +537,16 @@ bool extract_data(wxFile *input, wxFile *output, const char* input_file_name, un
if (verbose)
{
ConLog.Write("NPD HEADER\n");
ConLog.Write("NPD version: %d\n", NPD->version);
ConLog.Write("NPD license: %d\n", NPD->license);
ConLog.Write("NPD type: %d\n", NPD->type);
ConLog.Write("\n");
ConLog.Write("EDAT HEADER\n");
ConLog.Write("EDAT flags: 0x%08X\n", EDAT->flags);
ConLog.Write("EDAT block size: 0x%08X\n", EDAT->block_size);
ConLog.Write("EDAT file size: 0x%08X\n", EDAT->file_size);
ConLog.Write("\n");
LOG_NOTICE(LOADER, "NPD HEADER\n");
LOG_NOTICE(LOADER, "NPD version: %d\n", NPD->version);
LOG_NOTICE(LOADER, "NPD license: %d\n", NPD->license);
LOG_NOTICE(LOADER, "NPD type: %d\n", NPD->type);
LOG_NOTICE(LOADER, "\n");
LOG_NOTICE(LOADER, "EDAT HEADER\n");
LOG_NOTICE(LOADER, "EDAT flags: 0x%08X\n", EDAT->flags);
LOG_NOTICE(LOADER, "EDAT block size: 0x%08X\n", EDAT->block_size);
LOG_NOTICE(LOADER, "EDAT file size: 0x%08X\n", EDAT->file_size);
LOG_NOTICE(LOADER, "\n");
}
// Set decryption key.
@ -545,7 +555,7 @@ bool extract_data(wxFile *input, wxFile *output, const char* input_file_name, un
if((EDAT->flags & SDAT_FLAG) == SDAT_FLAG)
{
ConLog.Warning("EDAT: SDAT detected!\n");
LOG_WARNING(LOADER, "EDAT: SDAT detected!\n");
xor_(key, NPD->dev_hash, SDAT_KEY, 0x10);
}
else
@ -572,7 +582,7 @@ bool extract_data(wxFile *input, wxFile *output, const char* input_file_name, un
if (!test)
{
ConLog.Error("EDAT: A valid RAP file is needed!");
LOG_ERROR(LOADER, "EDAT: A valid RAP file is needed!");
delete NPD;
delete EDAT;
return 1;
@ -580,19 +590,19 @@ bool extract_data(wxFile *input, wxFile *output, const char* input_file_name, un
}
}
ConLog.Write("EDAT: Parsing data...\n");
LOG_NOTICE(LOADER, "EDAT: Parsing data...\n");
if (check_data(key, EDAT, NPD, input, verbose))
ConLog.Error("EDAT: Data parsing failed!\n");
LOG_ERROR(LOADER, "EDAT: Data parsing failed!\n");
else
ConLog.Success("EDAT: Data successfully parsed!\n");
LOG_SUCCESS(LOADER, "EDAT: Data successfully parsed!\n");
printf("\n");
ConLog.Write("EDAT: Decrypting data...\n");
LOG_NOTICE(LOADER, "EDAT: Decrypting data...\n");
if (decrypt_data(input, output, EDAT, NPD, key, verbose))
ConLog.Error("EDAT: Data decryption failed!");
LOG_ERROR(LOADER, "EDAT: Data decryption failed!");
else
ConLog.Success("EDAT: Data successfully decrypted!");
LOG_SUCCESS(LOADER, "EDAT: Data successfully decrypted!");
delete NPD;
delete EDAT;
@ -603,9 +613,9 @@ bool extract_data(wxFile *input, wxFile *output, const char* input_file_name, un
int DecryptEDAT(const std::string& input_file_name, const std::string& output_file_name, int mode, const std::string& rap_file_name, unsigned char *custom_klic, bool verbose)
{
// Prepare the files.
wxFile input(input_file_name.c_str());
wxFile output(output_file_name.c_str(), wxFile::write);
wxFile rap(rap_file_name.c_str());
rFile input(input_file_name.c_str());
rFile output(output_file_name.c_str(), rFile::write);
rFile rap(rap_file_name.c_str());
// Set keys (RIF and DEVKLIC).
unsigned char rifkey[0x10];
@ -645,21 +655,21 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
memcpy(devklic, custom_klic, 0x10);
else
{
ConLog.Error("EDAT: Invalid custom klic!\n");
LOG_ERROR(LOADER, "EDAT: Invalid custom klic!\n");
return -1;
}
break;
}
default:
ConLog.Error("EDAT: Invalid mode!\n");
LOG_ERROR(LOADER, "EDAT: Invalid mode!\n");
return -1;
}
// Check the input/output files.
if (!input.IsOpened() || !output.IsOpened())
{
ConLog.Error("EDAT: Failed to open files!\n");
LOG_ERROR(LOADER, "EDAT: Failed to open files!\n");
return -1;
}
@ -681,7 +691,7 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
{
input.Close();
output.Close();
wxRemoveFile(output_file_name);
rRemoveFile(output_file_name);
return 0;
}

View file

@ -1,10 +1,9 @@
#pragma once
#include "utils.h"
#include "key_vault.h"
#define SDAT_FLAG 0x01000000
#define EDAT_COMPRESSED_FLAG 0x00000001
#define EDAT_FLAG_0x02 0x00000002
#define EDAT_FLAG_0x04 0x00000004
#define EDAT_ENCRYPTED_KEY_FLAG 0x00000008
#define EDAT_FLAG_0x10 0x00000010
#define EDAT_FLAG_0x20 0x00000020
@ -31,4 +30,4 @@ typedef struct
unsigned long long file_size;
} EDAT_SDAT_HEADER;
int DecryptEDAT(const std::string& input_file_name, const std::string& output_file_name, int mode, const std::string& rap_file_name, unsigned char *custom_klic, bool verbose);
int DecryptEDAT(const std::string& input_file_name, const std::string& output_file_name, int mode, const std::string& rap_file_name, unsigned char *custom_klic, bool verbose);

View file

@ -1,12 +1,21 @@
#include "stdafx.h"
#include "utils.h"
#include "aes.h"
#include "sha1.h"
#include "key_vault.h"
#include "unpkg.h"
#include "restore_new.h"
#include <wx/progdlg.h>
#include "define_new_memleakdetect.h"
#include "Utilities/Log.h"
#include "Utilities/rFile.h"
// Decryption.
bool CheckHeader(wxFile& pkg_f, PKGHeader* m_header)
bool CheckHeader(rFile& pkg_f, PKGHeader* m_header)
{
if (m_header->pkg_magic != 0x7F504B47) {
ConLog.Error("PKG: Not a package file!");
LOG_ERROR(LOADER, "PKG: Not a package file!");
return false;
}
@ -15,7 +24,7 @@ bool CheckHeader(wxFile& pkg_f, PKGHeader* m_header)
case PKG_RELEASE_TYPE_DEBUG: break;
case PKG_RELEASE_TYPE_RELEASE: break;
default:
ConLog.Error("PKG: Unknown PKG type!");
LOG_ERROR(LOADER, "PKG: Unknown PKG type!");
return false;
}
@ -24,34 +33,34 @@ bool CheckHeader(wxFile& pkg_f, PKGHeader* m_header)
case PKG_PLATFORM_TYPE_PS3: break;
case PKG_PLATFORM_TYPE_PSP: break;
default:
ConLog.Error("PKG: Unknown PKG type!");
LOG_ERROR(LOADER, "PKG: Unknown PKG type!");
return false;
}
if (m_header->header_size != PKG_HEADER_SIZE) {
ConLog.Error("PKG: Wrong header size!");
LOG_ERROR(LOADER, "PKG: Wrong header size!");
return false;
}
if (m_header->pkg_size != pkg_f.Length()) {
ConLog.Error("PKG: File size mismatch.");
LOG_ERROR(LOADER, "PKG: File size mismatch.");
return false;
}
if (m_header->data_size + m_header->data_offset + 0x60 != pkg_f.Length()) {
ConLog.Error("PKG: Data size mismatch.");
LOG_ERROR(LOADER, "PKG: Data size mismatch.");
return false;
}
return true;
}
bool LoadHeader(wxFile& pkg_f, PKGHeader* m_header)
bool LoadHeader(rFile& pkg_f, PKGHeader* m_header)
{
pkg_f.Seek(0);
if (pkg_f.Read(m_header, sizeof(PKGHeader)) != sizeof(PKGHeader)) {
ConLog.Error("PKG: Package file is too short!");
LOG_ERROR(LOADER, "PKG: Package file is too short!");
return false;
}
@ -61,7 +70,7 @@ bool LoadHeader(wxFile& pkg_f, PKGHeader* m_header)
return true;
}
int Decrypt(wxFile& pkg_f, wxFile& dec_pkg_f, PKGHeader* m_header)
int Decrypt(rFile& pkg_f, rFile& dec_pkg_f, PKGHeader* m_header)
{
if (!LoadHeader(pkg_f, m_header))
return -1;
@ -111,8 +120,9 @@ int Decrypt(wxFile& pkg_f, wxFile& dec_pkg_f, PKGHeader* m_header)
{
aes_crypt_ecb(&c, AES_ENCRYPT, iv, ctr+j*HASH_LEN);
be_t<u64> hi = *(be_t<u64>*)&iv[0];
be_t<u64> lo = *(be_t<u64>*)&iv[8] + 1;
be_t<u64> hi = be_t<u64>::MakeFromBE(*(u64*)&iv[0]);
be_t<u64> lo = be_t<u64>::MakeFromBE(*(u64*)&iv[8]);
lo++;
if (lo == 0)
hi += 1;
@ -133,20 +143,20 @@ int Decrypt(wxFile& pkg_f, wxFile& dec_pkg_f, PKGHeader* m_header)
}
// Unpacking.
bool LoadEntries(wxFile& dec_pkg_f, PKGHeader* m_header, PKGEntry *m_entries)
bool LoadEntries(rFile& dec_pkg_f, PKGHeader* m_header, PKGEntry *m_entries)
{
dec_pkg_f.Seek(0);
dec_pkg_f.Read(m_entries, sizeof(PKGEntry) * m_header->file_count);
if (m_entries->name_offset / sizeof(PKGEntry) != m_header->file_count) {
ConLog.Error("PKG: Entries are damaged!");
LOG_ERROR(LOADER, "PKG: Entries are damaged!");
return false;
}
return true;
}
bool UnpackEntry(wxFile& dec_pkg_f, const PKGEntry& entry, std::string dir)
bool UnpackEntry(rFile& dec_pkg_f, const PKGEntry& entry, std::string dir)
{
u8 buf[BUF_SIZE];
@ -161,8 +171,8 @@ bool UnpackEntry(wxFile& dec_pkg_f, const PKGEntry& entry, std::string dir)
case PKG_FILE_ENTRY_SDAT:
case PKG_FILE_ENTRY_REGULAR:
{
wxFile out;
out.Create(dir + buf);
rFile out;
out.Create(dir + std::string(reinterpret_cast<char *>(buf), entry.name_size));
dec_pkg_f.Seek(entry.file_offset);
for (u64 size = 0; size < entry.file_size; ) {
@ -177,18 +187,19 @@ bool UnpackEntry(wxFile& dec_pkg_f, const PKGEntry& entry, std::string dir)
break;
case PKG_FILE_ENTRY_FOLDER:
wxMkdir(dir + buf);
rMkdir(dir + std::string(reinterpret_cast<char *>(buf), entry.name_size));
break;
}
return true;
}
int Unpack(wxFile& pkg_f, std::string src, std::string dst)
int Unpack(rFile& pkg_f, std::string src, std::string dst)
{
PKGHeader* m_header = (PKGHeader*) malloc (sizeof(PKGHeader));
wxFile dec_pkg_f;
std::string decryptedFile = wxGetCwd().ToStdString() + "/dev_hdd1/" + src + ".dec";
rFile dec_pkg_f;
// TODO: This shouldn't use current dir
std::string decryptedFile = "./dev_hdd1/" + src + ".dec";
dec_pkg_f.Create(decryptedFile, true);
@ -197,7 +208,7 @@ int Unpack(wxFile& pkg_f, std::string src, std::string dst)
dec_pkg_f.Close();
wxFile n_dec_pkg_f(decryptedFile, wxFile::read);
rFile n_dec_pkg_f(decryptedFile, rFile::read);
std::vector<PKGEntry> m_entries;
m_entries.resize(m_header->file_count);

View file

@ -1,6 +1,4 @@
#pragma once
#include "utils.h"
#include "key_vault.h"
// Constants
#define PKG_HEADER_SIZE 0xC0 //sizeof(pkg_header) + sizeof(pkg_unk_checksum)
@ -47,4 +45,6 @@ struct PKGEntry
be_t<u32> pad; // Padding (zeros)
};
extern int Unpack(wxFile& dec_pkg_f, std::string src, std::string dst);
class rFile;
extern int Unpack(rFile& dec_pkg_f, std::string src, std::string dst);

View file

@ -1,6 +1,318 @@
#include "stdafx.h"
#include "Utilities/Log.h"
#include "Utilities/rFile.h"
#include "aes.h"
#include "sha1.h"
#include "utils.h"
#include "Emu/FS/vfsLocalFile.h"
#include "unself.h"
#include <wx/mstream.h>
#include <wx/zstream.h>
void AppInfo::Load(vfsStream& f)
{
authid = Read64(f);
vendor_id = Read32(f);
self_type = Read32(f);
version = Read64(f);
padding = Read64(f);
}
void AppInfo::Show()
{
LOG_NOTICE(LOADER, "AuthID: 0x%llx", authid);
LOG_NOTICE(LOADER, "VendorID: 0x%08x", vendor_id);
LOG_NOTICE(LOADER, "SELF type: 0x%08x", self_type);
LOG_NOTICE(LOADER, "Version: 0x%llx", version);
}
void SectionInfo::Load(vfsStream& f)
{
offset = Read64(f);
size = Read64(f);
compressed = Read32(f);
unknown1 = Read32(f);
unknown2 = Read32(f);
encrypted = Read32(f);
}
void SectionInfo::Show()
{
LOG_NOTICE(LOADER, "Offset: 0x%llx", offset);
LOG_NOTICE(LOADER, "Size: 0x%llx", size);
LOG_NOTICE(LOADER, "Compressed: 0x%08x", compressed);
LOG_NOTICE(LOADER, "Unknown1: 0x%08x", unknown1);
LOG_NOTICE(LOADER, "Unknown2: 0x%08x", unknown2);
LOG_NOTICE(LOADER, "Encrypted: 0x%08x", encrypted);
}
void SCEVersionInfo::Load(vfsStream& f)
{
subheader_type = Read32(f);
present = Read32(f);
size = Read32(f);
unknown = Read32(f);
}
void SCEVersionInfo::Show()
{
LOG_NOTICE(LOADER, "Sub-header type: 0x%08x", subheader_type);
LOG_NOTICE(LOADER, "Present: 0x%08x", present);
LOG_NOTICE(LOADER, "Size: 0x%08x", size);
LOG_NOTICE(LOADER, "Unknown: 0x%08x", unknown);
}
void ControlInfo::Load(vfsStream& f)
{
type = Read32(f);
size = Read32(f);
next = Read64(f);
if (type == 1)
{
control_flags.ctrl_flag1 = Read32(f);
control_flags.unknown1 = Read32(f);
control_flags.unknown2 = Read32(f);
control_flags.unknown3 = Read32(f);
control_flags.unknown4 = Read32(f);
control_flags.unknown5 = Read32(f);
control_flags.unknown6 = Read32(f);
control_flags.unknown7 = Read32(f);
}
else if (type == 2)
{
if (size == 0x30)
{
f.Read(file_digest_30.digest, 20);
file_digest_30.unknown = Read64(f);
}
else if (size == 0x40)
{
f.Read(file_digest_40.digest1, 20);
f.Read(file_digest_40.digest2, 20);
file_digest_40.unknown = Read64(f);
}
}
else if (type == 3)
{
npdrm.magic = Read32(f);
npdrm.unknown1 = Read32(f);
npdrm.license = Read32(f);
npdrm.type = Read32(f);
f.Read(npdrm.content_id, 48);
f.Read(npdrm.digest, 16);
f.Read(npdrm.invdigest, 16);
f.Read(npdrm.xordigest, 16);
npdrm.unknown2 = Read64(f);
npdrm.unknown3 = Read64(f);
}
}
void ControlInfo::Show()
{
LOG_NOTICE(LOADER, "Type: 0x%08x", type);
LOG_NOTICE(LOADER, "Size: 0x%08x", size);
LOG_NOTICE(LOADER, "Next: 0x%llx", next);
if (type == 1)
{
LOG_NOTICE(LOADER, "Control flag 1: 0x%08x", control_flags.ctrl_flag1);
LOG_NOTICE(LOADER, "Unknown1: 0x%08x", control_flags.unknown1);
LOG_NOTICE(LOADER, "Unknown2: 0x%08x", control_flags.unknown2);
LOG_NOTICE(LOADER, "Unknown3: 0x%08x", control_flags.unknown3);
LOG_NOTICE(LOADER, "Unknown4: 0x%08x", control_flags.unknown4);
LOG_NOTICE(LOADER, "Unknown5: 0x%08x", control_flags.unknown5);
LOG_NOTICE(LOADER, "Unknown6: 0x%08x", control_flags.unknown6);
LOG_NOTICE(LOADER, "Unknown7: 0x%08x", control_flags.unknown7);
}
else if (type == 2)
{
if (size == 0x30)
{
std::string digest_str;
for (int i = 0; i < 20; i++)
digest_str += fmt::Format("%02x", file_digest_30.digest[i]);
LOG_NOTICE(LOADER, "Digest: %s", digest_str.c_str());
LOG_NOTICE(LOADER, "Unknown: 0x%llx", file_digest_30.unknown);
}
else if (size == 0x40)
{
std::string digest_str1;
std::string digest_str2;
for (int i = 0; i < 20; i++)
{
digest_str1 += fmt::Format("%02x", file_digest_40.digest1[i]);
digest_str2 += fmt::Format("%02x", file_digest_40.digest2[i]);
}
LOG_NOTICE(LOADER, "Digest1: %s", digest_str1.c_str());
LOG_NOTICE(LOADER, "Digest2: %s", digest_str2.c_str());
LOG_NOTICE(LOADER, "Unknown: 0x%llx", file_digest_40.unknown);
}
}
else if (type == 3)
{
std::string contentid_str;
std::string digest_str;
std::string invdigest_str;
std::string xordigest_str;
for (int i = 0; i < 48; i++)
contentid_str += fmt::Format("%02x", npdrm.content_id[i]);
for (int i = 0; i < 16; i++)
{
digest_str += fmt::Format("%02x", npdrm.digest[i]);
invdigest_str += fmt::Format("%02x", npdrm.invdigest[i]);
xordigest_str += fmt::Format("%02x", npdrm.xordigest[i]);
}
LOG_NOTICE(LOADER, "Magic: 0x%08x", npdrm.magic);
LOG_NOTICE(LOADER, "Unknown1: 0x%08x", npdrm.unknown1);
LOG_NOTICE(LOADER, "License: 0x%08x", npdrm.license);
LOG_NOTICE(LOADER, "Type: 0x%08x", npdrm.type);
LOG_NOTICE(LOADER, "ContentID: %s", contentid_str.c_str());
LOG_NOTICE(LOADER, "Digest: %s", digest_str.c_str());
LOG_NOTICE(LOADER, "Inverse digest: %s", invdigest_str.c_str());
LOG_NOTICE(LOADER, "XOR digest: %s", xordigest_str.c_str());
LOG_NOTICE(LOADER, "Unknown2: 0x%llx", npdrm.unknown2);
LOG_NOTICE(LOADER, "Unknown3: 0x%llx", npdrm.unknown3);
}
}
void MetadataInfo::Load(u8* in)
{
memcpy(key, in, 0x10);
memcpy(key_pad, in + 0x10, 0x10);
memcpy(iv, in + 0x20, 0x10);
memcpy(iv_pad, in + 0x30, 0x10);
}
void MetadataInfo::Show()
{
std::string key_str;
std::string key_pad_str;
std::string iv_str;
std::string iv_pad_str;
for (int i = 0; i < 0x10; i++)
{
key_str += fmt::Format("%02x", key[i]);
key_pad_str += fmt::Format("%02x", key_pad[i]);
iv_str += fmt::Format("%02x", iv[i]);
iv_pad_str += fmt::Format("%02x", iv_pad[i]);
}
LOG_NOTICE(LOADER, "Key: %s", key_str.c_str());
LOG_NOTICE(LOADER, "Key pad: %s", key_pad_str.c_str());
LOG_NOTICE(LOADER, "IV: %s", iv_str.c_str());
LOG_NOTICE(LOADER, "IV pad: %s", iv_pad_str.c_str());
}
void MetadataHeader::Load(u8* in)
{
memcpy(&signature_input_length, in, 8);
memcpy(&unknown1, in + 8, 4);
memcpy(&section_count, in + 12, 4);
memcpy(&key_count, in + 16, 4);
memcpy(&opt_header_size, in + 20, 4);
memcpy(&unknown2, in + 24, 4);
memcpy(&unknown3, in + 28, 4);
// Endian swap.
signature_input_length = swap64(signature_input_length);
unknown1 = swap32(unknown1);
section_count = swap32(section_count);
key_count = swap32(key_count);
opt_header_size = swap32(opt_header_size);
unknown2 = swap32(unknown2);
unknown3 = swap32(unknown3);
}
void MetadataHeader::Show()
{
LOG_NOTICE(LOADER, "Signature input length: 0x%llx", signature_input_length);
LOG_NOTICE(LOADER, "Unknown1: 0x%08x", unknown1);
LOG_NOTICE(LOADER, "Section count: 0x%08x", section_count);
LOG_NOTICE(LOADER, "Key count: 0x%08x", key_count);
LOG_NOTICE(LOADER, "Optional header size: 0x%08x", opt_header_size);
LOG_NOTICE(LOADER, "Unknown2: 0x%08x", unknown2);
LOG_NOTICE(LOADER, "Unknown3: 0x%08x", unknown3);
}
void MetadataSectionHeader::Load(u8* in)
{
memcpy(&data_offset, in, 8);
memcpy(&data_size, in + 8, 8);
memcpy(&type, in + 16, 4);
memcpy(&program_idx, in + 20, 4);
memcpy(&hashed, in + 24, 4);
memcpy(&sha1_idx, in + 28, 4);
memcpy(&encrypted, in + 32, 4);
memcpy(&key_idx, in + 36, 4);
memcpy(&iv_idx, in + 40, 4);
memcpy(&compressed, in + 44, 4);
// Endian swap.
data_offset = swap64(data_offset);
data_size = swap64(data_size);
type = swap32(type);
program_idx = swap32(program_idx);
hashed = swap32(hashed);
sha1_idx = swap32(sha1_idx);
encrypted = swap32(encrypted);
key_idx = swap32(key_idx);
iv_idx = swap32(iv_idx);
compressed = swap32(compressed);
}
void MetadataSectionHeader::Show()
{
LOG_NOTICE(LOADER, "Data offset: 0x%llx", data_offset);
LOG_NOTICE(LOADER, "Data size: 0x%llx", data_size);
LOG_NOTICE(LOADER, "Type: 0x%08x", type);
LOG_NOTICE(LOADER, "Program index: 0x%08x", program_idx);
LOG_NOTICE(LOADER, "Hashed: 0x%08x", hashed);
LOG_NOTICE(LOADER, "SHA1 index: 0x%08x", sha1_idx);
LOG_NOTICE(LOADER, "Encrypted: 0x%08x", encrypted);
LOG_NOTICE(LOADER, "Key index: 0x%08x", key_idx);
LOG_NOTICE(LOADER, "IV index: 0x%08x", iv_idx);
LOG_NOTICE(LOADER, "Compressed: 0x%08x", compressed);
}
void SectionHash::Load(vfsStream& f)
{
f.Read(sha1, 20);
f.Read(padding, 12);
f.Read(hmac_key, 64);
}
void CapabilitiesInfo::Load(vfsStream& f)
{
type = Read32(f);
capabilities_size = Read32(f);
next = Read32(f);
unknown1 = Read32(f);
unknown2 = Read64(f);
unknown3 = Read64(f);
flags = Read64(f);
unknown4 = Read32(f);
unknown5 = Read32(f);
}
void Signature::Load(vfsStream& f)
{
f.Read(r, 21);
f.Read(s, 21);
f.Read(padding, 6);
}
void SelfSection::Load(vfsStream& f)
{
*data = Read32(f);
size = Read64(f);
offset = Read64(f);
}
SELFDecrypter::SELFDecrypter(vfsStream& s)
: self_f(s), key_v(), data_buf_length(0)
{
@ -15,7 +327,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
// Check SCE magic.
if (!sce_hdr.CheckMagic())
{
ConLog.Error("SELF: Not a SELF file!");
LOG_ERROR(LOADER, "SELF: Not a SELF file!");
return false;
}
@ -39,7 +351,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
phdr32_arr.clear();
if(elf32_hdr.e_phoff == 0 && elf32_hdr.e_phnum)
{
ConLog.Error("SELF: ELF program header offset is null!");
LOG_ERROR(LOADER, "SELF: ELF program header offset is null!");
return false;
}
self_f.Seek(self_hdr.se_phdroff);
@ -54,7 +366,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
phdr64_arr.clear();
if(elf64_hdr.e_phoff == 0 && elf64_hdr.e_phnum)
{
ConLog.Error("SELF: ELF program header offset is null!");
LOG_ERROR(LOADER, "SELF: ELF program header offset is null!");
return false;
}
self_f.Seek(self_hdr.se_phdroff);
@ -99,7 +411,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
shdr32_arr.clear();
if(elf32_hdr.e_shoff == 0 && elf32_hdr.e_shnum)
{
ConLog.Warning("SELF: ELF section header offset is null!");
LOG_WARNING(LOADER, "SELF: ELF section header offset is null!");
return true;
}
self_f.Seek(self_hdr.se_shdroff);
@ -114,7 +426,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
shdr64_arr.clear();
if(elf64_hdr.e_shoff == 0 && elf64_hdr.e_shnum)
{
ConLog.Warning("SELF: ELF section header offset is null!");
LOG_WARNING(LOADER, "SELF: ELF section header offset is null!");
return true;
}
self_f.Seek(self_hdr.se_shdroff);
@ -130,46 +442,46 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
void SELFDecrypter::ShowHeaders(bool isElf32)
{
ConLog.Write("SCE header");
ConLog.Write("----------------------------------------------------");
LOG_NOTICE(LOADER, "SCE header");
LOG_NOTICE(LOADER, "----------------------------------------------------");
sce_hdr.Show();
ConLog.Write("----------------------------------------------------");
ConLog.Write("SELF header");
ConLog.Write("----------------------------------------------------");
LOG_NOTICE(LOADER, "----------------------------------------------------");
LOG_NOTICE(LOADER, "SELF header");
LOG_NOTICE(LOADER, "----------------------------------------------------");
self_hdr.Show();
ConLog.Write("----------------------------------------------------");
ConLog.Write("APP INFO");
ConLog.Write("----------------------------------------------------");
LOG_NOTICE(LOADER, "----------------------------------------------------");
LOG_NOTICE(LOADER, "APP INFO");
LOG_NOTICE(LOADER, "----------------------------------------------------");
app_info.Show();
ConLog.Write("----------------------------------------------------");
ConLog.Write("ELF header");
ConLog.Write("----------------------------------------------------");
LOG_NOTICE(LOADER, "----------------------------------------------------");
LOG_NOTICE(LOADER, "ELF header");
LOG_NOTICE(LOADER, "----------------------------------------------------");
isElf32 ? elf32_hdr.Show() : elf64_hdr.Show();
ConLog.Write("----------------------------------------------------");
ConLog.Write("ELF program headers");
ConLog.Write("----------------------------------------------------");
LOG_NOTICE(LOADER, "----------------------------------------------------");
LOG_NOTICE(LOADER, "ELF program headers");
LOG_NOTICE(LOADER, "----------------------------------------------------");
for(unsigned int i = 0; i < ((isElf32) ? phdr32_arr.size() : phdr64_arr.size()); i++)
isElf32 ? phdr32_arr[i].Show() : phdr64_arr[i].Show();
ConLog.Write("----------------------------------------------------");
ConLog.Write("Section info");
ConLog.Write("----------------------------------------------------");
LOG_NOTICE(LOADER, "----------------------------------------------------");
LOG_NOTICE(LOADER, "Section info");
LOG_NOTICE(LOADER, "----------------------------------------------------");
for(unsigned int i = 0; i < secinfo_arr.size(); i++)
secinfo_arr[i].Show();
ConLog.Write("----------------------------------------------------");
ConLog.Write("SCE version info");
ConLog.Write("----------------------------------------------------");
LOG_NOTICE(LOADER, "----------------------------------------------------");
LOG_NOTICE(LOADER, "SCE version info");
LOG_NOTICE(LOADER, "----------------------------------------------------");
scev_info.Show();
ConLog.Write("----------------------------------------------------");
ConLog.Write("Control info");
ConLog.Write("----------------------------------------------------");
LOG_NOTICE(LOADER, "----------------------------------------------------");
LOG_NOTICE(LOADER, "Control info");
LOG_NOTICE(LOADER, "----------------------------------------------------");
for(unsigned int i = 0; i < ctrlinfo_arr.size(); i++)
ctrlinfo_arr[i].Show();
ConLog.Write("----------------------------------------------------");
ConLog.Write("ELF section headers");
ConLog.Write("----------------------------------------------------");
LOG_NOTICE(LOADER, "----------------------------------------------------");
LOG_NOTICE(LOADER, "ELF section headers");
LOG_NOTICE(LOADER, "----------------------------------------------------");
for(unsigned int i = 0; i < ((isElf32) ? shdr32_arr.size() : shdr64_arr.size()); i++)
isElf32 ? shdr32_arr[i].Show() : shdr64_arr[i].Show();
ConLog.Write("----------------------------------------------------");
LOG_NOTICE(LOADER, "----------------------------------------------------");
}
bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
@ -193,7 +505,7 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
// If not, the data has no NPDRM layer.
if (!ctrl)
{
ConLog.Warning("SELF: No NPDRM control info found!");
LOG_WARNING(LOADER, "SELF: No NPDRM control info found!");
return true;
}
@ -206,7 +518,7 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
if (ctrl->npdrm.license == 1) // Network license.
{
ConLog.Error("SELF: Can't decrypt network NPDRM!");
LOG_ERROR(LOADER, "SELF: Can't decrypt network NPDRM!");
return false;
}
else if (ctrl->npdrm.license == 2) // Local license.
@ -214,7 +526,7 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
// Try to find a RAP file to get the key.
if (!GetKeyFromRap(ctrl->npdrm.content_id, npdrm_key))
{
ConLog.Error("SELF: Can't find RAP file for NPDRM decryption!");
LOG_ERROR(LOADER, "SELF: Can't find RAP file for NPDRM decryption!");
return false;
}
}
@ -225,7 +537,7 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
}
else
{
ConLog.Error("SELF: Invalid NPDRM license type!");
LOG_ERROR(LOADER, "SELF: Invalid NPDRM license type!");
return false;
}
@ -288,7 +600,7 @@ bool SELFDecrypter::LoadMetadata()
if ((meta_info.key_pad[0] != 0x00) ||
(meta_info.iv_pad[0] != 0x00))
{
ConLog.Error("SELF: Failed to decrypt metadata info!");
LOG_ERROR(LOADER, "SELF: Failed to decrypt metadata info!");
return false;
}
@ -387,10 +699,10 @@ bool SELFDecrypter::DecryptData()
bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
{
// Create a new ELF file.
wxFile e(elf.c_str(), wxFile::write);
rFile e(elf.c_str(), rFile::write);
if(!e.IsOpened())
{
ConLog.Error("Could not create ELF file! (%s)", elf.c_str());
LOG_ERROR(LOADER, "Could not create ELF file! (%s)", elf.c_str());
return false;
}
@ -503,25 +815,26 @@ bool SELFDecrypter::GetKeyFromRap(u8 *content_id, u8 *npdrm_key)
// Try to find a matching RAP file under dev_usb000.
std::string ci_str((const char *)content_id);
std::string rap_path(fmt::ToUTF8(wxGetCwd()) + "/dev_usb000/" + ci_str + ".rap");
// TODO: This shouldn't use current dir
std::string rap_path("./dev_usb000/" + ci_str + ".rap");
// Check if we have a valid RAP file.
if (!wxFile::Exists(fmt::FromUTF8(rap_path)))
if (!rExists(rap_path))
{
ConLog.Error("This application requires a valid RAP file for decryption!");
LOG_ERROR(LOADER, "This application requires a valid RAP file for decryption!");
return false;
}
// Open the RAP file and read the key.
wxFile rap_file(fmt::FromUTF8(rap_path), wxFile::read);
rFile rap_file(rap_path, rFile::read);
if (!rap_file.IsOpened())
{
ConLog.Error("Failed to load RAP file!");
LOG_ERROR(LOADER, "Failed to load RAP file!");
return false;
}
ConLog.Write("Loading RAP file %s", (ci_str + ".rap").c_str());
LOG_NOTICE(LOADER, "Loading RAP file %s", (ci_str + ".rap").c_str());
rap_file.Read(rap_key, 0x10);
rap_file.Close();
@ -567,11 +880,11 @@ bool IsSelfElf32(const std::string& path)
bool CheckDebugSelf(const std::string& self, const std::string& elf)
{
// Open the SELF file.
wxFile s(fmt::FromUTF8(self));
rFile s(self);
if(!s.IsOpened())
{
ConLog.Error("Could not open SELF file! (%s)", self.c_str());
LOG_ERROR(LOADER, "Could not open SELF file! (%s)", self.c_str());
return false;
}
@ -583,7 +896,7 @@ bool CheckDebugSelf(const std::string& self, const std::string& elf)
// Check for DEBUG version.
if(swap16(key_version) == 0x8000)
{
ConLog.Warning("Debug SELF detected! Removing fake header...");
LOG_WARNING(LOADER, "Debug SELF detected! Removing fake header...");
// Get the real elf offset.
s.Seek(0x10);
@ -595,10 +908,10 @@ bool CheckDebugSelf(const std::string& self, const std::string& elf)
s.Seek(elf_offset);
// Write the real ELF file back.
wxFile e(fmt::FromUTF8(elf), wxFile::write);
rFile e(elf, rFile::write);
if(!e.IsOpened())
{
ConLog.Error("Could not create ELF file! (%s)", elf.c_str());
LOG_ERROR(LOADER, "Could not create ELF file! (%s)", elf.c_str());
return false;
}
@ -638,28 +951,28 @@ bool DecryptSelf(const std::string& elf, const std::string& self)
// Load the SELF file headers.
if (!self_dec.LoadHeaders(isElf32))
{
ConLog.Error("SELF: Failed to load SELF file headers!");
LOG_ERROR(LOADER, "SELF: Failed to load SELF file headers!");
return false;
}
// Load and decrypt the SELF file metadata.
if (!self_dec.LoadMetadata())
{
ConLog.Error("SELF: Failed to load SELF file metadata!");
LOG_ERROR(LOADER, "SELF: Failed to load SELF file metadata!");
return false;
}
// Decrypt the SELF file data.
if (!self_dec.DecryptData())
{
ConLog.Error("SELF: Failed to decrypt SELF file data!");
LOG_ERROR(LOADER, "SELF: Failed to decrypt SELF file data!");
return false;
}
// Make a new ELF file from this SELF.
if (!self_dec.MakeElf(elf, isElf32))
{
ConLog.Error("SELF: Failed to make ELF file from SELF!");
LOG_ERROR(LOADER, "SELF: Failed to make ELF file from SELF!");
return false;
}
}

View file

@ -1,10 +1,8 @@
#pragma once
#include "utils.h"
#include "key_vault.h"
#include "Loader/ELF.h"
#include "Loader/SELF.h"
#include <wx/mstream.h>
#include <wx/zstream.h>
#include "Loader/ELF.h"
#include "key_vault.h"
struct AppInfo
{
@ -14,22 +12,9 @@ struct AppInfo
u64 version;
u64 padding;
void Load(vfsStream& f)
{
authid = Read64(f);
vendor_id = Read32(f);
self_type = Read32(f);
version = Read64(f);
padding = Read64(f);
}
void Load(vfsStream& f);
void Show()
{
ConLog.Write("AuthID: 0x%llx", authid);
ConLog.Write("VendorID: 0x%08x", vendor_id);
ConLog.Write("SELF type: 0x%08x", self_type);
ConLog.Write("Version: 0x%llx", version);
}
void Show();
};
struct SectionInfo
@ -41,25 +26,9 @@ struct SectionInfo
u32 unknown2;
u32 encrypted;
void Load(vfsStream& f)
{
offset = Read64(f);
size = Read64(f);
compressed = Read32(f);
unknown1 = Read32(f);
unknown2 = Read32(f);
encrypted = Read32(f);
}
void Load(vfsStream& f);
void Show()
{
ConLog.Write("Offset: 0x%llx", offset);
ConLog.Write("Size: 0x%llx", size);
ConLog.Write("Compressed: 0x%08x", compressed);
ConLog.Write("Unknown1: 0x%08x", unknown1);
ConLog.Write("Unknown2: 0x%08x", unknown2);
ConLog.Write("Encrypted: 0x%08x", encrypted);
}
void Show();
};
struct SCEVersionInfo
@ -69,21 +38,9 @@ struct SCEVersionInfo
u32 size;
u32 unknown;
void Load(vfsStream& f)
{
subheader_type = Read32(f);
present = Read32(f);
size = Read32(f);
unknown = Read32(f);
}
void Load(vfsStream& f);
void Show()
{
ConLog.Write("Sub-header type: 0x%08x", subheader_type);
ConLog.Write("Present: 0x%08x", present);
ConLog.Write("Size: 0x%08x", size);
ConLog.Write("Unknown: 0x%08x", unknown);
}
void Show();
};
struct ControlInfo
@ -133,122 +90,9 @@ struct ControlInfo
} npdrm;
};
void Load(vfsStream& f)
{
type = Read32(f);
size = Read32(f);
next = Read64(f);
void Load(vfsStream& f);
if (type == 1)
{
control_flags.ctrl_flag1 = Read32(f);
control_flags.unknown1 = Read32(f);
control_flags.unknown2 = Read32(f);
control_flags.unknown3 = Read32(f);
control_flags.unknown4 = Read32(f);
control_flags.unknown5 = Read32(f);
control_flags.unknown6 = Read32(f);
control_flags.unknown7 = Read32(f);
}
else if (type == 2)
{
if (size == 0x30)
{
f.Read(file_digest_30.digest, 20);
file_digest_30.unknown = Read64(f);
}
else if (size == 0x40)
{
f.Read(file_digest_40.digest1, 20);
f.Read(file_digest_40.digest2, 20);
file_digest_40.unknown = Read64(f);
}
}
else if (type == 3)
{
npdrm.magic = Read32(f);
npdrm.unknown1 = Read32(f);
npdrm.license = Read32(f);
npdrm.type = Read32(f);
f.Read(npdrm.content_id, 48);
f.Read(npdrm.digest, 16);
f.Read(npdrm.invdigest, 16);
f.Read(npdrm.xordigest, 16);
npdrm.unknown2 = Read64(f);
npdrm.unknown3 = Read64(f);
}
}
void Show()
{
ConLog.Write("Type: 0x%08x", type);
ConLog.Write("Size: 0x%08x", size);
ConLog.Write("Next: 0x%llx", next);
if (type == 1)
{
ConLog.Write("Control flag 1: 0x%08x", control_flags.ctrl_flag1);
ConLog.Write("Unknown1: 0x%08x", control_flags.unknown1);
ConLog.Write("Unknown2: 0x%08x", control_flags.unknown2);
ConLog.Write("Unknown3: 0x%08x", control_flags.unknown3);
ConLog.Write("Unknown4: 0x%08x", control_flags.unknown4);
ConLog.Write("Unknown5: 0x%08x", control_flags.unknown5);
ConLog.Write("Unknown6: 0x%08x", control_flags.unknown6);
ConLog.Write("Unknown7: 0x%08x", control_flags.unknown7);
}
else if (type == 2)
{
if (size == 0x30)
{
std::string digest_str;
for (int i = 0; i < 20; i++)
digest_str += fmt::Format("%02x", file_digest_30.digest[i]);
ConLog.Write("Digest: %s", digest_str.c_str());
ConLog.Write("Unknown: 0x%llx", file_digest_30.unknown);
}
else if (size == 0x40)
{
std::string digest_str1;
std::string digest_str2;
for (int i = 0; i < 20; i++)
{
digest_str1 += fmt::Format("%02x", file_digest_40.digest1[i]);
digest_str2 += fmt::Format("%02x", file_digest_40.digest2[i]);
}
ConLog.Write("Digest1: %s", digest_str1.c_str());
ConLog.Write("Digest2: %s", digest_str2.c_str());
ConLog.Write("Unknown: 0x%llx", file_digest_40.unknown);
}
}
else if (type == 3)
{
std::string contentid_str;
std::string digest_str;
std::string invdigest_str;
std::string xordigest_str;
for (int i = 0; i < 48; i++)
contentid_str += fmt::Format("%02x", npdrm.content_id[i]);
for (int i = 0; i < 16; i++)
{
digest_str += fmt::Format("%02x", npdrm.digest[i]);
invdigest_str += fmt::Format("%02x", npdrm.invdigest[i]);
xordigest_str += fmt::Format("%02x", npdrm.xordigest[i]);
}
ConLog.Write("Magic: 0x%08x", npdrm.magic);
ConLog.Write("Unknown1: 0x%08x", npdrm.unknown1);
ConLog.Write("License: 0x%08x", npdrm.license);
ConLog.Write("Type: 0x%08x", npdrm.type);
ConLog.Write("ContentID: %s", contentid_str.c_str());
ConLog.Write("Digest: %s", digest_str.c_str());
ConLog.Write("Inverse digest: %s", invdigest_str.c_str());
ConLog.Write("XOR digest: %s", xordigest_str.c_str());
ConLog.Write("Unknown2: 0x%llx", npdrm.unknown2);
ConLog.Write("Unknown3: 0x%llx", npdrm.unknown3);
}
}
void Show();
};
@ -259,33 +103,9 @@ struct MetadataInfo
u8 iv[0x10];
u8 iv_pad[0x10];
void Load(u8* in)
{
memcpy(key, in, 0x10);
memcpy(key_pad, in + 0x10, 0x10);
memcpy(iv, in + 0x20, 0x10);
memcpy(iv_pad, in + 0x30, 0x10);
}
void Load(u8* in);
void Show()
{
std::string key_str;
std::string key_pad_str;
std::string iv_str;
std::string iv_pad_str;
for (int i = 0; i < 0x10; i++)
{
key_str += fmt::Format("%02x", key[i]);
key_pad_str += fmt::Format("%02x", key_pad[i]);
iv_str += fmt::Format("%02x", iv[i]);
iv_pad_str += fmt::Format("%02x", iv_pad[i]);
}
ConLog.Write("Key: %s", key_str.c_str());
ConLog.Write("Key pad: %s", key_pad_str.c_str());
ConLog.Write("IV: %s", iv_str.c_str());
ConLog.Write("IV pad: %s", iv_pad_str.c_str());
}
void Show();
};
struct MetadataHeader
@ -298,36 +118,9 @@ struct MetadataHeader
u32 unknown2;
u32 unknown3;
void Load(u8* in)
{
memcpy(&signature_input_length, in, 8);
memcpy(&unknown1, in + 8, 4);
memcpy(&section_count, in + 12, 4);
memcpy(&key_count, in + 16, 4);
memcpy(&opt_header_size, in + 20, 4);
memcpy(&unknown2, in + 24, 4);
memcpy(&unknown3, in + 28, 4);
void Load(u8* in);
// Endian swap.
signature_input_length = swap64(signature_input_length);
unknown1 = swap32(unknown1);
section_count = swap32(section_count);
key_count = swap32(key_count);
opt_header_size = swap32(opt_header_size);
unknown2 = swap32(unknown2);
unknown3 = swap32(unknown3);
}
void Show()
{
ConLog.Write("Signature input length: 0x%llx", signature_input_length);
ConLog.Write("Unknown1: 0x%08x", unknown1);
ConLog.Write("Section count: 0x%08x", section_count);
ConLog.Write("Key count: 0x%08x", key_count);
ConLog.Write("Optional header size: 0x%08x", opt_header_size);
ConLog.Write("Unknown2: 0x%08x", unknown2);
ConLog.Write("Unknown3: 0x%08x", unknown3);
}
void Show();
};
struct MetadataSectionHeader
@ -343,45 +136,9 @@ struct MetadataSectionHeader
u32 iv_idx;
u32 compressed;
void Load(u8* in)
{
memcpy(&data_offset, in, 8);
memcpy(&data_size, in + 8, 8);
memcpy(&type, in + 16, 4);
memcpy(&program_idx, in + 20, 4);
memcpy(&hashed, in + 24, 4);
memcpy(&sha1_idx, in + 28, 4);
memcpy(&encrypted, in + 32, 4);
memcpy(&key_idx, in + 36, 4);
memcpy(&iv_idx, in + 40, 4);
memcpy(&compressed, in + 44, 4);
void Load(u8* in);
// Endian swap.
data_offset = swap64(data_offset);
data_size = swap64(data_size);
type = swap32(type);
program_idx = swap32(program_idx);
hashed = swap32(hashed);
sha1_idx = swap32(sha1_idx);
encrypted = swap32(encrypted);
key_idx = swap32(key_idx);
iv_idx = swap32(iv_idx);
compressed = swap32(compressed);
}
void Show()
{
ConLog.Write("Data offset: 0x%llx", data_offset);
ConLog.Write("Data size: 0x%llx", data_size);
ConLog.Write("Type: 0x%08x", type);
ConLog.Write("Program index: 0x%08x", program_idx);
ConLog.Write("Hashed: 0x%08x", hashed);
ConLog.Write("SHA1 index: 0x%08x", sha1_idx);
ConLog.Write("Encrypted: 0x%08x", encrypted);
ConLog.Write("Key index: 0x%08x", key_idx);
ConLog.Write("IV index: 0x%08x", iv_idx);
ConLog.Write("Compressed: 0x%08x", compressed);
}
void Show();
};
struct SectionHash {
@ -389,12 +146,7 @@ struct SectionHash {
u8 padding[12];
u8 hmac_key[64];
void Load(vfsStream& f)
{
f.Read(sha1, 20);
f.Read(padding, 12);
f.Read(hmac_key, 64);
}
void Load(vfsStream& f);
};
struct CapabilitiesInfo
@ -409,18 +161,7 @@ struct CapabilitiesInfo
u32 unknown4;
u32 unknown5;
void Load(vfsStream& f)
{
type = Read32(f);
capabilities_size = Read32(f);
next = Read32(f);
unknown1 = Read32(f);
unknown2 = Read64(f);
unknown3 = Read64(f);
flags = Read64(f);
unknown4 = Read32(f);
unknown5 = Read32(f);
}
void Load(vfsStream& f);
};
struct Signature
@ -429,12 +170,7 @@ struct Signature
u8 s[21];
u8 padding[6];
void Load(vfsStream& f)
{
f.Read(r, 21);
f.Read(s, 21);
f.Read(padding, 6);
}
void Load(vfsStream& f);
};
struct SelfSection
@ -443,12 +179,7 @@ struct SelfSection
u64 size;
u64 offset;
void Load(vfsStream& f)
{
*data = Read32(f);
size = Read64(f);
offset = Read64(f);
}
void Load(vfsStream& f);
};
class SELFDecrypter

View file

@ -1,4 +1,6 @@
#include "stdafx.h"
#include "aes.h"
#include "sha1.h"
#include "utils.h"
// Endian swap auxiliary functions.

View file

@ -1,6 +1,4 @@
#pragma once
#include "aes.h"
#include "sha1.h"
// Auxiliary functions (endian swap and xor).
u16 swap16(u16 i);

View file

@ -21,8 +21,8 @@ public:
virtual u8 DecodeMemory(const u64 address)
{
using namespace ARMv7_opcodes;
const u16 code0 = Memory.Read16(address);
const u16 code1 = Memory.Read16(address + 2);
const u16 code0 = vm::psv::read16((u32)address);
const u16 code1 = vm::psv::read16((u32)address + 2);
switch(code0 >> 12) //15 - 12
{
@ -33,7 +33,7 @@ public:
switch((code0 >> 8) & 0x1)
{
case 1:
m_op.CBZ((code0 >> 11) & 0x1, branchTarget((((code0 >> 9) & 0x1) << 5) | (code0 >> 3) & 0x1f), code0 & 0x7, 2);
m_op.CBZ((code0 >> 11) & 0x1, branchTarget((((code0 >> 9) & 0x1) << 5) | ((code0 >> 3) & 0x1f)), code0 & 0x7, 2);
return 2;
}
break;

View file

@ -1,8 +1,6 @@
#pragma once
#include "Emu/ARMv7/ARMv7Opcodes.h"
#include "Emu/CPU/CPUDisAsm.h"
#include "Gui/DisAsmFrame.h"
#include "Emu/Memory/Memory.h"
static const char* g_arm_cond_name[16] =
{
@ -24,7 +22,7 @@ public:
protected:
virtual u32 DisAsmBranchTarget(const s32 imm)
{
return dump_pc + imm;
return (u32)dump_pc + imm;
}
std::string GetRegsListString(u16 regs_list)

View file

@ -233,7 +233,7 @@ public:
return result;
}
bool ConditionPassed(u8 cond)
bool ConditionPassed(u8 cond) const
{
bool result = false;
@ -260,7 +260,7 @@ public:
protected:
void NULL_OP()
{
ConLog.Error("null");
LOG_ERROR(HLE, "null");
Emu.Pause();
}
@ -275,7 +275,7 @@ protected:
if(regs_list & mask)
{
CPU.SP -= 4;
Memory.Write32(CPU.SP, CPU.read_gpr(i));
vm::psv::write32(CPU.SP, CPU.read_gpr(i));
}
}
}
@ -286,7 +286,7 @@ protected:
{
if(regs_list & mask)
{
CPU.write_gpr(i, Memory.Read32(CPU.SP));
CPU.write_gpr(i, vm::psv::read32(CPU.SP));
CPU.SP += 4;
}
}
@ -310,13 +310,13 @@ protected:
void BL(u32 imm, u8 intstr_size)
{
CPU.LR = (CPU.PC + intstr_size) | 1;
CPU.LR = ((u32)CPU.PC + intstr_size) | 1;
CPU.SetBranch(CPU.PC + intstr_size + imm);
}
void UNK(const u16 code0, const u16 code1)
{
ConLog.Error("Unknown/Illegal opcode! (0x%04x : 0x%04x)", code0, code1);
LOG_ERROR(HLE, "Unknown/Illegal opcode! (0x%04x : 0x%04x)", code0, code1);
Emu.Pause();
}
};
};

View file

@ -1,4 +1,9 @@
#include "stdafx.h"
#include "rpcs3/Ini.h"
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "ARMv7Thread.h"
#include "ARMv7Decoder.h"
#include "ARMv7DisAsm.h"
@ -13,7 +18,7 @@ void ARMv7Thread::InitRegs()
memset(GPR, 0, sizeof(GPR[0]) * 15);
APSR.APSR = 0;
IPSR.IPSR = 0;
SP = m_stack_point;
SP = (u32)m_stack_point;
}
void ARMv7Thread::InitStack()
@ -99,4 +104,4 @@ void ARMv7Thread::DoStop()
void ARMv7Thread::DoCode()
{
}
}

View file

@ -51,7 +51,7 @@ public:
u32 IPSR;
} IPSR;
void write_gpr(u8 n, u32 value)
void write_gpr(u32 n, u32 value)
{
assert(n < 16);
@ -65,7 +65,7 @@ public:
}
}
u32 read_gpr(u8 n)
u32 read_gpr(u32 n)
{
assert(n < 16);
@ -74,7 +74,7 @@ public:
return GPR[n];
}
return PC;
return (u32)PC;
}
public:

View file

@ -1,4 +1,8 @@
#include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/System.h"
#include "rpcs3/Ini.h"
#include "OpenALThread.h"
ALenum g_last_al_error = AL_NO_ERROR;
@ -13,7 +17,7 @@ void printAlError(ALenum err, const char* situation)
{
if(err != AL_NO_ERROR)
{
ConLog.Error("%s: OpenAL error 0x%04x", situation, err);
LOG_ERROR(HLE, "%s: OpenAL error 0x%04x", situation, err);
Emu.Pause();
}
}
@ -22,7 +26,7 @@ void printAlcError(ALCenum err, const char* situation)
{
if(err != ALC_NO_ERROR)
{
ConLog.Error("%s: OpenALC error 0x%04x", situation, err);
LOG_ERROR(HLE, "%s: OpenALC error 0x%04x", situation, err);
Emu.Pause();
}
}
@ -132,7 +136,7 @@ void OpenALThread::AddData(const void* src, ALsizei size)
int bsize = size < m_buffer_size ? size : m_buffer_size;
if (!AddBlock(buffer, bsize, bsrc))
ConLog.Error("OpenALThread::AddBlock: invalid block size: %d", bsize);
LOG_ERROR(HLE, "OpenALThread::AddBlock: invalid block size: %d", bsize);
alSourceQueueBuffers(m_source, 1, &buffer);
checkForAlError("alSourceQueueBuffers");
@ -152,4 +156,4 @@ bool OpenALThread::AddBlock(const ALuint buffer_id, const ALsizei size, const vo
checkForAlError("alBufferData");
return true;
}
}

View file

@ -11,7 +11,7 @@ AudioDumper::~AudioDumper()
bool AudioDumper::Init()
{
return m_output.Open("audio.wav", wxFile::write);
return m_output.Open("audio.wav", rFile::write);
}
void AudioDumper::WriteHeader()
@ -34,8 +34,8 @@ size_t AudioDumper::WriteData(const void* buffer, size_t size)
if (!do_save) return size; // ignore empty data
#endif
size_t ret = m_output.Write(buffer, size);
m_header.Size += ret;
m_header.RIFF.Size += ret;
m_header.Size += (u32)ret;
m_header.RIFF.Size += (u32)ret;
return ret;
}

View file

@ -1,5 +1,7 @@
#pragma once
#include "Utilities/rFile.h"
struct WAVHeader
{
struct RIFFHeader
@ -55,7 +57,7 @@ class AudioDumper
{
private:
WAVHeader m_header;
wxFile m_output;
rFile m_output;
public:
AudioDumper(u8 ch);
@ -65,5 +67,5 @@ public:
void WriteHeader();
size_t WriteData(const void* buffer, size_t size);
void Finalize();
const u8 GetCh() const { return m_header.FMT.NumChannels; }
const u8 GetCh() const { return (u8)m_header.FMT.NumChannels; }
};

View file

@ -1,4 +1,5 @@
#include "stdafx.h"
#include "rpcs3/Ini.h"
#include "AudioManager.h"
OpenALThread* m_audio_out;

View file

@ -257,23 +257,38 @@ struct CellAudioInDeviceConfiguration
u8 reserved[31];
};
enum CellBgmPlaybackStatusState
enum CellSysutilBgmPlaybackStatusState
{
CELL_BGMPLAYBACK_STATUS_PLAY = 0,
CELL_BGMPLAYBACK_STATUS_STOP = 1
CELL_SYSUTIL_BGMPLAYBACK_STATUS_PLAY = 0,
CELL_SYSUTIL_BGMPLAYBACK_STATUS_STOP = 1
};
enum CellBgmPlaybackStatusEnabled
enum CellSysutilBgmPlaybackStatusEnabled
{
CELL_BGMPLAYBACK_STATUS_ENABLE = 0,
CELL_BGMPLAYBACK_STATUS_DISABLE = 1
CELL_SYSUTIL_BGMPLAYBACK_STATUS_ENABLE = 0,
CELL_SYSUTIL_BGMPLAYBACK_STATUS_DISABLE = 1
};
struct CellBgmPlaybackStatus
struct CellSysutilBgmPlaybackStatus
{
u8 playbackState;
u8 enabled;
u8 playerState;
u8 enableState;
char contentId[16];
u8 fadeRatio;
u8 currentFadeRatio;
char reserved[13];
};
struct CellSysutilBgmPlaybackStatus2
{
u8 playerState;
char reserved[7];
};
struct CellSysutilBgmPlaybackExtraParam
{
be_t<s32> systemBgmFadeInTime;
be_t<s32> systemBgmFadeOutTime;
be_t<s32> gameBgmFadeInTime;
be_t<s32> gameBgmFadeOutTime;
char reserved[8];
};

View file

@ -1,5 +1,4 @@
#pragma once
#include <algorithm>
#include "CPUInstrTable.h"
#pragma warning( disable : 4800 )

View file

@ -1,7 +1,5 @@
#pragma once
#include "Emu/Memory/Memory.h"
enum CPUDisAsmMode
{
CPUDisAsm_DumpMode,
@ -21,18 +19,18 @@ protected:
{
case CPUDisAsm_DumpMode:
last_opcode = fmt::Format("\t%08llx:\t%02x %02x %02x %02x\t%s\n", dump_pc,
Memory.Read8(offset + dump_pc),
Memory.Read8(offset + dump_pc + 1),
Memory.Read8(offset + dump_pc + 2),
Memory.Read8(offset + dump_pc + 3), value.c_str());
offset[dump_pc],
offset[dump_pc + 1],
offset[dump_pc + 2],
offset[dump_pc + 3], value.c_str());
break;
case CPUDisAsm_InterpreterMode:
last_opcode = fmt::Format("[%08llx] %02x %02x %02x %02x: %s", dump_pc,
Memory.Read8(offset + dump_pc),
Memory.Read8(offset + dump_pc + 1),
Memory.Read8(offset + dump_pc + 2),
Memory.Read8(offset + dump_pc + 3), value.c_str());
offset[dump_pc],
offset[dump_pc + 1],
offset[dump_pc + 2],
offset[dump_pc + 3], value.c_str());
break;
case CPUDisAsm_CompilerElfMode:
@ -44,7 +42,7 @@ protected:
public:
std::string last_opcode;
u64 dump_pc;
u64 offset;
u8* offset;
protected:
CPUDisAsm(CPUDisAsmMode mode)
@ -57,7 +55,7 @@ protected:
std::string FixOp(std::string op)
{
op.append(max<int>(10 - (int)op.length(), 0),' ');
op.append(std::max<int>(10 - (int)op.length(), 0),' ');
return op;
}
};

View file

@ -1,7 +1,13 @@
#include "stdafx.h"
#include "CPUThread.h"
#include "rpcs3/Ini.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/DbgCommand.h"
reservation_struct reservation;
#include "CPUDecoder.h"
#include "CPUThread.h"
CPUThread* GetCurrentCPUThread()
{
@ -21,6 +27,7 @@ CPUThread::CPUThread(CPUThreadType type)
, m_is_step(false)
, m_is_branch(false)
, m_status(Stopped)
, m_last_syscall(0)
{
}
@ -29,6 +36,10 @@ CPUThread::~CPUThread()
safe_delete(m_dec);
}
bool CPUThread::IsRunning() const { return m_status == Running; }
bool CPUThread::IsPaused() const { return m_status == Paused; }
bool CPUThread::IsStopped() const { return m_status == Stopped; }
void CPUThread::Close()
{
ThreadBase::Stop(m_sync_wait);
@ -79,13 +90,13 @@ void CPUThread::SetName(const std::string& name)
void CPUThread::Wait(bool wait)
{
wxCriticalSectionLocker lock(m_cs_sync);
std::lock_guard<std::mutex> lock(m_cs_sync);
m_sync_wait = wait;
}
void CPUThread::Wait(const CPUThread& thr)
{
wxCriticalSectionLocker lock(m_cs_sync);
std::lock_guard<std::mutex> lock(m_cs_sync);
m_wait_thread_id = thr.GetId();
m_sync_wait = true;
}
@ -141,12 +152,6 @@ void CPUThread::NextPc(u8 instr_size)
void CPUThread::SetBranch(const u64 pc, bool record_branch)
{
if(!Memory.IsGoodAddr(m_offset + pc))
{
ConLog.Error("%s branch error: bad address 0x%llx #pc: 0x%llx", GetFName().c_str(), m_offset + pc, m_offset + PC);
Emu.Pause();
}
m_is_branch = true;
nPC = pc;
@ -171,13 +176,13 @@ void CPUThread::SetError(const u32 error)
}
}
wxArrayString CPUThread::ErrorToString(const u32 error)
std::vector<std::string> CPUThread::ErrorToString(const u32 error)
{
wxArrayString earr;
std::vector<std::string> earr;
if(error == 0) return earr;
earr.Add("Unknown error");
earr.push_back("Unknown error");
return earr;
}
@ -189,9 +194,7 @@ void CPUThread::Run()
Reset();
#ifndef QT_UI
wxGetApp().SendDbgCommand(DID_START_THREAD, this);
#endif
SendDbgCommand(DID_START_THREAD, this);
m_status = Running;
@ -201,18 +204,14 @@ void CPUThread::Run()
DoRun();
Emu.CheckStatus();
#ifndef QT_UI
wxGetApp().SendDbgCommand(DID_STARTED_THREAD, this);
#endif
SendDbgCommand(DID_STARTED_THREAD, this);
}
void CPUThread::Resume()
{
if(!IsPaused()) return;
#ifndef QT_UI
wxGetApp().SendDbgCommand(DID_RESUME_THREAD, this);
#endif
SendDbgCommand(DID_RESUME_THREAD, this);
m_status = Running;
DoResume();
@ -220,36 +219,28 @@ void CPUThread::Resume()
ThreadBase::Start();
#ifndef QT_UI
wxGetApp().SendDbgCommand(DID_RESUMED_THREAD, this);
#endif
SendDbgCommand(DID_RESUMED_THREAD, this);
}
void CPUThread::Pause()
{
if(!IsRunning()) return;
#ifndef QT_UI
wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this);
#endif
SendDbgCommand(DID_PAUSE_THREAD, this);
m_status = Paused;
DoPause();
Emu.CheckStatus();
// ThreadBase::Stop(); // "Abort() called" exception
#ifndef QT_UI
wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this);
#endif
SendDbgCommand(DID_PAUSED_THREAD, this);
}
void CPUThread::Stop()
{
if(IsStopped()) return;
#ifndef QT_UI
wxGetApp().SendDbgCommand(DID_STOP_THREAD, this);
#endif
SendDbgCommand(DID_STOP_THREAD, this);
m_status = Stopped;
@ -263,17 +254,13 @@ void CPUThread::Stop()
Emu.CheckStatus();
#ifndef QT_UI
wxGetApp().SendDbgCommand(DID_STOPED_THREAD, this);
#endif
SendDbgCommand(DID_STOPED_THREAD, this);
}
void CPUThread::Exec()
{
m_is_step = false;
#ifndef QT_UI
wxGetApp().SendDbgCommand(DID_EXEC_THREAD, this);
#endif
SendDbgCommand(DID_EXEC_THREAD, this);
if(IsRunning())
ThreadBase::Start();
@ -282,63 +269,89 @@ void CPUThread::Exec()
void CPUThread::ExecOnce()
{
m_is_step = true;
#ifndef QT_UI
wxGetApp().SendDbgCommand(DID_EXEC_THREAD, this);
#endif
SendDbgCommand(DID_EXEC_THREAD, this);
m_status = Running;
ThreadBase::Start();
ThreadBase::Stop(true,false);
m_status = Paused;
#ifndef QT_UI
wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this);
wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this);
#endif
SendDbgCommand(DID_PAUSE_THREAD, this);
SendDbgCommand(DID_PAUSED_THREAD, this);
}
#ifdef _WIN32
void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
{
const u64 addr = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)Memory.GetBaseAddr();
if (u == EXCEPTION_ACCESS_VIOLATION && addr < 0x100000000)
{
// TODO: allow recovering from a page fault
throw fmt::Format("Access violation: addr = 0x%x (last_syscall=0x%llx (%s))",
(u32)addr, (u64)GetCurrentCPUThread()->m_last_syscall, SysCalls::GetHLEFuncName((u32)GetCurrentCPUThread()->m_last_syscall).c_str());
}
else
{
// some fatal error (should crash)
return;
}
}
#else
// TODO: linux version
#endif
void CPUThread::Task()
{
if (Ini.LogAllSysCalls.GetValue()) ConLog.Write("%s enter", CPUThread::GetFName().c_str());
if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s enter", CPUThread::GetFName().c_str());
const std::vector<u64>& bp = Emu.GetBreakPoints();
for (uint i = 0; i<bp.size(); ++i)
{
if (bp[i] == m_offset + PC)
{
Emu.Pause();
break;
}
}
std::vector<u64> trace;
#ifdef _WIN32
_set_se_translator(_se_translator);
#else
// TODO: linux version
#endif
try
{
for(uint i=0; i<bp.size(); ++i)
{
if(bp[i] == m_offset + PC)
{
Emu.Pause();
break;
}
}
while(true)
while (true)
{
int status = ThreadStatus();
if(status == CPUThread_Stopped || status == CPUThread_Break)
if (status == CPUThread_Stopped || status == CPUThread_Break)
{
break;
}
if(status == CPUThread_Sleeping)
if (status == CPUThread_Sleeping)
{
Sleep(1);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}
Step();
//if (PC - 0x13ED4 < 0x288) trace.push_back(PC);
NextPc(m_dec->DecodeMemory(PC + m_offset));
if(status == CPUThread_Step)
if (status == CPUThread_Step)
{
m_is_step = false;
break;
}
for(uint i=0; i<bp.size(); ++i)
for (uint i = 0; i < bp.size(); ++i)
{
if(bp[i] == PC)
if (bp[i] == PC)
{
Emu.Pause();
break;
@ -346,20 +359,20 @@ void CPUThread::Task()
}
}
}
catch(const std::string& e)
catch (const std::string& e)
{
ConLog.Error("Exception: %s", e.c_str());
LOG_ERROR(GENERAL, "Exception: %s", e.c_str());
Emu.Pause();
}
catch(const char* e)
catch (const char* e)
{
ConLog.Error("Exception: %s", e);
}
catch(int exitcode)
{
ConLog.Success("Exit Code: %d", exitcode);
LOG_ERROR(GENERAL, "Exception: %s", e);
Emu.Pause();
}
if (Ini.LogAllSysCalls.GetValue()) ConLog.Write("%s leave", CPUThread::GetFName().c_str());
for (auto& v : trace) LOG_NOTICE(PPU, "PC = 0x%llx", v);
if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s leave", CPUThread::GetFName().c_str());
}
s64 CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4) // not multithread-safe
@ -368,10 +381,10 @@ s64 CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4)
{
if (Emu.IsStopped())
{
ConLog.Warning("ExecAsCallback() aborted");
LOG_WARNING(PPU, "ExecAsCallback() aborted");
return CELL_ECANCELED; // doesn't mean anything
}
Sleep(1);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
Stop();
@ -394,11 +407,11 @@ s64 CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4)
{
if (Emu.IsStopped())
{
ConLog.Warning("ExecAsCallback(wait=%s) aborted", wait ? "true" : "false");
LOG_WARNING(PPU, "ExecAsCallback(wait=%s) aborted", wait ? "true" : "false");
return CELL_EABORT; // doesn't mean anything
}
Sleep(1);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
return wait * m_exit_status;
}
}

View file

@ -1,25 +1,6 @@
#pragma once
#include "Emu/Memory/MemoryBlock.h"
#include "Emu/CPU/CPUDecoder.h"
#include "Utilities/SMutex.h"
struct reservation_struct
{
SMutex mutex; // mutex for updating reservation_owner and data
u32 owner; // id of thread that got reservation
u32 addr;
u32 size;
u32 data32;
u64 data64;
u128 data[8];
__forceinline void clear()
{
owner = 0;
}
};
extern reservation_struct reservation;
#include "Utilities/Thread.h"
enum CPUThreadType :unsigned char
{
@ -40,6 +21,8 @@ enum CPUThreadStatus
CPUThread_Step,
};
class CPUDecoder;
class CPUThread : public ThreadBase
{
protected:
@ -54,7 +37,7 @@ protected:
bool m_is_step;
u64 m_stack_addr;
u64 m_stack_size;
u32 m_stack_size;
u64 m_stack_point;
u64 m_exit_status;
@ -68,11 +51,11 @@ public:
virtual void CloseStack();
u64 GetStackAddr() const { return m_stack_addr; }
u64 GetStackSize() const { return m_stack_size; }
u32 GetStackSize() const { return m_stack_size; }
virtual u64 GetFreeStackSize() const=0;
void SetStackAddr(u64 stack_addr) { m_stack_addr = stack_addr; }
void SetStackSize(u64 stack_size) { m_stack_size = stack_size; }
void SetStackSize(u32 stack_size) { m_stack_size = stack_size; }
virtual void SetArg(const uint pos, const u64 arg) = 0;
@ -125,6 +108,11 @@ public:
u64 cycle;
bool m_is_branch;
bool m_is_interrupt;
bool m_has_interrupt;
u64 m_interrupt_arg;
u64 m_last_syscall;
protected:
CPUThread(CPUThreadType type);
@ -133,7 +121,7 @@ public:
u32 m_wait_thread_id;
wxCriticalSection m_cs_sync;
std::mutex m_cs_sync;
bool m_sync_wait;
void Wait(bool wait);
void Wait(const CPUThread& thr);
@ -144,7 +132,7 @@ public:
{
while(func(ThreadStatus()))
{
Sleep(1);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
@ -157,16 +145,16 @@ public:
void SetError(const u32 error);
static wxArrayString ErrorToString(const u32 error);
wxArrayString ErrorToString() { return ErrorToString(m_error); }
static std::vector<std::string> ErrorToString(const u32 error);
std::vector<std::string> ErrorToString() { return ErrorToString(m_error); }
bool IsOk() const { return m_error == 0; }
bool IsRunning() const { return m_status == Running; }
bool IsPaused() const { return m_status == Paused; }
bool IsStopped() const { return m_status == Stopped; }
bool IsOk() const { return m_error == 0; }
bool IsRunning() const;
bool IsPaused() const;
bool IsStopped() const;
bool IsJoinable() const { return m_joinable; }
bool IsJoining() const { return m_joining; }
bool IsJoining() const { return m_joining; }
void SetJoinable(bool joinable) { m_joinable = joinable; }
void SetJoining(bool joining) { m_joining = joining; }

View file

@ -1,4 +1,9 @@
#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/DbgCommand.h"
#include "Emu/IdManager.h"
#include "CPUThreadManager.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/SPUThread.h"
@ -6,7 +11,6 @@
#include "Emu/ARMv7/ARMv7Thread.h"
CPUThreadManager::CPUThreadManager()
: m_raw_spu_num(0)
{
}
@ -17,7 +21,6 @@ CPUThreadManager::~CPUThreadManager()
void CPUThreadManager::Close()
{
m_raw_spu_num = 0;
while(m_threads.size()) RemoveThread(m_threads[0]->GetId());
}
@ -29,19 +32,33 @@ CPUThread& CPUThreadManager::AddThread(CPUThreadType type)
switch(type)
{
case CPU_THREAD_PPU: new_thread = new PPUThread(); break;
case CPU_THREAD_SPU: new_thread = new SPUThread(); break;
case CPU_THREAD_RAW_SPU: new_thread = new RawSPUThread(m_raw_spu_num++); break;
case CPU_THREAD_ARMv7: new_thread = new ARMv7Thread(); break;
case CPU_THREAD_PPU:
{
new_thread = new PPUThread();
break;
}
case CPU_THREAD_SPU:
{
new_thread = new SPUThread();
break;
}
case CPU_THREAD_RAW_SPU:
{
new_thread = new RawSPUThread();
break;
}
case CPU_THREAD_ARMv7:
{
new_thread = new ARMv7Thread();
break;
}
default: assert(0);
}
new_thread->SetId(Emu.GetIdManager().GetNewID(fmt::Format("%s Thread", new_thread->GetTypeString().c_str()), new_thread));
m_threads.push_back(new_thread);
#ifndef QT_UI
wxGetApp().SendDbgCommand(DID_CREATE_THREAD, new_thread);
#endif
SendDbgCommand(DID_CREATE_THREAD, new_thread);
return *new_thread;
}
@ -69,9 +86,7 @@ void CPUThreadManager::RemoveThread(const u32 id)
if (thr)
{
#ifndef QT_UI
wxGetApp().SendDbgCommand(DID_REMOVE_THREAD, thr);
#endif
SendDbgCommand(DID_REMOVE_THREAD, thr);
thr->Close();
m_threads.erase(m_threads.begin() + thread_index);
@ -108,6 +123,34 @@ CPUThread* CPUThreadManager::GetThread(u32 id)
return res;
}
RawSPUThread* CPUThreadManager::GetRawSPUThread(u32 num)
{
if (num < sizeof(Memory.RawSPUMem) / sizeof(Memory.RawSPUMem[0]))
{
return (RawSPUThread*)Memory.RawSPUMem[num];
}
else
{
return nullptr;
}
}
void CPUThreadManager::NotifyThread(const u32 id)
{
if (!id) return;
std::lock_guard<std::mutex> lock(m_mtx_thread);
for (u32 i = 0; i < m_threads.size(); i++)
{
if (m_threads[i]->GetId() == id)
{
m_threads[i]->Notify();
return;
}
}
}
void CPUThreadManager::Exec()
{
std::lock_guard<std::mutex> lock(m_mtx_thread);

View file

@ -1,13 +1,13 @@
#pragma once
class CPUThread;
class RawSPUThread;
enum CPUThreadType : unsigned char;
class CPUThreadManager
{
std::vector<CPUThread*> m_threads;
std::mutex m_mtx_thread;
wxSemaphore m_sem_task;
u32 m_raw_spu_num;
public:
CPUThreadManager();
@ -17,10 +17,12 @@ public:
CPUThread& AddThread(CPUThreadType type);
void RemoveThread(const u32 id);
void NotifyThread(const u32 id);
std::vector<CPUThread*>& GetThreads() { return m_threads; }
s32 GetThreadNumById(CPUThreadType type, u32 id);
CPUThread* GetThread(u32 id);
RawSPUThread* GetRawSPUThread(u32 num);
void Exec();
void Task();

View file

@ -1,5 +1,4 @@
#pragma once
#include <atomic>
enum
{
@ -60,237 +59,7 @@ enum
MFC_SPU_MAX_QUEUE_SPACE = 0x10,
};
/*struct DMAC_Queue
{
bool is_valid;
u64 ea;
u32 lsa;
u16 size;
u32 op;
u8 tag;
u8 rt;
u16 list_addr;
u16 list_size;
u32 dep_state;
u32 cmd;
u32 dep_type;
};
struct DMAC_Proxy
{
u64 ea;
u32 lsa;
u16 size;
u32 op;
u8 tag;
u8 rt;
u16 list_addr;
u16 list_size;
u32 dep_state;
u32 cmd;
u32 dep_type;
};
template<size_t _max_count>
class SPUReg
{
u64 m_addr;
u32 m_pos;
public:
static const size_t max_count = _max_count;
static const size_t size = max_count * 4;
SPUReg()
{
Init();
}
void Init()
{
m_pos = 0;
}
void SetAddr(u64 addr)
{
m_addr = addr;
}
u64 GetAddr() const
{
return m_addr;
}
__forceinline bool Pop(u32& res)
{
if(!m_pos) return false;
res = Memory.Read32(m_addr + m_pos--);
return true;
}
__forceinline bool Push(u32 value)
{
if(m_pos >= max_count) return false;
Memory.Write32(m_addr + m_pos++, value);
return true;
}
u32 GetCount() const
{
return m_pos;
}
u32 GetFreeCount() const
{
return max_count - m_pos;
}
void SetValue(u32 value)
{
Memory.Write32(m_addr, value);
}
u32 GetValue() const
{
return Memory.Read32(m_addr);
}
};*/
struct DMAC
{
u64 ls_offset;
/*//DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE]; //not used yet
DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE+MFC_SPU_MAX_QUEUE_SPACE]; //temporarily 24
u32 queue_pos;
u32 proxy_pos;
long queue_lock;
volatile std::atomic<int> proxy_lock;
bool ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
{
//returns true if the command should be deleted from the queue
if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence();
switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK))
{
case MFC_PUT_CMD:
Memory.Copy(ea, ls_offset + lsa, size);
return true;
case MFC_GET_CMD:
Memory.Copy(ls_offset + lsa, ea, size);
return true;
default:
ConLog.Error("DMAC::ProcessCmd(): Unknown DMA cmd.");
return true;
}
}
u32 Cmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
{
if(!Memory.IsGoodAddr(ls_offset + lsa, size) || !Memory.IsGoodAddr(ea, size))
{
return MFC_PPU_DMA_CMD_SEQUENCE_ERROR;
}
if(proxy_pos >= MFC_PPU_MAX_QUEUE_SPACE)
{
return MFC_PPU_DMA_QUEUE_FULL;
}
ProcessCmd(cmd, tag, lsa, ea, size);
return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
}
void ClearCmd()
{
while (std::atomic_exchange(&proxy_lock, 1));
_mm_lfence();
memcpy(proxy, proxy + 1, --proxy_pos * sizeof(DMAC_Proxy));
_mm_sfence();
proxy_lock = 0; //release lock
}
void DoCmd()
{
if(proxy_pos)
{
const DMAC_Proxy& p = proxy[0];
if (ProcessCmd(p.cmd, p.tag, p.lsa, p.ea, p.size))
{
ClearCmd();
}
}
}*/
};
/*struct MFC
{
SPUReg<1> MFC_LSA;
SPUReg<1> MFC_EAH;
SPUReg<1> MFC_EAL;
SPUReg<1> MFC_Size_Tag;
SPUReg<1> MFC_CMDStatus;
SPUReg<1> MFC_QStatus;
SPUReg<1> Prxy_QueryType;
SPUReg<1> Prxy_QueryMask;
SPUReg<1> Prxy_TagStatus;
SPUReg<1> SPU_Out_MBox;
SPUReg<4> SPU_In_MBox;
SPUReg<1> SPU_MBox_Status;
SPUReg<1> SPU_RunCntl;
SPUReg<1> SPU_Status;
SPUReg<1> SPU_NPC;
SPUReg<1> SPU_RdSigNotify1;
SPUReg<1> SPU_RdSigNotify2;
DMAC dmac;
void Handle()
{
u32 cmd = MFC_CMDStatus.GetValue();
if(cmd)
{
u16 op = cmd & MFC_MASK_CMD;
switch(op)
{
case MFC_PUT_CMD:
case MFC_GET_CMD:
{
u32 lsa = MFC_LSA.GetValue();
u64 ea = (u64)MFC_EAL.GetValue() | ((u64)MFC_EAH.GetValue() << 32);
u32 size_tag = MFC_Size_Tag.GetValue();
u16 tag = (u16)size_tag;
u16 size = size_tag >> 16;
ConLog.Warning("RawSPU DMA %s:", op == MFC_PUT_CMD ? "PUT" : "GET");
ConLog.Warning("*** lsa = 0x%x", lsa);
ConLog.Warning("*** ea = 0x%llx", ea);
ConLog.Warning("*** tag = 0x%x", tag);
ConLog.Warning("*** size = 0x%x", size);
ConLog.SkipLn();
MFC_CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
}
break;
default:
ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x)", op, cmd);
break;
}
}
if(Prxy_QueryType.GetValue() == 2)
{
Prxy_QueryType.SetValue(0);
u32 mask = Prxy_QueryMask.GetValue();
//
MFC_QStatus.SetValue(mask);
}
}
};*/

View file

@ -1,11 +1,11 @@
#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "PPCDecoder.h"
u8 PPCDecoder::DecodeMemory(const u64 address)
{
u32 instr;
Memory.Read32ByAddr(address, &instr);
u32 instr = vm::read32(address);
Decode(instr);
return 4;
return sizeof(u32);
}

View file

@ -1,8 +1,6 @@
#pragma once
#include "Emu/CPU/CPUDisAsm.h"
#include "Gui/DisAsmFrame.h"
#include "Emu/Memory/Memory.h"
class PPCDisAsm : public CPUDisAsm
{

View file

@ -1,6 +1,6 @@
#include "stdafx.h"
#include "PPCThread.h"
#include "Gui/InterpreterDisAsm.h"
#include "Emu/Memory/Memory.h"
PPCThread* GetCurrentPPCThread()
{
@ -37,9 +37,9 @@ void PPCThread::InitStack()
/*
m_stack_point += m_stack_size - 0x10;
m_stack_point &= -0x10;
Memory.Write64(m_stack_point, 0);
vm::write64(m_stack_point, 0);
m_stack_point -= 0x60;
Memory.Write64(m_stack_point, m_stack_point + 0x60);
vm::write64(m_stack_point, m_stack_point + 0x60);
*/
}

View file

@ -1,7 +1,5 @@
#pragma once
#include "Emu/Memory/MemoryBlock.h"
#include "Emu/CPU/CPUThread.h"
#include "Emu/Cell/PPCDecoder.h"
class PPCThread : public CPUThread
{

View file

@ -1,10 +1,6 @@
#pragma once
#include "Emu/Cell/PPUOpcodes.h"
#include "Emu/Cell/PPCDisAsm.h"
#include "Emu/Cell/PPCThread.h"
#include "Gui/DisAsmFrame.h"
#include "Emu/Memory/Memory.h"
class PPUDisAsm
: public PPUOpcodes

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
#include "stdafx.h"
#include "stdafx_gui.h"
#include "PPUProgramCompiler.h"
#include "Utilities/rFile.h"
using namespace PPU_instr;
@ -80,7 +81,7 @@ SectionInfo::SectionInfo(const std::string& _name)
void SectionInfo::SetDataSize(u32 size, u32 align)
{
if(align) shdr.sh_addralign = align;
if(shdr.sh_addralign) size = Memory.AlignAddr(size, shdr.sh_addralign);
if(shdr.sh_addralign) size = AlignAddr(size, shdr.sh_addralign);
if(!code.empty())
{
@ -527,7 +528,7 @@ void CompilePPUProgram::LoadArgs()
m_end_args = m_args.size() > 0;
}
u32 CompilePPUProgram::GetBranchValue(const std::string& branch_name)
u32 CompilePPUProgram::GetBranchValue(const std::string& branch_name) const
{
for(const Branch& branch : m_branches)
{
@ -984,7 +985,7 @@ void CompilePPUProgram::Compile()
elf_info.e_shnum = 15;
elf_info.e_shstrndx = elf_info.e_shnum - 1;
elf_info.e_phoff = elf_info.e_ehsize;
u32 section_offset = Memory.AlignAddr(elf_info.e_phoff + elf_info.e_phnum * elf_info.e_phentsize, 0x100);
u32 section_offset = AlignAddr(elf_info.e_phoff + elf_info.e_phnum * elf_info.e_phentsize, 0x100);
static const u32 sceStub_text_block = 8 * 4;
@ -1142,7 +1143,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_sceStub_text;
memset(&s_sceStub_text, 0, sizeof(Elf64_Shdr));
s_sceStub_text.sh_addralign = 4;
section_offset = Memory.AlignAddr(section_offset, s_sceStub_text.sh_addralign);
section_offset = AlignAddr(section_offset, s_sceStub_text.sh_addralign);
s_sceStub_text.sh_type = 1;
s_sceStub_text.sh_offset = section_offset;
s_sceStub_text.sh_addr = section_offset + 0x10000;
@ -1166,7 +1167,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_lib_stub_top;
memset(&s_lib_stub_top, 0, sizeof(Elf64_Shdr));
s_lib_stub_top.sh_addralign = 4;
section_offset = Memory.AlignAddr(section_offset, s_lib_stub_top.sh_addralign);
section_offset = AlignAddr(section_offset, s_lib_stub_top.sh_addralign);
s_lib_stub_top.sh_type = 1;
s_lib_stub_top.sh_name = section_name_offset;
s_lib_stub_top.sh_offset = section_offset;
@ -1206,7 +1207,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_rodata_sceFNID;
memset(&s_rodata_sceFNID, 0, sizeof(Elf64_Shdr));
s_rodata_sceFNID.sh_addralign = 4;
section_offset = Memory.AlignAddr(section_offset, s_rodata_sceFNID.sh_addralign);
section_offset = AlignAddr(section_offset, s_rodata_sceFNID.sh_addralign);
s_rodata_sceFNID.sh_type = 1;
s_rodata_sceFNID.sh_name = section_name_offset;
s_rodata_sceFNID.sh_offset = section_offset;
@ -1220,7 +1221,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_rodata_sceResident;
memset(&s_rodata_sceResident, 0, sizeof(Elf64_Shdr));
s_rodata_sceResident.sh_addralign = 4;
section_offset = Memory.AlignAddr(section_offset, s_rodata_sceResident.sh_addralign);
section_offset = AlignAddr(section_offset, s_rodata_sceResident.sh_addralign);
s_rodata_sceResident.sh_type = 1;
s_rodata_sceResident.sh_name = section_name_offset;
s_rodata_sceResident.sh_offset = section_offset;
@ -1231,7 +1232,7 @@ void CompilePPUProgram::Compile()
{
s_rodata_sceResident.sh_size += module.m_name.length() + 1;
}
s_rodata_sceResident.sh_size = Memory.AlignAddr(s_rodata_sceResident.sh_size, s_rodata_sceResident.sh_addralign);
s_rodata_sceResident.sh_size = AlignAddr(s_rodata_sceResident.sh_size, s_rodata_sceResident.sh_addralign);
sections_names.push_back(".rodata.sceResident");
section_name_offset += std::string(".rodata.sceResident").length() + 1;
section_offset += s_rodata_sceResident.sh_size;
@ -1239,7 +1240,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_lib_ent_top;
memset(&s_lib_ent_top, 0, sizeof(Elf64_Shdr));
s_lib_ent_top.sh_addralign = 4;
section_offset = Memory.AlignAddr(section_offset, s_lib_ent_top.sh_addralign);
section_offset = AlignAddr(section_offset, s_lib_ent_top.sh_addralign);
s_lib_ent_top.sh_size = 4;
s_lib_ent_top.sh_flags = 2;
s_lib_ent_top.sh_type = 1;
@ -1266,7 +1267,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_sys_proc_prx_param;
memset(&s_sys_proc_prx_param, 0, sizeof(Elf64_Shdr));
s_sys_proc_prx_param.sh_addralign = 4;
section_offset = Memory.AlignAddr(section_offset, s_sys_proc_prx_param.sh_addralign);
section_offset = AlignAddr(section_offset, s_sys_proc_prx_param.sh_addralign);
s_sys_proc_prx_param.sh_type = 1;
s_sys_proc_prx_param.sh_size = sizeof(sys_proc_prx_param);
s_sys_proc_prx_param.sh_name = section_name_offset;
@ -1279,14 +1280,14 @@ void CompilePPUProgram::Compile()
const u32 prog_load_0_end = section_offset;
section_offset = Memory.AlignAddr(section_offset + 0x10000, 0x10000);
section_offset = AlignAddr(section_offset + 0x10000, 0x10000);
const u32 prog_load_1_start = section_offset;
Elf64_Shdr s_data_sceFStub;
memset(&s_data_sceFStub, 0, sizeof(Elf64_Shdr));
s_data_sceFStub.sh_name = section_name_offset;
s_data_sceFStub.sh_addralign = 4;
section_offset = Memory.AlignAddr(section_offset, s_data_sceFStub.sh_addralign);
section_offset = AlignAddr(section_offset, s_data_sceFStub.sh_addralign);
s_data_sceFStub.sh_flags = 3;
s_data_sceFStub.sh_type = 1;
s_data_sceFStub.sh_offset = section_offset;
@ -1299,7 +1300,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_tbss;
memset(&s_tbss, 0, sizeof(Elf64_Shdr));
s_tbss.sh_addralign = 4;
section_offset = Memory.AlignAddr(section_offset, s_tbss.sh_addralign);
section_offset = AlignAddr(section_offset, s_tbss.sh_addralign);
s_tbss.sh_size = 4;
s_tbss.sh_flags = 0x403;
s_tbss.sh_type = 8;
@ -1313,7 +1314,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_opd;
memset(&s_opd, 0, sizeof(Elf64_Shdr));
s_opd.sh_addralign = 8;
section_offset = Memory.AlignAddr(section_offset, s_opd.sh_addralign);
section_offset = AlignAddr(section_offset, s_opd.sh_addralign);
s_opd.sh_size = 2*4;
s_opd.sh_type = 1;
s_opd.sh_offset = section_offset;
@ -1474,7 +1475,7 @@ void CompilePPUProgram::Compile()
if(!m_file_path.empty() && !m_analyze && !m_error)
{
s_opd.sh_size = Memory.AlignAddr(s_opd.sh_size, s_opd.sh_addralign);
s_opd.sh_size = AlignAddr(s_opd.sh_size, s_opd.sh_addralign);
section_offset += s_opd.sh_size;
const u32 prog_load_1_end = section_offset;
@ -1482,7 +1483,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_shstrtab;
memset(&s_shstrtab, 0, sizeof(Elf64_Shdr));
s_shstrtab.sh_addralign = 1;
section_offset = Memory.AlignAddr(section_offset, s_shstrtab.sh_addralign);
section_offset = AlignAddr(section_offset, s_shstrtab.sh_addralign);
s_shstrtab.sh_name = section_name_offset;
s_shstrtab.sh_type = 3;
s_shstrtab.sh_offset = section_offset;
@ -1492,7 +1493,7 @@ void CompilePPUProgram::Compile()
s_shstrtab.sh_size = section_name_offset;
section_offset += s_shstrtab.sh_size;
wxFile f(fmt::FromUTF8(m_file_path), wxFile::write);
rFile f(m_file_path, rFile::write);
elf_info.e_magic = 0x7F454C46;
elf_info.e_class = 2; //ELF64
@ -1504,7 +1505,7 @@ void CompilePPUProgram::Compile()
elf_info.e_machine = MACHINE_PPC64; //PowerPC64
elf_info.e_version = 1; //ver 1
elf_info.e_flags = 0x0;
elf_info.e_shoff = Memory.AlignAddr(section_offset, 4);
elf_info.e_shoff = AlignAddr(section_offset, 4);
u8* opd_data = new u8[s_opd.sh_size];
u32 entry_point = s_text.sh_addr;
@ -1582,7 +1583,7 @@ void CompilePPUProgram::Compile()
}
f.Seek(s_lib_stub_top.sh_offset);
f.Seek(s_lib_stub_top.sh_size, wxFromCurrent);
f.Seek(s_lib_stub_top.sh_size, rFromCurrent);
f.Seek(s_lib_stub.sh_offset);
for(u32 i=0, nameoffs=4, dataoffs=0; i<modules.size(); ++i)
@ -1605,7 +1606,7 @@ void CompilePPUProgram::Compile()
}
f.Seek(s_lib_stub_btm.sh_offset);
f.Seek(s_lib_stub_btm.sh_size, wxFromCurrent);
f.Seek(s_lib_stub_btm.sh_size, rFromCurrent);
f.Seek(s_data_sceFStub.sh_offset);
for(const Module& module : modules)
@ -1635,13 +1636,13 @@ void CompilePPUProgram::Compile()
f.Write(&prx_param, sizeof(sys_proc_prx_param));
f.Seek(s_lib_ent_top.sh_offset);
f.Seek(s_lib_ent_top.sh_size, wxFromCurrent);
f.Seek(s_lib_ent_top.sh_size, rFromCurrent);
f.Seek(s_lib_ent_btm.sh_offset);
f.Seek(s_lib_ent_btm.sh_size, wxFromCurrent);
f.Seek(s_lib_ent_btm.sh_size, rFromCurrent);
f.Seek(s_tbss.sh_offset);
f.Seek(s_tbss.sh_size, wxFromCurrent);
f.Seek(s_tbss.sh_size, rFromCurrent);
f.Seek(s_shstrtab.sh_offset + 1);
for(u32 i=0; i<sections_names.size(); ++i)

View file

@ -1,5 +1,4 @@
#pragma once
#include <vector>
#include "PPUInstrTable.h"
#include "Loader/ELF64.h"
@ -148,7 +147,7 @@ protected:
void DetectArgInfo(Arg& arg);
void LoadArgs();
u32 GetBranchValue(const std::string& branch);
u32 GetBranchValue(const std::string& branch) const;
bool SetNextArgType(u32 types, bool show_err = true);
bool SetNextArgBranch(u8 aa, bool show_err = true);

View file

@ -1,10 +1,14 @@
#include "stdafx.h"
#include "rpcs3/Ini.h"
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Static.h"
#include "Emu/Cell/PPUDecoder.h"
#include "Emu/Cell/PPUInterpreter.h"
#include "Emu/Cell/PPUDisAsm.h"
#include <thread>
extern gcmInfo gcm_info;
PPUThread& GetCurrentPPUThread()
{
@ -50,15 +54,15 @@ void PPUThread::DoReset()
void PPUThread::AddArgv(const std::string& arg)
{
m_stack_point -= arg.length() + 1;
m_stack_point = Memory.AlignAddr(m_stack_point, 0x10) - 0x10;
m_stack_point = AlignAddr(m_stack_point, 0x10) - 0x10;
m_argv_addr.push_back(m_stack_point);
Memory.WriteString(m_stack_point, arg);
memcpy(vm::get_ptr<char>(m_stack_point), arg.c_str(), arg.size() + 1);
}
void PPUThread::InitRegs()
{
const u32 pc = Memory.Read32(entry);
const u32 rtoc = Memory.Read32(entry + 4);
const u32 pc = vm::read32(entry);
const u32 rtoc = vm::read32(entry + 4);
//ConLog.Write("entry = 0x%x", entry);
//ConLog.Write("rtoc = 0x%x", rtoc);
@ -70,7 +74,7 @@ void PPUThread::InitRegs()
if(thread_num < 0)
{
ConLog.Error("GetThreadNumById failed.");
LOG_ERROR(PPU, "GetThreadNumById failed.");
Emu.Pause();
return;
}
@ -81,13 +85,13 @@ void PPUThread::InitRegs()
if(tls_size >= Emu.GetTLSMemsz())
{
ConLog.Error("Out of TLS memory.");
LOG_ERROR(PPU, "Out of TLS memory.");
Emu.Pause();
return;
}
*/
m_stack_point = Memory.AlignAddr(m_stack_point, 0x200) - 0x200;
m_stack_point = AlignAddr(m_stack_point, 0x200) - 0x200;
GPR[1] = m_stack_point;
GPR[2] = rtoc;
@ -104,8 +108,8 @@ void PPUThread::InitRegs()
m_stack_point -= 0xc + 4 * argc;
u64 argv = m_stack_point;
mem64_ptr_t argv_list(argv);
for(int i=0; i<argc; ++i) argv_list += m_argv_addr[i];
auto argv_list = vm::ptr<be_t<u64>>::make((u32)argv);
for(int i=0; i<argc; ++i) argv_list[i] = m_argv_addr[i];
GPR[3] = argc;
GPR[4] = argv;
@ -157,7 +161,7 @@ void PPUThread::DoRun()
break;
default:
ConLog.Error("Invalid CPU decoder mode: %d", Ini.CPUDecoderMode.GetValue());
LOG_ERROR(PPU, "Invalid CPU decoder mode: %d", Ini.CPUDecoderMode.GetValue());
Emu.Pause();
}
}
@ -185,7 +189,7 @@ bool FPRdouble::IsINF(PPCdouble d)
bool FPRdouble::IsNaN(PPCdouble d)
{
return wxIsNaN(d) ? 1 : 0;
return std::isnan((double)d) ? 1 : 0;
}
bool FPRdouble::IsQNaN(PPCdouble d)
@ -212,3 +216,52 @@ int FPRdouble::Cmp(PPCdouble a, PPCdouble b)
return CR_SO;
}
u64 PPUThread::GetStackArg(s32 i)
{
return vm::read64(GPR[1] + 0x70 + 0x8 * (i - 9));
}
u64 PPUThread::FastCall(u64 addr, u64 rtoc, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8)
{
GPR[3] = arg1;
GPR[4] = arg2;
GPR[5] = arg3;
GPR[6] = arg4;
GPR[7] = arg5;
GPR[8] = arg6;
GPR[9] = arg7;
GPR[10] = arg8;
return FastCall2(addr, rtoc);
}
u64 PPUThread::FastCall2(u64 addr, u64 rtoc)
{
auto old_status = m_status;
auto old_PC = PC;
auto old_rtoc = GPR[2];
auto old_LR = LR;
auto old_thread = GetCurrentNamedThread();
m_status = Running;
PC = addr;
GPR[2] = rtoc;
LR = Emu.m_ppu_thr_stop;
SetCurrentNamedThread(this);
Task();
m_status = old_status;
PC = old_PC;
GPR[2] = old_rtoc;
LR = old_LR;
SetCurrentNamedThread(old_thread);
return GPR[3];
}
void PPUThread::FastStop()
{
m_status = Stopped;
}

View file

@ -1,8 +1,5 @@
#pragma once
#pragma once
#include "Emu/Cell/PPCThread.h"
#include "Emu/SysCalls/SysCalls.h"
#include "rpcs3.h"
#include <cmath>
enum
{
@ -77,15 +74,15 @@ union FPSCRhdr
u32 RN :2; //Floating-point rounding control
u32 NI :1; //Floating-point non-IEEE mode
u32 XE :1; //Floating-point inexact exception enable
u32 ZE :1; //IEEE oating-point zero divide exception enable
u32 UE :1; //IEEE floating-point underflow exception enable
u32 OE :1; //IEEE floating-point overflow exception enable
u32 ZE :1; //IEEE floating-point zero divide exception enable
u32 UE :1; //IEEE floating-point underflow exception enable
u32 OE :1; //IEEE floating-point overflow exception enable
u32 VE :1; //Floating-point invalid operation exception enable
u32 VXCVI :1; //Floating-point invalid operation exception for invalid integer convert
u32 VXSQRT :1; //Floating-point invalid operation exception for invalid square root
u32 VXSOFT :1; //Floating-point invalid operation exception for software request
u32 :1; //Reserved
u32 FPRF :5; //Floating-point result ags
u32 FPRF :5; //Floating-point result flags
u32 FI :1; //Floating-point fraction inexact
u32 FR :1; //Floating-point fraction rounded
u32 VXVC :1; //Floating-point invalid operation exception for invalid compare
@ -96,8 +93,8 @@ union FPSCRhdr
u32 VXSNAN :1; //Floating-point invalid operation exception for SNaN
u32 XX :1; //Floating-point inexact exception
u32 ZX :1; //Floating-point zero divide exception
u32 UX :1; //Floating-point underow exception
u32 OX :1; //Floating-point overow exception
u32 UX :1; //Floating-point underflow exception
u32 OX :1; //Floating-point overflow exception
u32 VX :1; //Floating-point invalid operation exception summary
u32 FEX :1; //Floating-point enabled exception summary
u32 FX :1; //Floating-point exception summary
@ -133,7 +130,7 @@ union MSRhdr
//1 Instruction address translation is enabled.
u64 IR : 1;
//Exception prefix. The setting of this bit specifies whether an exception vector offset
//Exception prefix. The setting of this bit specifies whether an exception vector offset
//is prepended with Fs or 0s. In the following description, nnnnn is the offset of the
//exception.
//0 Exceptions are vectored to the physical address 0x0000_0000_000n_nnnn in 64-bit implementations.
@ -170,9 +167,9 @@ union MSRhdr
u64 ME : 1;
//Floating-point available
//0 The processor prevents dispatch of oating-point instructions, including
//oating-point loads, stores, and moves.
//1 The processor can execute oating-point instructions.
//0 The processor prevents dispatch of floating-point instructions, including
//floating-point loads, stores, and moves.
//1 The processor can execute floating-point instructions.
u64 FP : 1;
//Privilege level
@ -247,10 +244,11 @@ union XERhdr
struct
{
u64 L : 61;
u64 CA : 1;
u64 OV : 1;
u64 SO : 1;
u32 L : 29;
u32 CA : 1;
u32 OV : 1;
u32 SO : 1;
u32 : 32;
};
};
@ -262,7 +260,7 @@ union VSCRhdr
{
/*
Saturation. A sticky status bit indicating that some field in a saturating instruction saturated since the last
time SAT was cleared. In other words when SAT = 1 it remains set to 1 until it is cleared to 0 by an
time SAT was cleared. In other words when SAT = '1' it remains set to '1' until it is cleared to '0' by an
mtvscr instruction.
1 The vector saturate instruction implicitly sets when saturation has occurred on the results one of
the vector instructions having saturate in its name:
@ -284,12 +282,12 @@ union VSCRhdr
/*
Non-Java. A mode control bit that determines whether vector floating-point operations will be performed
in a Java-IEEE-C9Xcompliant mode or a possibly faster non-Java/non-IEEE mode.
0 The Java-IEEE-C9Xcompliant mode is selected. Denormalized values are handled as specified
in a Java-IEEE-C9X-compliant mode or a possibly faster non-Java/non-IEEE mode.
0 The Java-IEEE-C9X-compliant mode is selected. Denormalized values are handled as specified
by Java, IEEE, and C9X standard.
1 The non-Java/non-IEEEcompliant mode is selected. If an element in a source vector register
contains a denormalized value, the value 0 is used instead. If an instruction causes an underflow
exception, the corresponding element in the target VR is cleared to 0. In both cases, the 0
1 The non-Java/non-IEEE-compliant mode is selected. If an element in a source vector register
contains a denormalized value, the value '0' is used instead. If an instruction causes an underflow
exception, the corresponding element in the target VR is cleared to '0'. In both cases, the '0'
has the same sign as the denormalized or underflowing value.
*/
u32 NJ : 1;
@ -391,7 +389,7 @@ struct PPCdouble
u32 To32() const
{
float res = _double;
float res = (float)_double;
return (u32&)res;
}
@ -470,59 +468,6 @@ struct FPRdouble
static int Cmp(PPCdouble a, PPCdouble b);
};
union VPR_reg
{
//__m128i _m128i;
u128 _u128;
s128 _s128;
u64 _u64[2];
s64 _s64[2];
u32 _u32[4];
s32 _s32[4];
u16 _u16[8];
s16 _s16[8];
u8 _u8[16];
s8 _s8[16];
float _f[4];
double _d[2];
VPR_reg() { Clear(); }
std::string ToString(bool hex = false) const
{
if(hex) return fmt::Format("%08x%08x%08x%08x", _u32[3], _u32[2], _u32[1], _u32[0]);
return fmt::Format("x: %g y: %g z: %g w: %g", _f[3], _f[2], _f[1], _f[0]);
}
u8 GetBit(u8 bit)
{
if(bit < 64) return (_u64[0] >> bit) & 0x1;
return (_u64[1] >> (bit - 64)) & 0x1;
}
void SetBit(u8 bit, u8 value)
{
if(bit < 64)
{
_u64[0] &= ~(1 << bit);
_u64[0] |= (value & 0x1) << bit;
return;
}
bit -= 64;
_u64[1] &= ~(1 << bit);
_u64[1] |= (value & 0x1) << bit;
}
void Clear() { memset(this, 0, sizeof(*this)); }
};
static const s32 MAX_INT_VALUE = 0x7fffffff;
class PPUThread : public PPCThread
{
public:
@ -532,7 +477,7 @@ public:
PPCdouble FPR[32]; //Floating Point Register
FPSCRhdr FPSCR; //Floating Point Status and Control Register
u64 GPR[32]; //General-Purpose Register
VPR_reg VPR[32];
u128 VPR[32];
u32 vpcr;
CRhdr CR; //Condition Register
@ -608,6 +553,9 @@ public:
u64 cycle;
u64 R_ADDR; // reservation address
u64 R_VALUE; // reservation value (BE)
public:
PPUThread();
virtual ~PPUThread();
@ -685,7 +633,7 @@ public:
}
else
{
UpdateCRn<u32>(n, a, b);
UpdateCRn<u32>(n, (u32)a, (u32)b);
}
}
@ -693,11 +641,11 @@ public:
{
if(l)
{
UpdateCRn<s64>(n, a, b);
UpdateCRn<s64>(n, (s64)a, (s64)b);
}
else
{
UpdateCRn<s32>(n, a, b);
UpdateCRn<s32>(n, (s32)a, (s32)b);
}
}
@ -721,7 +669,8 @@ public:
const u8 IsCR(const u32 bit) const { return (GetCR(bit >> 2) & GetCRBit(bit)) ? 1 : 0; }
bool IsCarry(const u64 a, const u64 b) { return a > (a + b); }
bool IsCarry(const u64 a, const u64 b) { return (a + b) < a; }
bool IsCarry(const u64 a, const u64 b, const u64 c) { return IsCarry(a, b) || IsCarry(a + b, c); }
void SetFPSCRException(const FPSCR_EXP mask)
{
@ -741,7 +690,7 @@ public:
for(uint i=0; i<32; ++i) ret += fmt::Format("GPR[%d] = 0x%llx\n", i, GPR[i]);
for(uint i=0; i<32; ++i) ret += fmt::Format("FPR[%d] = %.6G\n", i, (double)FPR[i]);
for(uint i=0; i<32; ++i) ret += fmt::Format("VPR[%d] = 0x%s [%s]\n", i, (const char*)VPR[i].ToString(true).c_str(), (const char*)VPR[i].ToString().c_str());
for(uint i=0; i<32; ++i) ret += fmt::Format("VPR[%d] = 0x%s [%s]\n", i, VPR[i].to_hex().c_str(), VPR[i].to_xyzw().c_str());
ret += fmt::Format("CR = 0x%08x\n", CR.CR);
ret += fmt::Format("LR = 0x%llx\n", LR);
ret += fmt::Format("CTR = 0x%llx\n", CTR);
@ -820,7 +769,7 @@ public:
}
if (reg == "CR" || reg == "FPSCR")
{
unsigned long reg_value;
unsigned long long reg_value;
reg_value = std::stoull(value.substr(24, 31), 0, 16);
if (reg == "CR") CR.CR = (u32)reg_value;
if (reg == "FPSCR") FPSCR.FPSCR = (u32)reg_value;
@ -839,6 +788,10 @@ public:
public:
virtual void InitRegs();
virtual u64 GetFreeStackSize() const;
u64 GetStackArg(s32 i);
u64 FastCall(u64 addr, u64 rtoc, u64 arg1 = 0, u64 arg2 = 0, u64 arg3 = 0, u64 arg4 = 0, u64 arg5 = 0, u64 arg6 = 0, u64 arg7 = 0, u64 arg8 = 0);
u64 FastCall2(u64 addr, u64 rtoc);
void FastStop();
protected:
virtual void DoReset() override;
@ -859,3 +812,5 @@ protected:
};
PPUThread& GetCurrentPPUThread();
#define declCPU PPUThread& CPU = GetCurrentPPUThread

View file

@ -1,243 +1,193 @@
#include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/Cell/RawSPUThread.h"
RawSPUThread::RawSPUThread(u32 index, CPUThreadType type)
RawSPUThread::RawSPUThread(CPUThreadType type)
: SPUThread(type)
, MemoryBlock()
, m_index(index)
{
Memory.MemoryBlocks.push_back(SetRange(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, RAW_SPU_OFFSET));
m_index = Memory.InitRawSPU(this);
Reset();
}
RawSPUThread::~RawSPUThread()
{
for(int i=0; i<Memory.MemoryBlocks.size(); ++i)
{
if(Memory.MemoryBlocks[i]->GetStartAddr() == GetStartAddr())
{
Memory.MemoryBlocks.erase(Memory.MemoryBlocks.begin() + i);
break;
}
}
//Close();
}
bool RawSPUThread::Read8(const u64 addr, u8* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read8(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Read8(0x%x)", m_index, offset);
Emu.Pause();
return false;
}
bool RawSPUThread::Read16(const u64 addr, u16* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read16(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Read16(0x%x)", m_index, offset);
Emu.Pause();
return false;
Memory.CloseRawSPU(this, m_index);
}
bool RawSPUThread::Read32(const u64 addr, u32* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
const u64 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
switch (offset)
{
return MemoryBlock::Read32(addr, value);
case MFC_CMDStatus_offs:
{
*value = MFC2.CMDStatus.GetValue();
break;
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
switch(offset)
{
case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_LSA)", m_index); *value = MFC2.LSA.GetValue(); break;
case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAH)", m_index); *value = MFC2.EAH.GetValue(); break;
case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAL)", m_index); *value = MFC2.EAL.GetValue(); break;
case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_Size_Tag)", m_index); *value = MFC2.Size_Tag.GetValue(); break;
case MFC_CMDStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_CMDStatus)", m_index); *value = MFC2.CMDStatus.GetValue(); break;
case MFC_QStatus_offs:
ConLog.Warning("RawSPUThread[%d]: Read32(MFC_QStatus)", m_index);
*value = MFC2.QStatus.GetValue();
break;
case Prxy_QueryType_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryType)", m_index); *value = Prxy.QueryType.GetValue(); break;
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); *value = Prxy.QueryMask.GetValue(); break;
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); *value = Prxy.TagStatus.GetValue(); break;
case SPU_Out_MBox_offs:
ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index);
SPU.Out_MBox.PopUncond(*value); //if Out_MBox is empty yet, the result will be undefined
break;
case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); while(!SPU.In_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); break;
case SPU_MBox_Status_offs: //ConLog.Warning("RawSPUThread[%d]: Read32(SPU_MBox_Status)", m_index);
//SPU.MBox_Status.SetValue(SPU.Out_MBox.GetCount() ? SPU.MBox_Status.GetValue() | 1 : SPU.MBox_Status.GetValue() & ~1);
SPU.MBox_Status.SetValue((SPU.Out_MBox.GetCount() & 0xff) | (SPU.In_MBox.GetFreeCount() << 8));
*value = SPU.MBox_Status.GetValue();
{
// TagStatus is not used: mask is written directly
*value = MFC2.QueryMask.GetValue();
break;
case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index); *value = SPU.RunCntl.GetValue(); break;
case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Status)", m_index); *value = SPU.Status.GetValue(); break;
case SPU_NPC_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_NPC)", m_index); *value = SPU.NPC.GetValue(); break;
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify1)", m_index); *value = SPU.SNR[0].GetValue(); break;
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify2)", m_index); *value = SPU.SNR[1].GetValue(); break;
}
case SPU_Out_MBox_offs:
{
// if Out_MBox is empty, the result is undefined
SPU.Out_MBox.PopUncond(*value);
break;
}
case SPU_MBox_Status_offs:
{
*value = (SPU.Out_MBox.GetCount() & 0xff) | (SPU.In_MBox.GetFreeCount() << 8);
break;
}
case SPU_Status_offs:
{
*value = SPU.Status.GetValue();
break;
}
default:
ConLog.Error("RawSPUThread[%d]: Read32(0x%x)", m_index, offset);
Emu.Pause();
break;
{
// TODO: read value from LS if necessary (not important)
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(0x%llx)", m_index, offset);
return false;
}
}
return true;
}
bool RawSPUThread::Read64(const u64 addr, u64* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read64(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Read64(0x%x)", m_index, offset);
Emu.Pause();
return false;
}
bool RawSPUThread::Read128(const u64 addr, u128* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read128(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Read128(0x%x)", m_index, offset);
Emu.Pause();
return false;
}
bool RawSPUThread::Write8(const u64 addr, const u8 value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Write8(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Write8(0x%x, 0x%x)", m_index, offset, value);
Emu.Pause();
return false;
}
bool RawSPUThread::Write16(const u64 addr, const u16 value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Write16(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Write16(0x%x, 0x%x)", m_index, offset, value);
Emu.Pause();
return false;
}
bool RawSPUThread::Write32(const u64 addr, const u32 value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
const u64 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
switch (offset)
{
return MemoryBlock::Write32(addr, value);
case MFC_LSA_offs:
{
MFC2.LSA.SetValue(value);
break;
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
switch(offset)
case MFC_EAH_offs:
{
case MFC_LSA_offs: MFC2.LSA.SetValue(value); break;
case MFC_EAH_offs: MFC2.EAH.SetValue(value); break;
case MFC_EAL_offs: MFC2.EAL.SetValue(value); break;
case MFC_Size_Tag_offs: MFC2.Size_Tag.SetValue(value); break;
MFC2.EAH.SetValue(value);
break;
}
case MFC_EAL_offs:
{
MFC2.EAL.SetValue(value);
break;
}
case MFC_Size_Tag_offs:
{
MFC2.Size_Tag.SetValue(value);
break;
}
case MFC_CMDStatus_offs:
{
MFC2.CMDStatus.SetValue(value);
EnqMfcCmd(MFC2);
break;
case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); MFC2.QStatus.SetValue(value); break;
break;
}
case Prxy_QueryType_offs:
{
ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryType, 0x%x)", m_index, value);
Prxy.QueryType.SetValue(value);
switch(value)
{
case 2:
ConLog.Warning("RawSPUThread[%d]: Prxy Query Immediate.", m_index);
break;
case 2: break;
default:
ConLog.Error("RawSPUThread[%d]: Unknown Prxy Query Type. (prxy_query=0x%x)", m_index, value);
break;
{
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Unknown Prxy Query Type. (prxy_query=0x%x)", m_index, value);
return false;
}
}
Prxy.QueryType.SetValue(0);
MFC2.QStatus.SetValue(Prxy.QueryMask.GetValue());
MFC2.QueryType.SetValue(value); // not used
break;
}
break;
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value); Prxy.QueryMask.SetValue(value); break;
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_TagStatus, 0x%x)", m_index, value); Prxy.TagStatus.SetValue(value); break;
case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Out_MBox, 0x%x)", m_index, value); while(!SPU.Out_MBox.Push(value) && !Emu.IsStopped()) Sleep(1); break;
case Prxy_QueryMask_offs:
{
MFC2.QueryMask.SetValue(value); // TagStatus is not used
break;
}
case SPU_In_MBox_offs:
ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value);
SPU.In_MBox.PushUncond(value); //if In_MBox is already full, the last message will be overwritten
break;
case SPU_MBox_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_MBox_Status, 0x%x)", m_index, value); SPU.MBox_Status.SetValue(value); break;
case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RunCntl, 0x%x)", m_index, value); SPU.RunCntl.SetValue(value); break;
case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Status, 0x%x)", m_index, value); SPU.Status.SetValue(value); break;
case SPU_NPC_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_NPC, 0x%x)", m_index, value); SPU.NPC.SetValue(value); break;
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RdSigNotify1, 0x%x)", m_index, value); SPU.SNR[0].SetValue(value); break;
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RdSigNotify2, 0x%x)", m_index, value); SPU.SNR[1].SetValue(value); break;
{
// if In_MBox is already full, the last message is overwritten
SPU.In_MBox.PushUncond(value);
break;
}
case SPU_RunCntl_offs:
{
if (value == SPU_RUNCNTL_RUNNABLE)
{
SPU.Status.SetValue(SPU_STATUS_RUNNING);
Exec();
}
else if (value == SPU_RUNCNTL_STOP)
{
SPU.Status.SetValue(SPU_STATUS_STOPPED);
Stop();
}
else
{
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write32(SPU_RunCtrl, 0x%x): unknown value", m_index, value);
return false;
}
break;
}
case SPU_NPC_offs:
{
if (value & 3)
{
// least significant bit contains some interrupt flag
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write32(SPU_NPC_offs, 0x%x): lowest bits set", m_index, value);
return false;
}
SPU.NPC.SetValue(value);
break;
}
case SPU_RdSigNotify1_offs:
{
WriteSNR(0, value);
break;
}
case SPU_RdSigNotify2_offs:
{
WriteSNR(1, value);
break;
}
default:
ConLog.Error("RawSPUThread[%d]: Write32(0x%x, 0x%x)", m_index, offset, value);
Emu.Pause();
break;
{
// TODO: write value to LS if necessary (not important)
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write32(0x%llx, 0x%x)", m_index, offset, value);
return false;
}
}
return true;
}
bool RawSPUThread::Write64(const u64 addr, const u64 value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Write64(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Write64(0x%x, 0x%llx)", m_index, offset, value);
Emu.Pause();
return false;
}
bool RawSPUThread::Write128(const u64 addr, const u128 value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Write128(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Write128(0x%x, 0x%llx_%llx)", m_index, offset, value._u64[1], value._u64[0]);
Emu.Pause();
return false;
}
void RawSPUThread::InitRegs()
{
dmac.ls_offset = m_offset = GetStartAddr() + RAW_SPU_LS_OFFSET;
@ -251,88 +201,9 @@ u32 RawSPUThread::GetIndex() const
void RawSPUThread::Task()
{
if (Ini.LogAllSysCalls.GetValue()) ConLog.Write("%s enter", PPCThread::GetFName().c_str());
PC = SPU.NPC.GetValue();
const std::vector<u64>& bp = Emu.GetBreakPoints();
SPUThread::Task();
try
{
for(uint i=0; i<bp.size(); ++i)
{
if(bp[i] == m_offset + PC)
{
Emu.Pause();
break;
}
}
bool is_last_paused = true;
while(true)
{
int status = ThreadStatus();
if(status == CPUThread_Stopped || status == CPUThread_Break)
{
break;
}
if(status == CPUThread_Sleeping)
{
Sleep(1);
continue;
}
//dmac.DoCmd();
if(SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE)
{
if(!is_last_paused)
{
is_last_paused = true;
SPU.NPC.SetValue(PC);
SPU.Status.SetValue(SPU_STATUS_WAITING_FOR_CHANNEL);
}
Sleep(1);
continue;
}
if(is_last_paused)
{
is_last_paused = false;
PC = SPU.NPC.GetValue();
SPU.Status.SetValue(SPU_STATUS_RUNNING);
ConLog.Warning("Starting RawSPU...");
}
Step();
NextPc(m_dec->DecodeMemory(PC + m_offset));
if(status == CPUThread_Step)
{
m_is_step = false;
continue;
}
for(uint i=0; i<bp.size(); ++i)
{
if(bp[i] == PC)
{
Emu.Pause();
continue;
}
}
}
}
catch(const std::string& e)
{
ConLog.Error("Exception: %s", e.c_str());
}
catch(const char* e)
{
ConLog.Error("Exception: %s", e);
}
if (Ini.LogAllSysCalls.GetValue()) ConLog.Write("%s leave", PPCThread::GetFName().c_str());
SPU.NPC.SetValue((u32)PC);
}

View file

@ -1,47 +1,11 @@
#pragma once
#include "SPUThread.h"
#include "Emu/event.h"
enum
{
MFC_LSA_offs = 0x3004,
MFC_EAH_offs = 0x3008,
MFC_EAL_offs = 0x300C,
MFC_Size_Tag_offs = 0x3010,
MFC_Class_CMD_offs = 0x3014,
MFC_CMDStatus_offs = 0x3014,
MFC_QStatus_offs = 0x3104,
Prxy_QueryType_offs = 0x3204,
Prxy_QueryMask_offs = 0x321C,
Prxy_TagStatus_offs = 0x322C,
SPU_Out_MBox_offs = 0x4004,
SPU_In_MBox_offs = 0x400C,
SPU_MBox_Status_offs = 0x4014,
SPU_RunCntl_offs = 0x401C,
SPU_Status_offs = 0x4024,
SPU_NPC_offs = 0x4034,
SPU_RdSigNotify1_offs = 0x1400C,
SPU_RdSigNotify2_offs = 0x1C00C,
};
enum : u64
{
RAW_SPU_OFFSET = 0x0000000000100000,
RAW_SPU_BASE_ADDR = 0x00000000E0000000,
RAW_SPU_LS_OFFSET = 0x0000000000000000,
RAW_SPU_PROB_OFFSET = 0x0000000000040000,
};
__forceinline static u32 GetRawSPURegAddrByNum(int num, int offset)
{
return RAW_SPU_OFFSET * num + RAW_SPU_BASE_ADDR + RAW_SPU_PROB_OFFSET + offset;
}
__forceinline static u32 GetRawSPURegAddrById(int id, int offset)
{
return GetRawSPURegAddrByNum(Emu.GetCPU().GetThreadNumById(CPU_THREAD_RAW_SPU, id), offset);
}
class RawSPUThread
: public SPUThread
, public MemoryBlock
@ -49,20 +13,12 @@ class RawSPUThread
u32 m_index;
public:
RawSPUThread(u32 index, CPUThreadType type = CPU_THREAD_RAW_SPU);
RawSPUThread(CPUThreadType type = CPU_THREAD_RAW_SPU);
virtual ~RawSPUThread();
virtual bool Read8(const u64 addr, u8* value) override;
virtual bool Read16(const u64 addr, u16* value) override;
virtual bool Read32(const u64 addr, u32* value) override;
virtual bool Read64(const u64 addr, u64* value) override;
virtual bool Read128(const u64 addr, u128* value) override;
bool Read32(const u64 addr, u32* value);
virtual bool Write8(const u64 addr, const u8 value) override;
virtual bool Write16(const u64 addr, const u16 value) override;
virtual bool Write32(const u64 addr, const u32 value) override;
virtual bool Write64(const u64 addr, const u64 value) override;
virtual bool Write128(const u64 addr, const u128 value) override;
bool Write32(const u64 addr, const u32 value);
public:
virtual void InitRegs();

View file

@ -2,9 +2,69 @@
#include "Emu/Cell/SPUOpcodes.h"
#include "Emu/Cell/PPCDisAsm.h"
#include "Emu/Cell/SPUThread.h"
#include "Gui/DisAsmFrame.h"
#include "Emu/Memory/Memory.h"
static const char* spu_reg_name[128] =
{
"$LR", "$SP", "$2", "$3", "$4", "$5", "$6", "$7",
"$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
"$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31",
"$32", "$33", "$34", "$35", "$36", "$37", "$38", "$39",
"$40", "$41", "$42", "$43", "$44", "$45", "$46", "$47",
"$48", "$49", "$50", "$51", "$52", "$53", "$54", "$55",
"$56", "$57", "$58", "$59", "$60", "$61", "$62", "$63",
"$64", "$65", "$66", "$67", "$68", "$69", "$70", "$71",
"$72", "$73", "$74", "$75", "$76", "$77", "$78", "$79",
"$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87",
"$88", "$89", "$90", "$91", "$92", "$93", "$94", "$95",
"$96", "$97", "$98", "$99", "$100", "$101", "$102", "$103",
"$104", "$105", "$106", "$107", "$108", "$109", "$110", "$111",
"$112", "$113", "$114", "$115", "$116", "$117", "$118", "$119",
"$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127",
};
static const char* spu_spreg_name[128] =
{
"$sp0", "$sp1", "$sp2", "$sp3", "$sp4", "$sp5", "$sp6", "$sp7",
"$sp8", "$sp9", "$sp10", "$sp11", "$sp12", "$sp13", "$sp14", "$sp15",
"$sp16", "$sp17", "$sp18", "$sp19", "$sp20", "$sp21", "$sp22", "$sp23",
"$sp24", "$sp25", "$sp26", "$sp27", "$sp28", "$sp29", "$sp30", "$sp31",
"$sp32", "$sp33", "$sp34", "$sp35", "$sp36", "$sp37", "$sp38", "$sp39",
"$sp40", "$sp41", "$sp42", "$sp43", "$sp44", "$sp45", "$sp46", "$sp47",
"$sp48", "$sp49", "$sp50", "$sp51", "$sp52", "$sp53", "$sp54", "$sp55",
"$sp56", "$sp57", "$sp58", "$sp59", "$sp60", "$sp61", "$sp62", "$sp63",
"$sp64", "$sp65", "$sp66", "$sp67", "$sp68", "$sp69", "$sp70", "$sp71",
"$sp72", "$sp73", "$sp74", "$sp75", "$sp76", "$sp77", "$sp78", "$sp79",
"$sp80", "$sp81", "$sp82", "$sp83", "$sp84", "$sp85", "$sp86", "$sp87",
"$sp88", "$sp89", "$sp90", "$sp91", "$sp92", "$sp93", "$sp94", "$sp95",
"$sp96", "$sp97", "$sp98", "$sp99", "$sp100", "$sp101", "$sp102", "$sp103",
"$sp104", "$sp105", "$sp106", "$sp107", "$sp108", "$sp109", "$sp110", "$sp111",
"$sp112", "$sp113", "$sp114", "$sp115", "$sp116", "$sp117", "$sp118", "$sp119",
"$sp120", "$sp121", "$sp122", "$sp123", "$sp124", "$sp125", "$sp126", "$sp127",
};
static const char* spu_ch_name[128] =
{
"$SPU_RdEventStat", "$SPU_WrEventMask", "$SPU_WrEventAck", "$SPU_RdSigNotify1",
"$SPU_RdSigNotify2", "$ch5", "$ch6", "$SPU_WrDec", "$SPU_RdDec",
"$MFC_WrMSSyncReq", "$ch10", "$SPU_RdEventMask", "$MFC_RdTagMask", "$SPU_RdMachStat",
"$SPU_WrSRR0", "$SPU_RdSRR0", "$MFC_LSA", "$MFC_EAH", "$MFC_EAL", "$MFC_Size",
"$MFC_TagID", "$MFC_Cmd", "$MFC_WrTagMask", "$MFC_WrTagUpdate", "$MFC_RdTagStat",
"$MFC_RdListStallStat", "$MFC_WrListStallAck", "$MFC_RdAtomicStat",
"$SPU_WrOutMbox", "$SPU_RdInMbox", "$SPU_WrOutIntrMbox", "$ch31", "$ch32",
"$ch33", "$ch34", "$ch35", "$ch36", "$ch37", "$ch38", "$ch39", "$ch40",
"$ch41", "$ch42", "$ch43", "$ch44", "$ch45", "$ch46", "$ch47", "$ch48",
"$ch49", "$ch50", "$ch51", "$ch52", "$ch53", "$ch54", "$ch55", "$ch56",
"$ch57", "$ch58", "$ch59", "$ch60", "$ch61", "$ch62", "$ch63", "$ch64",
"$ch65", "$ch66", "$ch67", "$ch68", "$ch69", "$ch70", "$ch71", "$ch72",
"$ch73", "$ch74", "$ch75", "$ch76", "$ch77", "$ch78", "$ch79", "$ch80",
"$ch81", "$ch82", "$ch83", "$ch84", "$ch85", "$ch86", "$ch87", "$ch88",
"$ch89", "$ch90", "$ch91", "$ch92", "$ch93", "$ch94", "$ch95", "$ch96",
"$ch97", "$ch98", "$ch99", "$ch100", "$ch101", "$ch102", "$ch103", "$ch104",
"$ch105", "$ch106", "$ch107", "$ch108", "$ch109", "$ch110", "$ch111", "$ch112",
"$ch113", "$ch114", "$ch115", "$ch116", "$ch117", "$ch118", "$ch119", "$ch120",
"$ch121", "$ch122", "$ch123", "$ch124", "$ch125", "$ch126", "$ch127",
};
class SPUDisAsm
: public SPUOpcodes
@ -28,7 +88,7 @@ private:
private:
std::string& FixOp(std::string& op)
{
op.append(max<int>(10 - (int)op.length(), 0),' ');
op.append(std::max<int>(10 - (int)op.length(), 0),' ');
return op;
}
void DisAsm(const char* op)
@ -94,7 +154,7 @@ private:
}
void MFSPR(u32 rt, u32 sa)
{
DisAsm("mfspr", spu_reg_name[rt], spu_reg_name[sa]); // Are SPR mapped on the GPR or are there 128 additional registers ? Yes, there are also 128 SPR making 256 registers total
DisAsm("mfspr", spu_reg_name[rt], spu_spreg_name[sa]);
}
void RDCH(u32 rt, u32 ra)
{
@ -218,25 +278,25 @@ private:
}
void MTSPR(u32 rt, u32 sa)
{
DisAsm("mtspr", spu_reg_name[rt], spu_reg_name[sa]);
DisAsm("mtspr", spu_spreg_name[sa], spu_reg_name[rt]);
}
void WRCH(u32 ra, u32 rt)
{
DisAsm("wrch", spu_ch_name[ra], spu_reg_name[rt]);
}
void BIZ(u32 rt, u32 ra)
void BIZ(u32 intr, u32 rt, u32 ra)
{
DisAsm("biz", spu_reg_name[rt], spu_reg_name[ra]);
}
void BINZ(u32 rt, u32 ra)
void BINZ(u32 intr, u32 rt, u32 ra)
{
DisAsm("binz", spu_reg_name[rt], spu_reg_name[ra]);
}
void BIHZ(u32 rt, u32 ra)
void BIHZ(u32 intr, u32 rt, u32 ra)
{
DisAsm("bihz", spu_reg_name[rt], spu_reg_name[ra]);
}
void BIHNZ(u32 rt, u32 ra)
void BIHNZ(u32 intr, u32 rt, u32 ra)
{
DisAsm("bihnz", spu_reg_name[rt], spu_reg_name[ra]);
}
@ -248,11 +308,11 @@ private:
{
DisAsm("stqx", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb]);
}
void BI(u32 ra)
void BI(u32 intr, u32 ra)
{
DisAsm("bi", spu_reg_name[ra]);
}
void BISL(u32 rt, u32 ra)
void BISL(u32 intr, u32 rt, u32 ra)
{
DisAsm("bisl", spu_reg_name[rt], spu_reg_name[ra]);
}
@ -260,7 +320,7 @@ private:
{
DisAsm("iret", spu_reg_name[ra]);
}
void BISLED(u32 rt, u32 ra)
void BISLED(u32 intr, u32 rt, u32 ra)
{
DisAsm("bisled", spu_reg_name[rt], spu_reg_name[ra]);
}

View file

@ -1,5 +1,4 @@
#pragma once
#include "PPCInstrTable.h"
#include "PPCDecoder.h"
#include "SPUOpcodes.h"
@ -88,16 +87,16 @@ namespace SPU_instr
bind_instr(ri7_list, AVGB, RT, RA, RB);
bind_instr(ri7_list, MTSPR, RT, RA);
bind_instr(ri7_list, WRCH, RA, RT);
bind_instr(ri7_list, BIZ, RT, RA);
bind_instr(ri7_list, BINZ, RT, RA);
bind_instr(ri7_list, BIHZ, RT, RA);
bind_instr(ri7_list, BIHNZ, RT, RA);
bind_instr(ri7_list, BIZ, RB, RT, RA);
bind_instr(ri7_list, BINZ, RB, RT, RA);
bind_instr(ri7_list, BIHZ, RB, RT, RA);
bind_instr(ri7_list, BIHNZ, RB, RT, RA);
bind_instr(ri7_list, STOPD, RT, RA, RB);
bind_instr(ri7_list, STQX, RT, RA, RB);
bind_instr(ri7_list, BI, RA);
bind_instr(ri7_list, BISL, RT, RA);
bind_instr(ri7_list, BI, RB, RA);
bind_instr(ri7_list, BISL, RB, RT, RA);
bind_instr(ri7_list, IRET, RA);
bind_instr(ri7_list, BISLED, RT, RA);
bind_instr(ri7_list, BISLED, RB, RT, RA);
bind_instr(ri7_list, HBR, L_11, RO, RA);
bind_instr(ri7_list, GB, RT, RA);
bind_instr(ri7_list, GBH, RT, RA);

File diff suppressed because it is too large Load diff

View file

@ -272,16 +272,16 @@ public:
virtual void AVGB(u32 rt, u32 ra, u32 rb) = 0;
virtual void MTSPR(u32 rt, u32 sa) = 0;
virtual void WRCH(u32 ra, u32 rt) = 0;
virtual void BIZ(u32 rt, u32 ra) = 0;
virtual void BINZ(u32 rt, u32 ra) = 0;
virtual void BIHZ(u32 rt, u32 ra) = 0;
virtual void BIHNZ(u32 rt, u32 ra) = 0;
virtual void BIZ(u32 intr, u32 rt, u32 ra) = 0;
virtual void BINZ(u32 intr, u32 rt, u32 ra) = 0;
virtual void BIHZ(u32 intr, u32 rt, u32 ra) = 0;
virtual void BIHNZ(u32 intr, u32 rt, u32 ra) = 0;
virtual void STOPD(u32 rc, u32 ra, u32 rb) = 0;
virtual void STQX(u32 rt, u32 ra, u32 rb) = 0;
virtual void BI(u32 ra) = 0;
virtual void BISL(u32 rt, u32 ra) = 0;
virtual void BI(u32 intr, u32 ra) = 0;
virtual void BISL(u32 intr, u32 rt, u32 ra) = 0;
virtual void IRET(u32 ra) = 0;
virtual void BISLED(u32 rt, u32 ra) = 0;
virtual void BISLED(u32 intr, u32 rt, u32 ra) = 0;
virtual void HBR(u32 p, u32 ro, u32 ra) = 0;
virtual void GB(u32 rt, u32 ra) = 0;
virtual void GBH(u32 rt, u32 ra) = 0;

View file

@ -1,6 +1,51 @@
#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "SPURSManager.h"
SPURSManagerAttribute::SPURSManagerAttribute(int nSpus, int spuPriority, int ppuPriority, bool exitIfNoWork)
{
this->nSpus = nSpus;
this->spuThreadGroupPriority = spuPriority;
this->ppuThreadPriority = ppuPriority;
this->exitIfNoWork = exitIfNoWork;
memset(this->namePrefix, 0, CELL_SPURS_NAME_MAX_LENGTH + 1);
this->threadGroupType = 0;
this->container = 0;
}
int SPURSManagerAttribute::_setNamePrefix(const char *name, u32 size)
{
strncpy(this->namePrefix, name, size);
this->namePrefix[0] = 0;
return 0;
}
int SPURSManagerAttribute::_setSpuThreadGroupType(int type)
{
this->threadGroupType = type;
return 0;
}
int SPURSManagerAttribute::_setMemoryContainerForSpuThread(u32 container)
{
this->container = container;
return 0;
}
SPURSManagerEventFlag::SPURSManagerEventFlag(u32 flagClearMode, u32 flagDirection)
{
this->flagClearMode = flagClearMode;
this->flagDirection = flagDirection;
}
SPURSManagerTasksetAttribute::SPURSManagerTasksetAttribute(u64 args, vm::ptr<const u8> priority, u32 maxContention)
{
this->args = args;
this->maxContention = maxContention;
}
SPURSManager::SPURSManager(SPURSManagerAttribute *attr)
{
this->attr = attr;
@ -9,4 +54,20 @@ SPURSManager::SPURSManager(SPURSManagerAttribute *attr)
void SPURSManager::Finalize()
{
delete this->attr;
}
void SPURSManager::AttachLv2EventQueue(u32 queue, vm::ptr<u8> port, int isDynamic)
{
//TODO:
}
void SPURSManager::DetachLv2EventQueue(u8 port)
{
//TODO:
}
SPURSManagerTaskset::SPURSManagerTaskset(u32 address, SPURSManagerTasksetAttribute *tattr)
{
this->tattr = tattr;
this->address = address;
}

View file

@ -1,83 +1,18 @@
#pragma once
// SPURS defines.
enum SPURSKernelInterfaces
{
CELL_SPURS_MAX_SPU = 8,
CELL_SPURS_MAX_WORKLOAD = 16,
CELL_SPURS_MAX_WORKLOAD2 = 32,
CELL_SPURS_MAX_PRIORITY = 16,
CELL_SPURS_NAME_MAX_LENGTH = 15,
CELL_SPURS_SIZE = 4096,
CELL_SPURS_SIZE2 = 8192,
CELL_SPURS_ALIGN = 128,
CELL_SPURS_ATTRIBUTE_SIZE = 512,
CELL_SPURS_ATTRIBUTE_ALIGN = 8,
CELL_SPURS_INTERRUPT_VECTOR = 0x0,
CELL_SPURS_LOCK_LINE = 0x80,
CELL_SPURS_KERNEL_DMA_TAG_ID = 31,
};
enum RangeofEventQueuePortNumbers
{
CELL_SPURS_STATIC_PORT_RANGE_BOTTOM = 15,
CELL_SPURS_DYNAMIC_PORT_RANGE_TOP = 16,
CELL_SPURS_DYNAMIC_PORT_RANGE_BOTTOM = 63,
};
enum SPURSTraceTypes
{
CELL_SPURS_TRACE_TAG_LOAD = 0x2a,
CELL_SPURS_TRACE_TAG_MAP = 0x2b,
CELL_SPURS_TRACE_TAG_START = 0x2c,
CELL_SPURS_TRACE_TAG_STOP = 0x2d,
CELL_SPURS_TRACE_TAG_USER = 0x2e,
CELL_SPURS_TRACE_TAG_GUID = 0x2f,
};
// SPURS task defines.
enum TaskConstants
{
CELL_SPURS_MAX_TASK = 128,
CELL_SPURS_TASK_TOP = 0x3000,
CELL_SPURS_TASK_BOTTOM = 0x40000,
CELL_SPURS_MAX_TASK_NAME_LENGTH = 32,
};
#include "Emu/SysCalls/Modules/cellSpurs.h"
// Internal class to shape a SPURS attribute.
class SPURSManagerAttribute
{
public:
SPURSManagerAttribute(int nSpus, int spuPriority, int ppuPriority, bool exitIfNoWork)
{
this->nSpus = nSpus;
this->spuThreadGroupPriority = spuPriority;
this->ppuThreadPriority = ppuPriority;
this->exitIfNoWork = exitIfNoWork;
SPURSManagerAttribute(int nSpus, int spuPriority, int ppuPriority, bool exitIfNoWork);
memset(this->namePrefix, 0, CELL_SPURS_NAME_MAX_LENGTH + 1);
this->threadGroupType = 0;
this->container = 0;
}
int _setNamePrefix(const char *name, u32 size);
int _setNamePrefix(const char *name, u32 size)
{
strncpy(this->namePrefix, name, size);
this->namePrefix[0] = 0;
return 0;
}
int _setSpuThreadGroupType(int type);
int _setSpuThreadGroupType(int type)
{
this->threadGroupType = type;
return 0;
}
int _setMemoryContainerForSpuThread(u32 container)
{
this->container = container;
return 0;
}
int _setMemoryContainerForSpuThread(u32 container);
protected:
be_t<int> nSpus;
@ -89,12 +24,55 @@ protected:
be_t<u32> container;
};
class SPURSManagerEventFlag
{
public:
SPURSManagerEventFlag(u32 flagClearMode, u32 flagDirection);
u32 _getDirection() const
{
return this->flagDirection;
}
u32 _getClearMode() const
{
return this->flagClearMode;
}
protected:
be_t<u32> flagClearMode;
be_t<u32> flagDirection;
};
class SPURSManagerTasksetAttribute
{
public:
SPURSManagerTasksetAttribute(u64 args, vm::ptr<const u8> priority, u32 maxContention);
protected:
be_t<u64> args;
be_t<u32> maxContention;
};
class SPURSManagerTaskset
{
public:
SPURSManagerTaskset(u32 address, SPURSManagerTasksetAttribute *tattr);
protected:
u32 address;
SPURSManagerTasksetAttribute *tattr;
};
// Main SPURS manager class.
class SPURSManager
{
public:
SPURSManager(SPURSManagerAttribute *attr);
void Finalize();
void AttachLv2EventQueue(u32 queue, vm::ptr<u8> port, int isDynamic);
void DetachLv2EventQueue(u8 port);
protected:
SPURSManagerAttribute *attr;

View file

@ -1,8 +1,4 @@
#pragma once
#include "Emu/Cell/SPUOpcodes.h"
#include "Emu/Memory/Memory.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/SysCalls/SysCalls.h"
#define ASMJIT_STATIC
@ -89,6 +85,9 @@ public:
u16 count; // count of instructions compiled from current point (and to be checked)
u32 valid; // copy of valid opcode for validation
void* pointer; // pointer to executable memory object
#ifdef _WIN32
//_IMAGE_RUNTIME_FUNCTION_ENTRY info;
#endif
};
SPURecEntry entry[0x10000];
@ -109,14 +108,14 @@ public:
#define c (*compiler)
#ifdef _WIN32
#define cpu_xmm(x) oword_ptr(*cpu_var, (sizeof((*(SPUThread*)nullptr).x) == 16) ? offsetof(SPUThread, x) : throw "sizeof("#x") != 16")
#define cpu_qword(x) qword_ptr(*cpu_var, (sizeof((*(SPUThread*)nullptr).x) == 8) ? offsetof(SPUThread, x) : throw "sizeof("#x") != 8")
#define cpu_dword(x) dword_ptr(*cpu_var, (sizeof((*(SPUThread*)nullptr).x) == 4) ? offsetof(SPUThread, x) : throw "sizeof("#x") != 4")
#define cpu_word(x) word_ptr(*cpu_var, (sizeof((*(SPUThread*)nullptr).x) == 2) ? offsetof(SPUThread, x) : throw "sizeof("#x") != 2")
#define cpu_byte(x) byte_ptr(*cpu_var, (sizeof((*(SPUThread*)nullptr).x) == 1) ? offsetof(SPUThread, x) : throw "sizeof("#x") != 1")
#define cpu_xmm(x) oword_ptr(*cpu_var, (sizeof((*(SPUThread*)nullptr).x) == 16) ? (s32)offsetof(SPUThread, x) : throw "sizeof("#x") != 16")
#define cpu_qword(x) qword_ptr(*cpu_var, (sizeof((*(SPUThread*)nullptr).x) == 8) ? (s32)offsetof(SPUThread, x) : throw "sizeof("#x") != 8")
#define cpu_dword(x) dword_ptr(*cpu_var, (sizeof((*(SPUThread*)nullptr).x) == 4) ? (s32)offsetof(SPUThread, x) : throw "sizeof("#x") != 4")
#define cpu_word(x) word_ptr(*cpu_var, (sizeof((*(SPUThread*)nullptr).x) == 2) ? (s32)offsetof(SPUThread, x) : throw "sizeof("#x") != 2")
#define cpu_byte(x) byte_ptr(*cpu_var, (sizeof((*(SPUThread*)nullptr).x) == 1) ? (s32)offsetof(SPUThread, x) : throw "sizeof("#x") != 1")
#define g_imm_xmm(x) oword_ptr(*g_imm_var, offsetof(g_imm_table_struct, x))
#define g_imm2_xmm(x, y) oword_ptr(*g_imm_var, y, 0, offsetof(g_imm_table_struct, x))
#define g_imm_xmm(x) oword_ptr(*g_imm_var, (s32)offsetof(g_imm_table_struct, x))
#define g_imm2_xmm(x, y) oword_ptr(*g_imm_var, y, 0, (s32)offsetof(g_imm_table_struct, x))
#else
#define cpu_xmm(x) oword_ptr(*cpu_var, reinterpret_cast<uintptr_t>(&(((SPUThread*)0)->x)) )
#define cpu_qword(x) qword_ptr(*cpu_var, reinterpret_cast<uintptr_t>(&(((SPUThread*)0)->x)) )
@ -148,7 +147,7 @@ public:
if (#a1[0] == 'r') XmmInvalidate(a1); \
if (#a2[0] == 'r') XmmInvalidate(a2); \
if (#a3[0] == 'r') XmmInvalidate(a3); \
X86X64CallNode* call##a0 = c.call(imm_ptr(reinterpret_cast<void*>(&opwr_##a0::opcode)), kFuncConvHost, FuncBuilder4<FnVoid, u32, u32, u32, u32>()); \
X86CallNode* call##a0 = c.call(imm_ptr(reinterpret_cast<void*>(&opwr_##a0::opcode)), kFuncConvHost, FuncBuilder4<void, u32, u32, u32, u32>()); \
call##a0->setArg(0, imm_u(a0)); \
call##a0->setArg(1, imm_u(a1)); \
call##a0->setArg(2, imm_u(a2)); \
@ -163,24 +162,24 @@ private:
SPURecompilerCore& rec;
public:
Compiler* compiler;
X86Compiler* compiler;
bool do_finalize;
// input:
GpVar* cpu_var;
GpVar* ls_var;
GpVar* imm_var;
GpVar* g_imm_var;
X86GpVar* cpu_var;
X86GpVar* ls_var;
X86GpVar* imm_var;
X86GpVar* g_imm_var;
// output:
GpVar* pos_var;
X86GpVar* pos_var;
// temporary:
GpVar* addr;
GpVar* qw0;
GpVar* qw1;
GpVar* qw2;
X86GpVar* addr;
X86GpVar* qw0;
X86GpVar* qw1;
X86GpVar* qw2;
struct XmmLink
{
XmmVar* data;
X86XmmVar* data;
s8 reg;
bool taken;
mutable bool got;
@ -419,9 +418,9 @@ public:
return oword_ptr(*imm_var, i * sizeof(__m128i));
}
}
const int shift = rec.imm_table.size() * sizeof(__m128i);
const size_t shift = rec.imm_table.size() * sizeof(__m128i);
rec.imm_table.push_back(data);
return oword_ptr(*imm_var, shift);
return oword_ptr(*imm_var, (s32)shift);
}
Mem XmmConst(const __m128& data)
@ -438,12 +437,12 @@ private:
static void STOP(u32 code)
{
SPUThread& CPU = *(SPUThread*)GetCurrentCPUThread();
CPU.DoStop(code);
CPU.StopAndSignal(code);
LOG2_OPCODE();
}
};
c.mov(cpu_qword(PC), (u32)CPU.PC);
X86X64CallNode* call = c.call(imm_ptr(reinterpret_cast<void*>(&STOP_wrapper::STOP)), kFuncConvHost, FuncBuilder1<FnVoid, u32>());
X86CallNode* call = c.call(imm_ptr(reinterpret_cast<void*>(&STOP_wrapper::STOP)), kFuncConvHost, FuncBuilder1<void, u32>());
call->setArg(0, imm_u(code));
c.mov(*pos_var, (CPU.PC >> 2) + 1);
do_finalize = true;
@ -471,17 +470,6 @@ private:
void MFSPR(u32 rt, u32 sa)
{
UNIMPLEMENTED();
//If register is a dummy register (register labeled 0x0)
if(sa == 0x0)
{
CPU.GPR[rt]._u128.hi = 0x0;
CPU.GPR[rt]._u128.lo = 0x0;
}
else
{
CPU.GPR[rt]._u128.hi = CPU.SPR[sa]._u128.hi;
CPU.GPR[rt]._u128.lo = CPU.SPR[sa]._u128.lo;
}
}
void RDCH(u32 rt, u32 ra)
{
@ -495,7 +483,7 @@ private:
{
c.mov(cpu_qword(PC), (u32)CPU.PC);
WRAPPER_BEGIN(rt, ra, yy, zz);
CPU.GPR[rt].Reset();
CPU.GPR[rt].clear();
CPU.GPR[rt]._u32[3] = CPU.GetChannelCount(ra);
WRAPPER_END(rt, ra, 0, 0);
// TODO
@ -1098,11 +1086,6 @@ private:
void MTSPR(u32 rt, u32 sa)
{
UNIMPLEMENTED();
if(sa != 0)
{
CPU.SPR[sa]._u128.hi = CPU.GPR[rt]._u128.hi;
CPU.SPR[sa]._u128.lo = CPU.GPR[rt]._u128.lo;
}
}
void WRCH(u32 ra, u32 rt)
{
@ -1114,7 +1097,7 @@ private:
/*XmmInvalidate(rt);
GpVar v(c, kVarTypeUInt32);
X86GpVar v(c, kVarTypeUInt32);
c.mov(v, cpu_dword(GPR[rt]._u32[3]));
switch (ra)
{
@ -1146,8 +1129,14 @@ private:
}
}*/
}
void BIZ(u32 rt, u32 ra)
void BIZ(u32 intr, u32 rt, u32 ra)
{
if (intr)
{
UNIMPLEMENTED();
return;
}
c.mov(cpu_qword(PC), (u32)CPU.PC);
do_finalize = true;
@ -1158,8 +1147,14 @@ private:
c.shr(*pos_var, 2);
LOG_OPCODE();
}
void BINZ(u32 rt, u32 ra)
void BINZ(u32 intr, u32 rt, u32 ra)
{
if (intr)
{
UNIMPLEMENTED();
return;
}
c.mov(cpu_qword(PC), (u32)CPU.PC);
do_finalize = true;
@ -1170,8 +1165,14 @@ private:
c.shr(*pos_var, 2);
LOG_OPCODE();
}
void BIHZ(u32 rt, u32 ra)
void BIHZ(u32 intr, u32 rt, u32 ra)
{
if (intr)
{
UNIMPLEMENTED();
return;
}
c.mov(cpu_qword(PC), (u32)CPU.PC);
do_finalize = true;
@ -1182,8 +1183,14 @@ private:
c.shr(*pos_var, 2);
LOG_OPCODE();
}
void BIHNZ(u32 rt, u32 ra)
void BIHNZ(u32 intr, u32 rt, u32 ra)
{
if (intr)
{
UNIMPLEMENTED();
return;
}
c.mov(cpu_qword(PC), (u32)CPU.PC);
do_finalize = true;
@ -1197,7 +1204,6 @@ private:
void STOPD(u32 rc, u32 ra, u32 rb)
{
UNIMPLEMENTED();
Emu.Pause();
}
void STQX(u32 rt, u32 ra, u32 rb)
{
@ -1211,16 +1217,29 @@ private:
c.add(*addr, cpu_dword(GPR[rb]._u32[3]));
}
c.and_(*addr, 0x3fff0);
/*const XmmLink& vt = XmmGet(rt);
c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)));
c.movdqa(oword_ptr(*ls_var, *addr), vt.get());
XmmFinalize(vt);*/
c.mov(*qw0, cpu_qword(GPR[rt]._u64[0]));
c.mov(*qw1, cpu_qword(GPR[rt]._u64[1]));
c.bswap(*qw0);
c.bswap(*qw1);
c.mov(qword_ptr(*ls_var, *addr, 0, 0), *qw1);
c.mov(qword_ptr(*ls_var, *addr, 0, 8), *qw0);
LOG_OPCODE();
}
void BI(u32 ra)
void BI(u32 intr, u32 ra)
{
if (intr)
{
UNIMPLEMENTED();
return;
}
c.mov(cpu_qword(PC), (u32)CPU.PC);
do_finalize = true;
@ -1228,8 +1247,14 @@ private:
c.shr(*pos_var, 2);
LOG_OPCODE();
}
void BISL(u32 rt, u32 ra)
void BISL(u32 intr, u32 rt, u32 ra)
{
if (intr)
{
UNIMPLEMENTED();
return;
}
XmmInvalidate(rt);
c.mov(cpu_qword(PC), (u32)CPU.PC);
@ -1247,9 +1272,8 @@ private:
void IRET(u32 ra)
{
UNIMPLEMENTED();
//SetBranch(SRR0);
}
void BISLED(u32 rt, u32 ra)
void BISLED(u32 intr, u32 rt, u32 ra)
{
UNIMPLEMENTED();
}
@ -1350,12 +1374,19 @@ private:
c.add(*addr, cpu_dword(GPR[rb]._u32[3]));
}
c.and_(*addr, 0x3fff0);
/*const XmmLink& vt = XmmAlloc(rt);
c.movdqa(vt.get(), oword_ptr(*ls_var, *addr));
c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)));
XmmFinalize(vt, rt);*/
c.mov(*qw0, qword_ptr(*ls_var, *addr, 0, 0));
c.mov(*qw1, qword_ptr(*ls_var, *addr, 0, 8));
c.bswap(*qw0);
c.bswap(*qw1);
c.mov(cpu_qword(GPR[rt]._u64[0]), *qw1);
c.mov(cpu_qword(GPR[rt]._u64[1]), *qw0);
LOG_OPCODE();
}
void ROTQBYBI(u32 rt, u32 ra, u32 rb)
@ -1408,7 +1439,7 @@ private:
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(byte_ptr(*cpu_var, *addr, 0, offsetof(SPUThread, GPR[rt]._u8[0])), 0x03);
c.mov(byte_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u8[0])), 0x03);
LOG_OPCODE();
}
void CHX(u32 rt, u32 ra, u32 rb)
@ -1429,7 +1460,7 @@ private:
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(word_ptr(*cpu_var, *addr, 0, offsetof(SPUThread, GPR[rt]._u16[0])), 0x0203);
c.mov(word_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u16[0])), 0x0203);
LOG_OPCODE();
}
void CWX(u32 rt, u32 ra, u32 rb)
@ -1450,7 +1481,7 @@ private:
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(dword_ptr(*cpu_var, *addr, 0, offsetof(SPUThread, GPR[rt]._u32[0])), 0x00010203);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x00010203);
LOG_OPCODE();
}
void CDX(u32 rt, u32 ra, u32 rb)
@ -1471,8 +1502,8 @@ private:
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(dword_ptr(*cpu_var, *addr, 0, offsetof(SPUThread, GPR[rt]._u32[0])), 0x00010203);
c.mov(dword_ptr(*cpu_var, *addr, 0, offsetof(SPUThread, GPR[rt]._u32[1])), 0x04050607);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x04050607);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[1])), 0x00010203);
LOG_OPCODE();
}
void ROTQBI(u32 rt, u32 ra, u32 rb)
@ -1572,7 +1603,7 @@ private:
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(byte_ptr(*cpu_var, *addr, 0, offsetof(SPUThread, GPR[rt]._u8[0])), 0x03);
c.mov(byte_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u8[0])), 0x03);
LOG_OPCODE();
}
void CHD(u32 rt, u32 ra, s32 i7)
@ -1586,7 +1617,7 @@ private:
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(word_ptr(*cpu_var, *addr, 0, offsetof(SPUThread, GPR[rt]._u16[0])), 0x0203);
c.mov(word_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u16[0])), 0x0203);
LOG_OPCODE();
}
void CWD(u32 rt, u32 ra, s32 i7)
@ -1600,7 +1631,7 @@ private:
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(dword_ptr(*cpu_var, *addr, 0, offsetof(SPUThread, GPR[rt]._u32[0])), 0x00010203);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x00010203);
LOG_OPCODE();
}
void CDD(u32 rt, u32 ra, s32 i7)
@ -1614,8 +1645,8 @@ private:
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(dword_ptr(*cpu_var, *addr, 0, offsetof(SPUThread, GPR[rt]._u32[0])), 0x00010203);
c.mov(dword_ptr(*cpu_var, *addr, 0, offsetof(SPUThread, GPR[rt]._u32[1])), 0x04050607);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x04050607);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[1])), 0x00010203);
LOG_OPCODE();
}
void ROTQBII(u32 rt, u32 ra, s32 i7)
@ -1914,10 +1945,10 @@ private:
//HGT uses signed values. HLGT uses unsigned values
void HGT(u32 rt, s32 ra, s32 rb)
{
c.mov(*addr, cpu_dword(GPR[ra]._i32[3]));
c.cmp(*addr, cpu_dword(GPR[rb]._i32[3]));
c.mov(*addr, cpu_dword(GPR[ra]._s32[3]));
c.cmp(*addr, cpu_dword(GPR[rb]._s32[3]));
c.mov(*addr, 0);
c.setg(*addr);
c.setg(addr->r8());
c.neg(*addr);
c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr);
@ -1930,7 +1961,7 @@ private:
for (u32 i = 0; i < 4; i++)
{
c.bsr(*addr, cpu_dword(GPR[ra]._u32[i]));
c.cmovz(*addr, dword_ptr(*g_imm_var, offsetof(g_imm_table_struct, fsmb_table[0xffff]))); // load 0xffffffff
c.cmovz(*addr, dword_ptr(*g_imm_var, (s32)offsetof(g_imm_table_struct, fsmb_table[0xffff]))); // load 0xffffffff
c.neg(*addr);
c.add(*addr, 31);
c.mov(cpu_dword(GPR[rt]._u32[i]), *addr);
@ -1939,10 +1970,10 @@ private:
}
void XSWD(u32 rt, u32 ra)
{
c.movsxd(*qw0, cpu_dword(GPR[ra]._i32[0]));
c.movsxd(*qw1, cpu_dword(GPR[ra]._i32[2]));
c.mov(cpu_qword(GPR[rt]._i64[0]), *qw0);
c.mov(cpu_qword(GPR[rt]._i64[1]), *qw1);
c.movsxd(*qw0, cpu_dword(GPR[ra]._s32[0]));
c.movsxd(*qw1, cpu_dword(GPR[ra]._s32[2]));
c.mov(cpu_qword(GPR[rt]._s64[0]), *qw0);
c.mov(cpu_qword(GPR[rt]._s64[1]), *qw1);
XmmInvalidate(rt);
LOG_OPCODE();
}
@ -1960,7 +1991,7 @@ private:
for (u32 i = 0; i < 8; i++)
{
c.movzx(*addr, cpu_word(GPR[ra]._u16[i]));
c.movzx(*addr, word_ptr(*g_imm_var, *addr, 1, offsetof(g_imm_table_struct, cntb_table[0])));
c.movzx(*addr, word_ptr(*g_imm_var, *addr, 1, (s32)offsetof(g_imm_table_struct, cntb_table[0])));
c.mov(cpu_word(GPR[rt]._u16[i]), addr->r16());
}*/
const XmmLink& va = XmmGet(ra, rt);
@ -2051,18 +2082,7 @@ private:
}
void DFCGT(u32 rt, u32 ra, u32 rb)
{
// reverted less-than
const XmmLink& vb = XmmGet(rb, rt);
if (const XmmLink* va = XmmRead(ra))
{
c.cmppd(vb.get(), va->read(), 1);
}
else
{
c.cmppd(vb.get(), cpu_xmm(GPR[ra]), 1);
}
XmmFinalize(vb, rt);
LOG_OPCODE();
UNIMPLEMENTED();
}
void FA(u32 rt, u32 ra, u32 rb)
{
@ -2192,15 +2212,7 @@ private:
}
void DFCMGT(u32 rt, u32 ra, u32 rb)
{
// reverted less-than
const XmmLink& vb = XmmGet(rb, rt);
const XmmLink& va = XmmGet(ra);
c.andpd(vb.get(), XmmConst(_mm_set_epi32(0x7fffffff, 0xffffffff, 0x7fffffff, 0xffffffff))); // abs
c.andpd(va.get(), XmmConst(_mm_set_epi32(0x7fffffff, 0xffffffff, 0x7fffffff, 0xffffffff))); // abs
c.cmppd(vb.get(), va.get(), 1);
XmmFinalize(vb, rt);
XmmFinalize(va);
LOG_OPCODE();
UNIMPLEMENTED();
}
void DFA(u32 rt, u32 ra, u32 rb)
{
@ -2297,7 +2309,7 @@ private:
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.cmp(*addr, cpu_dword(GPR[rb]._u32[3]));
c.mov(*addr, 0);
c.seta(*addr);
c.seta(addr->r8());
c.neg(*addr);
c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr);
@ -2462,7 +2474,11 @@ private:
}
void FSCRRD(u32 rt)
{
UNIMPLEMENTED();
// zero (hack)
const XmmLink& v0 = XmmAlloc(rt);
c.pxor(v0.get(), v0.get());
XmmFinalize(v0, rt);
LOG_OPCODE();
}
void FESD(u32 rt, u32 ra)
{
@ -2482,62 +2498,12 @@ private:
}
void FSCRWR(u32 rt, u32 ra)
{
UNIMPLEMENTED();
// nop (not implemented)
LOG_OPCODE();
}
void DFTSV(u32 rt, u32 ra, s32 i7) //nf
void DFTSV(u32 rt, u32 ra, s32 i7)
{
WRAPPER_BEGIN(rt, ra, i7, zz);
const u64 DoubleExpMask = 0x7ff0000000000000;
const u64 DoubleFracMask = 0x000fffffffffffff;
const u64 DoubleSignMask = 0x8000000000000000;
const SPU_GPR_hdr temp = CPU.GPR[ra];
CPU.GPR[rt].Reset();
if (i7 & 1) //Negative Denorm Check (-, exp is zero, frac is non-zero)
for (int i = 0; i < 2; i++)
{
if (temp._u64[i] & DoubleFracMask)
if ((temp._u64[i] & (DoubleSignMask | DoubleExpMask)) == DoubleSignMask)
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
}
if (i7 & 2) //Positive Denorm Check (+, exp is zero, frac is non-zero)
for (int i = 0; i < 2; i++)
{
if (temp._u64[i] & DoubleFracMask)
if ((temp._u64[i] & (DoubleSignMask | DoubleExpMask)) == 0)
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
}
if (i7 & 4) //Negative Zero Check (-, exp is zero, frac is zero)
for (int i = 0; i < 2; i++)
{
if (temp._u64[i] == DoubleSignMask)
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
}
if (i7 & 8) //Positive Zero Check (+, exp is zero, frac is zero)
for (int i = 0; i < 2; i++)
{
if (temp._u64[i] == 0)
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
}
if (i7 & 16) //Negative Infinity Check (-, exp is 0x7ff, frac is zero)
for (int i = 0; i < 2; i++)
{
if (temp._u64[i] == (DoubleSignMask | DoubleExpMask))
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
}
if (i7 & 32) //Positive Infinity Check (+, exp is 0x7ff, frac is zero)
for (int i = 0; i < 2; i++)
{
if (temp._u64[i] == DoubleExpMask)
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
}
if (i7 & 64) //Not-a-Number Check (any sign, exp is 0x7ff, frac is non-zero)
for (int i = 0; i < 2; i++)
{
if (temp._u64[i] & DoubleFracMask)
if ((temp._u64[i] & DoubleExpMask) == DoubleExpMask)
CPU.GPR[rt]._u64[i] = 0xffffffffffffffff;
}
WRAPPER_END(rt, ra, i7, 0);
UNIMPLEMENTED();
}
void FCEQ(u32 rt, u32 ra, u32 rb)
{
@ -2556,18 +2522,7 @@ private:
}
void DFCEQ(u32 rt, u32 ra, u32 rb)
{
// compare equal
const XmmLink& vb = XmmGet(rb, rt);
if (const XmmLink* va = XmmRead(ra))
{
c.cmppd(vb.get(), va->read(), 0);
}
else
{
c.cmppd(vb.get(), cpu_xmm(GPR[ra]), 0);
}
XmmFinalize(vb, rt);
LOG_OPCODE();
UNIMPLEMENTED();
}
void MPY(u32 rt, u32 ra, u32 rb)
{
@ -2651,14 +2606,7 @@ private:
}
void DFCMEQ(u32 rt, u32 ra, u32 rb)
{
const XmmLink& vb = XmmGet(rb, rt);
const XmmLink& va = XmmGet(ra);
c.andpd(vb.get(), XmmConst(_mm_set_epi32(0x7fffffff, 0xffffffff, 0x7fffffff, 0xffffffff))); // abs
c.andpd(va.get(), XmmConst(_mm_set_epi32(0x7fffffff, 0xffffffff, 0x7fffffff, 0xffffffff))); // abs
c.cmppd(vb.get(), va.get(), 0); // ==
XmmFinalize(vb, rt);
XmmFinalize(va);
LOG_OPCODE();
UNIMPLEMENTED();
}
void MPYU(u32 rt, u32 ra, u32 rb)
{
@ -2712,10 +2660,10 @@ private:
}
void HEQ(u32 rt, u32 ra, u32 rb)
{
c.mov(*addr, cpu_dword(GPR[ra]._i32[3]));
c.cmp(*addr, cpu_dword(GPR[rb]._i32[3]));
c.mov(*addr, cpu_dword(GPR[ra]._s32[3]));
c.cmp(*addr, cpu_dword(GPR[rb]._s32[3]));
c.mov(*addr, 0);
c.sete(*addr);
c.sete(addr->r8());
c.neg(*addr);
c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr);
@ -2729,9 +2677,9 @@ private:
const XmmLink& va = XmmGet(ra, rt);
if (i8 != 173)
{
c.mulps(va.get(), XmmConst(_mm_set1_ps(pow(2, 173 - (i8 & 0xff))))); // scale
c.mulps(va.get(), XmmConst(_mm_set1_ps((float)pow(2, 173 - (i8 & 0xff))))); // scale
}
c.maxps(va.get(), XmmConst(_mm_set1_ps(-pow(2, 31)))); // saturate
c.maxps(va.get(), XmmConst(_mm_set1_ps((float)-pow(2, 31)))); // saturate
c.minps(va.get(), XmmConst(_mm_set1_ps((float)0x7fffffff)));
c.cvttps2dq(va.get(), va.get()); // convert to ints with truncation
XmmFinalize(va, rt);
@ -2742,13 +2690,13 @@ private:
const XmmLink& va = XmmGet(ra, rt);
if (i8 != 173)
{
c.mulps(va.get(), XmmConst(_mm_set1_ps(pow(2, 173 - (i8 & 0xff))))); // scale
c.mulps(va.get(), XmmConst(_mm_set1_ps((float)pow(2, 173 - (i8 & 0xff))))); // scale
}
c.maxps(va.get(), XmmConst(_mm_set1_ps(0.0f))); // saturate
c.minps(va.get(), XmmConst(_mm_set1_ps((float)0xffffffff)));
const XmmLink& v1 = XmmCopy(va);
c.cmpps(v1.get(), XmmConst(_mm_set1_ps(pow(2, 31))), 5); // generate mask of big values
c.andps(v1.get(), XmmConst(_mm_set1_ps(pow(2, 32)))); // generate correction component
c.cmpps(v1.get(), XmmConst(_mm_set1_ps((float)pow(2, 31))), 5); // generate mask of big values
c.andps(v1.get(), XmmConst(_mm_set1_ps((float)pow(2, 32)))); // generate correction component
c.subps(va.get(), v1.get()); // subtract correction component
c.cvttps2dq(va.get(), va.get()); // convert to ints with truncation
XmmFinalize(va, rt);
@ -2761,7 +2709,7 @@ private:
c.cvtdq2ps(va.get(), va.get()); // convert to floats
if (i8 != 155)
{
c.mulps(va.get(), XmmConst(_mm_set1_ps(pow(2, (i8 & 0xff) - 155)))); // scale
c.mulps(va.get(), XmmConst(_mm_set1_ps((float)pow(2, (i8 & 0xff) - 155)))); // scale
}
XmmFinalize(va, rt);
LOG_OPCODE();
@ -2772,11 +2720,11 @@ private:
const XmmLink& v1 = XmmCopy(va);
c.cvtdq2ps(va.get(), va.get()); // convert to floats
c.psrad(v1.get(), 32); // generate mask from sign bit
c.andps(v1.get(), XmmConst(_mm_set1_ps(pow(2, 32)))); // generate correction component
c.andps(v1.get(), XmmConst(_mm_set1_ps((float)pow(2, 32)))); // generate correction component
c.addps(va.get(), v1.get()); // add correction component
if (i8 != 155)
{
c.mulps(va.get(), XmmConst(_mm_set1_ps(pow(2, (i8 & 0xff) - 155)))); // scale
c.mulps(va.get(), XmmConst(_mm_set1_ps((float)pow(2, (i8 & 0xff) - 155)))); // scale
}
XmmFinalize(va, rt);
XmmFinalize(v1);
@ -2798,12 +2746,19 @@ private:
void STQA(u32 rt, s32 i16)
{
const u32 lsa = (i16 << 2) & 0x3fff0;
/*const XmmLink& vt = XmmGet(rt);
c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)));
c.movdqa(oword_ptr(*ls_var, lsa), vt.get());
XmmFinalize(vt);*/
c.mov(*qw0, cpu_qword(GPR[rt]._u64[0]));
c.mov(*qw1, cpu_qword(GPR[rt]._u64[1]));
c.bswap(*qw0);
c.bswap(*qw1);
c.mov(qword_ptr(*ls_var, lsa), *qw1);
c.mov(qword_ptr(*ls_var, lsa + 8), *qw0);
LOG_OPCODE();
}
void BRNZ(u32 rt, s32 i16)
@ -2842,12 +2797,19 @@ private:
void STQR(u32 rt, s32 i16)
{
const u32 lsa = branchTarget(CPU.PC, i16) & 0x3fff0;
/*const XmmLink& vt = XmmGet(rt);
c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)));
c.movdqa(oword_ptr(*ls_var, lsa), vt.get());
XmmFinalize(vt);*/
c.mov(*qw0, cpu_qword(GPR[rt]._u64[0]));
c.mov(*qw1, cpu_qword(GPR[rt]._u64[1]));
c.bswap(*qw0);
c.bswap(*qw1);
c.mov(qword_ptr(*ls_var, lsa), *qw1);
c.mov(qword_ptr(*ls_var, lsa + 8), *qw0);
LOG_OPCODE();
}
void BRA(s32 i16)
@ -2863,12 +2825,19 @@ private:
XmmInvalidate(rt);
const u32 lsa = (i16 << 2) & 0x3fff0;
/*const XmmLink& vt = XmmAlloc(rt);
c.movdqa(vt.get(), oword_ptr(*ls_var, lsa));
c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)));
XmmFinalize(vt, rt);*/
c.mov(*qw0, qword_ptr(*ls_var, lsa));
c.mov(*qw1, qword_ptr(*ls_var, lsa + 8));
c.bswap(*qw0);
c.bswap(*qw1);
c.mov(cpu_qword(GPR[rt]._u64[0]), *qw1);
c.mov(cpu_qword(GPR[rt]._u64[1]), *qw0);
LOG_OPCODE();
}
void BRASL(u32 rt, s32 i16)
@ -2931,12 +2900,19 @@ private:
XmmInvalidate(rt);
const u32 lsa = branchTarget(CPU.PC, i16) & 0x3fff0;
/*const XmmLink& vt = XmmAlloc(rt);
c.movdqa(vt.get(), oword_ptr(*ls_var, lsa));
c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)));
XmmFinalize(vt, rt);*/
c.mov(*qw0, qword_ptr(*ls_var, lsa));
c.mov(*qw1, qword_ptr(*ls_var, lsa + 8));
c.bswap(*qw0);
c.bswap(*qw1);
c.mov(cpu_qword(GPR[rt]._u64[0]), *qw1);
c.mov(cpu_qword(GPR[rt]._u64[1]), *qw0);
LOG_OPCODE();
}
void IL(u32 rt, s32 i16)
@ -3265,12 +3241,19 @@ private:
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
if (i10) c.add(*addr, i10);
c.and_(*addr, 0x3fff0);
/*const XmmLink& vt = XmmGet(rt);
c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)));
c.movdqa(oword_ptr(*ls_var, *addr), vt.get());
XmmFinalize(vt);*/
c.mov(*qw0, cpu_qword(GPR[rt]._u64[0]));
c.mov(*qw1, cpu_qword(GPR[rt]._u64[1]));
c.bswap(*qw0);
c.bswap(*qw1);
c.mov(qword_ptr(*ls_var, *addr, 0, 0), *qw1);
c.mov(qword_ptr(*ls_var, *addr, 0, 8), *qw0);
LOG_OPCODE();
}
void LQD(u32 rt, s32 i10, u32 ra) // i10 is shifted left by 4 while decoding
@ -3280,12 +3263,19 @@ private:
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
if (i10) c.add(*addr, i10);
c.and_(*addr, 0x3fff0);
/*const XmmLink& vt = XmmAlloc(rt);
c.movdqa(vt.get(), oword_ptr(*ls_var, *addr));
c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)));
XmmFinalize(vt, rt);*/
c.mov(*qw0, qword_ptr(*ls_var, *addr, 0, 0));
c.mov(*qw1, qword_ptr(*ls_var, *addr, 0, 8));
c.bswap(*qw0);
c.bswap(*qw1);
c.mov(cpu_qword(GPR[rt]._u64[0]), *qw1);
c.mov(cpu_qword(GPR[rt]._u64[1]), *qw0);
LOG_OPCODE();
}
void XORI(u32 rt, u32 ra, s32 i10)
@ -3332,10 +3322,10 @@ private:
}
void HGTI(u32 rt, u32 ra, s32 i10)
{
c.mov(*addr, cpu_dword(GPR[ra]._i32[3]));
c.mov(*addr, cpu_dword(GPR[ra]._s32[3]));
c.cmp(*addr, i10);
c.mov(*addr, 0);
c.setg(*addr);
c.setg(addr->r8());
c.neg(*addr);
c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr);
@ -3401,7 +3391,7 @@ private:
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.cmp(*addr, i10);
c.mov(*addr, 0);
c.seta(*addr);
c.seta(addr->r8());
c.neg(*addr);
c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr);
@ -3452,7 +3442,7 @@ private:
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.cmp(*addr, i10);
c.mov(*addr, 0);
c.sete(*addr);
c.sete(addr->r8());
c.neg(*addr);
c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr);
@ -3784,12 +3774,12 @@ private:
void UNK(u32 code, u32 opcode, u32 gcode)
{
UNK(fmt::Format("(SPURecompiler) Unimplemented opcode! (0x%08x, 0x%x, 0x%x)", code, opcode, gcode));
UNK(fmt::Format("Unimplemented opcode! (0x%08x, 0x%x, 0x%x)", code, opcode, gcode));
}
void UNK(const std::string& err)
{
ConLog.Error(err + fmt::Format(" #pc: 0x%x", CPU.PC));
LOG_ERROR(Log::SPU, err + fmt::Format(" #pc: 0x%x", CPU.PC));
c.mov(cpu_qword(PC), (u32)CPU.PC);
do_finalize = true;
Emu.Pause();

View file

@ -1,18 +1,34 @@
#include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Utilities/rFile.h"
#include "Emu/SysCalls/lv2/sys_time.h"
#include "SPUInstrTable.h"
#include "SPUDisAsm.h"
#include "SPUThread.h"
#include "SPUInterpreter.h"
#include "SPURecompiler.h"
static const g_imm_table_struct g_imm_table;
SPURecompilerCore::SPURecompilerCore(SPUThread& cpu)
: m_enc(new SPURecompiler(cpu, *this))
, inter(new SPUInterpreter(cpu))
, CPU(cpu)
, first(true)
: m_enc(new SPURecompiler(cpu, *this))
, inter(new SPUInterpreter(cpu))
, CPU(cpu)
, first(true)
{
memset(entry, 0, sizeof(entry));
X86CpuInfo inf;
X86CpuUtil::detect(&inf);
if (!inf.hasFeature(kX86CpuFeatureSse41))
{
LOG_ERROR(SPU, "SPU JIT requires SSE4.1 instruction set support");
Emu.Pause();
}
}
SPURecompilerCore::~SPURecompilerCore()
@ -32,11 +48,12 @@ void SPURecompilerCore::Compile(u16 pos)
u64 time0 = 0;
SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode);
dis_asm.offset = vm::get_ptr<u8>(CPU.dmac.ls_offset);
StringLogger stringLogger;
stringLogger.setOption(kLoggerOptionBinaryForm, true);
Compiler compiler(&runtime);
X86Compiler compiler(&runtime);
m_enc->compiler = &compiler;
compiler.setLogger(&stringLogger);
@ -45,53 +62,53 @@ void SPURecompilerCore::Compile(u16 pos)
u32 excess = 0;
entry[start].count = 0;
GpVar cpu_var(compiler, kVarTypeIntPtr, "cpu");
X86GpVar cpu_var(compiler, kVarTypeIntPtr, "cpu");
compiler.setArg(0, cpu_var);
compiler.alloc(cpu_var);
m_enc->cpu_var = &cpu_var;
GpVar ls_var(compiler, kVarTypeIntPtr, "ls");
X86GpVar ls_var(compiler, kVarTypeIntPtr, "ls");
compiler.setArg(1, ls_var);
compiler.alloc(ls_var);
m_enc->ls_var = &ls_var;
GpVar imm_var(compiler, kVarTypeIntPtr, "imm");
X86GpVar imm_var(compiler, kVarTypeIntPtr, "imm");
compiler.setArg(2, imm_var);
compiler.alloc(imm_var);
m_enc->imm_var = &imm_var;
GpVar g_imm_var(compiler, kVarTypeIntPtr, "g_imm");
X86GpVar g_imm_var(compiler, kVarTypeIntPtr, "g_imm");
compiler.setArg(3, g_imm_var);
compiler.alloc(g_imm_var);
m_enc->g_imm_var = &g_imm_var;
GpVar pos_var(compiler, kVarTypeUInt32, "pos");
X86GpVar pos_var(compiler, kVarTypeUInt32, "pos");
m_enc->pos_var = &pos_var;
GpVar addr_var(compiler, kVarTypeUInt32, "addr");
X86GpVar addr_var(compiler, kVarTypeUInt32, "addr");
m_enc->addr = &addr_var;
GpVar qw0_var(compiler, kVarTypeUInt64, "qw0");
X86GpVar qw0_var(compiler, kVarTypeUInt64, "qw0");
m_enc->qw0 = &qw0_var;
GpVar qw1_var(compiler, kVarTypeUInt64, "qw1");
X86GpVar qw1_var(compiler, kVarTypeUInt64, "qw1");
m_enc->qw1 = &qw1_var;
GpVar qw2_var(compiler, kVarTypeUInt64, "qw2");
X86GpVar qw2_var(compiler, kVarTypeUInt64, "qw2");
m_enc->qw2 = &qw2_var;
for (u32 i = 0; i < 16; i++)
{
m_enc->xmm_var[i].data = new XmmVar(compiler, kVarTypeXmm, fmt::Format("reg_%d", i).c_str());
m_enc->xmm_var[i].data = new X86XmmVar(compiler, kX86VarTypeXmm, fmt::Format("reg_%d", i).c_str());
}
compiler.xor_(pos_var, pos_var);
while (true)
{
const u32 opcode = Memory.Read32(CPU.dmac.ls_offset + pos * 4);
const u32 opcode = vm::read32(CPU.dmac.ls_offset + pos * 4);
m_enc->do_finalize = false;
if (opcode)
{
const u64 stamp1 = get_system_time();
// disasm for logging:
dis_asm.dump_pc = CPU.dmac.ls_offset + pos * 4;
dis_asm.dump_pc = pos * 4;
(*SPU_instr::rrr_list)(&dis_asm, opcode);
compiler.addComment(fmt::Format("SPU data: PC=0x%05x %s", pos * 4, dis_asm.last_opcode.c_str()).c_str());
// compile single opcode:
@ -110,11 +127,11 @@ void SPURecompilerCore::Compile(u16 pos)
m_enc->do_finalize = true;
}
bool fin = m_enc->do_finalize;
if (entry[pos].valid == re(opcode))
if (entry[pos].valid == re32(opcode))
{
excess++;
}
entry[pos].valid = re(opcode);
entry[pos].valid = re32(opcode);
if (fin) break;
CPU.PC += 4;
@ -136,12 +153,27 @@ void SPURecompilerCore::Compile(u16 pos)
entry[start].pointer = compiler.make();
compiler.setLogger(nullptr); // crashes without it
wxFile log;
log.Open(wxString::Format("SPUjit_%d.log", GetCurrentSPUThread().GetId()), first ? wxFile::write : wxFile::write_append);
log.Write(wxString::Format("========== START POSITION 0x%x ==========\n\n", start * 4));
log.Write(wxString(stringLogger.getString()));
log.Write(wxString::Format("========== COMPILED %d (excess %d), time: [start=%lld (decoding=%lld), finalize=%lld]\n\n",
entry[start].count, excess, stamp1 - stamp0, time0, get_system_time() - stamp1));
rFile log;
log.Open(fmt::Format("SPUjit_%d.log", GetCurrentSPUThread().GetId()), first ? rFile::write : rFile::write_append);
log.Write(fmt::Format("========== START POSITION 0x%x ==========\n\n", start * 4));
log.Write(std::string(stringLogger.getString()));
if (!entry[start].pointer)
{
LOG_ERROR(Log::SPU, "SPURecompilerCore::Compile(pos=0x%x) failed", start * sizeof(u32));
log.Write("========== FAILED ============\n\n");
Emu.Pause();
}
else
{
log.Write(fmt::Format("========== COMPILED %d (excess %d), time: [start=%lld (decoding=%lld), finalize=%lld]\n\n",
entry[start].count, excess, stamp1 - stamp0, time0, get_system_time() - stamp1));
#ifdef _WIN32
//if (!RtlAddFunctionTable(&info, 1, (u64)entry[start].pointer))
//{
// LOG_ERROR(Log::SPU, "RtlAddFunctionTable() failed");
//}
#endif
}
log.Close();
m_enc->compiler = nullptr;
first = false;
@ -151,37 +183,40 @@ u8 SPURecompilerCore::DecodeMemory(const u64 address)
{
assert(CPU.dmac.ls_offset == address - CPU.PC);
const u64 m_offset = CPU.dmac.ls_offset;
const u16 pos = (CPU.PC >> 2);
const u16 pos = (u16)(CPU.PC >> 2);
//ConLog.Write("DecodeMemory: pos=%d", pos);
u32* ls = (u32*)&Memory[m_offset];
if (!pos)
{
ConLog.Error("SPURecompilerCore::DecodeMemory(): ls_addr = 0");
Emu.Pause();
return 0;
}
u32* ls = vm::get_ptr<u32>(m_offset);
if (entry[pos].pointer)
{
// check data (hard way)
bool is_valid = true;
/*for (u32 i = pos; i < (u32)(entry[pos].count + pos); i++)
{
if (entry[i].valid != ls[i])
{
is_valid = false;
break;
}
}*/
//for (u32 i = pos; i < (u32)(entry[pos].count + pos); i++)
//{
// if (entry[i].valid != ls[i])
// {
// is_valid = false;
// break;
// }
//}
// invalidate if necessary
if (!is_valid)
{
// TODO
ConLog.Error("SPURecompilerCore::DecodeMemory(ls_addr=0x%x): code has changed", pos * sizeof(u32));
Emu.Pause();
return 0;
for (u32 i = 0; i < 0x10000; i++)
{
if (entry[i].pointer &&
i + (u32)entry[i].count > (u32)pos &&
i < (u32)pos + (u32)entry[pos].count)
{
runtime.release(entry[i].pointer);
#ifdef _WIN32
//RtlDeleteFunctionTable(&entry[i].info);
#endif
entry[i].pointer = nullptr;
}
}
//LOG_ERROR(Log::SPU, "SPURecompilerCore::DecodeMemory(ls_addr=0x%x): code has changed", pos * sizeof(u32));
}
}
@ -192,18 +227,13 @@ u8 SPURecompilerCore::DecodeMemory(const u64 address)
did_compile = true;
if (entry[pos].valid == 0)
{
ConLog.Error("SPURecompilerCore::Compile(ls_addr=0x%x): branch to 0x0 opcode", pos * sizeof(u32));
LOG_ERROR(Log::SPU, "SPURecompilerCore::Compile(ls_addr=0x%x): branch to 0x0 opcode", pos * sizeof(u32));
Emu.Pause();
return 0;
}
}
if (!entry[pos].pointer)
{
ConLog.Error("SPURecompilerCore::DecodeMemory(ls_addr=0x%x): compilation failed", pos * sizeof(u32));
Emu.Pause();
return 0;
}
if (!entry[pos].pointer) return 0;
typedef u32(*Func)(const void* _cpu, const void* _ls, const void* _imm, const void* _g_imm);
@ -217,15 +247,16 @@ u8 SPURecompilerCore::DecodeMemory(const u64 address)
//if (pos == 0x19c >> 2)
{
//Emu.Pause();
//for (uint i = 0; i < 128; ++i) ConLog.Write("r%d = 0x%s", i, CPU.GPR[i].ToString().c_str());
//for (uint i = 0; i < 128; ++i) LOG_NOTICE(Log::SPU, "r%d = 0x%s", i, CPU.GPR[i].ToString().c_str());
}
}
u32 res = pos;
res = func(cpu, &Memory[m_offset], imm_table.data(), &g_imm_table);
res = func(cpu, vm::get_ptr<void>(m_offset), imm_table.data(), &g_imm_table);
if (res > 0xffff)
{
CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT);
CPU.Stop();
res = ~res;
}
@ -236,7 +267,7 @@ u8 SPURecompilerCore::DecodeMemory(const u64 address)
//if (pos == 0x340 >> 2)
{
//Emu.Pause();
//for (uint i = 0; i < 128; ++i) ConLog.Write("r%d = 0x%s", i, CPU.GPR[i].ToString().c_str());
//for (uint i = 0; i < 128; ++i) LOG_NOTICE(Log::SPU, "r%d = 0x%s", i, CPU.GPR[i].ToString().c_str());
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

14
rpcs3/Emu/DbgCommand.cpp Normal file
View file

@ -0,0 +1,14 @@
#include "stdafx.h"
#include "DbgCommand.h"
SendDbgCommandCb SendDbgCommandFunc = nullptr;
void SendDbgCommand(DbgCommand id, CPUThread* t)
{
SendDbgCommandFunc(id, t);
}
void SetSendDbgCommandCallback(SendDbgCommandCb cb)
{
SendDbgCommandFunc = cb;
}

44
rpcs3/Emu/DbgCommand.h Normal file
View file

@ -0,0 +1,44 @@
#pragma once
class CPUThread;
enum DbgCommand
{
DID_FIRST_COMMAND = 0x500,
DID_START_EMU,
DID_STARTED_EMU,
DID_STOP_EMU,
DID_STOPPED_EMU,
DID_PAUSE_EMU,
DID_PAUSED_EMU,
DID_RESUME_EMU,
DID_RESUMED_EMU,
DID_READY_EMU,
DID_CREATE_THREAD,
DID_CREATED_THREAD,
DID_REMOVE_THREAD,
DID_REMOVED_THREAD,
DID_RENAME_THREAD,
DID_RENAMED_THREAD,
DID_START_THREAD,
DID_STARTED_THREAD,
DID_STOP_THREAD,
DID_STOPED_THREAD,
DID_PAUSE_THREAD,
DID_PAUSED_THREAD,
DID_RESUME_THREAD,
DID_RESUMED_THREAD,
DID_EXEC_THREAD,
DID_REGISTRED_CALLBACK,
DID_UNREGISTRED_CALLBACK,
DID_EXIT_THR_SYSCALL,
DID_LAST_COMMAND,
};
typedef void(*SendDbgCommandCb)(DbgCommand id, CPUThread* t);
void SetSendDbgCommandCallback(SendDbgCommandCb value);
void SendDbgCommand(DbgCommand id, CPUThread* thr = nullptr);

View file

@ -1,94 +0,0 @@
#include "stdafx.h"
#include "DbgConsole.h"
BEGIN_EVENT_TABLE(DbgConsole, FrameBase)
EVT_CLOSE(DbgConsole::OnQuit)
END_EVENT_TABLE()
DbgConsole::DbgConsole()
: FrameBase(nullptr, wxID_ANY, "Debug Console", "", wxDefaultSize, wxDefaultPosition, wxDEFAULT_FRAME_STYLE, true)
, ThreadBase("DbgConsole thread")
, m_output(nullptr)
{
m_console = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
wxSize(500, 500), wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2);
m_console->SetBackgroundColour(wxColor("Black"));
m_console->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
m_color_white = new wxTextAttr(wxColour(255, 255, 255));
m_color_red = new wxTextAttr(wxColour(255, 0, 0));
if (Ini.HLESaveTTY.GetValue())
m_output = new wxFile("tty.log", wxFile::write);
}
DbgConsole::~DbgConsole()
{
ThreadBase::Stop();
m_dbg_buffer.Flush();
safe_delete(m_console);
safe_delete(m_color_white);
safe_delete(m_color_red);
safe_delete(m_output);
}
void DbgConsole::Write(int ch, const std::string& text)
{
while (m_dbg_buffer.IsBusy())
{
if (Emu.IsStopped())
{
return;
}
Sleep(1);
}
m_dbg_buffer.Push(DbgPacket(ch, text));
if(!IsAlive()) Start();
}
void DbgConsole::Clear()
{
m_console->Clear();
}
void DbgConsole::Task()
{
while(!TestDestroy())
{
if(!m_dbg_buffer.HasNewPacket())
{
if (Emu.IsStopped())
{
break;
}
Sleep(1);
continue;
}
DbgPacket packet = m_dbg_buffer.Pop();
m_console->SetDefaultStyle(packet.m_ch == 1 ? *m_color_red : *m_color_white);
m_console->SetInsertionPointEnd();
m_console->WriteText(fmt::FromUTF8(packet.m_text));
if (m_output && Ini.HLESaveTTY.GetValue())
m_output->Write(fmt::FromUTF8(packet.m_text));
if(!DbgConsole::IsShown()) Show();
}
}
void DbgConsole::OnQuit(wxCloseEvent& event)
{
ThreadBase::Stop(false);
Hide();
if (m_output)
{
m_output->Close();
m_output = nullptr;
}
//event.Skip();
}

View file

@ -1,91 +0,0 @@
#pragma once
struct DbgPacket
{
int m_ch;
std::string m_text;
DbgPacket(int ch, const std::string& text)
: m_ch(ch)
, m_text(text)
{
}
DbgPacket()
{
}
void Clear()
{
m_text.clear();
}
};
struct _DbgBuffer : public MTPacketBuffer<DbgPacket>
{
_DbgBuffer() : MTPacketBuffer<DbgPacket>(1024)
{
}
void _push(const DbgPacket& data)
{
const u32 stext = data.m_text.length();
m_buffer.resize(m_buffer.size() + sizeof(int) + sizeof(u32) + stext);
u32 c_put = m_put;
memcpy(&m_buffer[c_put], &data.m_ch, sizeof(int));
c_put += sizeof(int);
memcpy(&m_buffer[c_put], &stext, sizeof(u32));
c_put += sizeof(u32);
memcpy(&m_buffer[c_put], data.m_text.data(), stext);
c_put += stext;
m_put = c_put;
CheckBusy();
}
DbgPacket _pop()
{
DbgPacket ret;
u32 c_get = m_get;
ret.m_ch = *(int*)&m_buffer[c_get];
c_get += sizeof(int);
const u32& stext = *(u32*)&m_buffer[c_get];
c_get += sizeof(u32);
if (stext) ret.m_text = std::string(reinterpret_cast<const char*>(&m_buffer[c_get]), stext );
c_get += stext;
m_get = c_get;
if(!HasNewPacket()) Flush();
return ret;
}
};
class DbgConsole
: public FrameBase
, public ThreadBase
{
wxFile* m_output;
wxTextCtrl* m_console;
wxTextAttr* m_color_white;
wxTextAttr* m_color_red;
_DbgBuffer m_dbg_buffer;
public:
DbgConsole();
~DbgConsole();
void Write(int ch, const std::string& text);
void Clear();
virtual void Task();
private:
void OnQuit(wxCloseEvent& event);
DECLARE_EVENT_TABLE();
};

View file

@ -1,9 +1,10 @@
#include "stdafx.h"
#include "event.h"
#include "Emu/Memory/Memory.h"
//#include "Emu/System.h"
#include "Event.h"
void EventManager::Init()
{
}
void EventManager::Clear()
@ -14,7 +15,7 @@ void EventManager::Clear()
bool EventManager::CheckKey(u64 key)
{
if (!key) return true;
SMutexLocker lock(m_lock);
std::lock_guard<std::mutex> lock(m_lock);
return key_map.find(key) != key_map.end();
}
@ -22,7 +23,7 @@ bool EventManager::CheckKey(u64 key)
bool EventManager::RegisterKey(EventQueue* data, u64 key)
{
if (!key) return true;
SMutexLocker lock(m_lock);
std::lock_guard<std::mutex> lock(m_lock);
if (key_map.find(key) != key_map.end()) return false;
@ -40,7 +41,7 @@ bool EventManager::GetEventQueue(u64 key, EventQueue*& data)
{
data = nullptr;
if (!key) return false;
SMutexLocker lock(m_lock);
std::lock_guard<std::mutex> lock(m_lock);
auto f = key_map.find(key);
if (f != key_map.end())
@ -54,7 +55,7 @@ bool EventManager::GetEventQueue(u64 key, EventQueue*& data)
bool EventManager::UnregisterKey(u64 key)
{
if (!key) return false;
SMutexLocker lock(m_lock);
std::lock_guard<std::mutex> lock(m_lock);
auto f = key_map.find(key);
if (f != key_map.end())
@ -68,7 +69,7 @@ bool EventManager::UnregisterKey(u64 key)
bool EventManager::SendEvent(u64 key, u64 source, u64 d1, u64 d2, u64 d3)
{
if (!key) return false;
SMutexLocker lock(m_lock);
std::lock_guard<std::mutex> lock(m_lock);
auto f = key_map.find(key);
if (f == key_map.end())

Some files were not shown because too many files have changed in this diff Show more