diff --git a/.gitignore b/.gitignore index cfe1dc5f6e..a404287376 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/.travis.yml b/.travis.yml index bdf0fec902..90ddcfd4de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/CMakeLists.txt b/CMakeLists.txt index bfb3c82402..3abe8d579a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 ) diff --git a/OpenAL/Win32/libOpenAL32.dll.a b/OpenAL/Win32/libOpenAL32.dll.a deleted file mode 100644 index 6911f1b308..0000000000 Binary files a/OpenAL/Win32/libOpenAL32.dll.a and /dev/null differ diff --git a/README.md b/README.md index 98ffc9be25..9701937b1b 100644 --- a/README.md +++ b/README.md @@ -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` diff --git a/Utilities/Array.h b/Utilities/Array.h deleted file mode 100644 index 0855fdbdc7..0000000000 --- a/Utilities/Array.h +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once - -template 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 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; - } -}; diff --git a/Utilities/AutoPause.cpp b/Utilities/AutoPause.cpp new file mode 100644 index 0000000000..9c3fc70edf --- /dev/null +++ b/Utilities/AutoPause.cpp @@ -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 + } + } + } +} \ No newline at end of file diff --git a/Utilities/AutoPause.h b/Utilities/AutoPause.h new file mode 100644 index 0000000000..cf871b46cb --- /dev/null +++ b/Utilities/AutoPause.h @@ -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 m_pause_syscall; + std::vector 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); + }; +} \ No newline at end of file diff --git a/Utilities/BEType.h b/Utilities/BEType.h index 853fd32dec..a261146e8c 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -1,26 +1,242 @@ #pragma once -#include "Utilities/GNU.h" +#include + +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 struct se_t; -template struct se_t { static __forceinline void func(T& dst, const T src) { (u8&)dst = (u8&)src; } }; -template struct se_t { static __forceinline void func(T& dst, const T src) { (u16&)dst = _byteswap_ushort((u16&)src); } }; -template struct se_t { static __forceinline void func(T& dst, const T src) { (u32&)dst = _byteswap_ulong((u32&)src); } }; -template struct se_t { static __forceinline void func(T& dst, const T src) { (u64&)dst = _byteswap_uint64((u64&)src); } }; +template struct se_t +{ + static __forceinline T func(const T src) + { + return src; + } +}; -template struct const_se_t; -template struct const_se_t +template struct se_t +{ + static __forceinline T func(const T src) + { + const u16 res = _byteswap_ushort((u16&)src); + return (T&)res; + } +}; + +template struct se_t +{ + static __forceinline T func(const T src) + { + const u32 res = _byteswap_ulong((u32&)src); + return (T&)res; + } +}; + +template struct se_t +{ + static __forceinline T func(const T src) + { + const u64 res = _byteswap_uint64((u64&)src); + return (T&)res; + } +}; + +//template T re(const T val) { T res; se_t::func(res, val); return res; } +//template void re(T1& dst, const T2 val) { se_t::func(dst, val); } + +template struct const_se_t; +template struct const_se_t { static const T value = (T)_value; }; -template struct const_se_t +template struct const_se_t { static const T value = ((_value >> 8) & 0xff) | ((_value << 8) & 0xff00); }; -template struct const_se_t +template struct const_se_t { static const T value = ((_value >> 24) & 0x000000ff) | @@ -29,7 +245,7 @@ template struct const_se_t ((_value << 24) & 0xff000000); }; -template struct const_se_t +template struct const_se_t { static const T value = ((_value >> 56) & 0x00000000000000ff) | @@ -42,32 +258,14 @@ template struct const_se_t ((_value << 56) & 0xff00000000000000); }; -template +template 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& value) = default; - be_t(const T& value) - { - FromLE(value); - } - - template - explicit be_t(const be_t& value) - { - FromBE(value.ToBE()); - } const T& ToBE() const { @@ -76,11 +274,7 @@ public: T ToLE() const { - T res; - - se_t::func(res, m_data); - - return res; + return se_t::func(m_data); } void FromBE(const T& value) @@ -90,21 +284,18 @@ public: void FromLE(const T& value) { - se_t::func(m_data, value); + m_data = se_t::func(value); } static be_t MakeFromLE(const T value) { - be_t res; - res.FromLE(value); - return res; + T data = se_t::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 @@ -116,18 +307,36 @@ public: template operator const be_t() const { - be_t res; - res.FromBE(ToBE()); - return res; + if (sizeof(T1) > sizeof(T) || std::is_floating_point::value || std::is_floating_point::value) + { + T1 res = se_t::func(ToLE()); + return (be_t&)res; + } + else if (sizeof(T1) < sizeof(T)) + { + T1 res = ToBE() >> ((sizeof(T) - sizeof(T1)) * 8); + return (be_t&)res; + } + else + { + T1 res = ToBE(); + return (be_t&)res; + } } be_t& operator = (const T& right) { - FromLE(right); + m_data = se_t::func(right); return *this; } - be_t& operator = (const be_t& right) = default; + be_t& operator = (const be_t& right) = default; + + be_t& operator = (const be_t& right) + { + m_data = right.ToBE(); + return *this; + } template be_t& operator += (T1 right) { return *this = T(*this) + right; } template be_t& operator -= (T1 right) { return *this = T(*this) - right; } @@ -173,10 +382,244 @@ public: be_t& operator-- () { *this -= 1; return *this; } }; +template +class be_t +{ + 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::func(m_data); + } + + static be_t MakeFromLE(const T value) + { + const T data = se_t::func(value); + return (be_t&)data; + } + + static be_t MakeFromBE(const T value) + { + return (be_t&)value; + } + + //template + operator const T() const + { + return ToLE(); + } + + template + operator const be_t() const + { + if (sizeof(T1) > sizeof(T) || std::is_floating_point::value || std::is_floating_point::value) + { + T1 res = se_t::func(ToLE()); + return (be_t&)res; + } + else if (sizeof(T1) < sizeof(T)) + { + T1 res = ToBE() >> ((sizeof(T) - sizeof(T1)) * 8); + return (be_t&)res; + } + else + { + T1 res = ToBE(); + return (be_t&)res; + } + } + + template be_t operator & (const be_t& right) const { const T res; res = ToBE() & right.ToBE(); return (be_t&)res; } + template be_t operator | (const be_t& right) const { const T res; res = ToBE() | right.ToBE(); return (be_t&)res; } + template be_t operator ^ (const be_t& right) const { const T res; res = ToBE() ^ right.ToBE(); return (be_t&)res; } + + template bool operator == (T1 right) const { return (T1)ToLE() == right; } + template bool operator != (T1 right) const { return !(*this == right); } + template bool operator > (T1 right) const { return (T1)ToLE() > right; } + template bool operator < (T1 right) const { return (T1)ToLE() < right; } + template bool operator >= (T1 right) const { return (T1)ToLE() >= right; } + template bool operator <= (T1 right) const { return (T1)ToLE() <= right; } + + template bool operator == (const be_t& right) const { return ToBE() == right.ToBE(); } + template bool operator != (const be_t& right) const { return !(*this == right); } + template bool operator > (const be_t& right) const { return (T1)ToLE() > right.ToLE(); } + template bool operator < (const be_t& right) const { return (T1)ToLE() < right.ToLE(); } + template bool operator >= (const be_t& right) const { return (T1)ToLE() >= right.ToLE(); } + template bool operator <= (const be_t& right) const { return (T1)ToLE() <= right.ToLE(); } +}; + +template +struct is_be_t : public std::integral_constant {}; + +template +struct is_be_t, T2> : public std::integral_constant {}; + +template +struct remove_be_t +{ + typedef T type; +}; + +template +struct remove_be_t> +{ + typedef T type; +}; + +template +class to_be_t +{ + template + struct _be_type_selector + { + typedef TT type; + }; + + template + struct _be_type_selector + { + typedef be_t type; + }; + +public: + //true if need swap endianes for be + static const bool value = (sizeof(T2) > 1) && std::is_arithmetic::value; + + //be_t if need swap endianes, T otherwise + typedef typename _be_type_selector< T, T2, value >::type type; +}; + +template +class to_be_t +{ +public: + //true if need swap endianes for be + static const bool value = false; + + //be_t if need swap endianes, T otherwise + typedef void type; +}; + +template +class to_be_t +{ +public: + //true if need swap endianes for be + static const bool value = false; + + //be_t if need swap endianes, T otherwise + typedef const void type; +}; + +template +struct invert_be_t +{ + typedef typename to_be_t::type type; +}; + +template +struct invert_be_t> +{ + typedef T type; +}; + template struct _se : public const_se_t {}; template struct _se, T1, value> : public const_se_t {}; -#define se(t, x) _se::value +//#define se(t, x) _se::value #define se16(x) _se::value #define se32(x) _se::value #define se64(x) _se::value + +template __forceinline static u8 Read8(T& f) +{ + u8 ret; + f.Read(&ret, sizeof(ret)); + return ret; +} + +template __forceinline static u16 Read16(T& f) +{ + be_t ret; + f.Read(&ret, sizeof(ret)); + return ret; +} + +template __forceinline static u32 Read32(T& f) +{ + be_t ret; + f.Read(&ret, sizeof(ret)); + return ret; +} + +template __forceinline static u64 Read64(T& f) +{ + be_t ret; + f.Read(&ret, sizeof(ret)); + return ret; +} + +template __forceinline static u16 Read16LE(T& f) +{ + u16 ret; + f.Read(&ret, sizeof(ret)); + return ret; +} + +template __forceinline static u32 Read32LE(T& f) +{ + u32 ret; + f.Read(&ret, sizeof(ret)); + return ret; +} + +template __forceinline static u64 Read64LE(T& f) +{ + u64 ret; + f.Read(&ret, sizeof(ret)); + return ret; +} + +template __forceinline static void Write8(T& f, const u8 data) +{ + f.Write(&data, sizeof(data)); +} + +template __forceinline static void Write16LE(T& f, const u16 data) +{ + f.Write(&data, sizeof(data)); +} + +template __forceinline static void Write32LE(T& f, const u32 data) +{ + f.Write(&data, sizeof(data)); +} + +template __forceinline static void Write64LE(T& f, const u64 data) +{ + f.Write(&data, sizeof(data)); +} + +template __forceinline static void Write16(T& f, const u16 data) +{ + Write16LE(f, re16(data)); +} + +template __forceinline static void Write32(T& f, const u32 data) +{ + Write32LE(f, re32(data)); +} + +template __forceinline static void Write64(T& f, const u64 data) +{ + Write64LE(f, re64(data)); +} \ No newline at end of file diff --git a/Utilities/GNU.cpp b/Utilities/GNU.cpp index bb0a784fe7..9f21a344ba 100644 --- a/Utilities/GNU.cpp +++ b/Utilities/GNU.cpp @@ -1,20 +1,23 @@ -#include -#include #include "GNU.h" #ifdef __APPLE__ -void * _aligned_malloc(size_t size, size_t alignment) { - void *buffer; - posix_memalign(&buffer, alignment, size); - return buffer; -} +#include +#include 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 + diff --git a/Utilities/GNU.h b/Utilities/GNU.h index 32f616a6d2..43b00feafc 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -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 +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 #include @@ -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 \ No newline at end of file diff --git a/Utilities/Interval.h b/Utilities/Interval.h new file mode 100644 index 0000000000..bc8009c743 --- /dev/null +++ b/Utilities/Interval.h @@ -0,0 +1,42 @@ +#pragma once + +template +struct BaseInterval +{ + static const uint64_t zero = 0ull; + static const uint64_t notz = 0xffffffffffffffffull; + + T m_min, m_max; + + static BaseInterval make(T min_value, T max_value) + { + BaseInterval res = { min_value, max_value }; + return res; + } + + static BaseInterval 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) + { + + } + } +}; \ No newline at end of file diff --git a/Utilities/Log.cpp b/Utilities/Log.cpp new file mode 100644 index 0000000000..1f736617cf --- /dev/null +++ b/Utilities/Log.cpp @@ -0,0 +1,235 @@ +#include "stdafx.h" +#include "rPlatform.h" +#include "Log.h" +#include "rMsgBox.h" +#include +#include +#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(input)); + input += sizeof(LogMessage::size_type); + msg.mType = *(reinterpret_cast(input)); + input += sizeof(LogType); + msg.mServerity = *(reinterpret_cast(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 lock(mListenerLock); + for (auto &listener : mListeners) + { + listener->log(msg); + } +} + +void LogChannel::addListener(std::shared_ptr listener) +{ + std::lock_guard lock(mListenerLock); + mListeners.insert(listener); +} +void LogChannel::removeListener(std::shared_ptr listener) +{ + std::lock_guard 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(msg.mType)].mName); + } + mFile.Write(msg.mText); + } +}; + +LogManager::LogManager() +#ifdef BUFFERED_LOGGING + : mExiting(false), mLogConsumer() +#endif +{ + auto it = mChannels.begin(); + std::shared_ptr listener(new FileListener()); + for (const LogTypeName& name : gTypeNameTable) + { + it->name = name.mName; + it->addListener(listener); + it++; + } + std::shared_ptr 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 lock(mStatusMut); + while (!mExiting) + { + mBufferReady.wait(lock); + mBuffer.lockGet(); + size_t size = mBuffer.size(); + std::vector 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 temp_buffer(size); + msg.serialize(temp_buffer.data()); + mBuffer.pushRange(temp_buffer.begin(), temp_buffer.end()); + mBufferReady.notify_one(); +#else + mChannels[static_cast(msg.mType)].log(msg); +#endif +} + +void LogManager::addListener(std::shared_ptr listener) +{ + for (auto& channel : mChannels) + { + channel.addListener(listener); + } +} +void LogManager::removeListener(std::shared_ptr 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(type)]; +} diff --git a/Utilities/Log.h b/Utilities/Log.h new file mode 100644 index 0000000000..c1826ef727 --- /dev/null +++ b/Utilities/Log.h @@ -0,0 +1,141 @@ +#pragma once +#include +#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 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 listener); + void removeListener(std::shared_ptr listener); + std::string name; + private: + bool mEnabled; + LogSeverity mLogLevel; + std::mutex mListenerLock; + std::set> mListeners; + }; + + struct LogManager + { + LogManager(); + ~LogManager(); + static LogManager& getInstance(); + LogChannel& getChannel(LogType type); + void log(LogMessage msg); + void addListener(std::shared_ptr listener); + void removeListener(std::shared_ptr listener); +#ifdef BUFFERED_LOGGING + void consumeLog(); +#endif + private: +#ifdef BUFFERED_LOGGING + MTRingbuffer mBuffer; + std::condition_variable mBufferReady; + std::mutex mStatusMut; + std::atomic mExiting; + std::thread mLogConsumer; +#endif + std::array::value> mChannels; + //std::array 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 +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); +} \ No newline at end of file diff --git a/Utilities/MTRingbuffer.h b/Utilities/MTRingbuffer.h new file mode 100644 index 0000000000..991dbc077b --- /dev/null +++ b/Utilities/MTRingbuffer.h @@ -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 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 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 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 + void pushRange(IteratorType from, IteratorType until) + { + std::lock_guard 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 + void popN(IteratorType output, size_t n) + { + std::lock_guard lock(mMutGet); + //make sure we're not trying to retrieve more than is in + assert(n <= size()); + peekN(output, n); + mGet = moveGet(n); + } + + //takes output iterator to T + template + 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(); + } +}; diff --git a/Utilities/SMutex.cpp b/Utilities/SMutex.cpp index 06820a7afa..80b9fc849f 100644 --- a/Utilities/SMutex.cpp +++ b/Utilities/SMutex.cpp @@ -1,26 +1,34 @@ -#include -#include +#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::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 SM_GetCurrentCPUThreadIdBE() +be_t SM_GetCurrentCPUThreadIdBE() { - return SM_GetCurrentCPUThreadId(); + return be_t::MakeFromLE(SM_GetCurrentCPUThreadId()); } diff --git a/Utilities/SMutex.h b/Utilities/SMutex.h index fe856f501e..efd99b840f 100644 --- a/Utilities/SMutex.h +++ b/Utilities/SMutex.h @@ -1,9 +1,10 @@ #pragma once -extern void SM_Sleep(); -extern size_t SM_GetCurrentThreadId(); -extern u32 SM_GetCurrentCPUThreadId(); -extern be_t SM_GetCurrentCPUThreadIdBE(); +bool SM_IsAborted(); +void SM_Sleep(); +size_t SM_GetCurrentThreadId(); +u32 SM_GetCurrentCPUThreadId(); +be_t 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 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 +template class SMutexLockerBase { - SMutexBase& sm; + T& sm; public: - const T tid; + const Tid tid; - __forceinline SMutexLockerBase(SMutexBase& _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 typedef SMutexBase> SMutexBE; -typedef SMutexLockerBase +typedef SMutexLockerBase SMutexGeneralLocker; -typedef SMutexLockerBase +typedef SMutexLockerBase SMutexLocker; -typedef SMutexLockerBase, SM_GetCurrentCPUThreadIdBE> +typedef SMutexLockerBase, SM_GetCurrentCPUThreadIdBE> SMutexBELocker; diff --git a/Utilities/SQueue.h b/Utilities/SQueue.h index dd0b7787fc..83d7adc3dd 100644 --- a/Utilities/SQueue.h +++ b/Utilities/SQueue.h @@ -1,9 +1,11 @@ #pragma once +#include "Utilities/SMutex.h" + template 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 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 lock(m_mutex); if (!m_count) continue; @@ -84,19 +78,26 @@ public: } } - volatile u32 GetCount() // may be not safe + u32 GetCount() + { + std::lock_guard lock(m_mutex); + return m_count; + } + + u32 GetCountUnsafe() { return m_count; } - volatile bool IsEmpty() // may be not safe + bool IsEmpty() { + std::lock_guard lock(m_mutex); return !m_count; } void Clear() { - SMutexGeneralLocker lock(m_mutex); + std::lock_guard 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 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 lock(m_mutex); + if (m_count <= pos) + { + return def_value; + } + else + { + return m_data[(m_pos + pos) % SQSize]; + } + } }; diff --git a/Utilities/SSemaphore.cpp b/Utilities/SSemaphore.cpp new file mode 100644 index 0000000000..37c3cc6faa --- /dev/null +++ b/Utilities/SSemaphore.cpp @@ -0,0 +1,88 @@ +#include "stdafx.h" +#include "Utilities/SSemaphore.h" +#include "Emu/System.h" + +void SSemaphore::wait() +{ + u32 order; + { + std::lock_guard lock(m_mutex); + if (m_count && m_out_order == m_in_order) + { + m_count--; + return; + } + order = m_in_order++; + } + + std::unique_lock cv_lock(m_cv_mutex); + + while (true) + { + if (Emu.IsStopped()) + { + return; + } + + m_cond.wait_for(cv_lock, std::chrono::milliseconds(1)); + + { + std::lock_guard 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 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 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; +} diff --git a/Utilities/SSemaphore.h b/Utilities/SSemaphore.h new file mode 100644 index 0000000000..2e61262959 --- /dev/null +++ b/Utilities/SSemaphore.h @@ -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(); +}; \ No newline at end of file diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index fc469c7b79..6e79d92d07 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "StrFmt.h" +#include extern const std::string fmt::placeholder = "???"; @@ -14,7 +15,11 @@ std::string fmt::FormatV(const char *fmt, va_list args) for (;;) { std::vector 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 fmt::rSplit(const std::string& source, const std::string& delim) +{ + std::vector 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; } \ No newline at end of file diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 744d6ea189..de78cb74a8 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -1,9 +1,5 @@ #pragma once -#include -#include -#include -#include -#include +class wxString; #if defined(_MSC_VER) #define snprintf _snprintf @@ -18,6 +14,38 @@ namespace fmt{ extern const string placeholder; + template + 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 + 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 + 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 + 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 - 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 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(parameters)...); #pragma clang diagnostic pop +#else + size_t printlen = _snprintf_s(buffptr.data(), length, length - 1, fmt.c_str(), std::forward(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 + std::string replace_all(std::string src, const std::pair(&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 + std::string replace_all(std::string src, const std::pair>(&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 rSplit(const std::string& source, const std::string& delim); } diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 6ad547bfff..aa59aa2384 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -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 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 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 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--; }); } diff --git a/Utilities/Thread.h b/Utilities/Thread.h index cba6bcbdf3..1daeeb5f59 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -1,18 +1,14 @@ #pragma once -#include "Array.h" -#include -#include -#include -#include -#include -#include -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 class MTPacketBuffer -{ -protected: - volatile bool m_busy; - volatile u32 m_put, m_get; - std::vector 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 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 lock(m_cs_main); - _push(v); - } - - T Pop() - { - std::lock_guard lock(m_cs_main); - return _pop(); - } - - bool HasNewPacket() const { std::lock_guard 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(); - } -}; -*/ +}; \ No newline at end of file diff --git a/Utilities/rFile.cpp b/Utilities/rFile.cpp new file mode 100644 index 0000000000..302813e50a --- /dev/null +++ b/Utilities/rFile.cpp @@ -0,0 +1,403 @@ +#include "stdafx.h" +#include "Log.h" +#include +#include +#include +#include "rFile.h" + +#ifdef _WIN32 +#include + +// 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(new wxFile()); +} + +rFile::rFile(const std::string& filename, rFile::OpenMode open) +{ + + handle = reinterpret_cast(new wxFile(fmt::FromUTF8(filename), convertOpenMode(open))); +} + +rFile::rFile(int fd) +{ + handle = reinterpret_cast(new wxFile(fd)); +} + +rFile::~rFile() +{ + delete reinterpret_cast(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(handle)->Write(buffer,count); +} + +bool rFile::Write(const std::string &text) +{ + return reinterpret_cast(handle)->Write(reinterpret_cast(text.c_str()),text.size()); +} + +bool rFile::Close() +{ + return reinterpret_cast(handle)->Close(); +} + +bool rFile::Create(const std::string &filename, bool overwrite, int access) +{ + return reinterpret_cast(handle)->Create(fmt::FromUTF8(filename), overwrite, access); +} + +bool rFile::Open(const std::string &filename, rFile::OpenMode mode, int access) +{ + return reinterpret_cast(handle)->Open(fmt::FromUTF8(filename), convertOpenMode(mode), access); +} + +bool rFile::IsOpened() const +{ + return reinterpret_cast(handle)->IsOpened(); +} + +size_t rFile::Length() const +{ + return reinterpret_cast(handle)->Length(); +} + +size_t rFile::Read(void *buffer, size_t count) +{ + return reinterpret_cast(handle)->Read(buffer,count); +} + +size_t rFile::Seek(size_t ofs, rSeekMode mode) +{ + return reinterpret_cast(handle)->Seek(ofs, convertSeekMode(mode)); +} + +size_t rFile::Tell() const +{ + return reinterpret_cast(handle)->Tell(); +} + +rDir::rDir() +{ + handle = reinterpret_cast(new wxDir()); +} + +rDir::~rDir() +{ + delete reinterpret_cast(handle); +} + +rDir::rDir(const std::string &path) +{ + handle = reinterpret_cast(new wxDir(fmt::FromUTF8(path))); +} + +bool rDir::Open(const std::string& path) +{ + return reinterpret_cast(handle)->Open(fmt::FromUTF8(path)); +} + +bool rDir::IsOpened() const +{ + return reinterpret_cast(handle)->IsOpened(); +} + +bool rDir::GetFirst(std::string *filename) const +{ + wxString str; + bool res; + res = reinterpret_cast(handle)->GetFirst(&str); + *filename = str.ToStdString(); + return res; +} + +bool rDir::GetNext(std::string *filename) const +{ + wxString str; + bool res; + res = reinterpret_cast(handle)->GetNext(&str); + *filename = str.ToStdString(); + return res; +} + +rFileName::rFileName() +{ + handle = reinterpret_cast(new wxFileName()); +} + +rFileName::~rFileName() +{ + delete reinterpret_cast(handle); +} + +rFileName::rFileName(const rFileName& filename) +{ + handle = reinterpret_cast(new wxFileName(*reinterpret_cast(filename.handle))); +} + + +rFileName::rFileName(const std::string& name) +{ + handle = reinterpret_cast(new wxFileName(fmt::FromUTF8(name))); +} + +std::string rFileName::GetFullPath() +{ + return fmt::ToUTF8(reinterpret_cast(handle)->GetFullPath()); +} + +std::string rFileName::GetPath() +{ + return fmt::ToUTF8(reinterpret_cast(handle)->GetPath()); +} + +std::string rFileName::GetName() +{ + return fmt::ToUTF8(reinterpret_cast(handle)->GetName()); +} + +std::string rFileName::GetFullName() +{ + return fmt::ToUTF8(reinterpret_cast(handle)->GetFullName()); +} + +bool rFileName::Normalize() +{ + return reinterpret_cast(handle)->Normalize(); +} + diff --git a/Utilities/rFile.h b/Utilities/rFile.h new file mode 100644 index 0000000000..563b7475be --- /dev/null +++ b/Utilities/rFile.h @@ -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; +}; diff --git a/Utilities/rMsgBox.cpp b/Utilities/rMsgBox.cpp new file mode 100644 index 0000000000..cd3a46be0d --- /dev/null +++ b/Utilities/rMsgBox.cpp @@ -0,0 +1,34 @@ +#include "stdafx.h" +#include "restore_new.h" +#include +#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(new wxMessageDialog( + reinterpret_cast(parent) + , fmt::FromUTF8(msg) + , fmt::FromUTF8(title) + , style + )); +} + +rMessageDialog::~rMessageDialog() +{ + delete reinterpret_cast(handle); +} + +long rMessageDialog::ShowModal() +{ + return reinterpret_cast(handle)->ShowModal(); +} + +long rMessageBox(const std::string& message, const std::string& title, long style) +{ + return wxMessageBox(fmt::FromUTF8(message), fmt::FromUTF8(title),style); +} + +#endif + diff --git a/Utilities/rMsgBox.h b/Utilities/rMsgBox.h new file mode 100644 index 0000000000..f19081fe5c --- /dev/null +++ b/Utilities/rMsgBox.h @@ -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); + diff --git a/Utilities/rPlatform.cpp b/Utilities/rPlatform.cpp new file mode 100644 index 0000000000..a947b7a00f --- /dev/null +++ b/Utilities/rPlatform.cpp @@ -0,0 +1,57 @@ +#include "stdafx.h" +#include "restore_new.h" +#include +#include "define_new_memleakdetect.h" + +#ifndef _WIN32 +#include +#endif + +#include "rPlatform.h" + +rImage::rImage() +{ + handle = static_cast(new wxImage()); +} + +rImage::~rImage() +{ + delete static_cast(handle); +} + +void rImage::Create(int width, int height, void *data, void *alpha) +{ + static_cast(handle)->Create(width, height, static_cast(data), static_cast(alpha)); +} +void rImage::SaveFile(const std::string& name, rImageType type) +{ + if (type == rBITMAP_TYPE_PNG) + { + static_cast(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; +} diff --git a/Utilities/rPlatform.h b/Utilities/rPlatform.h new file mode 100644 index 0000000000..ce88b70ecc --- /dev/null +++ b/Utilities/rPlatform.h @@ -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 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; +}; diff --git a/Utilities/rTime.cpp b/Utilities/rTime.cpp new file mode 100644 index 0000000000..fccb0ac7df --- /dev/null +++ b/Utilities/rTime.cpp @@ -0,0 +1,232 @@ +#include "stdafx.h" +#include "rTime.h" + +#include + +std::string rDefaultDateTimeFormat = "%c"; + +rTimeSpan::rTimeSpan() +{ + handle = static_cast(new wxTimeSpan()); +} + +rTimeSpan::~rTimeSpan() +{ + delete static_cast(handle); +} + +rTimeSpan::rTimeSpan(const rTimeSpan& other) + +{ + handle = static_cast(new wxTimeSpan(*static_cast(other.handle))); + +} + +rTimeSpan::rTimeSpan(int a, int b , int c, int d) +{ + handle = static_cast(new wxTimeSpan(a,b,c,d)); +} + + +rDateSpan::rDateSpan() +{ + handle = static_cast(new wxDateSpan()); +} + +rDateSpan::~rDateSpan() +{ + delete static_cast(handle); +} + +rDateSpan::rDateSpan(const rDateSpan& other) +{ + handle = static_cast(new wxDateSpan(*static_cast(other.handle))); +} + +rDateSpan::rDateSpan(int a, int b, int c, int d) +{ + handle = static_cast(new wxDateSpan(a,b,c,d)); +} + +rDateTime::rDateTime() +{ + handle = static_cast(new wxDateTime()); +} + +rDateTime::~rDateTime() +{ + delete static_cast(handle); +} + +rDateTime::rDateTime(const rDateTime& other) +{ + handle = static_cast(new wxDateTime(*static_cast(other.handle))); +} + +rDateTime::rDateTime(const time_t& time) +{ + handle = static_cast(new wxDateTime(time)); +} + +rDateTime::rDateTime(u16 day, rDateTime::Month month, u16 year, u16 hour, u16 minute, u16 second, u32 millisecond) +{ + handle = static_cast(new wxDateTime(day,(wxDateTime::Month)month,year,hour,minute,second,millisecond)); +} + +rDateTime rDateTime::UNow() +{ + rDateTime time; + delete static_cast(time.handle); + time.handle = static_cast(new wxDateTime(wxDateTime::UNow())); + + return time; +} + +rDateTime rDateTime::FromUTC(bool val) +{ + rDateTime time(*this); + void *temp = time.handle; + + time.handle = static_cast(new wxDateTime(static_cast(temp)->FromTimezone(wxDateTime::GMT0, val))); + delete static_cast(temp); + + return time; +} + +rDateTime rDateTime::ToUTC(bool val) +{ + rDateTime time(*this); + void *temp = time.handle; + + time.handle = static_cast(new wxDateTime(static_cast(temp)->ToTimezone(wxDateTime::GMT0, val))); + delete static_cast(temp); + + return time; +} + +time_t rDateTime::GetTicks() +{ + return static_cast(handle)->GetTicks(); +} + +void rDateTime::Add(const rTimeSpan& span) +{ + static_cast(handle)->Add(*static_cast(span.handle)); +} + +void rDateTime::Add(const rDateSpan& span) +{ + static_cast(handle)->Add(*static_cast(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(handle)->Format(fmt::FromUTF8(format),convertTZ(tz))); +} + +void rDateTime::ParseDateTime(const char* format) +{ + static_cast(handle)->ParseDateTime(format); +} + +u32 rDateTime::GetAsDOS() +{ + return static_cast(handle)->GetAsDOS(); +} + +rDateTime &rDateTime::SetFromDOS(u32 fromdos) +{ + static_cast(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(month), year, wxDateTime::Gregorian); + } + else + { + return wxDateTime::GetNumberOfDays(static_cast(month), year, wxDateTime::Julian); + } +} + +void rDateTime::SetToWeekDay(rDateTime::WeekDay day, int n, rDateTime::Month month, int year) +{ + static_cast(handle)->SetToWeekDay( + static_cast(day) + , n + , static_cast(month) + , year + ); +} + +int rDateTime::GetWeekDay() +{ + return static_cast(handle)->GetWeekDay(); +} + +u16 rDateTime::GetYear(rDateTime::TZ timezone) +{ + return static_cast(handle)->GetYear(convertTZ(timezone)); +} + +u16 rDateTime::GetMonth(rDateTime::TZ timezone) +{ + return static_cast(handle)->GetMonth(convertTZ(timezone)); +} + +u16 rDateTime::GetDay(rDateTime::TZ timezone) +{ + return static_cast(handle)->GetDay(convertTZ(timezone)); +} + +u16 rDateTime::GetHour(rDateTime::TZ timezone) +{ + return static_cast(handle)->GetHour(convertTZ(timezone)); +} + +u16 rDateTime::GetMinute(rDateTime::TZ timezone) +{ + return static_cast(handle)->GetMinute(convertTZ(timezone)); +} + +u16 rDateTime::GetSecond(rDateTime::TZ timezone) +{ + return static_cast(handle)->GetSecond(convertTZ(timezone)); +} + +u32 rDateTime::GetMillisecond(rDateTime::TZ timezone) +{ + return static_cast(handle)->GetMillisecond(convertTZ(timezone)); +} + + diff --git a/Utilities/rTime.h b/Utilities/rTime.h new file mode 100644 index 0000000000..9c39c46b30 --- /dev/null +++ b/Utilities/rTime.h @@ -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; +}; + diff --git a/Utilities/rXml.cpp b/Utilities/rXml.cpp new file mode 100644 index 0000000000..7d2ed9a533 --- /dev/null +++ b/Utilities/rXml.cpp @@ -0,0 +1,113 @@ +#include "stdafx.h" +#include "Utilities/rXml.h" +#include + +rXmlNode::rXmlNode() +{ + ownPtr = true; + handle = reinterpret_cast(new wxXmlNode()); +} + +rXmlNode::rXmlNode(void *ptr) +{ + ownPtr = false; + handle = ptr; +} + +rXmlNode::rXmlNode(const rXmlNode& other) +{ + ownPtr = true; + handle = reinterpret_cast(new wxXmlNode(*reinterpret_cast(other.handle))); +} + +rXmlNode &rXmlNode::operator=(const rXmlNode& other) +{ + if (ownPtr) + { + delete reinterpret_cast(handle); + } + handle = reinterpret_cast(new wxXmlNode(*reinterpret_cast(other.handle))); + ownPtr = true; + return *this; +} + +rXmlNode::~rXmlNode() +{ + if (ownPtr) + { + delete reinterpret_cast(handle); + } +} + +std::shared_ptr rXmlNode::GetChildren() +{ + wxXmlNode* result = reinterpret_cast(handle)->GetChildren(); + if (result) + { + return std::make_shared(reinterpret_cast(result)); + } + else + { + return std::shared_ptr(nullptr); + } +} + +std::shared_ptr rXmlNode::GetNext() +{ + wxXmlNode* result = reinterpret_cast(handle)->GetNext(); + if (result) + { + return std::make_shared(reinterpret_cast(result)); + } + else + { + return std::shared_ptr(nullptr); + } +} + +std::string rXmlNode::GetName() +{ + return fmt::ToUTF8(reinterpret_cast(handle)->GetName()); +} + +std::string rXmlNode::GetAttribute(const std::string &name) +{ + return fmt::ToUTF8(reinterpret_cast(handle)->GetAttribute(fmt::FromUTF8(name))); +} + +std::string rXmlNode::GetNodeContent() +{ + return fmt::ToUTF8(reinterpret_cast(handle)->GetNodeContent()); +} + +rXmlDocument::rXmlDocument() +{ + handle = reinterpret_cast(new wxXmlDocument()); +} + +rXmlDocument::rXmlDocument(const rXmlDocument& other) +{ + handle = reinterpret_cast(new wxXmlDocument(*reinterpret_cast(other.handle))); +} + +rXmlDocument &rXmlDocument::operator = (const rXmlDocument& other) +{ + delete reinterpret_cast(handle); + handle = reinterpret_cast(new wxXmlDocument(*reinterpret_cast(other.handle))); + return *this; +} + +rXmlDocument::~rXmlDocument() +{ + delete reinterpret_cast(handle); +} + +void rXmlDocument::Load(const std::string & path) +{ + reinterpret_cast(handle)->Load(fmt::FromUTF8(path)); +} + +std::shared_ptr rXmlDocument::GetRoot() +{ + return std::make_shared(reinterpret_cast(reinterpret_cast(handle)->GetRoot())); +} diff --git a/Utilities/rXml.h b/Utilities/rXml.h new file mode 100644 index 0000000000..9531936f73 --- /dev/null +++ b/Utilities/rXml.h @@ -0,0 +1,30 @@ +#pragma once + +struct rXmlNode +{ + rXmlNode(); + rXmlNode(void *); + rXmlNode(const rXmlNode& other); + rXmlNode &operator=(const rXmlNode& other); + ~rXmlNode(); + std::shared_ptr GetChildren(); + std::shared_ptr 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 GetRoot(); + + void *handle; +}; \ No newline at end of file diff --git a/Utilities/simpleini/ConvertUTF.h b/Utilities/simpleini/ConvertUTF.h index 14d7b70dca..4c8ab6086b 100644 --- a/Utilities/simpleini/ConvertUTF.h +++ b/Utilities/simpleini/ConvertUTF.h @@ -1,3 +1,5 @@ +#pragma once + /* * Copyright 2001-2004 Unicode, Inc. * diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000000..9ebfa5fbe6 --- /dev/null +++ b/appveyor.yml @@ -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 + diff --git a/asmjit b/asmjit index b76922fde9..d7fc62d9e9 160000 --- a/asmjit +++ b/asmjit @@ -1 +1 @@ -Subproject commit b76922fde96232030be302b3bdd9673e9bcec568 +Subproject commit d7fc62d9e905859579f5965eee6f7f99b65c2246 diff --git a/asmjitsrc/asmjit.vcxproj b/asmjitsrc/asmjit.vcxproj index 28da0c7bdb..92a1201431 100644 --- a/asmjitsrc/asmjit.vcxproj +++ b/asmjitsrc/asmjit.vcxproj @@ -1,4 +1,4 @@ - + @@ -23,30 +23,55 @@ + - - + - - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {AC40FF01-426E-4838-A317-66354CEFAE88} diff --git a/asmjitsrc/asmjit.vcxproj.filters b/asmjitsrc/asmjit.vcxproj.filters index 3bc6ddf9b2..705a68121c 100644 --- a/asmjitsrc/asmjit.vcxproj.filters +++ b/asmjitsrc/asmjit.vcxproj.filters @@ -1,33 +1,58 @@ - + - - - - - - - + + - - + - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bin/soft_oal.dll b/bin/soft_oal.dll new file mode 100644 index 0000000000..b47ff952b7 Binary files /dev/null and b/bin/soft_oal.dll differ diff --git a/package.bat b/package.bat new file mode 100644 index 0000000000..30efc34ebf --- /dev/null +++ b/package.bat @@ -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 .. diff --git a/rpcs3.sln b/rpcs3.sln index acba28bea4..24c63c95cf 100644 --- a/rpcs3.sln +++ b/rpcs3.sln @@ -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 diff --git a/rpcs3/CMakeLists.txt b/rpcs3/CMakeLists.txt index cf4ec60490..59f146c6dc 100644 --- a/rpcs3/CMakeLists.txt +++ b/rpcs3/CMakeLists.txt @@ -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) + diff --git a/rpcs3/Crypto/aes.h b/rpcs3/Crypto/aes.h index 7a9c20a567..6d85edc369 100644 --- a/rpcs3/Crypto/aes.h +++ b/rpcs3/Crypto/aes.h @@ -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 \ No newline at end of file +#endif diff --git a/rpcs3/Crypto/key_vault.cpp b/rpcs3/Crypto/key_vault.cpp index 8565addb4d..5cbc04ac02 100644 --- a/rpcs3/Crypto/key_vault.cpp +++ b/rpcs3/Crypto/key_vault.cpp @@ -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); diff --git a/rpcs3/Crypto/key_vault.h b/rpcs3/Crypto/key_vault.h index 3f78228e9e..e57cfe5b90 100644 --- a/rpcs3/Crypto/key_vault.h +++ b/rpcs3/Crypto/key_vault.h @@ -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. diff --git a/rpcs3/Crypto/lz.h b/rpcs3/Crypto/lz.h index 78cce623b6..c27192624c 100644 --- a/rpcs3/Crypto/lz.h +++ b/rpcs3/Crypto/lz.h @@ -1,3 +1,4 @@ +#pragma once #include int decode_range(unsigned int *range, unsigned int *code, unsigned char **src); diff --git a/rpcs3/Crypto/sha1.h b/rpcs3/Crypto/sha1.h index 9272d94746..84d4bd80d2 100644 --- a/rpcs3/Crypto/sha1.h +++ b/rpcs3/Crypto/sha1.h @@ -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 \ No newline at end of file +#endif diff --git a/rpcs3/Crypto/unedat.cpp b/rpcs3/Crypto/unedat.cpp index f7f44cf16f..b484cabf38 100644 --- a/rpcs3/Crypto/unedat.cpp +++ b/rpcs3/Crypto/unedat.cpp @@ -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; } diff --git a/rpcs3/Crypto/unedat.h b/rpcs3/Crypto/unedat.h index 01ce706f3f..7efc8b3808 100644 --- a/rpcs3/Crypto/unedat.h +++ b/rpcs3/Crypto/unedat.h @@ -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); \ No newline at end of file +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); diff --git a/rpcs3/Crypto/unpkg.cpp b/rpcs3/Crypto/unpkg.cpp index db5eed77e5..caae7fb9f7 100644 --- a/rpcs3/Crypto/unpkg.cpp +++ b/rpcs3/Crypto/unpkg.cpp @@ -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 +#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 hi = *(be_t*)&iv[0]; - be_t lo = *(be_t*)&iv[8] + 1; + be_t hi = be_t::MakeFromBE(*(u64*)&iv[0]); + be_t lo = be_t::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(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(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 m_entries; m_entries.resize(m_header->file_count); diff --git a/rpcs3/Crypto/unpkg.h b/rpcs3/Crypto/unpkg.h index cb89f8dbee..e47e061fbc 100644 --- a/rpcs3/Crypto/unpkg.h +++ b/rpcs3/Crypto/unpkg.h @@ -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 pad; // Padding (zeros) }; -extern int Unpack(wxFile& dec_pkg_f, std::string src, std::string dst); \ No newline at end of file +class rFile; + +extern int Unpack(rFile& dec_pkg_f, std::string src, std::string dst); \ No newline at end of file diff --git a/rpcs3/Crypto/unself.cpp b/rpcs3/Crypto/unself.cpp index 5fababbb02..61422f5328 100644 --- a/rpcs3/Crypto/unself.cpp +++ b/rpcs3/Crypto/unself.cpp @@ -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 +#include + +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(§ion_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; } } diff --git a/rpcs3/Crypto/unself.h b/rpcs3/Crypto/unself.h index bd72125eac..947904e13a 100644 --- a/rpcs3/Crypto/unself.h +++ b/rpcs3/Crypto/unself.h @@ -1,10 +1,8 @@ #pragma once -#include "utils.h" -#include "key_vault.h" -#include "Loader/ELF.h" + #include "Loader/SELF.h" -#include -#include +#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(§ion_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 diff --git a/rpcs3/Crypto/utils.cpp b/rpcs3/Crypto/utils.cpp index a17013cda9..b395643f20 100644 --- a/rpcs3/Crypto/utils.cpp +++ b/rpcs3/Crypto/utils.cpp @@ -1,4 +1,6 @@ #include "stdafx.h" +#include "aes.h" +#include "sha1.h" #include "utils.h" // Endian swap auxiliary functions. diff --git a/rpcs3/Crypto/utils.h b/rpcs3/Crypto/utils.h index 17ec4e8f5a..4ae1466607 100644 --- a/rpcs3/Crypto/utils.h +++ b/rpcs3/Crypto/utils.h @@ -1,6 +1,4 @@ #pragma once -#include "aes.h" -#include "sha1.h" // Auxiliary functions (endian swap and xor). u16 swap16(u16 i); diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.h b/rpcs3/Emu/ARMv7/ARMv7Decoder.h index b19bf94cd3..6603e45e3e 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.h +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.h @@ -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; diff --git a/rpcs3/Emu/ARMv7/ARMv7DisAsm.h b/rpcs3/Emu/ARMv7/ARMv7DisAsm.h index 1ccba0dc1b..cf84835cd8 100644 --- a/rpcs3/Emu/ARMv7/ARMv7DisAsm.h +++ b/rpcs3/Emu/ARMv7/ARMv7DisAsm.h @@ -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) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h index 9aabb473fc..bc2ae6f2c7 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h @@ -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(); } -}; \ No newline at end of file +}; diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 5aff8a50c6..a49c8ed3e9 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -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() { -} \ No newline at end of file +} diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index f5a21c8cc8..7a4234f00e 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -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: diff --git a/rpcs3/Emu/Audio/AL/OpenALThread.cpp b/rpcs3/Emu/Audio/AL/OpenALThread.cpp index ef912dc0f2..5d24514d46 100644 --- a/rpcs3/Emu/Audio/AL/OpenALThread.cpp +++ b/rpcs3/Emu/Audio/AL/OpenALThread.cpp @@ -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; -} \ No newline at end of file +} diff --git a/rpcs3/Emu/Audio/AudioDumper.cpp b/rpcs3/Emu/Audio/AudioDumper.cpp index 1a2e61fea2..0e51fd4a42 100644 --- a/rpcs3/Emu/Audio/AudioDumper.cpp +++ b/rpcs3/Emu/Audio/AudioDumper.cpp @@ -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; } diff --git a/rpcs3/Emu/Audio/AudioDumper.h b/rpcs3/Emu/Audio/AudioDumper.h index 11a2f6e7e9..ebf0f1db25 100644 --- a/rpcs3/Emu/Audio/AudioDumper.h +++ b/rpcs3/Emu/Audio/AudioDumper.h @@ -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; } }; diff --git a/rpcs3/Emu/Audio/AudioManager.cpp b/rpcs3/Emu/Audio/AudioManager.cpp index f0cbfc0d78..1207e61d6b 100644 --- a/rpcs3/Emu/Audio/AudioManager.cpp +++ b/rpcs3/Emu/Audio/AudioManager.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "rpcs3/Ini.h" #include "AudioManager.h" OpenALThread* m_audio_out; diff --git a/rpcs3/Emu/Audio/sysutil_audio.h b/rpcs3/Emu/Audio/sysutil_audio.h index 94ea6dafd0..2fd567461f 100644 --- a/rpcs3/Emu/Audio/sysutil_audio.h +++ b/rpcs3/Emu/Audio/sysutil_audio.h @@ -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 systemBgmFadeInTime; + be_t systemBgmFadeOutTime; + be_t gameBgmFadeInTime; + be_t gameBgmFadeOutTime; + char reserved[8]; +}; diff --git a/rpcs3/Emu/CPU/CPUDecoder.h b/rpcs3/Emu/CPU/CPUDecoder.h index 95b168b7af..b9b47dd7f4 100644 --- a/rpcs3/Emu/CPU/CPUDecoder.h +++ b/rpcs3/Emu/CPU/CPUDecoder.h @@ -1,5 +1,4 @@ #pragma once -#include #include "CPUInstrTable.h" #pragma warning( disable : 4800 ) diff --git a/rpcs3/Emu/CPU/CPUDisAsm.h b/rpcs3/Emu/CPU/CPUDisAsm.h index 1a46e623c7..4a7eca77c0 100644 --- a/rpcs3/Emu/CPU/CPUDisAsm.h +++ b/rpcs3/Emu/CPU/CPUDisAsm.h @@ -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(10 - (int)op.length(), 0),' '); + op.append(std::max(10 - (int)op.length(), 0),' '); return op; } }; diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index a1caaa1bf0..ec5278fe67 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -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 lock(m_cs_sync); m_sync_wait = wait; } void CPUThread::Wait(const CPUThread& thr) { - wxCriticalSectionLocker lock(m_cs_sync); + std::lock_guard 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 CPUThread::ErrorToString(const u32 error) { - wxArrayString earr; + std::vector 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& bp = Emu.GetBreakPoints(); + for (uint i = 0; i trace; + +#ifdef _WIN32 + _set_se_translator(_se_translator); +#else + // TODO: linux version +#endif + try { - for(uint i=0; iDecodeMemory(PC + m_offset)); - if(status == CPUThread_Step) + if (status == CPUThread_Step) { m_is_step = false; break; } - for(uint i=0; i ErrorToString(const u32 error); + std::vector 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; } diff --git a/rpcs3/Emu/CPU/CPUThreadManager.cpp b/rpcs3/Emu/CPU/CPUThreadManager.cpp index d29c5e6373..af9368f338 100644 --- a/rpcs3/Emu/CPU/CPUThreadManager.cpp +++ b/rpcs3/Emu/CPU/CPUThreadManager.cpp @@ -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 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 lock(m_mtx_thread); diff --git a/rpcs3/Emu/CPU/CPUThreadManager.h b/rpcs3/Emu/CPU/CPUThreadManager.h index c0595dc693..480ef940f0 100644 --- a/rpcs3/Emu/CPU/CPUThreadManager.h +++ b/rpcs3/Emu/CPU/CPUThreadManager.h @@ -1,13 +1,13 @@ #pragma once + class CPUThread; +class RawSPUThread; enum CPUThreadType : unsigned char; class CPUThreadManager { std::vector 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& GetThreads() { return m_threads; } s32 GetThreadNumById(CPUThreadType type, u32 id); CPUThread* GetThread(u32 id); + RawSPUThread* GetRawSPUThread(u32 num); void Exec(); void Task(); diff --git a/rpcs3/Emu/Cell/MFC.h b/rpcs3/Emu/Cell/MFC.h index a4cb348559..7bd4281f7c 100644 --- a/rpcs3/Emu/Cell/MFC.h +++ b/rpcs3/Emu/Cell/MFC.h @@ -1,5 +1,4 @@ #pragma once -#include 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 -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 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); - } - } -};*/ diff --git a/rpcs3/Emu/Cell/PPCDecoder.cpp b/rpcs3/Emu/Cell/PPCDecoder.cpp index c9bf8139b2..4c36affd87 100644 --- a/rpcs3/Emu/Cell/PPCDecoder.cpp +++ b/rpcs3/Emu/Cell/PPCDecoder.cpp @@ -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); } \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPCDisAsm.h b/rpcs3/Emu/Cell/PPCDisAsm.h index 59086e8d94..2666033919 100644 --- a/rpcs3/Emu/Cell/PPCDisAsm.h +++ b/rpcs3/Emu/Cell/PPCDisAsm.h @@ -1,8 +1,6 @@ #pragma once #include "Emu/CPU/CPUDisAsm.h" -#include "Gui/DisAsmFrame.h" -#include "Emu/Memory/Memory.h" class PPCDisAsm : public CPUDisAsm { diff --git a/rpcs3/Emu/Cell/PPCThread.cpp b/rpcs3/Emu/Cell/PPCThread.cpp index f1d966cde7..3e75620609 100644 --- a/rpcs3/Emu/Cell/PPCThread.cpp +++ b/rpcs3/Emu/Cell/PPCThread.cpp @@ -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); */ } diff --git a/rpcs3/Emu/Cell/PPCThread.h b/rpcs3/Emu/Cell/PPCThread.h index e7bc4ddbe1..e0fbd5888c 100644 --- a/rpcs3/Emu/Cell/PPCThread.h +++ b/rpcs3/Emu/Cell/PPCThread.h @@ -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 { diff --git a/rpcs3/Emu/Cell/PPUDisAsm.h b/rpcs3/Emu/Cell/PPUDisAsm.h index 102f30dd78..34e51f7fb2 100644 --- a/rpcs3/Emu/Cell/PPUDisAsm.h +++ b/rpcs3/Emu/Cell/PPUDisAsm.h @@ -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 diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index bb23f6a147..f72a38cf64 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -1,10 +1,7 @@ #pragma once #include "Emu/Cell/PPUOpcodes.h" -#include "Emu/Memory/Memory.h" -#include "Emu/Cell/PPUThread.h" -#include "Emu/SysCalls/SysCalls.h" -#include "rpcs3.h" + #include #ifdef _MSC_VER #include @@ -67,23 +64,22 @@ private: void SysCall() { - SysCalls::DoSyscall(CPU.GPR[11]); + const u64 sc = CPU.GPR[11]; + const u64 old_sc = CPU.m_last_syscall; - if (Ini.LogAllSysCalls.GetValue()) + CPU.m_last_syscall = sc; + SysCalls::DoSyscall((u32)sc); + + if(Ini.HLELogging.GetValue()) { - ConLog.Warning("SysCall[0x%llx] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC); - if(CPU.GPR[11] > 1024) - SysCalls::DoFunc(CPU.GPR[11]); + LOG_WARNING(PPU, "SysCall[0x%llx ('%s')] done with code [0x%llx]! #pc: 0x%llx", + sc, SysCalls::GetHLEFuncName((u32)sc).c_str(), CPU.GPR[3], CPU.PC); } - /*else if ((s64)CPU.GPR[3] < 0) // probably, error code - { - ConLog.Error("SysCall[0x%llx] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC); - if(CPU.GPR[11] > 1024) - SysCalls::DoFunc(CPU.GPR[11]); - }*/ #ifdef HLE_CALL_DEBUG - ConLog.Write("SysCall[%lld] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC); + LOG_NOTICE(PPU, "SysCall[%lld] done with code [0x%llx]! #pc: 0x%llx", sc, CPU.GPR[3], CPU.PC); #endif + + CPU.m_last_syscall = old_sc; } void NULL_OP() @@ -159,7 +155,7 @@ private: void TWI(u32 to, u32 ra, s32 simm16) { - s32 a = CPU.GPR[ra]; + s32 a = (s32)CPU.GPR[ra]; if( (a < simm16 && (to & 0x10)) || (a > simm16 && (to & 0x8)) || @@ -171,9 +167,9 @@ private: } } - void MFVSCR(u32 vd) + void MFVSCR(u32 vd) //nf { - CPU.VPR[vd].Clear(); + CPU.VPR[vd].clear(); CPU.VPR[vd]._u32[0] = CPU.VSCR.VSCR; } void MTVSCR(u32 vb) @@ -212,7 +208,7 @@ private: CPU.VSCR.SAT = 1; } else - CPU.VPR[vd]._s8[b] = result; + CPU.VPR[vd]._s8[b] = (s8)result; } } void VADDSHS(u32 vd, u32 va, u32 vb) @@ -252,7 +248,7 @@ private: CPU.VSCR.SAT = 1; } else - CPU.VPR[vd]._s32[w] = result; + CPU.VPR[vd]._s32[w] = (s32)result; } } void VADDUBM(u32 vd, u32 va, u32 vb) @@ -274,7 +270,7 @@ private: CPU.VSCR.SAT = 1; } else - CPU.VPR[vd]._u8[b] = result; + CPU.VPR[vd]._u8[b] = (u8)result; } } void VADDUHM(u32 vd, u32 va, u32 vb) @@ -318,7 +314,7 @@ private: CPU.VSCR.SAT = 1; } else - CPU.VPR[vd]._u32[w] = result; + CPU.VPR[vd]._u32[w] = (u32)result; } } void VAND(u32 vd, u32 va, u32 vb) @@ -775,10 +771,10 @@ private: { float result = CPU.VPR[vb]._f[w] * nScale; - if (result > INT_MAX) - CPU.VPR[vd]._s32[w] = (int)INT_MAX; - else if (result < INT_MIN) - CPU.VPR[vd]._s32[w] = (int)INT_MIN; + if (result > 0x7fffffff) + CPU.VPR[vd]._s32[w] = (int)0x7fffffff; + else if (result < -pow(2, 31)) + CPU.VPR[vd]._s32[w] = (int)0x80000000; else // C rounding = Round towards 0 CPU.VPR[vd]._s32[w] = (int)result; } @@ -792,8 +788,8 @@ private: // C rounding = Round towards 0 s64 result = (s64)(CPU.VPR[vb]._f[w] * nScale); - if (result > UINT_MAX) - CPU.VPR[vd]._u32[w] = (u32)UINT_MAX; + if (result > 0xffffffffu) + CPU.VPR[vd]._u32[w] = 0xffffffffu; else if (result < 0) CPU.VPR[vd]._u32[w] = 0; else @@ -830,45 +826,45 @@ private: { for (uint w = 0; w < 4; w++) { - CPU.VPR[vd]._f[w] = max(CPU.VPR[va]._f[w], CPU.VPR[vb]._f[w]); + CPU.VPR[vd]._f[w] = std::max(CPU.VPR[va]._f[w], CPU.VPR[vb]._f[w]); } } void VMAXSB(u32 vd, u32 va, u32 vb) //nf { for (uint b = 0; b < 16; b++) - CPU.VPR[vd]._s8[b] = max(CPU.VPR[va]._s8[b], CPU.VPR[vb]._s8[b]); + CPU.VPR[vd]._s8[b] = std::max(CPU.VPR[va]._s8[b], CPU.VPR[vb]._s8[b]); } void VMAXSH(u32 vd, u32 va, u32 vb) { for (uint h = 0; h < 8; h++) { - CPU.VPR[vd]._s16[h] = max(CPU.VPR[va]._s16[h], CPU.VPR[vb]._s16[h]); + CPU.VPR[vd]._s16[h] = std::max(CPU.VPR[va]._s16[h], CPU.VPR[vb]._s16[h]); } } void VMAXSW(u32 vd, u32 va, u32 vb) { for (uint w = 0; w < 4; w++) { - CPU.VPR[vd]._s32[w] = max(CPU.VPR[va]._s32[w], CPU.VPR[vb]._s32[w]); + CPU.VPR[vd]._s32[w] = std::max(CPU.VPR[va]._s32[w], CPU.VPR[vb]._s32[w]); } } void VMAXUB(u32 vd, u32 va, u32 vb) { for (uint b = 0; b < 16; b++) - CPU.VPR[vd]._u8[b] = max(CPU.VPR[va]._u8[b], CPU.VPR[vb]._u8[b]); + CPU.VPR[vd]._u8[b] = std::max(CPU.VPR[va]._u8[b], CPU.VPR[vb]._u8[b]); } void VMAXUH(u32 vd, u32 va, u32 vb) { for (uint h = 0; h < 8; h++) { - CPU.VPR[vd]._u16[h] = max(CPU.VPR[va]._u16[h], CPU.VPR[vb]._u16[h]); + CPU.VPR[vd]._u16[h] = std::max(CPU.VPR[va]._u16[h], CPU.VPR[vb]._u16[h]); } } void VMAXUW(u32 vd, u32 va, u32 vb) { for (uint w = 0; w < 4; w++) { - CPU.VPR[vd]._u32[w] = max(CPU.VPR[va]._u32[w], CPU.VPR[vb]._u32[w]); + CPU.VPR[vd]._u32[w] = std::max(CPU.VPR[va]._u32[w], CPU.VPR[vb]._u32[w]); } } void VMHADDSHS(u32 vd, u32 va, u32 vb, u32 vc) @@ -915,49 +911,49 @@ private: { for (uint w = 0; w < 4; w++) { - CPU.VPR[vd]._f[w] = min(CPU.VPR[va]._f[w], CPU.VPR[vb]._f[w]); + CPU.VPR[vd]._f[w] = std::min(CPU.VPR[va]._f[w], CPU.VPR[vb]._f[w]); } } void VMINSB(u32 vd, u32 va, u32 vb) //nf { for (uint b = 0; b < 16; b++) { - CPU.VPR[vd]._s8[b] = min(CPU.VPR[va]._s8[b], CPU.VPR[vb]._s8[b]); + CPU.VPR[vd]._s8[b] = std::min(CPU.VPR[va]._s8[b], CPU.VPR[vb]._s8[b]); } } void VMINSH(u32 vd, u32 va, u32 vb) { for (uint h = 0; h < 8; h++) { - CPU.VPR[vd]._s16[h] = min(CPU.VPR[va]._s16[h], CPU.VPR[vb]._s16[h]); + CPU.VPR[vd]._s16[h] = std::min(CPU.VPR[va]._s16[h], CPU.VPR[vb]._s16[h]); } } void VMINSW(u32 vd, u32 va, u32 vb) { for (uint w = 0; w < 4; w++) { - CPU.VPR[vd]._s32[w] = min(CPU.VPR[va]._s32[w], CPU.VPR[vb]._s32[w]); + CPU.VPR[vd]._s32[w] = std::min(CPU.VPR[va]._s32[w], CPU.VPR[vb]._s32[w]); } } void VMINUB(u32 vd, u32 va, u32 vb) { for (uint b = 0; b < 16; b++) { - CPU.VPR[vd]._u8[b] = min(CPU.VPR[va]._u8[b], CPU.VPR[vb]._u8[b]); + CPU.VPR[vd]._u8[b] = std::min(CPU.VPR[va]._u8[b], CPU.VPR[vb]._u8[b]); } } void VMINUH(u32 vd, u32 va, u32 vb) { for (uint h = 0; h < 8; h++) { - CPU.VPR[vd]._u16[h] = min(CPU.VPR[va]._u16[h], CPU.VPR[vb]._u16[h]); + CPU.VPR[vd]._u16[h] = std::min(CPU.VPR[va]._u16[h], CPU.VPR[vb]._u16[h]); } } void VMINUW(u32 vd, u32 va, u32 vb) { for (uint w = 0; w < 4; w++) { - CPU.VPR[vd]._u32[w] = min(CPU.VPR[va]._u32[w], CPU.VPR[vb]._u32[w]); + CPU.VPR[vd]._u32[w] = std::min(CPU.VPR[va]._u32[w], CPU.VPR[vb]._u32[w]); } } void VMLADDUHM(u32 vd, u32 va, u32 vb, u32 vc) @@ -969,8 +965,8 @@ private: } void VMRGHB(u32 vd, u32 va, u32 vb) { - VPR_reg VA = CPU.VPR[va]; - VPR_reg VB = CPU.VPR[vb]; + u128 VA = CPU.VPR[va]; + u128 VB = CPU.VPR[vb]; for (uint h = 0; h < 8; h++) { CPU.VPR[vd]._u8[15 - h*2] = VA._u8[15 - h]; @@ -979,8 +975,8 @@ private: } void VMRGHH(u32 vd, u32 va, u32 vb) { - VPR_reg VA = CPU.VPR[va]; - VPR_reg VB = CPU.VPR[vb]; + u128 VA = CPU.VPR[va]; + u128 VB = CPU.VPR[vb]; for (uint w = 0; w < 4; w++) { CPU.VPR[vd]._u16[7 - w*2] = VA._u16[7 - w]; @@ -989,8 +985,8 @@ private: } void VMRGHW(u32 vd, u32 va, u32 vb) { - VPR_reg VA = CPU.VPR[va]; - VPR_reg VB = CPU.VPR[vb]; + u128 VA = CPU.VPR[va]; + u128 VB = CPU.VPR[vb]; for (uint d = 0; d < 2; d++) { CPU.VPR[vd]._u32[3 - d*2] = VA._u32[3 - d]; @@ -1065,14 +1061,14 @@ private: result += CPU.VPR[vc]._s32[w]; - if (result > INT_MAX) + if (result > 0x7fffffff) { - saturated = INT_MAX; + saturated = 0x7fffffff; CPU.VSCR.SAT = 1; } - else if (result < INT_MIN) + else if (result < (s64)(s32)0x80000000) { - saturated = INT_MIN; + saturated = 0x80000000; CPU.VSCR.SAT = 1; } else @@ -1125,9 +1121,9 @@ private: result += CPU.VPR[vc]._u32[w]; - if (result > UINT_MAX) + if (result > 0xffffffffu) { - saturated = UINT_MAX; + saturated = 0xffffffff; CPU.VSCR.SAT = 1; } else @@ -1260,7 +1256,7 @@ private: CPU.VSCR.SAT = 1; } - CPU.VPR[vd]._s8[b+8] = result; + CPU.VPR[vd]._s8[b+8] = (s8)result; result = CPU.VPR[vb]._s16[b]; @@ -1275,7 +1271,7 @@ private: CPU.VSCR.SAT = 1; } - CPU.VPR[vd]._s8[b] = result; + CPU.VPR[vd]._s8[b] = (s8)result; } } void VPKSHUS(u32 vd, u32 va, u32 vb) @@ -1295,7 +1291,7 @@ private: CPU.VSCR.SAT = 1; } - CPU.VPR[vd]._u8[b+8] = result; + CPU.VPR[vd]._u8[b+8] = (u8)result; result = CPU.VPR[vb]._s16[b]; @@ -1310,7 +1306,7 @@ private: CPU.VSCR.SAT = 1; } - CPU.VPR[vd]._u8[b] = result; + CPU.VPR[vd]._u8[b] = (u8)result; } } void VPKSWSS(u32 vd, u32 va, u32 vb) @@ -1403,7 +1399,7 @@ private: CPU.VSCR.SAT = 1; } - CPU.VPR[vd]._u8[b+8] = result; + CPU.VPR[vd]._u8[b+8] = (u8)result; result = CPU.VPR[vb]._u16[b]; @@ -1413,7 +1409,7 @@ private: CPU.VSCR.SAT = 1; } - CPU.VPR[vd]._u8[b] = result; + CPU.VPR[vd]._u8[b] = (u8)result; } } void VPKUWUM(u32 vd, u32 va, u32 vb) @@ -1506,7 +1502,7 @@ private: { for (uint w = 0; w < 4; w++) { - CPU.VPR[vd]._u32[w] = rotl32(CPU.VPR[va]._u32[w], CPU.VPR[vb]._u8[w*4] & 0x1f); + CPU.VPR[vd]._u32[w] = (u32)rotl32(CPU.VPR[va]._u32[w], CPU.VPR[vb]._u8[w*4] & 0x1f); } } void VRSQRTEFP(u32 vd, u32 vb) @@ -1582,7 +1578,7 @@ private: { u8 nShift = (CPU.VPR[vb]._u8[0] >> 3) & 0xf; - CPU.VPR[vd].Clear(); + CPU.VPR[vd].clear(); for (u8 b = 0; b < 16 - nShift; b++) { @@ -1715,7 +1711,7 @@ private: { u8 nShift = (CPU.VPR[vb]._u8[0] >> 3) & 0xf; - CPU.VPR[vd].Clear(); + CPU.VPR[vd].clear(); for (u8 b = 0; b < 16 - nShift; b++) { @@ -1871,7 +1867,7 @@ private: } void VSUMSWS(u32 vd, u32 va, u32 vb) { - CPU.VPR[vd].Clear(); + CPU.VPR[vd].clear(); s64 sum = CPU.VPR[vb]._s32[3]; @@ -2047,9 +2043,10 @@ private: void SUBFIC(u32 rd, u32 ra, s32 simm16) { const u64 RA = CPU.GPR[ra]; - const u64 IMM = (u64)(s64)simm16; - CPU.GPR[rd] = IMM - RA; - CPU.XER.CA = RA > IMM; + const u64 IMM = (s64)simm16; + CPU.GPR[rd] = ~RA + IMM + 1; + + CPU.XER.CA = CPU.IsCarry(~RA, IMM, 1); } void CMPLI(u32 crfd, u32 l, u32 ra, u32 uimm16) { @@ -2096,13 +2093,14 @@ private: case 0x1: UNK(fmt::Format("HyperCall %d", CPU.GPR[0])); break; case 0x2: SysCall(); break; case 0x3: - StaticExecute(CPU.GPR[11]); - if (Ini.LogAllSysCalls.GetValue()) + Emu.GetSFuncManager().StaticExecute((u32)CPU.GPR[11]); + if (Ini.HLELogging.GetValue()) { - ConLog.Write("'%s' done with code[0x%llx]! #pc: 0x%llx", - g_static_funcs_list[CPU.GPR[11]]->name, CPU.GPR[3], CPU.PC); + LOG_NOTICE(PPU, "'%s' done with code[0x%llx]! #pc: 0x%llx", + Emu.GetSFuncManager()[CPU.GPR[11]]->name, CPU.GPR[3], CPU.PC); } break; + case 0x4: CPU.FastStop(); break; case 0x22: UNK("HyperCall LV1"); break; default: UNK(fmt::Format("Unknown sc: %x", sc_code)); } @@ -2183,17 +2181,17 @@ private: { const u64 mask = rotate_mask[32 + mb][32 + me]; CPU.GPR[ra] = (CPU.GPR[ra] & ~mask) | (rotl32(CPU.GPR[rs], sh) & mask); - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } void RLWINM(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, bool rc) { CPU.GPR[ra] = rotl32(CPU.GPR[rs], sh) & rotate_mask[32 + mb][32 + me]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } void RLWNM(u32 ra, u32 rs, u32 rb, u32 mb, u32 me, bool rc) { CPU.GPR[ra] = rotl32(CPU.GPR[rs], CPU.GPR[rb] & 0x1f) & rotate_mask[32 + mb][32 + me]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } void ORI(u32 ra, u32 rs, u32 uimm16) { @@ -2214,12 +2212,12 @@ private: void ANDI_(u32 ra, u32 rs, u32 uimm16) { CPU.GPR[ra] = CPU.GPR[rs] & uimm16; - CPU.UpdateCR0(CPU.GPR[ra]); + CPU.UpdateCR0(CPU.GPR[ra]); } void ANDIS_(u32 ra, u32 rs, u32 uimm16) { CPU.GPR[ra] = CPU.GPR[rs] & (uimm16 << 16); - CPU.UpdateCR0(CPU.GPR[ra]); + CPU.UpdateCR0(CPU.GPR[ra]); } void RLDICL(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) { @@ -2246,11 +2244,11 @@ private: { if (is_r) // rldcr { - RLDICR(ra, rs, CPU.GPR[rb], m_eb, rc); + RLDICR(ra, rs, (u32)CPU.GPR[rb], m_eb, rc); } else // rldcl { - RLDICL(ra, rs, CPU.GPR[rb], m_eb, rc); + RLDICL(ra, rs, (u32)CPU.GPR[rb], m_eb, rc); } } void CMP(u32 crfd, u32 l, u32 ra, u32 rb) @@ -2259,8 +2257,8 @@ private: } void TW(u32 to, u32 ra, u32 rb) { - s32 a = CPU.GPR[ra]; - s32 b = CPU.GPR[rb]; + s32 a = (s32)CPU.GPR[ra]; + s32 b = (s32)CPU.GPR[rb]; if( (a < b && (to & 0x10)) || (a > b && (to & 0x8)) || @@ -2302,15 +2300,15 @@ private: { //const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; //CPU.VPR[vd].Clear(); - //CPU.VPR[vd]._u8[addr & 0xf] = Memory.Read8(addr); - CPU.VPR[vd]._u128 = Memory.Read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); + //CPU.VPR[vd]._u8[addr & 0xf] = vm::read8(addr); + CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); } void SUBFC(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - const s64 RA = CPU.GPR[ra]; - const s64 RB = CPU.GPR[rb]; + const u64 RA = CPU.GPR[ra]; + const u64 RB = CPU.GPR[rb]; CPU.GPR[rd] = ~RA + RB + 1; - CPU.XER.CA = CPU.IsCarry(RA, RB); + CPU.XER.CA = CPU.IsCarry(~RA, RB, 1); if(oe) UNK("subfco"); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } @@ -2319,7 +2317,7 @@ private: const s64 RA = CPU.GPR[ra]; const s64 RB = CPU.GPR[rb]; CPU.GPR[rd] = RA + RB; - CPU.XER.CA = RA <= RB; + CPU.XER.CA = CPU.IsCarry(RA, RB); if(oe) UNK("addco"); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } @@ -2330,10 +2328,10 @@ private: } void MULHWU(u32 rd, u32 ra, u32 rb, bool rc) { - u32 a = CPU.GPR[ra]; - u32 b = CPU.GPR[rb]; + u32 a = (u32)CPU.GPR[ra]; + u32 b = (u32)CPU.GPR[rb]; CPU.GPR[rd] = ((u64)a * (u64)b) >> 32; - if(rc) CPU.UpdateCR0(CPU.GPR[rd]); + if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } void MFOCRF(u32 a, u32 rd, u32 crm) { @@ -2367,31 +2365,27 @@ private: } void LWARX(u32 rd, u32 ra, u32 rb) { - const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - - SMutexLocker lock(reservation.mutex); - reservation.owner = lock.tid; - reservation.addr = addr; - reservation.size = 4; - reservation.data32 = CPU.GPR[rd] = Memory.Read32(addr); + CPU.R_ADDR = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + CPU.R_VALUE = vm::get_ref(CPU.R_ADDR); + CPU.GPR[rd] = re32((u32)CPU.R_VALUE); } void LDX(u32 rd, u32 ra, u32 rb) { - CPU.GPR[rd] = Memory.Read64(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); + CPU.GPR[rd] = vm::read64(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } void LWZX(u32 rd, u32 ra, u32 rb) { - CPU.GPR[rd] = Memory.Read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); + CPU.GPR[rd] = vm::read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } void SLW(u32 ra, u32 rs, u32 rb, bool rc) { u32 n = CPU.GPR[rb] & 0x1f; - u32 r = rotl32((u32)CPU.GPR[rs], n); - u32 m = (CPU.GPR[rb] & 0x20) ? 0 : rotate_mask[32][63 - n]; + u32 r = (u32)rotl32((u32)CPU.GPR[rs], n); + u32 m = ((u32)CPU.GPR[rb] & 0x20) ? 0 : (u32)rotate_mask[32][63 - n]; CPU.GPR[ra] = r & m; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } void CNTLZW(u32 ra, u32 rs, bool rc) { @@ -2455,8 +2449,8 @@ private: { //const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL; //CPU.VPR[vd].Clear(); - //(u16&)CPU.VPR[vd]._u8[addr & 0xf] = Memory.Read16(addr); - CPU.VPR[vd]._u128 = Memory.Read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); + //(u16&)CPU.VPR[vd]._u8[addr & 0xf] = vm::read16(addr); + CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); } void SUBF(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { @@ -2467,7 +2461,7 @@ private: void LDUX(u32 rd, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - CPU.GPR[rd] = Memory.Read64(addr); + CPU.GPR[rd] = vm::read64(addr); CPU.GPR[ra] = addr; } void DCBST(u32 ra, u32 rb) @@ -2478,7 +2472,7 @@ private: void LWZUX(u32 rd, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - CPU.GPR[rd] = Memory.Read32(addr); + CPU.GPR[rd] = vm::read32(addr); CPU.GPR[ra] = addr; } void CNTLZD(u32 ra, u32 rs, bool rc) @@ -2505,8 +2499,8 @@ private: { //const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL; //CPU.VPR[vd].Clear(); - //(u32&)CPU.VPR[vd]._u8[addr & 0xf] = Memory.Read32(addr); - CPU.VPR[vd]._u128 = Memory.Read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); + //(u32&)CPU.VPR[vd]._u8[addr & 0xf] = vm::read32(addr); + CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); } void MULHD(u32 rd, u32 ra, u32 rb, bool rc) { @@ -2515,20 +2509,16 @@ private: } void MULHW(u32 rd, u32 ra, u32 rb, bool rc) { - s32 a = CPU.GPR[ra]; - s32 b = CPU.GPR[rb]; + s32 a = (s32)CPU.GPR[ra]; + s32 b = (s32)CPU.GPR[rb]; CPU.GPR[rd] = ((s64)a * (s64)b) >> 32; - if(rc) CPU.UpdateCR0(CPU.GPR[rd]); + if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } void LDARX(u32 rd, u32 ra, u32 rb) { - const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - - SMutexLocker lock(reservation.mutex); - reservation.owner = lock.tid; - reservation.addr = addr; - reservation.size = 8; - reservation.data64 = CPU.GPR[rd] = Memory.Read64(addr); + CPU.R_ADDR = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + CPU.R_VALUE = vm::get_ref(CPU.R_ADDR); + CPU.GPR[rd] = re64(CPU.R_VALUE); } void DCBF(u32 ra, u32 rb) { @@ -2537,11 +2527,11 @@ private: } void LBZX(u32 rd, u32 ra, u32 rb) { - CPU.GPR[rd] = Memory.Read8(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); + CPU.GPR[rd] = vm::read8(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } void LVX(u32 vd, u32 ra, u32 rb) { - CPU.VPR[vd]._u128 = Memory.Read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); + CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); } void NEG(u32 rd, u32 ra, u32 oe, bool rc) { @@ -2554,7 +2544,7 @@ private: //if(ra == 0 || ra == rd) throw "Bad instruction [LBZUX]"; const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - CPU.GPR[rd] = Memory.Read8(addr); + CPU.GPR[rd] = vm::read8(addr); CPU.GPR[ra] = addr; } void NOR(u32 ra, u32 rs, u32 rb, bool rc) @@ -2566,14 +2556,14 @@ private: { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u8 eb = addr & 0xf; - Memory.Write8(addr, CPU.VPR[vs]._u8[15 - eb]); + vm::write8(addr, CPU.VPR[vs]._u8[15 - eb]); } void SUBFE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { const u64 RA = CPU.GPR[ra]; const u64 RB = CPU.GPR[rb]; CPU.GPR[rd] = ~RA + RB + CPU.XER.CA; - CPU.XER.CA = (~RA + CPU.XER.CA > ~RB) | ((RA == 0) & CPU.XER.CA); + CPU.XER.CA = CPU.IsCarry(~RA, RB, CPU.XER.CA); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); if(oe) UNK("subfeo"); } @@ -2637,100 +2627,94 @@ private: } void STDX(u32 rs, u32 ra, u32 rb) { - Memory.Write64((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.GPR[rs]); + vm::write64((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.GPR[rs]); } void STWCX_(u32 rs, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - SMutexLocker lock(reservation.mutex); - if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 4) + if (CPU.R_ADDR == addr) { - // Memory.Write32(addr, CPU.GPR[rs]); - CPU.SetCR_EQ(0, InterlockedCompareExchange((volatile long*) (Memory + addr), re((u32) CPU.GPR[rs]), re(reservation.data32)) == re(reservation.data32)); - reservation.clear(); + CPU.SetCR_EQ(0, InterlockedCompareExchange(vm::get_ptr(addr), re32((u32)CPU.GPR[rs]), (u32)CPU.R_VALUE) == (u32)CPU.R_VALUE); + CPU.R_ADDR = 0; } else { CPU.SetCR_EQ(0, false); - if (lock.tid == reservation.owner) reservation.clear(); } } void STWX(u32 rs, u32 ra, u32 rb) { - Memory.Write32((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.GPR[rs]); + vm::write32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb], (u32)CPU.GPR[rs]); } void STVEHX(u32 vs, u32 ra, u32 rb) { const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL; const u8 eb = (addr & 0xf) >> 1; - Memory.Write16(addr, CPU.VPR[vs]._u16[7 - eb]); + vm::write16(addr, CPU.VPR[vs]._u16[7 - eb]); } void STDUX(u32 rs, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - Memory.Write64(addr, CPU.GPR[rs]); + vm::write64(addr, CPU.GPR[rs]); CPU.GPR[ra] = addr; } void STWUX(u32 rs, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - Memory.Write32(addr, CPU.GPR[rs]); + vm::write32(addr, (u32)CPU.GPR[rs]); CPU.GPR[ra] = addr; } void STVEWX(u32 vs, u32 ra, u32 rb) { const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL; const u8 eb = (addr & 0xf) >> 2; - Memory.Write32(addr, CPU.VPR[vs]._u32[3 - eb]); + vm::write32(addr, CPU.VPR[vs]._u32[3 - eb]); } void ADDZE(u32 rd, u32 ra, u32 oe, bool rc) { const u64 RA = CPU.GPR[ra]; CPU.GPR[rd] = RA + CPU.XER.CA; CPU.XER.CA = CPU.IsCarry(RA, CPU.XER.CA); - if(oe) ConLog.Warning("addzeo"); + if(oe) LOG_WARNING(PPU, "addzeo"); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } void SUBFZE(u32 rd, u32 ra, u32 oe, bool rc) { const u64 RA = CPU.GPR[ra]; CPU.GPR[rd] = ~RA + CPU.XER.CA; - CPU.XER.CA = ((RA == 0) & CPU.XER.CA); - if (oe) ConLog.Warning("subfzeo"); + CPU.XER.CA = CPU.IsCarry(~RA, CPU.XER.CA); + if (oe) LOG_WARNING(PPU, "subfzeo"); if (rc) CPU.UpdateCR0(CPU.GPR[rd]); } void STDCX_(u32 rs, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - SMutexLocker lock(reservation.mutex); - if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 8) + if (CPU.R_ADDR == addr) { - // Memory.Write64(addr, CPU.GPR[rs]); - CPU.SetCR_EQ(0, InterlockedCompareExchange64((volatile long long*)(Memory + addr), re(CPU.GPR[rs]), re(reservation.data64)) == re(reservation.data64)); - reservation.clear(); + CPU.SetCR_EQ(0, InterlockedCompareExchange(vm::get_ptr(addr), re64(CPU.GPR[rs]), CPU.R_VALUE) == CPU.R_VALUE); + CPU.R_ADDR = 0; } else { CPU.SetCR_EQ(0, false); - if (lock.tid == reservation.owner) reservation.clear(); } } void STBX(u32 rs, u32 ra, u32 rb) { - Memory.Write8((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.GPR[rs]); + vm::write8((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), (u8)CPU.GPR[rs]); } void STVX(u32 vs, u32 ra, u32 rb) { - Memory.Write128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL, CPU.VPR[vs]._u128); + vm::write128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL, CPU.VPR[vs]); } void SUBFME(u32 rd, u32 ra, u32 oe, bool rc) { const u64 RA = CPU.GPR[ra]; - CPU.GPR[rd] = ~RA + CPU.XER.CA + 0xFFFFFFFFFFFFFFFF; - CPU.XER.CA = (~RA + CPU.XER.CA > ~0xFFFFFFFFFFFFFFFF) | ((RA == 0) & CPU.XER.CA); - if (oe) ConLog.Warning("subfmeo"); + CPU.GPR[rd] = ~RA + CPU.XER.CA + ~0ULL; + CPU.XER.CA = CPU.IsCarry(~RA, CPU.XER.CA, ~0ULL); + if (oe) LOG_WARNING(PPU, "subfmeo"); if (rc) CPU.UpdateCR0(CPU.GPR[rd]); } void MULLD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) @@ -2751,7 +2735,7 @@ private: void MULLW(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { CPU.GPR[rd] = (s64)((s64)(s32)CPU.GPR[ra] * (s64)(s32)CPU.GPR[rb]); - if(rc) CPU.UpdateCR0(CPU.GPR[rd]); + if(rc) CPU.UpdateCR0(CPU.GPR[rd]); if(oe) UNK("mullwo"); } void DCBTST(u32 ra, u32 rb, u32 th) @@ -2762,7 +2746,7 @@ private: void STBUX(u32 rs, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - Memory.Write8(addr, CPU.GPR[rs]); + vm::write8(addr, (u8)CPU.GPR[rs]); CPU.GPR[ra] = addr; } void ADD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) @@ -2780,7 +2764,7 @@ private: } void LHZX(u32 rd, u32 ra, u32 rb) { - CPU.GPR[rd] = Memory.Read16(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); + CPU.GPR[rd] = vm::read16(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } void EQV(u32 ra, u32 rs, u32 rb, bool rc) { @@ -2790,12 +2774,12 @@ private: void ECIWX(u32 rd, u32 ra, u32 rb) { //HACK! - CPU.GPR[rd] = Memory.Read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); + CPU.GPR[rd] = vm::read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } void LHZUX(u32 rd, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.GPR[rd] = Memory.Read16(addr); + CPU.GPR[rd] = vm::read16(addr); CPU.GPR[ra] = addr; } void XOR(u32 ra, u32 rs, u32 rb, bool rc) @@ -2809,7 +2793,7 @@ private: } void LWAX(u32 rd, u32 ra, u32 rb) { - CPU.GPR[rd] = (s64)(s32)Memory.Read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); + CPU.GPR[rd] = (s64)(s32)vm::read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } void DST(u32 ra, u32 rb, u32 strm, u32 t) { @@ -2817,11 +2801,11 @@ private: } void LHAX(u32 rd, u32 ra, u32 rb) { - CPU.GPR[rd] = (s64)(s16)Memory.Read16(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); + CPU.GPR[rd] = (s64)(s16)vm::read16(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } void LVXL(u32 vd, u32 ra, u32 rb) { - CPU.VPR[vd]._u128 = Memory.Read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); + CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); } void MFTB(u32 rd, u32 spr) { @@ -2837,7 +2821,7 @@ private: void LWAUX(u32 rd, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.GPR[rd] = (s64)(s32)Memory.Read32(addr); + CPU.GPR[rd] = (s64)(s32)vm::read32(addr); CPU.GPR[ra] = addr; } void DSTST(u32 ra, u32 rb, u32 strm, u32 t) @@ -2847,12 +2831,12 @@ private: void LHAUX(u32 rd, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.GPR[rd] = (s64)(s16)Memory.Read16(addr); + CPU.GPR[rd] = (s64)(s16)vm::read16(addr); CPU.GPR[ra] = addr; } void STHX(u32 rs, u32 ra, u32 rb) { - Memory.Write16(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb], CPU.GPR[rs]); + vm::write16(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb], (u16)CPU.GPR[rs]); } void ORC(u32 ra, u32 rs, u32 rb, bool rc) { @@ -2862,12 +2846,12 @@ private: void ECOWX(u32 rs, u32 ra, u32 rb) { //HACK! - Memory.Write32((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.GPR[rs]); + vm::write32((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), (u32)CPU.GPR[rs]); } void STHUX(u32 rs, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - Memory.Write16(addr, CPU.GPR[rs]); + vm::write16(addr, (u16)CPU.GPR[rs]); CPU.GPR[ra] = addr; } void OR(u32 ra, u32 rs, u32 rb, bool rc) @@ -2894,8 +2878,8 @@ private: } void DIVWU(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - const u32 RA = CPU.GPR[ra]; - const u32 RB = CPU.GPR[rb]; + const u32 RA = (u32)CPU.GPR[ra]; + const u32 RB = (u32)CPU.GPR[rb]; if(RB == 0) { @@ -2907,7 +2891,7 @@ private: CPU.GPR[rd] = RA / RB; } - if(rc) CPU.UpdateCR0(CPU.GPR[rd]); + if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } void MTSPR(u32 spr, u32 rs) { @@ -2922,7 +2906,7 @@ private: } void STVXL(u32 vs, u32 ra, u32 rb) { - Memory.Write128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL, CPU.VPR[vs]._u128); + vm::write128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL, CPU.VPR[vs]); } void DIVD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { @@ -2943,8 +2927,8 @@ private: } void DIVW(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - const s32 RA = CPU.GPR[ra]; - const s32 RB = CPU.GPR[rb]; + const s32 RA = (s32)CPU.GPR[ra]; + const s32 RB = (s32)CPU.GPR[rb]; if (RB == 0 || ((u32)RA == (1 << 31) && RB == -1)) { @@ -2956,18 +2940,19 @@ private: CPU.GPR[rd] = (u32)(RA / RB); } - if(rc) CPU.UpdateCR0(CPU.GPR[rd]); + if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } void LVLX(u32 vd, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u8 eb = addr & 0xf; - Memory.ReadLeft(CPU.VPR[vd]._u8 + eb, addr, 16 - eb); + CPU.VPR[vd].clear(); + for (u32 i = 0; i < 16 - eb; ++i) CPU.VPR[vd]._u8[15 - i] = vm::read8(addr + i); } void LDBRX(u32 rd, u32 ra, u32 rb) { - CPU.GPR[rd] = (u64&)Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]]; + CPU.GPR[rd] = vm::get_ref(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } void LSWX(u32 rd, u32 ra, u32 rb) { @@ -2975,21 +2960,21 @@ private: } void LWBRX(u32 rd, u32 ra, u32 rb) { - CPU.GPR[rd] = (u32&)Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]]; + CPU.GPR[rd] = vm::get_ref(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } void LFSX(u32 frd, u32 ra, u32 rb) { - (u32&)CPU.FPR[frd] = Memory.Read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); + (u32&)CPU.FPR[frd] = vm::read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); CPU.FPR[frd] = (float&)CPU.FPR[frd]; } void SRW(u32 ra, u32 rs, u32 rb, bool rc) { u32 n = CPU.GPR[rb] & 0x1f; - u32 r = rotl32((u32)CPU.GPR[rs], 64 - n); - u32 m = (CPU.GPR[rb] & 0x20) ? 0 : rotate_mask[32 + n][63]; + u32 r = (u32)rotl32((u32)CPU.GPR[rs], 64 - n); + u32 m = ((u32)CPU.GPR[rb] & 0x20) ? 0 : (u32)rotate_mask[32 + n][63]; CPU.GPR[ra] = r & m; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } void SRD(u32 ra, u32 rs, u32 rb, bool rc) { @@ -3005,19 +2990,20 @@ private: const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u8 eb = addr & 0xf; - Memory.ReadRight(CPU.VPR[vd]._u8, addr & ~0xf, eb); + CPU.VPR[vd].clear(); + for (u32 i = 16 - eb; i < 16; ++i) CPU.VPR[vd]._u8[15 - i] = vm::read8(addr + i - 16); } void LSWI(u32 rd, u32 ra, u32 nb) { u64 EA = ra ? CPU.GPR[ra] : 0; u64 N = nb ? nb : 32; - u8 reg = CPU.GPR[rd]; + u8 reg = (u8)CPU.GPR[rd]; while (N > 0) { if (N > 3) { - CPU.GPR[reg] = Memory.Read32(EA); + CPU.GPR[reg] = vm::read32(EA); EA += 4; N -= 4; } @@ -3027,7 +3013,7 @@ private: while (N > 0) { N = N - 1; - buf |= Memory.Read8(EA) <<(N*8) ; + buf |= vm::read8(EA) <<(N*8) ; EA = EA + 1; } CPU.GPR[reg] = buf; @@ -3038,7 +3024,7 @@ private: void LFSUX(u32 frd, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - (u64&)CPU.FPR[frd] = Memory.Read32(addr); + (u64&)CPU.FPR[frd] = vm::read32(addr); CPU.FPR[frd] = (float&)CPU.FPR[frd]; CPU.GPR[ra] = addr; } @@ -3048,12 +3034,12 @@ private: } void LFDX(u32 frd, u32 ra, u32 rb) { - (u64&)CPU.FPR[frd] = Memory.Read64(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); + (u64&)CPU.FPR[frd] = vm::read64(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } void LFDUX(u32 frd, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - (u64&)CPU.FPR[frd] = Memory.Read64(addr); + (u64&)CPU.FPR[frd] = vm::read64(addr); CPU.GPR[ra] = addr; } void STVLX(u32 vs, u32 ra, u32 rb) @@ -3061,7 +3047,7 @@ private: const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u8 eb = addr & 0xf; - Memory.WriteLeft(addr, 16 - eb, CPU.VPR[vs]._u8 + eb); + for (u32 i = 0; i < 16 - eb; ++i) vm::write8(addr + i, CPU.VPR[vs]._u8[15 - i]); } void STSWX(u32 rs, u32 ra, u32 rb) { @@ -3069,61 +3055,61 @@ private: } void STWBRX(u32 rs, u32 ra, u32 rb) { - (u32&)Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]] = CPU.GPR[rs]; + vm::get_ref(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) = (u32)CPU.GPR[rs]; } void STFSX(u32 frs, u32 ra, u32 rb) { - Memory.Write32((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.FPR[frs].To32()); + vm::write32((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.FPR[frs].To32()); } void STVRX(u32 vs, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u8 eb = addr & 0xf; - Memory.WriteRight(addr - eb, eb, CPU.VPR[vs]._u8); + for (u32 i = 16 - eb; i < 16; ++i) vm::write8(addr + i - 16, CPU.VPR[vs]._u8[15 - i]); } void STFSUX(u32 frs, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - Memory.Write32(addr, CPU.FPR[frs].To32()); + vm::write32(addr, CPU.FPR[frs].To32()); CPU.GPR[ra] = addr; } void STSWI(u32 rd, u32 ra, u32 nb) { - u64 EA = ra ? CPU.GPR[ra] : 0; - u64 N = nb ? nb : 32; - u8 reg = CPU.GPR[rd]; + u64 EA = ra ? CPU.GPR[ra] : 0; + u64 N = nb ? nb : 32; + u8 reg = (u8)CPU.GPR[rd]; - while (N > 0) + while (N > 0) + { + if (N > 3) { - if (N > 3) - { - Memory.Write32(EA, CPU.GPR[reg]); - EA += 4; - N -= 4; - } - else - { - u32 buf = CPU.GPR[reg]; - while (N > 0) - { - N = N - 1; - Memory.Write8(EA, (0xFF000000 & buf) >> 24); - buf <<= 8; - EA = EA + 1; - } - } - reg = (reg + 1) % 32; + vm::write32(EA, (u32)CPU.GPR[reg]); + EA += 4; + N -= 4; } + else + { + u32 buf = (u32)CPU.GPR[reg]; + while (N > 0) + { + N = N - 1; + vm::write8(EA, (0xFF000000 & buf) >> 24); + buf <<= 8; + EA = EA + 1; + } + } + reg = (reg + 1) % 32; + } } void STFDX(u32 frs, u32 ra, u32 rb) { - Memory.Write64((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), (u64&)CPU.FPR[frs]); + vm::write64((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), (u64&)CPU.FPR[frs]); } void STFDUX(u32 frs, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - Memory.Write64(addr, (u64&)CPU.FPR[frs]); + vm::write64(addr, (u64&)CPU.FPR[frs]); CPU.GPR[ra] = addr; } void LVLXL(u32 vd, u32 ra, u32 rb) @@ -3131,15 +3117,16 @@ private: const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u8 eb = addr & 0xf; - Memory.ReadLeft(CPU.VPR[vd]._u8 + eb, addr, 16 - eb); + CPU.VPR[vd].clear(); + for (u32 i = 0; i < 16 - eb; ++i) CPU.VPR[vd]._u8[15 - i] = vm::read8(addr + i); } void LHBRX(u32 rd, u32 ra, u32 rb) { - CPU.GPR[rd] = (u16&)Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]]; + CPU.GPR[rd] = vm::get_ref(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } void SRAW(u32 ra, u32 rs, u32 rb, bool rc) { - s32 RS = CPU.GPR[rs]; + s32 RS = (s32)CPU.GPR[rs]; u8 shift = CPU.GPR[rb] & 63; if (shift > 31) { @@ -3176,7 +3163,8 @@ private: const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u8 eb = addr & 0xf; - Memory.ReadRight(CPU.VPR[vd]._u8, addr & ~0xf, eb); + CPU.VPR[vd].clear(); + for (u32 i = 16 - eb; i < 16; ++i) CPU.VPR[vd]._u8[15 - i] = vm::read8(addr + i - 16); } void DSS(u32 strm, u32 a) { @@ -3211,37 +3199,37 @@ private: const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u8 eb = addr & 0xf; - Memory.WriteLeft(addr, 16 - eb, CPU.VPR[vs]._u8 + eb); + for (u32 i = 0; i < 16 - eb; ++i) vm::write8(addr + i, CPU.VPR[vs]._u8[15 - i]); } void STHBRX(u32 rs, u32 ra, u32 rb) { - (u16&)Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]] = CPU.GPR[rs]; + vm::get_ref(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) = (u16)CPU.GPR[rs]; } void EXTSH(u32 ra, u32 rs, bool rc) { CPU.GPR[ra] = (s64)(s16)CPU.GPR[rs]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } void STVRXL(u32 vs, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u8 eb = addr & 0xf; - Memory.WriteRight(addr - eb, eb, CPU.VPR[vs]._u8); + for (u32 i = 16 - eb; i < 16; ++i) vm::write8(addr + i - 16, CPU.VPR[vs]._u8[15 - i]); } void EXTSB(u32 ra, u32 rs, bool rc) { CPU.GPR[ra] = (s64)(s8)CPU.GPR[rs]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } void STFIWX(u32 frs, u32 ra, u32 rb) { - Memory.Write32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb], (u32&)CPU.FPR[frs]); + vm::write32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb], (u32&)CPU.FPR[frs]); } void EXTSW(u32 ra, u32 rs, bool rc) { CPU.GPR[ra] = (s64)(s32)CPU.GPR[rs]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } void ICBI(u32 ra, u32 rs) { @@ -3250,79 +3238,79 @@ private: void DCBZ(u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - u8 *const cache_line = Memory.GetMemFromAddr(addr & ~127); + auto const cache_line = vm::get_ptr(addr & ~127); if (cache_line) memset(cache_line, 0, 128); _mm_mfence(); } void LWZ(u32 rd, u32 ra, s32 d) { - CPU.GPR[rd] = Memory.Read32(ra ? CPU.GPR[ra] + d : d); + CPU.GPR[rd] = vm::read32(ra ? CPU.GPR[ra] + d : d); } void LWZU(u32 rd, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; - CPU.GPR[rd] = Memory.Read32(addr); + CPU.GPR[rd] = vm::read32(addr); CPU.GPR[ra] = addr; } void LBZ(u32 rd, u32 ra, s32 d) { - CPU.GPR[rd] = Memory.Read8(ra ? CPU.GPR[ra] + d : d); + CPU.GPR[rd] = vm::read8(ra ? CPU.GPR[ra] + d : d); } void LBZU(u32 rd, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; - CPU.GPR[rd] = Memory.Read8(addr); + CPU.GPR[rd] = vm::read8(addr); CPU.GPR[ra] = addr; } void STW(u32 rs, u32 ra, s32 d) { - Memory.Write32(ra ? CPU.GPR[ra] + d : d, CPU.GPR[rs]); + vm::write32(ra ? CPU.GPR[ra] + d : d, (u32)CPU.GPR[rs]); } void STWU(u32 rs, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; - Memory.Write32(addr, CPU.GPR[rs]); + vm::write32(addr, (u32)CPU.GPR[rs]); CPU.GPR[ra] = addr; } void STB(u32 rs, u32 ra, s32 d) { - Memory.Write8(ra ? CPU.GPR[ra] + d : d, CPU.GPR[rs]); + vm::write8(ra ? CPU.GPR[ra] + d : d, (u8)CPU.GPR[rs]); } void STBU(u32 rs, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; - Memory.Write8(addr, CPU.GPR[rs]); + vm::write8(addr, (u8)CPU.GPR[rs]); CPU.GPR[ra] = addr; } void LHZ(u32 rd, u32 ra, s32 d) { - CPU.GPR[rd] = Memory.Read16(ra ? CPU.GPR[ra] + d : d); + CPU.GPR[rd] = vm::read16(ra ? CPU.GPR[ra] + d : d); } void LHZU(u32 rd, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; - CPU.GPR[rd] = Memory.Read16(addr); + CPU.GPR[rd] = vm::read16(addr); CPU.GPR[ra] = addr; } void LHA(u32 rd, u32 ra, s32 d) { - CPU.GPR[rd] = (s64)(s16)Memory.Read16(ra ? CPU.GPR[ra] + d : d); + CPU.GPR[rd] = (s64)(s16)vm::read16(ra ? CPU.GPR[ra] + d : d); } void LHAU(u32 rd, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; - CPU.GPR[rd] = (s64)(s16)Memory.Read16(addr); + CPU.GPR[rd] = (s64)(s16)vm::read16(addr); CPU.GPR[ra] = addr; } void STH(u32 rs, u32 ra, s32 d) { - Memory.Write16(ra ? CPU.GPR[ra] + d : d, CPU.GPR[rs]); + vm::write16(ra ? CPU.GPR[ra] + d : d, (u16)CPU.GPR[rs]); } void STHU(u32 rs, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; - Memory.Write16(addr, CPU.GPR[rs]); + vm::write16(addr, (u16)CPU.GPR[rs]); CPU.GPR[ra] = addr; } void LMW(u32 rd, u32 ra, s32 d) @@ -3330,7 +3318,7 @@ private: u64 addr = ra ? CPU.GPR[ra] + d : d; for(u32 i=rd; i<32; ++i, addr += 4) { - CPU.GPR[i] = Memory.Read32(addr); + CPU.GPR[i] = vm::read32(addr); } } void STMW(u32 rs, u32 ra, s32 d) @@ -3338,65 +3326,65 @@ private: u64 addr = ra ? CPU.GPR[ra] + d : d; for(u32 i=rs; i<32; ++i, addr += 4) { - Memory.Write32(addr, CPU.GPR[i]); + vm::write32(addr, (u32)CPU.GPR[i]); } } void LFS(u32 frd, u32 ra, s32 d) { - const u32 v = Memory.Read32(ra ? CPU.GPR[ra] + d : d); + const u32 v = vm::read32(ra ? CPU.GPR[ra] + d : d); CPU.FPR[frd] = (float&)v; } void LFSU(u32 frd, u32 ra, s32 ds) { const u64 addr = CPU.GPR[ra] + ds; - const u32 v = Memory.Read32(addr); + const u32 v = vm::read32(addr); CPU.FPR[frd] = (float&)v; CPU.GPR[ra] = addr; } void LFD(u32 frd, u32 ra, s32 d) { - (u64&)CPU.FPR[frd] = Memory.Read64(ra ? CPU.GPR[ra] + d : d); + (u64&)CPU.FPR[frd] = vm::read64(ra ? CPU.GPR[ra] + d : d); } void LFDU(u32 frd, u32 ra, s32 ds) { const u64 addr = CPU.GPR[ra] + ds; - (u64&)CPU.FPR[frd] = Memory.Read64(addr); + (u64&)CPU.FPR[frd] = vm::read64(addr); CPU.GPR[ra] = addr; } void STFS(u32 frs, u32 ra, s32 d) { - Memory.Write32(ra ? CPU.GPR[ra] + d : d, CPU.FPR[frs].To32()); + vm::write32(ra ? CPU.GPR[ra] + d : d, CPU.FPR[frs].To32()); } void STFSU(u32 frs, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; - Memory.Write32(addr, CPU.FPR[frs].To32()); + vm::write32(addr, CPU.FPR[frs].To32()); CPU.GPR[ra] = addr; } void STFD(u32 frs, u32 ra, s32 d) { - Memory.Write64(ra ? CPU.GPR[ra] + d : d, (u64&)CPU.FPR[frs]); + vm::write64(ra ? CPU.GPR[ra] + d : d, (u64&)CPU.FPR[frs]); } void STFDU(u32 frs, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; - Memory.Write64(addr, (u64&)CPU.FPR[frs]); + vm::write64(addr, (u64&)CPU.FPR[frs]); CPU.GPR[ra] = addr; } void LD(u32 rd, u32 ra, s32 ds) { - CPU.GPR[rd] = Memory.Read64(ra ? CPU.GPR[ra] + ds : ds); + CPU.GPR[rd] = vm::read64(ra ? CPU.GPR[ra] + ds : ds); } void LDU(u32 rd, u32 ra, s32 ds) { //if(ra == 0 || rt == ra) return; const u64 addr = CPU.GPR[ra] + ds; - CPU.GPR[rd] = Memory.Read64(addr); + CPU.GPR[rd] = vm::read64(addr); CPU.GPR[ra] = addr; } void LWA(u32 rd, u32 ra, s32 ds) { - CPU.GPR[rd] = (s64)(s32)Memory.Read32(ra ? CPU.GPR[ra] + ds : ds); + CPU.GPR[rd] = (s64)(s32)vm::read32(ra ? CPU.GPR[ra] + ds : ds); } void FDIVS(u32 frd, u32 fra, u32 frb, bool rc) { @@ -3499,19 +3487,19 @@ private: } void STD(u32 rs, u32 ra, s32 d) { - Memory.Write64(ra ? CPU.GPR[ra] + d : d, CPU.GPR[rs]); + vm::write64(ra ? CPU.GPR[ra] + d : d, CPU.GPR[rs]); } void STDU(u32 rs, u32 ra, s32 ds) { //if(ra == 0 || rs == ra) return; const u64 addr = CPU.GPR[ra] + ds; - Memory.Write64(addr, CPU.GPR[rs]); + vm::write64(addr, CPU.GPR[rs]); CPU.GPR[ra] = addr; } void MTFSB1(u32 crbd, bool rc) { u64 mask = (1ULL << crbd); - if ((crbd == 29) && !CPU.FPSCR.NI) ConLog.Warning("Non-IEEE mode enabled"); + if ((crbd == 29) && !CPU.FPSCR.NI) LOG_WARNING(PPU, "Non-IEEE mode enabled"); CPU.FPSCR.FPSCR |= mask; if(rc) UNIMPLEMENTED(); @@ -3525,7 +3513,7 @@ private: void MTFSB0(u32 crbd, bool rc) { u64 mask = (1ULL << crbd); - if ((crbd == 29) && !CPU.FPSCR.NI) ConLog.Warning("Non-IEEE mode disabled"); + if ((crbd == 29) && !CPU.FPSCR.NI) LOG_WARNING(PPU, "Non-IEEE mode disabled"); CPU.FPSCR.FPSCR &= ~mask; if(rc) UNIMPLEMENTED(); @@ -3536,12 +3524,12 @@ private: if(i) { - if ((crfd == 29) && !CPU.FPSCR.NI) ConLog.Warning("Non-IEEE mode enabled"); + if ((crfd == 29) && !CPU.FPSCR.NI) LOG_WARNING(PPU, "Non-IEEE mode enabled"); CPU.FPSCR.FPSCR |= mask; } else { - if ((crfd == 29) && CPU.FPSCR.NI) ConLog.Warning("Non-IEEE mode disabled"); + if ((crfd == 29) && CPU.FPSCR.NI) LOG_WARNING(PPU, "Non-IEEE mode disabled"); CPU.FPSCR.FPSCR &= ~mask; } @@ -3565,9 +3553,9 @@ private: if (CPU.FPSCR.NI != oldNI) { if (oldNI) - ConLog.Warning("Non-IEEE mode disabled"); + LOG_WARNING(PPU, "Non-IEEE mode disabled"); else - ConLog.Warning("Non-IEEE mode enabled"); + LOG_WARNING(PPU, "Non-IEEE mode enabled"); } if(rc) UNK("mtfsf."); } @@ -3909,7 +3897,7 @@ private: break; } r = (u64)i; - double di = i; + double di = (double)i; if (di == b) { CPU.SetFPSCR_FI(0); @@ -3948,7 +3936,7 @@ private: else { s64 i = (s64)b; - double di = i; + double di = (double)i; if (di == b) { CPU.SetFPSCR_FI(0); @@ -3997,20 +3985,20 @@ private: void UNK(const std::string& err, bool pause = true) { - ConLog.Error(err + fmt::Format(" #pc: 0x%llx", CPU.PC)); + LOG_ERROR(PPU, err + fmt::Format(" #pc: 0x%llx", CPU.PC)); if(!pause) return; Emu.Pause(); - for(uint i=0; i<32; ++i) ConLog.Write("r%d = 0x%llx", i, CPU.GPR[i]); - for(uint i=0; i<32; ++i) ConLog.Write("f%d = %llf", i, CPU.FPR[i]); - for(uint i=0; i<32; ++i) ConLog.Write("v%d = 0x%s [%s]", i, CPU.VPR[i].ToString(true).c_str(), CPU.VPR[i].ToString().c_str()); - ConLog.Write("CR = 0x%08x", CPU.CR); - ConLog.Write("LR = 0x%llx", CPU.LR); - ConLog.Write("CTR = 0x%llx", CPU.CTR); - ConLog.Write("XER = 0x%llx [CA=%lld | OV=%lld | SO=%lld]", CPU.XER, fmt::by_value(CPU.XER.CA), fmt::by_value(CPU.XER.OV), fmt::by_value(CPU.XER.SO)); - ConLog.Write("FPSCR = 0x%x " + for(uint i=0; i<32; ++i) LOG_NOTICE(PPU, "r%d = 0x%llx", i, CPU.GPR[i]); + for(uint i=0; i<32; ++i) LOG_NOTICE(PPU, "f%d = %llf", i, CPU.FPR[i]); + for(uint i=0; i<32; ++i) LOG_NOTICE(PPU, "v%d = 0x%s [%s]", i, CPU.VPR[i].to_hex().c_str(), CPU.VPR[i].to_xyzw().c_str()); + LOG_NOTICE(PPU, "CR = 0x%08x", CPU.CR); + LOG_NOTICE(PPU, "LR = 0x%llx", CPU.LR); + LOG_NOTICE(PPU, "CTR = 0x%llx", CPU.CTR); + LOG_NOTICE(PPU, "XER = 0x%llx [CA=%lld | OV=%lld | SO=%lld]", CPU.XER, fmt::by_value(CPU.XER.CA), fmt::by_value(CPU.XER.OV), fmt::by_value(CPU.XER.SO)); + LOG_NOTICE(PPU, "FPSCR = 0x%x " "[RN=%d | NI=%d | XE=%d | ZE=%d | UE=%d | OE=%d | VE=%d | " "VXCVI=%d | VXSQRT=%d | VXSOFT=%d | FPRF=%d | " "FI=%d | FR=%d | VXVC=%d | VXIMZ=%d | " diff --git a/rpcs3/Emu/Cell/PPUProgramCompiler.cpp b/rpcs3/Emu/Cell/PPUProgramCompiler.cpp index 06e913ff83..9c3b760ea7 100644 --- a/rpcs3/Emu/Cell/PPUProgramCompiler.cpp +++ b/rpcs3/Emu/Cell/PPUProgramCompiler.cpp @@ -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 #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); diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 7a824b30ec..dfa0654251 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -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 -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(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>::make((u32)argv); + for(int i=0; i 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 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 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 flags + 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 underflow exception - u32 OX :1; //Floating-point overflow 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 floating-point instructions, including - //floating-point loads, stores, and moves. - //1 The processor can execute floating-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-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 + 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-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’ + 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(n, a, b); + UpdateCRn(n, (u32)a, (u32)b); } } @@ -693,11 +641,11 @@ public: { if(l) { - UpdateCRn(n, a, b); + UpdateCRn(n, (s64)a, (s64)b); } else { - UpdateCRn(n, a, b); + UpdateCRn(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 diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index d0cc2bb941..175dba64ce 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -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; iGetStartAddr() == 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& bp = Emu.GetBreakPoints(); + SPUThread::Task(); - try - { - for(uint i=0; iDecodeMemory(PC + m_offset)); - - if(status == CPUThread_Step) - { - m_is_step = false; - continue; - } - - for(uint i=0; i(10 - (int)op.length(), 0),' '); + op.append(std::max(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]); } diff --git a/rpcs3/Emu/Cell/SPUInstrTable.h b/rpcs3/Emu/Cell/SPUInstrTable.h index 2349f4aab6..267db8df8d 100644 --- a/rpcs3/Emu/Cell/SPUInstrTable.h +++ b/rpcs3/Emu/Cell/SPUInstrTable.h @@ -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); diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index 8522a34889..a14fee2ef1 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -1,26 +1,13 @@ #pragma once -#include "Emu/Cell/SPUOpcodes.h" -#include "Emu/Memory/Memory.h" -#include "Emu/Cell/SPUThread.h" -#include "Emu/SysCalls/SysCalls.h" -#include "Crypto/sha1.h" - #define UNIMPLEMENTED() UNK(__FUNCTION__) -/* typedef union _CRT_ALIGN(16) __u32x4 { - u32 _u32[4]; - __m128i m128i; - __m128 m128; - __m128d m128d; - } __u32x4; */ - #define MEM_AND_REG_HASH() \ - unsigned char mem_h[20]; sha1(&Memory[CPU.dmac.ls_offset], 256*1024, mem_h); \ + unsigned char mem_h[20]; sha1(vm::get_ptr(CPU.dmac.ls_offset), 256*1024, mem_h); \ unsigned char reg_h[20]; sha1((const unsigned char*)CPU.GPR, sizeof(CPU.GPR), reg_h); \ - ConLog.Write("Mem hash: 0x%llx, reg hash: 0x%llx", *(u64*)mem_h, *(u64*)reg_h); + LOG_NOTICE(Log::SPU, "Mem hash: 0x%llx, reg hash: 0x%llx", *(u64*)mem_h, *(u64*)reg_h); -#define LOG2_OPCODE(...) //MEM_AND_REG_HASH(); ConLog.Write(__FUNCTION__ "(): " __VA_ARGS__) +#define LOG2_OPCODE(...) //MEM_AND_REG_HASH(); LOG_NOTICE(Log::SPU, __FUNCTION__ "(): " __VA_ARGS__) #define LOG5_OPCODE(...) /// @@ -42,7 +29,7 @@ private: //0 - 10 void STOP(u32 code) { - CPU.DoStop(code); + CPU.StopAndSignal(code); LOG2_OPCODE(); } void LNOP() @@ -60,18 +47,7 @@ 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; - } + UNIMPLEMENTED(); // not used } void RDCH(u32 rt, u32 ra) { @@ -79,7 +55,7 @@ private: } void RCHCNT(u32 rt, u32 ra) { - CPU.GPR[rt].Reset(); + CPU.GPR[rt].clear(); CPU.GPR[rt]._u32[3] = CPU.GetChannelCount(ra); } void SF(u32 rt, u32 ra, u32 rb) @@ -136,10 +112,10 @@ private: } void ROTMA(u32 rt, u32 ra, u32 rb) { - CPU.GPR[rt]._i32[0] = ((0 - CPU.GPR[rb]._u32[0]) & 0x3f) < 32 ? CPU.GPR[ra]._i32[0] >> ((0 - CPU.GPR[rb]._u32[0]) & 0x3f) : CPU.GPR[ra]._i32[0] >> 31; - CPU.GPR[rt]._i32[1] = ((0 - CPU.GPR[rb]._u32[1]) & 0x3f) < 32 ? CPU.GPR[ra]._i32[1] >> ((0 - CPU.GPR[rb]._u32[1]) & 0x3f) : CPU.GPR[ra]._i32[1] >> 31; - CPU.GPR[rt]._i32[2] = ((0 - CPU.GPR[rb]._u32[2]) & 0x3f) < 32 ? CPU.GPR[ra]._i32[2] >> ((0 - CPU.GPR[rb]._u32[2]) & 0x3f) : CPU.GPR[ra]._i32[2] >> 31; - CPU.GPR[rt]._i32[3] = ((0 - CPU.GPR[rb]._u32[3]) & 0x3f) < 32 ? CPU.GPR[ra]._i32[3] >> ((0 - CPU.GPR[rb]._u32[3]) & 0x3f) : CPU.GPR[ra]._i32[3] >> 31; + CPU.GPR[rt]._s32[0] = ((0 - CPU.GPR[rb]._u32[0]) & 0x3f) < 32 ? CPU.GPR[ra]._s32[0] >> ((0 - CPU.GPR[rb]._u32[0]) & 0x3f) : CPU.GPR[ra]._s32[0] >> 31; + CPU.GPR[rt]._s32[1] = ((0 - CPU.GPR[rb]._u32[1]) & 0x3f) < 32 ? CPU.GPR[ra]._s32[1] >> ((0 - CPU.GPR[rb]._u32[1]) & 0x3f) : CPU.GPR[ra]._s32[1] >> 31; + CPU.GPR[rt]._s32[2] = ((0 - CPU.GPR[rb]._u32[2]) & 0x3f) < 32 ? CPU.GPR[ra]._s32[2] >> ((0 - CPU.GPR[rb]._u32[2]) & 0x3f) : CPU.GPR[ra]._s32[2] >> 31; + CPU.GPR[rt]._s32[3] = ((0 - CPU.GPR[rb]._u32[3]) & 0x3f) < 32 ? CPU.GPR[ra]._s32[3] >> ((0 - CPU.GPR[rb]._u32[3]) & 0x3f) : CPU.GPR[ra]._s32[3] >> 31; } void SHL(u32 rt, u32 ra, u32 rb) { @@ -161,7 +137,7 @@ private: void ROTMAH(u32 rt, u32 ra, u32 rb) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._i16[h] = ((0 - CPU.GPR[rb]._u16[h]) & 0x1f) < 16 ? CPU.GPR[ra]._i16[h] >> ((0 - CPU.GPR[rb]._u16[h]) & 0x1f) : CPU.GPR[ra]._i16[h] >> 15; + CPU.GPR[rt]._s16[h] = ((0 - CPU.GPR[rb]._u16[h]) & 0x1f) < 16 ? CPU.GPR[ra]._s16[h] >> ((0 - CPU.GPR[rb]._u16[h]) & 0x1f) : CPU.GPR[ra]._s16[h] >> 15; } void SHLH(u32 rt, u32 ra, u32 rb) { @@ -187,10 +163,10 @@ private: void ROTMAI(u32 rt, u32 ra, s32 i7) { const int nRot = (0 - i7) & 0x3f; - CPU.GPR[rt]._i32[0] = nRot < 32 ? CPU.GPR[ra]._i32[0] >> nRot : CPU.GPR[ra]._i32[0] >> 31; - CPU.GPR[rt]._i32[1] = nRot < 32 ? CPU.GPR[ra]._i32[1] >> nRot : CPU.GPR[ra]._i32[1] >> 31; - CPU.GPR[rt]._i32[2] = nRot < 32 ? CPU.GPR[ra]._i32[2] >> nRot : CPU.GPR[ra]._i32[2] >> 31; - CPU.GPR[rt]._i32[3] = nRot < 32 ? CPU.GPR[ra]._i32[3] >> nRot : CPU.GPR[ra]._i32[3] >> 31; + CPU.GPR[rt]._s32[0] = nRot < 32 ? CPU.GPR[ra]._s32[0] >> nRot : CPU.GPR[ra]._s32[0] >> 31; + CPU.GPR[rt]._s32[1] = nRot < 32 ? CPU.GPR[ra]._s32[1] >> nRot : CPU.GPR[ra]._s32[1] >> 31; + CPU.GPR[rt]._s32[2] = nRot < 32 ? CPU.GPR[ra]._s32[2] >> nRot : CPU.GPR[ra]._s32[2] >> 31; + CPU.GPR[rt]._s32[3] = nRot < 32 ? CPU.GPR[ra]._s32[3] >> nRot : CPU.GPR[ra]._s32[3] >> 31; } void SHLI(u32 rt, u32 ra, s32 i7) { @@ -218,7 +194,7 @@ private: const int nRot = (0 - i7) & 0x1f; for (int h = 0; h < 8; h++) - CPU.GPR[rt]._i16[h] = nRot < 16 ? CPU.GPR[ra]._i16[h] >> nRot : CPU.GPR[ra]._i16[h] >> 15; + CPU.GPR[rt]._s16[h] = nRot < 16 ? CPU.GPR[ra]._s16[h] >> nRot : CPU.GPR[ra]._s16[h] >> 15; } void SHLHI(u32 rt, u32 ra, s32 i7) { @@ -267,18 +243,20 @@ private: } void MTSPR(u32 rt, u32 sa) { - if(sa != 0) - { - CPU.SPR[sa]._u128.hi = CPU.GPR[rt]._u128.hi; - CPU.SPR[sa]._u128.lo = CPU.GPR[rt]._u128.lo; - } + UNIMPLEMENTED(); // not used } void WRCH(u32 ra, u32 rt) { CPU.WriteChannel(ra, CPU.GPR[rt]); } - void BIZ(u32 rt, u32 ra) + void BIZ(u32 intr, u32 rt, u32 ra) { + if (intr) + { + UNIMPLEMENTED(); + return; + } + u64 target = branchTarget(CPU.GPR[ra]._u32[3], 0); if (CPU.GPR[rt]._u32[3] == 0) { @@ -290,8 +268,14 @@ private: LOG5_OPCODE("not taken (0x%llx)", target); } } - void BINZ(u32 rt, u32 ra) + void BINZ(u32 intr, u32 rt, u32 ra) { + if (intr) + { + UNIMPLEMENTED(); + return; + } + u64 target = branchTarget(CPU.GPR[ra]._u32[3], 0); if (CPU.GPR[rt]._u32[3] != 0) { @@ -303,8 +287,14 @@ private: LOG5_OPCODE("not taken (0x%llx)", target); } } - void BIHZ(u32 rt, u32 ra) + void BIHZ(u32 intr, u32 rt, u32 ra) { + if (intr) + { + UNIMPLEMENTED(); + return; + } + u64 target = branchTarget(CPU.GPR[ra]._u32[3], 0); if (CPU.GPR[rt]._u16[6] == 0) { @@ -316,8 +306,14 @@ private: LOG5_OPCODE("not taken (0x%llx)", target); } } - void BIHNZ(u32 rt, u32 ra) + void BIHNZ(u32 intr, u32 rt, u32 ra) { + if (intr) + { + UNIMPLEMENTED(); + return; + } + u64 target = branchTarget(CPU.GPR[ra]._u32[3], 0); if (CPU.GPR[rt]._u16[6] != 0) { @@ -331,43 +327,47 @@ private: } void STOPD(u32 rc, u32 ra, u32 rb) { - UNIMPLEMENTED(); - Emu.Pause(); + UNIMPLEMENTED(); // not used } void STQX(u32 rt, u32 ra, u32 rb) { u32 lsa = (CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]) & 0x3fff0; - if(!CPU.IsGoodLSA(lsa)) + + CPU.WriteLS128(lsa, CPU.GPR[rt]); + } + void BI(u32 intr, u32 ra) + { + if (intr) { - ConLog.Error("STQX: bad lsa (0x%x)", lsa); - Emu.Pause(); + UNIMPLEMENTED(); return; } - CPU.WriteLS128(lsa, CPU.GPR[rt]._u128); - } - void BI(u32 ra) - { u64 target = branchTarget(CPU.GPR[ra]._u32[3], 0); LOG5_OPCODE("branch (0x%llx)", target); CPU.SetBranch(target); } - void BISL(u32 rt, u32 ra) + void BISL(u32 intr, u32 rt, u32 ra) { + if (intr) + { + UNIMPLEMENTED(); + return; + } + u64 target = branchTarget(CPU.GPR[ra]._u32[3], 0); - CPU.GPR[rt].Reset(); - CPU.GPR[rt]._u32[3] = CPU.PC + 4; + CPU.GPR[rt].clear(); + CPU.GPR[rt]._u32[3] = (u32)CPU.PC + 4; LOG5_OPCODE("branch (0x%llx)", target); CPU.SetBranch(target); } void IRET(u32 ra) { - UNIMPLEMENTED(); - //SetBranch(SRR0); + UNIMPLEMENTED(); // not used } - void BISLED(u32 rt, u32 ra) + void BISLED(u32 intr, u32 rt, u32 ra) { - UNIMPLEMENTED(); + UNIMPLEMENTED(); // not used } void HBR(u32 p, u32 ro, u32 ra) { @@ -436,35 +436,28 @@ private: u32 lsa = (a + b) & 0x3fff0; - if(!CPU.IsGoodLSA(lsa)) - { - ConLog.Error("LQX: bad lsa (0x%x)", lsa); - Emu.Pause(); - return; - } - - CPU.GPR[rt]._u128 = CPU.ReadLS128(lsa); + CPU.GPR[rt] = CPU.ReadLS128(lsa); } void ROTQBYBI(u32 rt, u32 ra, u32 rb) { const int s = (CPU.GPR[rb]._u32[3] >> 3) & 0xf; - const SPU_GPR_hdr temp = CPU.GPR[ra]; + const u128 temp = CPU.GPR[ra]; for (int b = 0; b < 16; b++) CPU.GPR[rt]._u8[b] = temp._u8[(b - s) & 0xf]; } void ROTQMBYBI(u32 rt, u32 ra, u32 rb) { const int s = (0 - (CPU.GPR[rb]._u32[3] >> 3)) & 0x1f; - const SPU_GPR_hdr temp = CPU.GPR[ra]; - CPU.GPR[rt].Reset(); + const u128 temp = CPU.GPR[ra]; + CPU.GPR[rt].clear(); for (int b = 0; b < 16 - s; b++) CPU.GPR[rt]._u8[b] = temp._u8[b + s]; } void SHLQBYBI(u32 rt, u32 ra, u32 rb) { const int s = (CPU.GPR[rb]._u32[3] >> 3) & 0x1f; - const SPU_GPR_hdr temp = CPU.GPR[ra]; - CPU.GPR[rt].Reset(); + const u128 temp = CPU.GPR[ra]; + CPU.GPR[rt].clear(); for (int b = s; b < 16; b++) CPU.GPR[rt]._u8[b] = temp._u8[b - s]; } @@ -503,50 +496,71 @@ private: void ROTQBI(u32 rt, u32 ra, u32 rb) { const int t = CPU.GPR[rb]._u32[3] & 0x7; - const SPU_GPR_hdr temp = CPU.GPR[ra]; - CPU.GPR[rt]._u32[0] = (temp._u32[0] << t) | (temp._u32[3] >> (32 - t)); - CPU.GPR[rt]._u32[1] = (temp._u32[1] << t) | (temp._u32[0] >> (32 - t)); - CPU.GPR[rt]._u32[2] = (temp._u32[2] << t) | (temp._u32[1] >> (32 - t)); - CPU.GPR[rt]._u32[3] = (temp._u32[3] << t) | (temp._u32[2] >> (32 - t)); + if (t) // not an optimization, it fixes shifts + { + const u128 temp = CPU.GPR[ra]; + CPU.GPR[rt]._u32[0] = (temp._u32[0] << t) | (temp._u32[3] >> (32 - t)); + CPU.GPR[rt]._u32[1] = (temp._u32[1] << t) | (temp._u32[0] >> (32 - t)); + CPU.GPR[rt]._u32[2] = (temp._u32[2] << t) | (temp._u32[1] >> (32 - t)); + CPU.GPR[rt]._u32[3] = (temp._u32[3] << t) | (temp._u32[2] >> (32 - t)); + } + else + { + CPU.GPR[rt] = CPU.GPR[ra]; + } } void ROTQMBI(u32 rt, u32 ra, u32 rb) { const int t = (0 - CPU.GPR[rb]._u32[3]) & 0x7; - const SPU_GPR_hdr temp = CPU.GPR[ra]; - CPU.GPR[rt]._u32[0] = (temp._u32[0] >> t) | (temp._u32[1] << (32 - t)); - CPU.GPR[rt]._u32[1] = (temp._u32[1] >> t) | (temp._u32[2] << (32 - t)); - CPU.GPR[rt]._u32[2] = (temp._u32[2] >> t) | (temp._u32[3] << (32 - t)); - CPU.GPR[rt]._u32[3] = (temp._u32[3] >> t); + if (t) // not an optimization, it fixes shifts + { + const u128 temp = CPU.GPR[ra]; + CPU.GPR[rt]._u32[0] = (temp._u32[0] >> t) | (temp._u32[1] << (32 - t)); + CPU.GPR[rt]._u32[1] = (temp._u32[1] >> t) | (temp._u32[2] << (32 - t)); + CPU.GPR[rt]._u32[2] = (temp._u32[2] >> t) | (temp._u32[3] << (32 - t)); + CPU.GPR[rt]._u32[3] = (temp._u32[3] >> t); + } + else + { + CPU.GPR[rt] = CPU.GPR[ra]; + } } void SHLQBI(u32 rt, u32 ra, u32 rb) { const int t = CPU.GPR[rb]._u32[3] & 0x7; - const SPU_GPR_hdr temp = CPU.GPR[ra]; - CPU.GPR[rt]._u32[0] = (temp._u32[0] << t); - CPU.GPR[rt]._u32[1] = (temp._u32[1] << t) | (temp._u32[0] >> (32 - t)); - CPU.GPR[rt]._u32[2] = (temp._u32[2] << t) | (temp._u32[1] >> (32 - t)); - CPU.GPR[rt]._u32[3] = (temp._u32[3] << t) | (temp._u32[2] >> (32 - t)); + if (t) // not an optimization, it fixes shifts + { + const u128 temp = CPU.GPR[ra]; + CPU.GPR[rt]._u32[0] = (temp._u32[0] << t); + CPU.GPR[rt]._u32[1] = (temp._u32[1] << t) | (temp._u32[0] >> (32 - t)); + CPU.GPR[rt]._u32[2] = (temp._u32[2] << t) | (temp._u32[1] >> (32 - t)); + CPU.GPR[rt]._u32[3] = (temp._u32[3] << t) | (temp._u32[2] >> (32 - t)); + } + else + { + CPU.GPR[rt] = CPU.GPR[ra]; + } } void ROTQBY(u32 rt, u32 ra, u32 rb) { const int s = CPU.GPR[rb]._u32[3] & 0xf; - const SPU_GPR_hdr temp = CPU.GPR[ra]; + const u128 temp = CPU.GPR[ra]; for (int b = 0; b < 16; ++b) CPU.GPR[rt]._u8[b] = temp._u8[(b - s) & 0xf]; } void ROTQMBY(u32 rt, u32 ra, u32 rb) { const int s = (0 - CPU.GPR[rb]._u32[3]) & 0x1f; - const SPU_GPR_hdr temp = CPU.GPR[ra]; - CPU.GPR[rt].Reset(); + const u128 temp = CPU.GPR[ra]; + CPU.GPR[rt].clear(); for (int b = 0; b < 16 - s; b++) CPU.GPR[rt]._u8[b] = temp._u8[b + s]; } void SHLQBY(u32 rt, u32 ra, u32 rb) { const int s = CPU.GPR[rb]._u32[3] & 0x1f; - const SPU_GPR_hdr temp = CPU.GPR[ra]; - CPU.GPR[rt].Reset(); + const u128 temp = CPU.GPR[ra]; + CPU.GPR[rt].clear(); for (int b = s; b < 16; b++) CPU.GPR[rt]._u8[b] = temp._u8[b - s]; } @@ -591,50 +605,71 @@ private: void ROTQBII(u32 rt, u32 ra, s32 i7) { const int s = i7 & 0x7; - const SPU_GPR_hdr temp = CPU.GPR[ra]; - CPU.GPR[rt]._u32[0] = (temp._u32[0] << s) | (temp._u32[3] >> (32 - s)); - CPU.GPR[rt]._u32[1] = (temp._u32[1] << s) | (temp._u32[0] >> (32 - s)); - CPU.GPR[rt]._u32[2] = (temp._u32[2] << s) | (temp._u32[1] >> (32 - s)); - CPU.GPR[rt]._u32[3] = (temp._u32[3] << s) | (temp._u32[2] >> (32 - s)); + if (s) // not an optimization, it fixes shifts + { + const u128 temp = CPU.GPR[ra]; + CPU.GPR[rt]._u32[0] = (temp._u32[0] << s) | (temp._u32[3] >> (32 - s)); + CPU.GPR[rt]._u32[1] = (temp._u32[1] << s) | (temp._u32[0] >> (32 - s)); + CPU.GPR[rt]._u32[2] = (temp._u32[2] << s) | (temp._u32[1] >> (32 - s)); + CPU.GPR[rt]._u32[3] = (temp._u32[3] << s) | (temp._u32[2] >> (32 - s)); + } + else + { + CPU.GPR[rt] = CPU.GPR[ra]; + } } void ROTQMBII(u32 rt, u32 ra, s32 i7) { const int s = (0 - i7) & 0x7; - const SPU_GPR_hdr temp = CPU.GPR[ra]; - CPU.GPR[rt]._u32[0] = (temp._u32[0] >> s) | (temp._u32[1] << (32 - s)); - CPU.GPR[rt]._u32[1] = (temp._u32[1] >> s) | (temp._u32[2] << (32 - s)); - CPU.GPR[rt]._u32[2] = (temp._u32[2] >> s) | (temp._u32[3] << (32 - s)); - CPU.GPR[rt]._u32[3] = (temp._u32[3] >> s); + if (s) // not an optimization, it fixes shifts + { + const u128 temp = CPU.GPR[ra]; + CPU.GPR[rt]._u32[0] = (temp._u32[0] >> s) | (temp._u32[1] << (32 - s)); + CPU.GPR[rt]._u32[1] = (temp._u32[1] >> s) | (temp._u32[2] << (32 - s)); + CPU.GPR[rt]._u32[2] = (temp._u32[2] >> s) | (temp._u32[3] << (32 - s)); + CPU.GPR[rt]._u32[3] = (temp._u32[3] >> s); + } + else + { + CPU.GPR[rt] = CPU.GPR[ra]; + } } void SHLQBII(u32 rt, u32 ra, s32 i7) { const int s = i7 & 0x7; - const SPU_GPR_hdr temp = CPU.GPR[ra]; - CPU.GPR[rt]._u32[0] = (temp._u32[0] << s); - CPU.GPR[rt]._u32[1] = (temp._u32[1] << s) | (temp._u32[0] >> (32 - s)); - CPU.GPR[rt]._u32[2] = (temp._u32[2] << s) | (temp._u32[1] >> (32 - s)); - CPU.GPR[rt]._u32[3] = (temp._u32[3] << s) | (temp._u32[2] >> (32 - s)); + if (s) // not an optimization, it fixes shifts + { + const u128 temp = CPU.GPR[ra]; + CPU.GPR[rt]._u32[0] = (temp._u32[0] << s); + CPU.GPR[rt]._u32[1] = (temp._u32[1] << s) | (temp._u32[0] >> (32 - s)); + CPU.GPR[rt]._u32[2] = (temp._u32[2] << s) | (temp._u32[1] >> (32 - s)); + CPU.GPR[rt]._u32[3] = (temp._u32[3] << s) | (temp._u32[2] >> (32 - s)); + } + else + { + CPU.GPR[rt] = CPU.GPR[ra]; + } } void ROTQBYI(u32 rt, u32 ra, s32 i7) { const int s = i7 & 0xf; - const SPU_GPR_hdr temp = CPU.GPR[ra]; + const u128 temp = CPU.GPR[ra]; for (int b = 0; b < 16; b++) CPU.GPR[rt]._u8[b] = temp._u8[(b - s) & 0xf]; } void ROTQMBYI(u32 rt, u32 ra, s32 i7) { const int s = (0 - i7) & 0x1f; - const SPU_GPR_hdr temp = CPU.GPR[ra]; - CPU.GPR[rt].Reset(); + const u128 temp = CPU.GPR[ra]; + CPU.GPR[rt].clear(); for (int b = 0; b < 16 - s; b++) CPU.GPR[rt]._u8[b] = temp._u8[b + s]; } void SHLQBYI(u32 rt, u32 ra, s32 i7) { const int s = i7 & 0x1f; - const SPU_GPR_hdr temp = CPU.GPR[ra]; - CPU.GPR[rt].Reset(); + const u128 temp = CPU.GPR[ra]; + CPU.GPR[rt].clear(); for (int b = s; b < 16; b++) CPU.GPR[rt]._u8[b] = temp._u8[b - s]; } @@ -644,7 +679,7 @@ private: void CGT(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._i32[w] > CPU.GPR[rb]._i32[w] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._s32[w] > CPU.GPR[rb]._s32[w] ? 0xffffffff : 0; } void XOR(u32 rt, u32 ra, u32 rb) { @@ -654,7 +689,7 @@ private: void CGTH(u32 rt, u32 ra, u32 rb) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._i16[h] > CPU.GPR[rb]._i16[h] ? 0xffff : 0; + CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._s16[h] > CPU.GPR[rb]._s16[h] ? 0xffff : 0; } void EQV(u32 rt, u32 ra, u32 rb) { @@ -664,12 +699,12 @@ private: void CGTB(u32 rt, u32 ra, u32 rb) { for (int b = 0; b < 16; b++) - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._i8[b] > CPU.GPR[rb]._i8[b] ? 0xff : 0; + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._s8[b] > CPU.GPR[rb]._s8[b] ? 0xff : 0; } void SUMB(u32 rt, u32 ra, u32 rb) { - const SPU_GPR_hdr _a = CPU.GPR[ra]; - const SPU_GPR_hdr _b = CPU.GPR[rb]; + const u128 _a = CPU.GPR[ra]; + const u128 _b = CPU.GPR[rb]; for (int w = 0; w < 4; w++) { CPU.GPR[rt]._u16[w*2] = _a._u8[w*4] + _a._u8[w*4 + 1] + _a._u8[w*4 + 2] + _a._u8[w*4 + 3]; @@ -679,7 +714,11 @@ private: //HGT uses signed values. HLGT uses unsigned values void HGT(u32 rt, s32 ra, s32 rb) { - if(CPU.GPR[ra]._i32[3] > CPU.GPR[rb]._i32[3]) CPU.Stop(); + if (CPU.GPR[ra]._s32[3] > CPU.GPR[rb]._s32[3]) + { + CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); + CPU.Stop(); + } } void CLZ(u32 rt, u32 ra) { @@ -696,18 +735,18 @@ private: } void XSWD(u32 rt, u32 ra) { - CPU.GPR[rt]._i64[0] = (s64)CPU.GPR[ra]._i32[0]; - CPU.GPR[rt]._i64[1] = (s64)CPU.GPR[ra]._i32[2]; + CPU.GPR[rt]._s64[0] = (s64)CPU.GPR[ra]._s32[0]; + CPU.GPR[rt]._s64[1] = (s64)CPU.GPR[ra]._s32[2]; } void XSHW(u32 rt, u32 ra) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = (s32)CPU.GPR[ra]._i16[w*2]; + CPU.GPR[rt]._s32[w] = (s32)CPU.GPR[ra]._s16[w*2]; } void CNTB(u32 rt, u32 ra) { - const SPU_GPR_hdr temp = CPU.GPR[ra]; - CPU.GPR[rt].Reset(); + const u128 temp = CPU.GPR[ra]; + CPU.GPR[rt].clear(); for (int b = 0; b < 16; b++) for (int i = 0; i < 8; i++) CPU.GPR[rt]._u8[b] += (temp._u8[b] & (1 << i)) ? 1 : 0; @@ -715,7 +754,7 @@ private: void XSBH(u32 rt, u32 ra) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._i16[h] = (s16)CPU.GPR[ra]._i8[h*2]; + CPU.GPR[rt]._s16[h] = (s16)CPU.GPR[ra]._s8[h*2]; } void CLGT(u32 rt, u32 ra, u32 rb) { @@ -738,29 +777,31 @@ private: } void DFCGT(u32 rt, u32 ra, u32 rb) { - CPU.GPR[rt]._u64[0] = CPU.GPR[ra]._d[0] > CPU.GPR[rb]._d[0] ? 0xffffffffffffffff : 0; - CPU.GPR[rt]._u64[1] = CPU.GPR[ra]._d[1] > CPU.GPR[rb]._d[1] ? 0xffffffffffffffff : 0; + UNIMPLEMENTED(); // cannot be used } void FA(u32 rt, u32 ra, u32 rb) { - CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] + CPU.GPR[rb]._f[0]; - CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] + CPU.GPR[rb]._f[1]; - CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] + CPU.GPR[rb]._f[2]; - CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] + CPU.GPR[rb]._f[3]; + for (int w = 0; w < 4; w++) + { + CPU.GPR[rt]._f[w] = CPU.GPR[ra]._f[w] + CPU.GPR[rb]._f[w]; + //if (CPU.GPR[rt]._f[w] == -0.0f) CPU.GPR[rt]._f[w] = 0.0f; + } } void FS(u32 rt, u32 ra, u32 rb) { - CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] - CPU.GPR[rb]._f[0]; - CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] - CPU.GPR[rb]._f[1]; - CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] - CPU.GPR[rb]._f[2]; - CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] - CPU.GPR[rb]._f[3]; + for (int w = 0; w < 4; w++) + { + CPU.GPR[rt]._f[w] = CPU.GPR[ra]._f[w] - CPU.GPR[rb]._f[w]; + //if (CPU.GPR[rt]._f[w] == -0.0f) CPU.GPR[rt]._f[w] = 0.0f; + } } void FM(u32 rt, u32 ra, u32 rb) { - CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0]; - CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1]; - CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2]; - CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3]; + for (int w = 0; w < 4; w++) + { + CPU.GPR[rt]._f[w] = CPU.GPR[ra]._f[w] * CPU.GPR[rb]._f[w]; + //if (CPU.GPR[rt]._f[w] == -0.0f) CPU.GPR[rt]._f[w] = 0.0f; + } } void CLGTH(u32 rt, u32 ra, u32 rb) { @@ -781,8 +822,7 @@ private: } void DFCMGT(u32 rt, u32 ra, u32 rb) { - CPU.GPR[rt]._u64[0] = fabs(CPU.GPR[ra]._d[0]) > fabs(CPU.GPR[rb]._d[0]) ? 0xffffffffffffffff : 0; - CPU.GPR[rt]._u64[1] = fabs(CPU.GPR[ra]._d[1]) > fabs(CPU.GPR[rb]._d[1]) ? 0xffffffffffffffff : 0; + UNIMPLEMENTED(); // cannot be used } void DFA(u32 rt, u32 ra, u32 rb) { @@ -806,7 +846,11 @@ private: } void HLGT(u32 rt, u32 ra, u32 rb) { - if(CPU.GPR[ra]._u32[3] > CPU.GPR[rb]._u32[3]) CPU.Stop(); + if (CPU.GPR[ra]._u32[3] > CPU.GPR[rb]._u32[3]) + { + CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); + CPU.Stop(); + } } void DFMA(u32 rt, u32 ra, u32 rb) { @@ -831,7 +875,7 @@ private: void CEQ(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._i32[w] == CPU.GPR[rb]._i32[w] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._s32[w] == CPU.GPR[rb]._s32[w] ? 0xffffffff : 0; } void MPYHHU(u32 rt, u32 ra, u32 rb) { @@ -850,11 +894,13 @@ private: } void CGX(u32 rt, u32 ra, u32 rb) { + // rarely used for (int w = 0; w < 4; w++) CPU.GPR[rt]._u32[w] = ((u64)CPU.GPR[ra]._u32[w] + (u64)CPU.GPR[rb]._u32[w] + (u64)(CPU.GPR[rt]._u32[w] & 1)) >> 32; } void BGX(u32 rt, u32 ra, u32 rb) { + // rarely used s64 nResult; for (int w = 0; w < 4; w++) @@ -866,7 +912,7 @@ private: void MPYHHA(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] += CPU.GPR[ra]._i16[w*2+1] * CPU.GPR[rb]._i16[w*2+1]; + CPU.GPR[rt]._s32[w] += CPU.GPR[ra]._s16[w*2+1] * CPU.GPR[rb]._s16[w*2+1]; } void MPYHHAU(u32 rt, u32 ra, u32 rb) { @@ -877,10 +923,8 @@ private: void FSCRRD(u32 rt) { - /*CPU.GPR[rt]._u128.lo = - CPU.FPSCR.Exception0 << 20 & - CPU.FPSCR.*/ - UNIMPLEMENTED(); + // TODO (rarely used) + CPU.GPR[rt].clear(); } void FESD(u32 rt, u32 ra) { @@ -896,60 +940,16 @@ private: } void FSCRWR(u32 rt, u32 ra) { - UNIMPLEMENTED(); + // TODO (rarely used) + if (CPU.GPR[ra]._u64[0] || CPU.GPR[ra]._u64[1]) + { + LOG_ERROR(SPU, "FSCRWR(%d,%d): value = %s", rt, ra, CPU.GPR[ra].to_hex().c_str()); + UNIMPLEMENTED(); + } } void DFTSV(u32 rt, u32 ra, s32 i7) { - 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; - } + UNIMPLEMENTED(); // cannot be used } void FCEQ(u32 rt, u32 ra, u32 rb) { @@ -960,28 +960,27 @@ private: } void DFCEQ(u32 rt, u32 ra, u32 rb) { - CPU.GPR[rt]._u64[0] = CPU.GPR[ra]._d[0] == CPU.GPR[rb]._d[0] ? 0xffffffffffffffff : 0; - CPU.GPR[rt]._u64[1] = CPU.GPR[ra]._d[1] == CPU.GPR[rb]._d[1] ? 0xffffffffffffffff : 0; + UNIMPLEMENTED(); // cannot be used } void MPY(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2] * CPU.GPR[rb]._i16[w*2]; + CPU.GPR[rt]._s32[w] = CPU.GPR[ra]._s16[w*2] * CPU.GPR[rb]._s16[w*2]; } void MPYH(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = (CPU.GPR[ra]._i16[w*2+1] * CPU.GPR[rb]._i16[w*2]) << 16; + CPU.GPR[rt]._s32[w] = (CPU.GPR[ra]._s16[w*2+1] * CPU.GPR[rb]._s16[w*2]) << 16; } void MPYHH(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2+1] * CPU.GPR[rb]._i16[w*2+1]; + CPU.GPR[rt]._s32[w] = CPU.GPR[ra]._s16[w*2+1] * CPU.GPR[rb]._s16[w*2+1]; } void MPYS(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = (CPU.GPR[ra]._i16[w*2] * CPU.GPR[rb]._i16[w*2]) >> 16; + CPU.GPR[rt]._s32[w] = (CPU.GPR[ra]._s16[w*2] * CPU.GPR[rb]._s16[w*2]) >> 16; } void CEQH(u32 rt, u32 ra, u32 rb) { @@ -997,8 +996,7 @@ private: } void DFCMEQ(u32 rt, u32 ra, u32 rb) { - CPU.GPR[rt]._u64[0] = fabs(CPU.GPR[ra]._d[0]) == fabs(CPU.GPR[rb]._d[0]) ? 0xffffffffffffffff : 0; - CPU.GPR[rt]._u64[1] = fabs(CPU.GPR[ra]._d[1]) == fabs(CPU.GPR[rb]._d[1]) ? 0xffffffffffffffff : 0; + UNIMPLEMENTED(); // cannot be used } void MPYU(u32 rt, u32 ra, u32 rb) { @@ -1012,13 +1010,17 @@ private: } void FI(u32 rt, u32 ra, u32 rb) { - //Floating Interpolation: ra will be ignored. - //It should work correctly if result of preceding FREST or FRSQEST is sufficiently exact + // TODO: Floating Interpolation: ra will be ignored. + // It should work correctly if result of preceding FREST or FRSQEST is sufficiently exact CPU.GPR[rt] = CPU.GPR[rb]; } void HEQ(u32 rt, u32 ra, u32 rb) { - if(CPU.GPR[ra]._i32[3] == CPU.GPR[rb]._i32[3]) CPU.Stop(); + if (CPU.GPR[ra]._s32[3] == CPU.GPR[rb]._s32[3]) + { + CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); + CPU.Stop(); + } } //0 - 9 @@ -1039,7 +1041,7 @@ private: else if (CPU.GPR[rt]._f[i] < -pow(2, 31)) CPU.GPR[rt]._u32[i] = 0x80000000; else - CPU.GPR[rt]._i32[i] = (s32)CPU.GPR[rt]._f[i]; //trunc + CPU.GPR[rt]._s32[i] = (s32)CPU.GPR[rt]._f[i]; //trunc } } void CFLTU(u32 rt, u32 ra, s32 i8) @@ -1061,7 +1063,7 @@ private: if (CPU.GPR[rt]._f[i] > 0xffffffff) //if big, result = max CPU.GPR[rt]._u32[i] = 0xffffffff; else - CPU.GPR[rt]._u32[i] = floor(CPU.GPR[rt]._f[i]); + CPU.GPR[rt]._u32[i] = (u32)floor(CPU.GPR[rt]._f[i]); } } } @@ -1070,7 +1072,7 @@ private: const u32 scale = 155 - (i8 & 0xff); //unsigned immediate for (int i = 0; i < 4; i++) { - CPU.GPR[rt]._f[i] = (s32)CPU.GPR[ra]._i32[i]; + CPU.GPR[rt]._f[i] = (float)CPU.GPR[ra]._s32[i]; u32 exp = ((CPU.GPR[rt]._u32[i] >> 23) & 0xff) - scale; @@ -1112,14 +1114,8 @@ private: void STQA(u32 rt, s32 i16) { u32 lsa = (i16 << 2) & 0x3fff0; - if(!CPU.IsGoodLSA(lsa)) - { - ConLog.Error("STQA: bad lsa (0x%x)", lsa); - Emu.Pause(); - return; - } - CPU.WriteLS128(lsa, CPU.GPR[rt]._u128); + CPU.WriteLS128(lsa, CPU.GPR[rt]); } void BRNZ(u32 rt, s32 i16) { @@ -1163,14 +1159,8 @@ private: void STQR(u32 rt, s32 i16) { u32 lsa = branchTarget(CPU.PC, i16) & 0x3fff0; - if(!CPU.IsGoodLSA(lsa)) - { - ConLog.Error("STQR: bad lsa (0x%x)", lsa); - Emu.Pause(); - return; - } - CPU.WriteLS128(lsa, CPU.GPR[rt]._u128); + CPU.WriteLS128(lsa, CPU.GPR[rt]); } void BRA(s32 i16) { @@ -1181,20 +1171,14 @@ private: void LQA(u32 rt, s32 i16) { u32 lsa = (i16 << 2) & 0x3fff0; - if(!CPU.IsGoodLSA(lsa)) - { - ConLog.Error("LQA: bad lsa (0x%x)", lsa); - Emu.Pause(); - return; - } - CPU.GPR[rt]._u128 = CPU.ReadLS128(lsa); + CPU.GPR[rt] = CPU.ReadLS128(lsa); } void BRASL(u32 rt, s32 i16) { u64 target = branchTarget(0, i16); - CPU.GPR[rt].Reset(); - CPU.GPR[rt]._u32[3] = CPU.PC + 4; + CPU.GPR[rt].clear(); + CPU.GPR[rt]._u32[3] = (u32)CPU.PC + 4; LOG5_OPCODE("branch (0x%llx)", target); CPU.SetBranch(target); } @@ -1223,44 +1207,38 @@ private: void BRSL(u32 rt, s32 i16) { u64 target = branchTarget(CPU.PC, i16); - CPU.GPR[rt].Reset(); - CPU.GPR[rt]._u32[3] = CPU.PC + 4; + CPU.GPR[rt].clear(); + CPU.GPR[rt]._u32[3] = (u32)CPU.PC + 4; LOG5_OPCODE("branch (0x%llx)", target); CPU.SetBranch(target); } void LQR(u32 rt, s32 i16) { u32 lsa = branchTarget(CPU.PC, i16) & 0x3fff0; - if(!CPU.IsGoodLSA(lsa)) - { - ConLog.Error("LQR: bad lsa (0x%x)", lsa); - Emu.Pause(); - return; - } - CPU.GPR[rt]._u128 = CPU.ReadLS128(lsa); + CPU.GPR[rt] = CPU.ReadLS128(lsa); } void IL(u32 rt, s32 i16) { - CPU.GPR[rt]._i32[0] = - CPU.GPR[rt]._i32[1] = - CPU.GPR[rt]._i32[2] = - CPU.GPR[rt]._i32[3] = i16; + CPU.GPR[rt]._s32[0] = + CPU.GPR[rt]._s32[1] = + CPU.GPR[rt]._s32[2] = + CPU.GPR[rt]._s32[3] = i16; } void ILHU(u32 rt, s32 i16) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = i16 << 16; + CPU.GPR[rt]._s32[w] = i16 << 16; } void ILH(u32 rt, s32 i16) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._i16[h] = i16; + CPU.GPR[rt]._s16[h] = i16; } void IOHL(u32 rt, s32 i16) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] |= (i16 & 0xFFFF); + CPU.GPR[rt]._s32[w] |= (i16 & 0xFFFF); } @@ -1268,112 +1246,105 @@ private: void ORI(u32 rt, u32 ra, s32 i10) { for(u32 i = 0; i < 4; ++i) - CPU.GPR[rt]._i32[i] = CPU.GPR[ra]._i32[i] | i10; + CPU.GPR[rt]._s32[i] = CPU.GPR[ra]._s32[i] | i10; } void ORHI(u32 rt, u32 ra, s32 i10) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._i16[h] = CPU.GPR[ra]._i16[h] | i10; + CPU.GPR[rt]._s16[h] = CPU.GPR[ra]._s16[h] | i10; } void ORBI(u32 rt, u32 ra, s32 i10) { for (int b = 0; b < 16; b++) - CPU.GPR[rt]._i8[b] = CPU.GPR[ra]._i8[b] | i10; + CPU.GPR[rt]._s8[b] = CPU.GPR[ra]._s8[b] | i10; } void SFI(u32 rt, u32 ra, s32 i10) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = i10 - CPU.GPR[ra]._i32[w]; + CPU.GPR[rt]._s32[w] = i10 - CPU.GPR[ra]._s32[w]; } void SFHI(u32 rt, u32 ra, s32 i10) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._i16[h] = i10 - CPU.GPR[ra]._i16[h]; + CPU.GPR[rt]._s16[h] = i10 - CPU.GPR[ra]._s16[h]; } void ANDI(u32 rt, u32 ra, s32 i10) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i32[w] & i10; + CPU.GPR[rt]._s32[w] = CPU.GPR[ra]._s32[w] & i10; } void ANDHI(u32 rt, u32 ra, s32 i10) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._i16[h] = CPU.GPR[ra]._i16[h] & i10; + CPU.GPR[rt]._s16[h] = CPU.GPR[ra]._s16[h] & i10; } void ANDBI(u32 rt, u32 ra, s32 i10) { for (int b = 0; b < 16; b++) - CPU.GPR[rt]._i8[b] = CPU.GPR[ra]._i8[b] & i10; + CPU.GPR[rt]._s8[b] = CPU.GPR[ra]._s8[b] & i10; } void AI(u32 rt, u32 ra, s32 i10) { - CPU.GPR[rt]._i32[0] = CPU.GPR[ra]._i32[0] + i10; - CPU.GPR[rt]._i32[1] = CPU.GPR[ra]._i32[1] + i10; - CPU.GPR[rt]._i32[2] = CPU.GPR[ra]._i32[2] + i10; - CPU.GPR[rt]._i32[3] = CPU.GPR[ra]._i32[3] + i10; + CPU.GPR[rt]._s32[0] = CPU.GPR[ra]._s32[0] + i10; + CPU.GPR[rt]._s32[1] = CPU.GPR[ra]._s32[1] + i10; + CPU.GPR[rt]._s32[2] = CPU.GPR[ra]._s32[2] + i10; + CPU.GPR[rt]._s32[3] = CPU.GPR[ra]._s32[3] + i10; } void AHI(u32 rt, u32 ra, s32 i10) { for(u32 h = 0; h < 8; ++h) - CPU.GPR[rt]._i16[h] = CPU.GPR[ra]._i16[h] + i10; + CPU.GPR[rt]._s16[h] = CPU.GPR[ra]._s16[h] + i10; } void STQD(u32 rt, s32 i10, u32 ra) //i10 is shifted left by 4 while decoding { - const u32 lsa = (CPU.GPR[ra]._i32[3] + i10) & 0x3fff0; - if(!CPU.IsGoodLSA(lsa)) - { - ConLog.Error("STQD: bad lsa (0x%x)", lsa); - Emu.Pause(); - return; - } - //ConLog.Write("STQD(lsa=0x%x): GPR[%d] (0x%llx%llx)", lsa, rt, CPU.GPR[rt]._u64[1], CPU.GPR[rt]._u64[0]); - CPU.WriteLS128(lsa, CPU.GPR[rt]._u128); + const u32 lsa = (CPU.GPR[ra]._s32[3] + i10) & 0x3fff0; + + //LOG_NOTICE(Log::SPU, "STQD(lsa=0x%x): GPR[%d] (0x%llx%llx)", lsa, rt, CPU.GPR[rt]._u64[1], CPU.GPR[rt]._u64[0]); + CPU.WriteLS128(lsa, CPU.GPR[rt]); } void LQD(u32 rt, s32 i10, u32 ra) //i10 is shifted left by 4 while decoding { - const u32 lsa = (CPU.GPR[ra]._i32[3] + i10) & 0x3fff0; - if(!CPU.IsGoodLSA(lsa)) - { - ConLog.Error("LQD: bad lsa (0x%x)", lsa); - Emu.Pause(); - return; - } + const u32 lsa = (CPU.GPR[ra]._s32[3] + i10) & 0x3fff0; - CPU.GPR[rt]._u128 = CPU.ReadLS128(lsa); + CPU.GPR[rt] = CPU.ReadLS128(lsa); } void XORI(u32 rt, u32 ra, s32 i10) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i32[w] ^ i10; + CPU.GPR[rt]._s32[w] = CPU.GPR[ra]._s32[w] ^ i10; } void XORHI(u32 rt, u32 ra, s32 i10) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._i16[h] = CPU.GPR[ra]._i16[h] ^ i10; + CPU.GPR[rt]._s16[h] = CPU.GPR[ra]._s16[h] ^ i10; } void XORBI(u32 rt, u32 ra, s32 i10) { for (int b = 0; b < 16; b++) - CPU.GPR[rt]._i8[b] = CPU.GPR[ra]._i8[b] ^ i10; + CPU.GPR[rt]._s8[b] = CPU.GPR[ra]._s8[b] ^ i10; } void CGTI(u32 rt, u32 ra, s32 i10) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._i32[w] > i10 ? 0xffffffff : 0; + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._s32[w] > i10 ? 0xffffffff : 0; } void CGTHI(u32 rt, u32 ra, s32 i10) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._i16[h] > i10 ? 0xffff : 0; + CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._s16[h] > i10 ? 0xffff : 0; } void CGTBI(u32 rt, u32 ra, s32 i10) { for (int b = 0; b < 16; b++) - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._i8[b] > (s8)(i10 & 0xff) ? 0xff : 0; + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._s8[b] > (s8)(i10 & 0xff) ? 0xff : 0; } void HGTI(u32 rt, u32 ra, s32 i10) { - if(CPU.GPR[ra]._i32[3] > i10) CPU.Stop(); + if (CPU.GPR[ra]._s32[3] > i10) + { + CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); + CPU.Stop(); + } } void CLGTI(u32 rt, u32 ra, s32 i10) { @@ -1396,12 +1367,16 @@ private: } void HLGTI(u32 rt, u32 ra, s32 i10) { - if(CPU.GPR[ra]._u32[3] > (u32)i10) CPU.Stop(); + if (CPU.GPR[ra]._u32[3] > (u32)i10) + { + CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); + CPU.Stop(); + } } void MPYI(u32 rt, u32 ra, s32 i10) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2] * i10; + CPU.GPR[rt]._s32[w] = CPU.GPR[ra]._s16[w*2] * i10; } void MPYUI(u32 rt, u32 ra, s32 i10) { @@ -1411,21 +1386,25 @@ private: void CEQI(u32 rt, u32 ra, s32 i10) { for(u32 i = 0; i < 4; ++i) - CPU.GPR[rt]._u32[i] = (CPU.GPR[ra]._i32[i] == i10) ? 0xffffffff : 0x00000000; + CPU.GPR[rt]._u32[i] = (CPU.GPR[ra]._s32[i] == i10) ? 0xffffffff : 0x00000000; } void CEQHI(u32 rt, u32 ra, s32 i10) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._u16[h] = (CPU.GPR[ra]._i16[h] == (s16)i10) ? 0xffff : 0; + CPU.GPR[rt]._u16[h] = (CPU.GPR[ra]._s16[h] == (s16)i10) ? 0xffff : 0; } void CEQBI(u32 rt, u32 ra, s32 i10) { for (int b = 0; b < 16; b++) - CPU.GPR[rt]._i8[b] = (CPU.GPR[ra]._i8[b] == (s8)(i10 & 0xff)) ? 0xff : 0; + CPU.GPR[rt]._s8[b] = (CPU.GPR[ra]._s8[b] == (s8)(i10 & 0xff)) ? 0xff : 0; } void HEQI(u32 rt, u32 ra, s32 i10) { - if(CPU.GPR[ra]._i32[3] == i10) CPU.Stop(); + if (CPU.GPR[ra]._s32[3] == i10) + { + CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); + CPU.Stop(); + } } @@ -1456,8 +1435,8 @@ private: } void SHUFB(u32 rt, u32 ra, u32 rb, u32 rc) { - const SPU_GPR_hdr _a = CPU.GPR[ra]; - const SPU_GPR_hdr _b = CPU.GPR[rb]; + const u128 _a = CPU.GPR[ra]; + const u128 _b = CPU.GPR[rb]; for (int i = 0; i < 16; i++) { u8 b = CPU.GPR[rc]._u8[i]; @@ -1485,28 +1464,31 @@ private: void MPYA(u32 rt, u32 ra, u32 rb, u32 rc) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2] * CPU.GPR[rb]._i16[w*2] + CPU.GPR[rc]._i32[w]; + CPU.GPR[rt]._s32[w] = CPU.GPR[ra]._s16[w*2] * CPU.GPR[rb]._s16[w*2] + CPU.GPR[rc]._s32[w]; } void FNMS(u32 rt, u32 ra, u32 rb, u32 rc) { - CPU.GPR[rt]._f[0] = CPU.GPR[rc]._f[0] - CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0]; - CPU.GPR[rt]._f[1] = CPU.GPR[rc]._f[1] - CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1]; - CPU.GPR[rt]._f[2] = CPU.GPR[rc]._f[2] - CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2]; - CPU.GPR[rt]._f[3] = CPU.GPR[rc]._f[3] - CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3]; + for (int w = 0; w < 4; w++) + { + CPU.GPR[rt]._f[w] = CPU.GPR[rc]._f[w] - CPU.GPR[ra]._f[w] * CPU.GPR[rb]._f[w]; + //if (CPU.GPR[rt]._f[w] == -0.0f) CPU.GPR[rt]._f[w] = 0.0f; + } } void FMA(u32 rt, u32 ra, u32 rb, u32 rc) { - CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0] + CPU.GPR[rc]._f[0]; - CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1] + CPU.GPR[rc]._f[1]; - CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2] + CPU.GPR[rc]._f[2]; - CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3] + CPU.GPR[rc]._f[3]; + for (int w = 0; w < 4; w++) + { + CPU.GPR[rt]._f[w] = CPU.GPR[rc]._f[w] + CPU.GPR[ra]._f[w] * CPU.GPR[rb]._f[w]; + //if (CPU.GPR[rt]._f[w] == -0.0f) CPU.GPR[rt]._f[w] = 0.0f; + } } void FMS(u32 rt, u32 ra, u32 rb, u32 rc) { - CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0] - CPU.GPR[rc]._f[0]; - CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1] - CPU.GPR[rc]._f[1]; - CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2] - CPU.GPR[rc]._f[2]; - CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3] - CPU.GPR[rc]._f[3]; + for (int w = 0; w < 4; w++) + { + CPU.GPR[rt]._f[w] = CPU.GPR[ra]._f[w] * CPU.GPR[rb]._f[w] - CPU.GPR[rc]._f[w]; + //if (CPU.GPR[rt]._f[w] == -0.0f) CPU.GPR[rt]._f[w] = 0.0f; + } } void UNK(u32 code, u32 opcode, u32 gcode) @@ -1516,8 +1498,8 @@ private: 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)); 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].to_hex().c_str()); } }; diff --git a/rpcs3/Emu/Cell/SPUOpcodes.h b/rpcs3/Emu/Cell/SPUOpcodes.h index d486ba7495..4c0901f45d 100644 --- a/rpcs3/Emu/Cell/SPUOpcodes.h +++ b/rpcs3/Emu/Cell/SPUOpcodes.h @@ -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; diff --git a/rpcs3/Emu/Cell/SPURSManager.cpp b/rpcs3/Emu/Cell/SPURSManager.cpp index 83548482dd..365c15847b 100644 --- a/rpcs3/Emu/Cell/SPURSManager.cpp +++ b/rpcs3/Emu/Cell/SPURSManager.cpp @@ -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 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 port, int isDynamic) +{ + //TODO: +} + +void SPURSManager::DetachLv2EventQueue(u8 port) +{ + //TODO: +} + +SPURSManagerTaskset::SPURSManagerTaskset(u32 address, SPURSManagerTasksetAttribute *tattr) +{ + this->tattr = tattr; + this->address = address; } \ No newline at end of file diff --git a/rpcs3/Emu/Cell/SPURSManager.h b/rpcs3/Emu/Cell/SPURSManager.h index ab250b44a4..ccfbcc16e8 100644 --- a/rpcs3/Emu/Cell/SPURSManager.h +++ b/rpcs3/Emu/Cell/SPURSManager.h @@ -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 nSpus; @@ -89,12 +24,55 @@ protected: be_t container; }; +class SPURSManagerEventFlag +{ +public: + SPURSManagerEventFlag(u32 flagClearMode, u32 flagDirection); + + u32 _getDirection() const + { + return this->flagDirection; + } + + u32 _getClearMode() const + { + return this->flagClearMode; + } + +protected: + be_t flagClearMode; + be_t flagDirection; +}; + +class SPURSManagerTasksetAttribute +{ +public: + SPURSManagerTasksetAttribute(u64 args, vm::ptr priority, u32 maxContention); + +protected: + be_t args; + be_t 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 port, int isDynamic); + void DetachLv2EventQueue(u8 port); protected: SPURSManagerAttribute *attr; diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 8a4c2d9ce2..03602fc564 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -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(&(((SPUThread*)0)->x)) ) #define cpu_qword(x) qword_ptr(*cpu_var, reinterpret_cast(&(((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(&opwr_##a0::opcode)), kFuncConvHost, FuncBuilder4()); \ + X86CallNode* call##a0 = c.call(imm_ptr(reinterpret_cast(&opwr_##a0::opcode)), kFuncConvHost, FuncBuilder4()); \ 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(&STOP_wrapper::STOP)), kFuncConvHost, FuncBuilder1()); + X86CallNode* call = c.call(imm_ptr(reinterpret_cast(&STOP_wrapper::STOP)), kFuncConvHost, FuncBuilder1()); 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(); diff --git a/rpcs3/Emu/Cell/SPURecompilerCore.cpp b/rpcs3/Emu/Cell/SPURecompilerCore.cpp index 839b2775e7..ff1d74942b 100644 --- a/rpcs3/Emu/Cell/SPURecompilerCore.cpp +++ b/rpcs3/Emu/Cell/SPURecompilerCore.cpp @@ -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(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(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(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()); } } diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 87c2956d1d..137b5c2326 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1,10 +1,25 @@ #include "stdafx.h" +#include "rpcs3/Ini.h" +#include "Utilities/Log.h" +#include "Emu/Memory/Memory.h" +#include "Emu/System.h" + +#include "Emu/IdManager.h" +#include "Emu/CPU/CPUThreadManager.h" +#include "Emu/Cell/PPUThread.h" +#include "Emu/SysCalls/ErrorCodes.h" +#include "Emu/SysCalls/lv2/sys_spu.h" +#include "Emu/SysCalls/lv2/sys_event_flag.h" +#include "Emu/SysCalls/lv2/sys_time.h" + +#include "Emu/Cell/SPUDisAsm.h" #include "Emu/Cell/SPUThread.h" #include "Emu/Cell/SPUDecoder.h" #include "Emu/Cell/SPUInterpreter.h" -#include "Emu/Cell/SPUDisAsm.h" #include "Emu/Cell/SPURecompiler.h" +#include + SPUThread& GetCurrentSPUThread() { PPCThread* thread = GetCurrentPPCThread(); @@ -30,12 +45,25 @@ SPUThread::~SPUThread() { } +void SPUThread::Task() +{ + const int round = std::fegetround(); + std::fesetround(FE_TOWARDZERO); + + CPUThread::Task(); + if (std::fegetround() != FE_TOWARDZERO) + { + LOG_ERROR(Log::SPU, "Rounding mode has changed(%d)", std::fegetround()); + } + std::fesetround(round); +} + void SPUThread::DoReset() { PPCThread::DoReset(); //reset regs - memset(GPR, 0, sizeof(SPU_GPR_hdr) * 128); + memset(GPR, 0, sizeof(u128) * 128); } void SPUThread::InitRegs() @@ -54,12 +82,18 @@ void SPUThread::InitRegs() dmac.proxy_lock = 0; dmac.queue_lock = 0;*/ - SPU.RunCntl.SetValue(SPU_RUNCNTL_STOP); - SPU.Status.SetValue(SPU_STATUS_RUNNING); - Prxy.QueryType.SetValue(0); + SPU.Status.SetValue(SPU_STATUS_STOPPED); + + // TODO: check initialization if necessary + MFC2.QueryType.SetValue(0); // prxy MFC1.CMDStatus.SetValue(0); MFC2.CMDStatus.SetValue(0); + MFC1.TagStatus.SetValue(0); + MFC2.TagStatus.SetValue(0); //PC = SPU.NPC.GetValue(); + + m_event_mask = 0; + m_events = 0; } u64 SPUThread::GetFreeStackSize() const @@ -79,7 +113,7 @@ void SPUThread::DoRun() break; default: - ConLog.Error("Invalid SPU decoder mode: %d", Ini.SPUDecoderMode.GetValue()); + LOG_ERROR(Log::SPU, "Invalid SPU decoder mode: %d", Ini.SPUDecoderMode.GetValue()); Emu.Pause(); } } @@ -108,7 +142,7 @@ void SPUThread::DoClose() for (u32 i = 0; i < 64; i++) { EventPort& port = SPUPs[i]; - SMutexLocker lock(port.mutex); + std::lock_guard lock(port.m_mutex); if (port.eq) { port.eq->ports.remove(&port); @@ -116,3 +150,950 @@ void SPUThread::DoClose() } } } + +void SPUThread::WriteSNR(bool number, u32 value) +{ + if (cfg.value & ((u64)1 << (u64)number)) + { + SPU.SNR[number ? 1 : 0].PushUncond_OR(value); // logical OR + } + else + { + SPU.SNR[number ? 1 : 0].PushUncond(value); // overwrite + } +} + +#define LOG_DMAC(type, text) type(Log::SPU, "DMAC::ProcessCmd(cmd=0x%x, tag=0x%x, lsa=0x%x, ea=0x%llx, size=0x%x): " text, cmd, tag, lsa, ea, size) + +void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) +{ + if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence(); + + if (ea >= SYS_SPU_THREAD_BASE_LOW) + { + if (ea >= 0x100000000) + { + LOG_DMAC(LOG_ERROR, "Invalid external address"); + Emu.Pause(); + return; + } + else if (group) + { + // SPU Thread Group MMIO (LS and SNR) + u32 num = (ea & SYS_SPU_THREAD_BASE_MASK) / SYS_SPU_THREAD_OFFSET; // thread number in group + if (num >= group->list.size() || !group->list[num]) + { + LOG_DMAC(LOG_ERROR, "Invalid thread (SPU Thread Group MMIO)"); + Emu.Pause(); + return; + } + + SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]); + + u32 addr = (ea & SYS_SPU_THREAD_BASE_MASK) % SYS_SPU_THREAD_OFFSET; + if ((addr <= 0x3ffff) && (addr + size <= 0x40000)) + { + // LS access + ea = spu->dmac.ls_offset + addr; + } + else if ((cmd & MFC_PUT_CMD) && size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2)) + { + spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, vm::read32(dmac.ls_offset + lsa)); + return; + } + else + { + LOG_DMAC(LOG_ERROR, "Invalid register (SPU Thread Group MMIO)"); + Emu.Pause(); + return; + } + } + else + { + LOG_DMAC(LOG_ERROR, "Thread group not set (SPU Thread Group MMIO)"); + Emu.Pause(); + return; + } + } + else if (ea >= RAW_SPU_BASE_ADDR && size == 4) + { + switch (cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK)) + { + case MFC_PUT_CMD: + { + vm::write32(ea, ReadLS32(lsa)); + return; + } + + case MFC_GET_CMD: + { + WriteLS32(lsa, vm::read32(ea)); + return; + } + + default: + { + LOG_DMAC(LOG_ERROR, "Unknown DMA command"); + Emu.Pause(); + return; + } + } + } + + switch (cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK)) + { + case MFC_PUT_CMD: + { + memcpy(vm::get_ptr(ea), vm::get_ptr(dmac.ls_offset + lsa), size); + return; + } + + case MFC_GET_CMD: + { + memcpy(vm::get_ptr(dmac.ls_offset + lsa), vm::get_ptr(ea), size); + return; + } + + default: + { + LOG_DMAC(LOG_ERROR, "Unknown DMA command"); + Emu.Pause(); + return; + } + } +} + +#undef LOG_CMD + +void SPUThread::ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs) +{ + u32 list_addr = ea & 0x3ffff; + u32 list_size = size / 8; + lsa &= 0x3fff0; + + struct list_element + { + be_t s; // Stall-and-Notify bit (0x8000) + be_t ts; // List Transfer Size + be_t ea; // External Address Low + }; + + u32 result = MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL; + + for (u32 i = 0; i < list_size; i++) + { + auto rec = vm::ptr::make((u32)dmac.ls_offset + list_addr + i * 8); + + u32 size = rec->ts; + if (size < 16 && size != 1 && size != 2 && size != 4 && size != 8) + { + LOG_ERROR(Log::SPU, "DMA List: invalid transfer size(%d)", size); + result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR; + break; + } + + u32 addr = rec->ea; + ProcessCmd(cmd, tag, lsa | (addr & 0xf), addr, size); + + if (Ini.HLELogging.GetValue() || rec->s) + LOG_NOTICE(Log::SPU, "*** list element(%d/%d): s = 0x%x, ts = 0x%x, low ea = 0x%x (lsa = 0x%x)", + i, list_size, (u16)rec->s, (u16)rec->ts, (u32)rec->ea, lsa | (addr & 0xf)); + + lsa += std::max(size, (u32)16); + + if (rec->s.ToBE() & se16(0x8000)) + { + StallStat.PushUncond_OR(1 << tag); + + if (StallList[tag].MFCArgs) + { + LOG_ERROR(Log::SPU, "DMA List: existing stalled list found (tag=%d)", tag); + result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR; + break; + } + StallList[tag].MFCArgs = &MFCArgs; + StallList[tag].cmd = cmd; + StallList[tag].ea = (ea & ~0xffffffff) | (list_addr + (i + 1) * 8); + StallList[tag].lsa = lsa; + StallList[tag].size = (list_size - i - 1) * 8; + + break; + } + } + + MFCArgs.CMDStatus.SetValue(result); +} + +void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) +{ + u32 cmd = MFCArgs.CMDStatus.GetValue(); + u16 op = cmd & MFC_MASK_CMD; + + u32 lsa = MFCArgs.LSA.GetValue(); + u64 ea = (u64)MFCArgs.EAL.GetValue() | ((u64)MFCArgs.EAH.GetValue() << 32); + u32 size_tag = MFCArgs.Size_Tag.GetValue(); + u16 tag = (u16)size_tag; + u16 size = size_tag >> 16; + + switch (op & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) + { + case MFC_PUT_CMD: + case MFC_PUTR_CMD: // ??? + case MFC_GET_CMD: + { + if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "DMA %s%s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", + (op & MFC_PUT_CMD ? "PUT" : "GET"), + (op & MFC_RESULT_MASK ? "R" : ""), + (op & MFC_BARRIER_MASK ? "B" : ""), + (op & MFC_FENCE_MASK ? "F" : ""), + lsa, ea, tag, size, cmd); + + ProcessCmd(cmd, tag, lsa, ea, size); + MFCArgs.CMDStatus.SetValue(MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL); + break; + } + + case MFC_PUTL_CMD: + case MFC_PUTRL_CMD: // ??? + case MFC_GETL_CMD: + { + if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "DMA %s%s%s%s: lsa = 0x%x, list = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", + (op & MFC_PUT_CMD ? "PUT" : "GET"), + (op & MFC_RESULT_MASK ? "RL" : "L"), + (op & MFC_BARRIER_MASK ? "B" : ""), + (op & MFC_FENCE_MASK ? "F" : ""), + lsa, ea, tag, size, cmd); + + ListCmd(lsa, ea, tag, size, cmd, MFCArgs); + break; + } + + case MFC_GETLLAR_CMD: + case MFC_PUTLLC_CMD: + case MFC_PUTLLUC_CMD: + case MFC_PUTQLLUC_CMD: + { + if (Ini.HLELogging.GetValue() || size != 128) LOG_NOTICE(Log::SPU, "DMA %s: lsa=0x%x, ea = 0x%llx, (tag) = 0x%x, (size) = 0x%x, cmd = 0x%x", + (op == MFC_GETLLAR_CMD ? "GETLLAR" : + op == MFC_PUTLLC_CMD ? "PUTLLC" : + op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC"), + lsa, ea, tag, size, cmd); + + if (op == MFC_GETLLAR_CMD) // get reservation + { + if (R_ADDR) + { + m_events |= SPU_EVENT_LR; + } + + R_ADDR = ea; + for (u32 i = 0; i < 16; i++) + { + R_DATA[i] = vm::get_ptr(R_ADDR)[i]; + vm::get_ptr(dmac.ls_offset + lsa)[i] = R_DATA[i]; + } + MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS); + } + else if (op == MFC_PUTLLC_CMD) // store conditional + { + MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS); + + if (R_ADDR == ea) + { + u32 changed = 0, mask = 0; + u64 buf[16]; + for (u32 i = 0; i < 16; i++) + { + buf[i] = vm::get_ptr(dmac.ls_offset + lsa)[i]; + if (buf[i] != R_DATA[i]) + { + changed++; + mask |= (0x3 << (i * 2)); + if (vm::get_ptr(R_ADDR)[i] != R_DATA[i]) + { + m_events |= SPU_EVENT_LR; + MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); + R_ADDR = 0; + return; + } + } + } + + for (u32 i = 0; i < 16; i++) + { + if (buf[i] != R_DATA[i]) + { + if (InterlockedCompareExchange(&vm::get_ptr(ea)[i], buf[i], R_DATA[i]) != R_DATA[i]) + { + m_events |= SPU_EVENT_LR; + MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); + + if (changed > 1) + { + LOG_ERROR(Log::SPU, "MFC_PUTLLC_CMD: Memory corrupted (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", + changed, mask, op, cmd, lsa, ea, tag, size); + Emu.Pause(); + } + + break; + } + } + } + + if (changed > 1) + { + LOG_WARNING(Log::SPU, "MFC_PUTLLC_CMD: Reservation impossibru (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", + changed, mask, op, cmd, lsa, ea, tag, size); + + SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode); + for (s32 i = (s32)PC; i < (s32)PC + 4 * 7; i += 4) + { + dis_asm.dump_pc = i; + dis_asm.offset = vm::get_ptr(dmac.ls_offset); + const u32 opcode = vm::read32(i + dmac.ls_offset); + (*SPU_instr::rrr_list)(&dis_asm, opcode); + if (i >= 0 && i < 0x40000) + { + LOG_NOTICE(Log::SPU, "*** %s", dis_asm.last_opcode.c_str()); + } + } + } + } + else + { + MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); + } + R_ADDR = 0; + } + else // store unconditional + { + if (R_ADDR) + { + m_events |= SPU_EVENT_LR; + } + + ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); + if (op == MFC_PUTLLUC_CMD) + { + MFCArgs.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS); + } + R_ADDR = 0; + } + break; + } + + default: + LOG_ERROR(Log::SPU, "Unknown MFC cmd. (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", + op, cmd, lsa, ea, tag, size); + break; + } +} + +bool SPUThread::CheckEvents() +{ + // checks events: + // SPU_EVENT_LR: + if (R_ADDR) + { + for (u32 i = 0; i < 16; i++) + { + if (vm::get_ptr(R_ADDR)[i] != R_DATA[i]) + { + m_events |= SPU_EVENT_LR; + R_ADDR = 0; + break; + } + } + } + + return (m_events & m_event_mask) != 0; +} + +u32 SPUThread::GetChannelCount(u32 ch) +{ + switch (ch) + { + case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount(); + case SPU_WrOutIntrMbox: return SPU.Out_IntrMBox.GetFreeCount(); + case SPU_RdInMbox: return SPU.In_MBox.GetCount(); + case MFC_RdTagStat: return MFC1.TagStatus.GetCount(); + case MFC_RdListStallStat: return StallStat.GetCount(); + case MFC_WrTagUpdate: return MFC1.TagStatus.GetCount(); // hack + case SPU_RdSigNotify1: return SPU.SNR[0].GetCount(); + case SPU_RdSigNotify2: return SPU.SNR[1].GetCount(); + case MFC_RdAtomicStat: return MFC1.AtomicStat.GetCount(); + case SPU_RdEventStat: return CheckEvents() ? 1 : 0; + + default: + { + LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).", + __FUNCTION__, ch, spu_ch_name[ch]); + return 0; + } + } +} + +void SPUThread::WriteChannel(u32 ch, const u128& r) +{ + const u32 v = r._u32[3]; + + switch (ch) + { + case SPU_WrOutIntrMbox: + { + if (!group) // if RawSPU + { + if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "SPU_WrOutIntrMbox: interrupt(v=0x%x)", v); + while (!SPU.Out_IntrMBox.Push(v)) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + if (Emu.IsStopped()) + { + LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); + return; + } + } + m_intrtag[2].stat |= 1; + if (CPUThread* t = Emu.GetCPU().GetThread(m_intrtag[2].thread)) + { + if (t->GetType() == CPU_THREAD_PPU && !t->IsAlive()) + { + PPUThread& ppu = *(PPUThread*)t; + ppu.FastStop(); + ppu.Run(); + ppu.FastCall(ppu.PC, ppu.GPR[2], ppu.m_interrupt_arg); + } + } + } + else + { + const u8 code = v >> 24; + if (code < 64) + { + /* ===== sys_spu_thread_send_event (used by spu_printf) ===== */ + + u8 spup = code & 63; + + u32 data; + if (!SPU.Out_MBox.Pop(data)) + { + LOG_ERROR(Log::SPU, "sys_spu_thread_send_event(v=0x%x, spup=%d): Out_MBox is empty", v, spup); + return; + } + + if (Ini.HLELogging.GetValue()) + { + LOG_NOTICE(Log::SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x)", spup, v & 0x00ffffff, data); + } + + EventPort& port = SPUPs[spup]; + + std::lock_guard lock(port.m_mutex); + + if (!port.eq) + { + LOG_WARNING(Log::SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (v & 0x00ffffff), data); + SPU.In_MBox.PushUncond(CELL_ENOTCONN); // TODO: check error passing + return; + } + + if (!port.eq->events.push(SYS_SPU_THREAD_EVENT_USER_KEY, GetCurrentCPUThread()->GetId(), ((u64)spup << 32) | (v & 0x00ffffff), data)) + { + SPU.In_MBox.PushUncond(CELL_EBUSY); + return; + } + + SPU.In_MBox.PushUncond(CELL_OK); + return; + } + else if (code < 128) + { + /* ===== sys_spu_thread_throw_event ===== */ + + const u8 spup = code & 63; + + u32 data; + if (!SPU.Out_MBox.Pop(data)) + { + LOG_ERROR(Log::SPU, "sys_spu_thread_throw_event(v=0x%x, spup=%d): Out_MBox is empty", v, spup); + return; + } + + //if (Ini.HLELogging.GetValue()) + { + LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x)", spup, v & 0x00ffffff, data); + } + + EventPort& port = SPUPs[spup]; + + std::lock_guard lock(port.m_mutex); + + if (!port.eq) + { + LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (v & 0x00ffffff), data); + return; + } + + // TODO: check passing spup value + if (!port.eq->events.push(SYS_SPU_THREAD_EVENT_USER_KEY, GetCurrentCPUThread()->GetId(), ((u64)spup << 32) | (v & 0x00ffffff), data)) + { + LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x) failed (queue is full)", spup, (v & 0x00ffffff), data); + return; + } + + return; + } + else if (code == 128) + { + /* ===== sys_event_flag_set_bit ===== */ + u32 flag = v & 0xffffff; + + u32 data; + if (!SPU.Out_MBox.Pop(data)) + { + LOG_ERROR(Log::SPU, "sys_event_flag_set_bit(v=0x%x (flag=%d)): Out_MBox is empty", v, flag); + return; + } + + if (flag > 63) + { + LOG_ERROR(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x): flag > 63", data, v, flag); + return; + } + + //if (Ini.HLELogging.GetValue()) + { + LOG_WARNING(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d))", data, v, flag); + } + + EventFlag* ef; + if (!Emu.GetIdManager().GetIDData(data, ef)) + { + LOG_ERROR(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d)): EventFlag not found", data, v, flag); + SPU.In_MBox.PushUncond(CELL_ESRCH); + return; + } + + u32 tid = GetCurrentCPUThread()->GetId(); + + ef->m_mutex.lock(tid); + ef->flags |= (u64)1 << flag; + if (u32 target = ef->check()) + { + // if signal, leave both mutexes locked... + ef->signal.lock(target); + ef->m_mutex.unlock(tid, target); + } + else + { + ef->m_mutex.unlock(tid); + } + + SPU.In_MBox.PushUncond(CELL_OK); + return; + } + else if (code == 192) + { + /* ===== sys_event_flag_set_bit_impatient ===== */ + u32 flag = v & 0xffffff; + + u32 data; + if (!SPU.Out_MBox.Pop(data)) + { + LOG_ERROR(Log::SPU, "sys_event_flag_set_bit_impatient(v=0x%x (flag=%d)): Out_MBox is empty", v, flag); + return; + } + + if (flag > 63) + { + LOG_ERROR(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x): flag > 63", data, v, flag); + return; + } + + //if (Ini.HLELogging.GetValue()) + { + LOG_WARNING(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x (flag=%d))", data, v, flag); + } + + EventFlag* ef; + if (!Emu.GetIdManager().GetIDData(data, ef)) + { + LOG_WARNING(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x (flag=%d)): EventFlag not found", data, v, flag); + return; + } + + u32 tid = GetCurrentCPUThread()->GetId(); + + ef->m_mutex.lock(tid); + ef->flags |= (u64)1 << flag; + if (u32 target = ef->check()) + { + // if signal, leave both mutexes locked... + ef->signal.lock(target); + ef->m_mutex.unlock(tid, target); + } + else + { + ef->m_mutex.unlock(tid); + } + + return; + } + else + { + u32 data; + if (SPU.Out_MBox.Pop(data)) + { + LOG_ERROR(Log::SPU, "SPU_WrOutIntrMbox: unknown data (v=0x%x); Out_MBox = 0x%x", v, data); + } + else + { + LOG_ERROR(Log::SPU, "SPU_WrOutIntrMbox: unknown data (v=0x%x)", v); + } + SPU.In_MBox.PushUncond(CELL_EINVAL); // ??? + return; + } + } + break; + } + + case SPU_WrOutMbox: + { + while (!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case MFC_WrTagMask: + { + MFC1.QueryMask.SetValue(v); + break; + } + + case MFC_WrTagUpdate: + { + MFC1.TagStatus.PushUncond(MFC1.QueryMask.GetValue()); + break; + } + + case MFC_LSA: + { + MFC1.LSA.SetValue(v); + break; + } + + case MFC_EAH: + { + MFC1.EAH.SetValue(v); + break; + } + + case MFC_EAL: + { + MFC1.EAL.SetValue(v); + break; + } + + case MFC_Size: + { + MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & 0xffff) | (v << 16)); + break; + } + + case MFC_TagID: + { + MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff)); + break; + } + + + case MFC_Cmd: + { + MFC1.CMDStatus.SetValue(v); + EnqMfcCmd(MFC1); + break; + } + + case MFC_WrListStallAck: + { + if (v >= 32) + { + LOG_ERROR(Log::SPU, "MFC_WrListStallAck error: invalid tag(%d)", v); + return; + } + StalledList temp = StallList[v]; + if (!temp.MFCArgs) + { + LOG_ERROR(Log::SPU, "MFC_WrListStallAck error: empty tag(%d)", v); + return; + } + StallList[v].MFCArgs = nullptr; + ListCmd(temp.lsa, temp.ea, temp.tag, temp.size, temp.cmd, *temp.MFCArgs); + break; + } + + case SPU_WrDec: + { + m_dec_start = get_time(); + m_dec_value = v; + break; + } + + case SPU_WrEventMask: + { + m_event_mask = v; + if (v & ~(SPU_EVENT_IMPLEMENTED)) LOG_ERROR(Log::SPU, "SPU_WrEventMask: unsupported event masked (0x%x)"); + break; + } + + case SPU_WrEventAck: + { + m_events &= ~v; + break; + } + + default: + { + LOG_ERROR(Log::SPU, "%s error (v=0x%x): unknown/illegal channel (%d [%s]).", __FUNCTION__, v, ch, spu_ch_name[ch]); + break; + } + } + + if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); +} + +void SPUThread::ReadChannel(u128& r, u32 ch) +{ + r.clear(); + u32& v = r._u32[3]; + + switch (ch) + { + case SPU_RdInMbox: + { + while (!SPU.In_MBox.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case MFC_RdTagStat: + { + while (!MFC1.TagStatus.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case MFC_RdTagMask: + { + v = MFC1.QueryMask.GetValue(); + break; + } + + case SPU_RdSigNotify1: + { + while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case SPU_RdSigNotify2: + { + while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case MFC_RdAtomicStat: + { + while (!MFC1.AtomicStat.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case MFC_RdListStallStat: + { + while (!StallStat.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case SPU_RdDec: + { + v = m_dec_value - (u32)(get_time() - m_dec_start); + break; + } + + case SPU_RdEventMask: + { + v = m_event_mask; + break; + } + + case SPU_RdEventStat: + { + while (!CheckEvents() && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + v = m_events & m_event_mask; + break; + } + + case SPU_RdMachStat: + { + v = 1; // hack (not isolated, interrupts enabled) + // TODO: check value + break; + } + + default: + { + LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); + break; + } + } + + if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); +} + +void SPUThread::StopAndSignal(u32 code) +{ + SetExitStatus(code); // exit code (not status) + // TODO: process interrupts for RawSPU + + switch (code) + { + case 0x110: + { + /* ===== sys_spu_thread_receive_event ===== */ + + u32 spuq = 0; + if (!SPU.Out_MBox.Pop(spuq)) + { + LOG_ERROR(Log::SPU, "sys_spu_thread_receive_event: cannot read Out_MBox"); + SPU.In_MBox.PushUncond(CELL_EINVAL); // ??? + return; + } + + if (SPU.In_MBox.GetCount()) + { + LOG_ERROR(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x): In_MBox is not empty", spuq); + SPU.In_MBox.PushUncond(CELL_EBUSY); // ??? + return; + } + + if (Ini.HLELogging.GetValue()) + { + LOG_NOTICE(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x)", spuq); + } + + EventQueue* eq; + if (!SPUQs.GetEventQueue(FIX_SPUQ(spuq), eq)) + { + SPU.In_MBox.PushUncond(CELL_EINVAL); // TODO: check error value + return; + } + + u32 tid = GetId(); + + eq->sq.push(tid); // add thread to sleep queue + + while (true) + { + switch (eq->owner.trylock(tid)) + { + case SMR_OK: + if (!eq->events.count()) + { + eq->owner.unlock(tid); + break; + } + else + { + u32 next = (eq->protocol == SYS_SYNC_FIFO) ? eq->sq.pop() : eq->sq.pop_prio(); + if (next != tid) + { + eq->owner.unlock(tid, next); + break; + } + } + case SMR_SIGNAL: + { + sys_event_data event; + eq->events.pop(event); + eq->owner.unlock(tid); + SPU.In_MBox.PushUncond(CELL_OK); + SPU.In_MBox.PushUncond((u32)event.data1); + SPU.In_MBox.PushUncond((u32)event.data2); + SPU.In_MBox.PushUncond((u32)event.data3); + return; + } + case SMR_FAILED: break; + default: eq->sq.invalidate(tid); SPU.In_MBox.PushUncond(CELL_ECANCELED); return; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + if (Emu.IsStopped()) + { + LOG_WARNING(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x) aborted", spuq); + eq->sq.invalidate(tid); + return; + } + } + break; + } + + case 0x101: + { + /* ===== sys_spu_thread_group_exit ===== */ + + if (!group) + { + LOG_ERROR(Log::SPU, "sys_spu_thread_group_exit(): group not set"); + break; + } + else if (!SPU.Out_MBox.GetCount()) + { + LOG_ERROR(Log::SPU, "sys_spu_thread_group_exit(): Out_MBox is empty"); + } + else if (Ini.HLELogging.GetValue()) + { + LOG_NOTICE(Log::SPU, "sys_spu_thread_group_exit(status=0x%x)", SPU.Out_MBox.GetValue()); + } + + group->m_group_exit = true; + group->m_exit_status = SPU.Out_MBox.GetValue(); + for (auto& v : group->list) + { + if (CPUThread* t = Emu.GetCPU().GetThread(v)) + { + t->Stop(); + } + } + + break; + } + + case 0x102: + { + /* ===== sys_spu_thread_exit ===== */ + + if (!SPU.Out_MBox.GetCount()) + { + LOG_ERROR(Log::SPU, "sys_spu_thread_exit(): Out_MBox is empty"); + } + else if (Ini.HLELogging.GetValue()) + { + // the real exit status + LOG_NOTICE(Log::SPU, "sys_spu_thread_exit(status=0x%x)", SPU.Out_MBox.GetValue()); + } + SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP); + Stop(); + break; + } + + default: + { + if (!SPU.Out_MBox.GetCount()) + { + LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (no message)", code); + } + else + { + LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue()); + } + Stop(); + break; + } + } +} \ No newline at end of file diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 0684ee93ff..935c169192 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -1,71 +1,7 @@ #pragma once #include "PPCThread.h" -#include "Emu/event.h" -#include "Emu/SysCalls/lv2/SC_SPU_Thread.h" +#include "Emu/Event.h" #include "MFC.h" -#include - -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", -}; -//SPU reg $0 is a dummy reg, and is used for certain instructions. -static const char* spu_specialreg_name[128] = { - "$0", "$1", "$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_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", -}; enum SPUchannels { @@ -103,6 +39,24 @@ enum MFCchannels MFC_RdAtomicStat = 27, //Read completion status of last completed immediate MFC atomic update command }; +enum SPUEvents +{ + SPU_EVENT_MS = 0x1000, // multisource synchronization event + SPU_EVENT_A = 0x800, // privileged attention event + SPU_EVENT_LR = 0x400, // lock line reservation lost event + SPU_EVENT_S1 = 0x200, // signal notification register 1 available + SPU_EVENT_S2 = 0x100, // signal notification register 2 available + SPU_EVENT_LE = 0x80, // SPU outbound mailbox available + SPU_EVENT_ME = 0x40, // SPU outbound interrupt mailbox available + SPU_EVENT_TM = 0x20, // SPU decrementer became negative (?) + SPU_EVENT_MB = 0x10, // SPU inbound mailbox available + SPU_EVENT_QV = 0x4, // MFC SPU command queue available + SPU_EVENT_SN = 0x2, // MFC list command stall-and-notify event + SPU_EVENT_TG = 0x1, // MFC tag-group status update event + + SPU_EVENT_IMPLEMENTED = SPU_EVENT_LR, +}; + enum { SPU_RUNCNTL_STOP = 0, @@ -128,6 +82,28 @@ enum : u32 SYS_SPU_THREAD_SNR2 = 0x05C00c, }; +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, +}; + //Floating point status and control register. Unsure if this is one of the GPRs or SPRs //Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused class FPSCR @@ -169,7 +145,7 @@ public: this->low = this->low & mask; } //Slice 0 or 1 - u8 checkSliceRounding(u8 slice) + u8 checkSliceRounding(u8 slice) const { switch(slice) { @@ -180,7 +156,7 @@ public: return this->low >> 22 & 0x3; default: - ConLog.Error("Unexpected slice value in FPSCR::checkSliceRounding(): %d", slice); + throw fmt::Format("Unexpected slice value in FPSCR::checkSliceRounding(): %d", slice); return 0; } } @@ -215,56 +191,6 @@ public: }; -union SPU_GPR_hdr -{ - u32 _u32[4]; - float _f[4]; - u128 _u128; - s128 _i128; - __m128 _m128; - __m128i _m128i; - u64 _u64[2]; - s64 _i64[2]; - s32 _i32[4]; - u16 _u16[8]; - s16 _i16[8]; - u8 _u8[16]; - s8 _i8[16]; - double _d[2]; - - - SPU_GPR_hdr() {} - - std::string ToString() const - { - return fmt::Format("%08x%08x%08x%08x", _u32[3], _u32[2], _u32[1], _u32[0]); - } - - void Reset() - { - memset(this, 0, sizeof(*this)); - } -}; - -union SPU_SPR_hdr -{ - u32 _u32[4]; - u128 _u128; - s128 _i128; - - SPU_SPR_hdr() {} - - std::string ToString() const - { - return fmt::Format("%08x%08x%08x%08x", _u32[3], _u32[2], _u32[1], _u32[0]); - } - - void Reset() - { - memset(this, 0, sizeof(*this)); - } -}; - union SPU_SNRConfig_hdr { u64 value; @@ -282,18 +208,44 @@ union SPU_SNRConfig_hdr } }; +struct SpuGroupInfo; + class SPUThread : public PPCThread { public: - SPU_GPR_hdr GPR[128]; //General-Purpose Register - SPU_SPR_hdr SPR[128]; //Special-Purpose Registers - FPSCR FPSCR; - SPU_SNRConfig_hdr cfg; //Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2) + u128 GPR[128]; // General-Purpose Registers + //FPSCR FPSCR; + SPU_SNRConfig_hdr cfg; // Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2) + + u64 R_ADDR; // reservation address + u64 R_DATA[16]; // lock line data (BE) EventPort SPUPs[64]; // SPU Thread Event Ports EventManager SPUQs; // SPU Queue Mapping SpuGroupInfo* group; // associated SPU Thread Group (null for raw spu) + u64 m_dec_start; // timestamp of writing decrementer value + u32 m_dec_value; // written decrementer value + + u32 m_event_mask; + u32 m_events; + + struct IntrTag + { + u32 enabled; // 1 == true + u32 thread; // established interrupt PPU thread + u64 mask; + u64 stat; + + IntrTag() + : enabled(0) + , thread(0) + , mask(0) + , stat(0) + { + } + } m_intrtag[3]; + template class Channel { @@ -318,7 +270,7 @@ public: void Init() { - m_index = 0; + m_indval = 0; } __forceinline bool Pop(u32& res) @@ -479,16 +431,11 @@ public: Channel<1> EAL; Channel<1> Size_Tag; Channel<1> CMDStatus; - Channel<1> QStatus; - } MFC1, MFC2; - - struct - { - Channel<1> QueryType; + Channel<1> QueryType; // only for prxy Channel<1> QueryMask; Channel<1> TagStatus; Channel<1> AtomicStat; - } Prxy; + } MFC1, MFC2; struct StalledList { @@ -509,25 +456,14 @@ public: struct { Channel<1> Out_MBox; + Channel<1> Out_IntrMBox; Channel<4> In_MBox; - Channel<1> MBox_Status; - Channel<1> RunCntl; Channel<1> Status; Channel<1> NPC; Channel<1> SNR[2]; } SPU; - void WriteSNR(bool number, u32 value) - { - if (cfg.value & ((u64)1 << (u64)number)) - { - SPU.SNR[number].PushUncond_OR(value); // logical OR - } - else - { - SPU.SNR[number].PushUncond(value); // overwrite - } - } + void WriteSNR(bool number, u32 value); u32 LSA; @@ -539,708 +475,33 @@ public: DMAC dmac; - bool ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) - { - if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence(); + void ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size); - if ((ea & 0xf0000000) == SYS_SPU_THREAD_BASE_LOW) - { - if (group) - { - // SPU Thread Group MMIO (LS and SNR) - u32 num = (ea & SYS_SPU_THREAD_BASE_MASK) / SYS_SPU_THREAD_OFFSET; // thread number in group - if (num >= group->list.size() || !group->list[num]) - { - ConLog.Error("DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx): invalid thread", ea); - return false; - } + void ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs); - SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]); + void EnqMfcCmd(MFCReg& MFCArgs); - u32 addr = (ea & SYS_SPU_THREAD_BASE_MASK) % SYS_SPU_THREAD_OFFSET; - if ((addr <= 0x3ffff) && (addr + size <= 0x40000)) - { - // LS access - ea = spu->dmac.ls_offset + addr; - } - else if ((cmd & MFC_PUT_CMD) && size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2)) - { - spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, Memory.Read32(dmac.ls_offset + lsa)); - return true; - } - else - { - ConLog.Error("DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx, size=%d, cmd=0x%x): invalid command", ea, size, cmd); - return false; - } - } - else - { - ConLog.Error("DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx): group not set", ea); - return false; - } - } + bool CheckEvents(); - //Sleep(1); // hack + u32 GetChannelCount(u32 ch); - switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK)) - { - case MFC_PUT_CMD: - { - return Memory.Copy(ea, dmac.ls_offset + lsa, size); - } + void WriteChannel(u32 ch, const u128& r); - case MFC_GET_CMD: - { - return Memory.Copy(dmac.ls_offset + lsa, ea, size); - } + void ReadChannel(u128& r, u32 ch); - default: - { - ConLog.Error("DMAC::ProcessCmd(): Unknown DMA cmd."); - return false; - } - } - } + void StopAndSignal(u32 code); - u32 dmacCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) - { - /*if(proxy_pos >= MFC_PPU_MAX_QUEUE_SPACE) - { - return MFC_PPU_DMA_QUEUE_FULL; - }*/ + u8 ReadLS8 (const u32 lsa) const { return vm::read8 (lsa + m_offset); } + u16 ReadLS16 (const u32 lsa) const { return vm::read16 (lsa + m_offset); } + u32 ReadLS32 (const u32 lsa) const { return vm::read32 (lsa + m_offset); } + u64 ReadLS64 (const u32 lsa) const { return vm::read64 (lsa + m_offset); } + u128 ReadLS128(const u32 lsa) const { return vm::read128(lsa + m_offset); } - if (ProcessCmd(cmd, tag, lsa, ea, size)) - return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL; - else - return MFC_PPU_DMA_CMD_SEQUENCE_ERROR; - } - - void ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs) - { - u32 list_addr = ea & 0x3ffff; - u32 list_size = size / 8; - lsa &= 0x3fff0; - - struct list_element - { - be_t s; // Stall-and-Notify bit (0x8000) - be_t ts; // List Transfer Size - be_t ea; // External Address Low - }; - - u32 result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR; - - for (u32 i = 0; i < list_size; i++) - { - mem_ptr_t rec(dmac.ls_offset + list_addr + i * 8); - - u32 size = rec->ts; - if (size < 16 && size != 1 && size != 2 && size != 4 && size != 8) - { - ConLog.Error("DMA List: invalid transfer size(%d)", size); - return; - } - - u32 addr = rec->ea; - result = dmacCmd(cmd, tag, lsa | (addr & 0xf), addr, size); - if (result == MFC_PPU_DMA_CMD_SEQUENCE_ERROR) - { - break; - } - - if (Ini.LogAllSysCalls.GetValue() || rec->s) - ConLog.Write("*** list element(%d/%d): s = 0x%x, ts = 0x%x, low ea = 0x%x (lsa = 0x%x)", - i, list_size, (u16)rec->s, (u16)rec->ts, (u32)rec->ea, lsa | (addr & 0xf)); - - lsa += max(size, (u32)16); - - if (rec->s & se16(0x8000)) - { - StallStat.PushUncond_OR(1 << tag); - - if (StallList[tag].MFCArgs) - { - ConLog.Error("DMA List: existing stalled list found (tag=%d)", tag); - } - StallList[tag].MFCArgs = &MFCArgs; - StallList[tag].cmd = cmd; - StallList[tag].ea = (ea & ~0xffffffff) | (list_addr + (i + 1) * 8); - StallList[tag].lsa = lsa; - StallList[tag].size = (list_size - i - 1) * 8; - - return; - } - } - - MFCArgs.CMDStatus.SetValue(result); - } - - void EnqMfcCmd(MFCReg& MFCArgs) - { - u32 cmd = MFCArgs.CMDStatus.GetValue(); - u16 op = cmd & MFC_MASK_CMD; - - u32 lsa = MFCArgs.LSA.GetValue(); - u64 ea = (u64)MFCArgs.EAL.GetValue() | ((u64)MFCArgs.EAH.GetValue() << 32); - u32 size_tag = MFCArgs.Size_Tag.GetValue(); - u16 tag = (u16)size_tag; - u16 size = size_tag >> 16; - - switch(op & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) - { - case MFC_PUT_CMD: - case MFC_PUTR_CMD: // ??? - case MFC_GET_CMD: - { - if (Ini.LogAllSysCalls.GetValue()) ConLog.Write("DMA %s%s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", - (op & MFC_PUT_CMD ? "PUT" : "GET"), - (op & MFC_RESULT_MASK ? "R" : ""), - (op & MFC_BARRIER_MASK ? "B" : ""), - (op & MFC_FENCE_MASK ? "F" : ""), - lsa, ea, tag, size, cmd); - - MFCArgs.CMDStatus.SetValue(dmacCmd(cmd, tag, lsa, ea, size)); - } - break; - - case MFC_PUTL_CMD: - case MFC_PUTRL_CMD: // ??? - case MFC_GETL_CMD: - { - if (Ini.LogAllSysCalls.GetValue()) ConLog.Write("DMA %s%s%s%s: lsa = 0x%x, list = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", - (op & MFC_PUT_CMD ? "PUT" : "GET"), - (op & MFC_RESULT_MASK ? "RL" : "L"), - (op & MFC_BARRIER_MASK ? "B" : ""), - (op & MFC_FENCE_MASK ? "F" : ""), - lsa, ea, tag, size, cmd); - - ListCmd(lsa, ea, tag, size, cmd, MFCArgs); - } - break; - - case MFC_GETLLAR_CMD: - case MFC_PUTLLC_CMD: - case MFC_PUTLLUC_CMD: - case MFC_PUTQLLUC_CMD: - { - if (Ini.LogAllSysCalls.GetValue() || size != 128) ConLog.Write("DMA %s: lsa=0x%x, ea = 0x%llx, (tag) = 0x%x, (size) = 0x%x, cmd = 0x%x", - (op == MFC_GETLLAR_CMD ? "GETLLAR" : - op == MFC_PUTLLC_CMD ? "PUTLLC" : - op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC"), - lsa, ea, tag, size, cmd); - - if (op == MFC_GETLLAR_CMD) // get reservation - { - SMutexLocker lock(reservation.mutex); - reservation.owner = lock.tid; - reservation.addr = ea; - reservation.size = 128; - for (u32 i = 0; i < 8; i++) - { - reservation.data[i] = *(u128*)&Memory[(u32)ea + i * 16]; - *(u128*)&Memory[dmac.ls_offset + lsa + i * 16] = reservation.data[i]; - } - Prxy.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS); - } - else if (op == MFC_PUTLLC_CMD) // store conditional - { - SMutexLocker lock(reservation.mutex); - if (reservation.owner == lock.tid) // succeeded - { - if (reservation.addr == ea && reservation.size == 128) - { - u128 buf[8]; // data being written newly - u32 changed = 0, mask = 0, last = 0; - for (u32 i = 0; i < 8; i++) - { - buf[i] = *(u128*)&Memory[dmac.ls_offset + lsa + i * 16]; - if (buf[i] != reservation.data[i]) - { - changed++; - last = i; - mask |= (0xf << (i * 4)); - } - } - if (changed == 0) // nothing changed? - { - Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS); - } - else if (changed == 1) - { - if (buf[last].hi != reservation.data[last].hi && buf[last].lo != reservation.data[last].lo) - { - ConLog.Error("MFC_PUTLLC_CMD: TODO: 128bit compare and swap"); - Emu.Pause(); - Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS); - } - else - { - const u32 last_q = (buf[last].hi == reservation.data[last].hi); - - if (InterlockedCompareExchange64((volatile long long*)(Memory + (u32)ea + last * 16 + last_q * 8), - buf[last]._u64[last_q], reservation.data[last]._u64[last_q]) == reservation.data[last]._u64[last_q]) - { - Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS); - } - else - { - Prxy.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); - } - /*u32 last_d = last_q * 2; - if (buf[last]._u32[last_d] == reservation.data[last]._u32[last_d] && buf[last]._u32[last_d+1] != reservation.data[last]._u32[last_d+1]) - { - last_d++; - } - else if (buf[last]._u32[last_d+1] == reservation.data[last]._u32[last_d+1]) - { - last_d; - } - else // full 64 bit - { - ConLog.Error("MFC_PUTLLC_CMD: TODO: 64bit compare and swap"); - Emu.Pause(); - Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS); - }*/ - } - } - else - { - ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); - ConLog.Error("MFC_PUTLLC_CMD: Reservation Error: impossibru (~ 16x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", - changed, mask, op, cmd, lsa, ea, tag, size); - Emu.Pause(); - Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS); - } - } - else - { - Prxy.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); - } - reservation.clear(); - } - else // failed - { - Prxy.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); - } - } - else // store unconditional - { - SMutexLocker lock(reservation.mutex); - ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); - if (op == MFC_PUTLLUC_CMD) - { - Prxy.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS); - } - if ((reservation.addr + reservation.size > ea && reservation.addr <= ea + size) || - (ea + size > reservation.addr && ea <= reservation.addr + reservation.size)) - { - reservation.clear(); - } - } - } - break; - - default: - ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", - op, cmd, lsa, ea, tag, size); - break; - } - } - - u32 GetChannelCount(u32 ch) - { - u32 count; - switch(ch) - { - case SPU_WrOutMbox: - return SPU.Out_MBox.GetFreeCount(); - - case SPU_RdInMbox: - count = SPU.In_MBox.GetCount(); - //ConLog.Warning("GetChannelCount(%s) -> %d", spu_ch_name[ch], count); - return count; - - case SPU_WrOutIntrMbox: - ConLog.Warning("GetChannelCount(%s) = 0", spu_ch_name[ch]); - return 0; - - case MFC_RdTagStat: - return Prxy.TagStatus.GetCount(); - - case MFC_RdListStallStat: - return StallStat.GetCount(); - - case MFC_WrTagUpdate: - return Prxy.TagStatus.GetCount(); // hack - - case SPU_RdSigNotify1: - return SPU.SNR[0].GetCount(); - - case SPU_RdSigNotify2: - return SPU.SNR[1].GetCount(); - - case MFC_RdAtomicStat: - return Prxy.AtomicStat.GetCount(); - - default: - ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", - __FUNCTION__, ch, spu_ch_name[ch]); - break; - } - - return 0; - } - - void WriteChannel(u32 ch, const SPU_GPR_hdr& r) - { - const u32 v = r._u32[3]; - - switch(ch) - { - case SPU_WrOutIntrMbox: - { - u8 code = v >> 24; - if (code < 64) - { - /* ===== sys_spu_thread_send_event ===== */ - - u8 spup = code & 63; - - u32 data; - if (!SPU.Out_MBox.Pop(data)) - { - ConLog.Error("sys_spu_thread_send_event(v=0x%x, spup=%d): Out_MBox is empty", v, spup); - return; - } - - if (SPU.In_MBox.GetCount()) - { - ConLog.Error("sys_spu_thread_send_event(v=0x%x, spup=%d): In_MBox is not empty", v, spup); - SPU.In_MBox.PushUncond(CELL_EBUSY); // ??? - return; - } - - if (Ini.LogAllSysCalls.GetValue()) - { - ConLog.Write("sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x)", spup, v & 0x00ffffff, data); - } - - EventPort& port = SPUPs[spup]; - - SMutexLocker lock(port.mutex); - - if (!port.eq) - { - SPU.In_MBox.PushUncond(CELL_ENOTCONN); // check error passing - return; - } - - if (!port.eq->events.push(SYS_SPU_THREAD_EVENT_USER_KEY, lock.tid, ((u64)code << 32) | (v & 0x00ffffff), data)) - { - SPU.In_MBox.PushUncond(CELL_EBUSY); - return; - } - - SPU.In_MBox.PushUncond(CELL_OK); - return; - } - else if (code == 128) - { - /* ===== sys_event_flag_set_bit ===== */ - u32 flag = v & 0xffffff; - - u32 data; - if (!SPU.Out_MBox.Pop(data)) - { - ConLog.Error("sys_event_flag_set_bit(v=0x%x (flag=%d)): Out_MBox is empty", v, flag); - return; - } - - if (flag > 63) - { - ConLog.Error("sys_event_flag_set_bit(id=%d, v=0x%x): flag > 63", data, v, flag); - return; - } - - //if (Ini.HLELogging.GetValue()) - { - ConLog.Warning("sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d))", data, v, flag); - } - - EventFlag* ef; - if (!Emu.GetIdManager().GetIDData(data, ef)) - { - ConLog.Error("sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d)): EventFlag not found", data, v, flag); - SPU.In_MBox.PushUncond(CELL_ESRCH); - return; - } - - u32 tid = GetCurrentCPUThread()->GetId(); - - ef->m_mutex.lock(tid); - ef->flags |= (u64)1 << flag; - if (u32 target = ef->check()) - { - // if signal, leave both mutexes locked... - ef->signal.lock(target); - ef->m_mutex.unlock(tid, target); - } - else - { - ef->m_mutex.unlock(tid); - } - - SPU.In_MBox.PushUncond(CELL_OK); - return; - } - else - { - u32 data; - if (SPU.Out_MBox.Pop(data)) - { - ConLog.Error("SPU_WrOutIntrMbox: unknown data (v=0x%x); Out_MBox = 0x%x", v, data); - } - else - { - ConLog.Error("SPU_WrOutIntrMbox: unknown data (v=0x%x)", v); - } - SPU.In_MBox.PushUncond(CELL_EINVAL); // ??? - return; - } - } - break; - - case SPU_WrOutMbox: - //ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v); - while (!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) Sleep(1); - break; - - case MFC_WrTagMask: - //ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v); - Prxy.QueryMask.SetValue(v); - break; - - case MFC_WrTagUpdate: - //ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v); - Prxy.TagStatus.PushUncond(Prxy.QueryMask.GetValue()); - break; - - case MFC_LSA: - MFC1.LSA.SetValue(v); - break; - - case MFC_EAH: - MFC1.EAH.SetValue(v); - break; - - case MFC_EAL: - MFC1.EAL.SetValue(v); - break; - - case MFC_Size: - MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & 0xffff) | (v << 16)); - break; - - case MFC_TagID: - MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff)); - break; - - case MFC_Cmd: - MFC1.CMDStatus.SetValue(v); - EnqMfcCmd(MFC1); - break; - - case MFC_WrListStallAck: - { - if (v >= 32) - { - ConLog.Error("MFC_WrListStallAck error: invalid tag(%d)", v); - return; - } - StalledList temp = StallList[v]; - if (!temp.MFCArgs) - { - ConLog.Error("MFC_WrListStallAck error: empty tag(%d)", v); - return; - } - StallList[v].MFCArgs = nullptr; - ListCmd(temp.lsa, temp.ea, temp.tag, temp.size, temp.cmd, *temp.MFCArgs); - } - break; - - default: - ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); - break; - } - - if (Emu.IsStopped()) ConLog.Warning("%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); - } - - void ReadChannel(SPU_GPR_hdr& r, u32 ch) - { - r.Reset(); - u32& v = r._u32[3]; - - switch(ch) - { - case SPU_RdInMbox: - while (!SPU.In_MBox.Pop(v) && !Emu.IsStopped()) Sleep(1); - //ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); - break; - - case MFC_RdTagStat: - while (!Prxy.TagStatus.Pop(v) && !Emu.IsStopped()) Sleep(1); - //ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); - break; - - case SPU_RdSigNotify1: - while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) Sleep(1); - //ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); - break; - - case SPU_RdSigNotify2: - while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) Sleep(1); - //ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); - break; - - case MFC_RdAtomicStat: - while (!Prxy.AtomicStat.Pop(v) && !Emu.IsStopped()) Sleep(1); - break; - - case MFC_RdListStallStat: - while (!StallStat.Pop(v) && !Emu.IsStopped()) Sleep(1); - break; - - default: - ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); - break; - } - - if (Emu.IsStopped()) ConLog.Warning("%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); - } - - void DoStop(u32 code) - { - SetExitStatus(code); // exit code (not status) - - switch (code) - { - case 0x110: /* ===== sys_spu_thread_receive_event ===== */ - { - u32 spuq = 0; - if (!SPU.Out_MBox.Pop(spuq)) - { - ConLog.Error("sys_spu_thread_receive_event: cannot read Out_MBox"); - SPU.In_MBox.PushUncond(CELL_EINVAL); // ??? - return; - } - - if (SPU.In_MBox.GetCount()) - { - ConLog.Error("sys_spu_thread_receive_event(spuq=0x%x): In_MBox is not empty", spuq); - SPU.In_MBox.PushUncond(CELL_EBUSY); // ??? - return; - } - - if (Ini.LogAllSysCalls.GetValue()) - { - ConLog.Write("sys_spu_thread_receive_event(spuq=0x%x)", spuq); - } - - EventQueue* eq; - if (!SPUQs.GetEventQueue(FIX_SPUQ(spuq), eq)) - { - SPU.In_MBox.PushUncond(CELL_EINVAL); // TODO: check error value - return; - } - - u32 tid = GetId(); - - eq->sq.push(tid); // add thread to sleep queue - - while (true) - { - switch (eq->owner.trylock(tid)) - { - case SMR_OK: - if (!eq->events.count()) - { - eq->owner.unlock(tid); - break; - } - else - { - u32 next = (eq->protocol == SYS_SYNC_FIFO) ? eq->sq.pop() : eq->sq.pop_prio(); - if (next != tid) - { - eq->owner.unlock(tid, next); - break; - } - } - case SMR_SIGNAL: - { - sys_event_data event; - eq->events.pop(event); - eq->owner.unlock(tid); - SPU.In_MBox.PushUncond(CELL_OK); - SPU.In_MBox.PushUncond(event.data1); - SPU.In_MBox.PushUncond(event.data2); - SPU.In_MBox.PushUncond(event.data3); - return; - } - case SMR_FAILED: break; - default: eq->sq.invalidate(tid); SPU.In_MBox.PushUncond(CELL_ECANCELED); return; - } - - Sleep(1); - if (Emu.IsStopped()) - { - ConLog.Warning("sys_spu_thread_receive_event(spuq=0x%x) aborted", spuq); - eq->sq.invalidate(tid); - return; - } - } - } - break; - case 0x102: - if (!SPU.Out_MBox.GetCount()) - { - ConLog.Error("sys_spu_thread_exit (no status, code 0x102)"); - } - else if (Ini.LogAllSysCalls.GetValue()) - { - // the real exit status - ConLog.Write("sys_spu_thread_exit (status=0x%x)", SPU.Out_MBox.GetValue()); - } - Stop(); - break; - default: - if (!SPU.Out_MBox.GetCount()) - { - ConLog.Error("Unknown STOP code: 0x%x (no message)", code); - } - else - { - ConLog.Error("Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue()); - } - Stop(); - break; - } - } - - bool IsGoodLSA(const u32 lsa) const { return Memory.IsGoodAddr(lsa + m_offset) && lsa < 0x40000; } - virtual u8 ReadLS8 (const u32 lsa) const { return Memory.Read8 (lsa + m_offset); } // m_offset & 0x3fffc ????? - virtual u16 ReadLS16 (const u32 lsa) const { return Memory.Read16 (lsa + m_offset); } - virtual u32 ReadLS32 (const u32 lsa) const { return Memory.Read32 (lsa + m_offset); } - virtual u64 ReadLS64 (const u32 lsa) const { return Memory.Read64 (lsa + m_offset); } - virtual u128 ReadLS128(const u32 lsa) const { return Memory.Read128(lsa + m_offset); } - - virtual void WriteLS8 (const u32 lsa, const u8& data) const { Memory.Write8 (lsa + m_offset, data); } - virtual void WriteLS16 (const u32 lsa, const u16& data) const { Memory.Write16 (lsa + m_offset, data); } - virtual void WriteLS32 (const u32 lsa, const u32& data) const { Memory.Write32 (lsa + m_offset, data); } - virtual void WriteLS64 (const u32 lsa, const u64& data) const { Memory.Write64 (lsa + m_offset, data); } - virtual void WriteLS128(const u32 lsa, const u128& data) const { Memory.Write128(lsa + m_offset, data); } + void WriteLS8 (const u32 lsa, const u8& data) const { vm::write8 (lsa + m_offset, data); } + void WriteLS16 (const u32 lsa, const u16& data) const { vm::write16 (lsa + m_offset, data); } + void WriteLS32 (const u32 lsa, const u32& data) const { vm::write32 (lsa + m_offset, data); } + void WriteLS64 (const u32 lsa, const u64& data) const { vm::write64 (lsa + m_offset, data); } + void WriteLS128(const u32 lsa, const u128& data) const { vm::write128(lsa + m_offset, data); } public: SPUThread(CPUThreadType type = CPU_THREAD_SPU); @@ -1250,7 +511,7 @@ public: { std::string ret = "Registers:\n=========\n"; - for(uint i=0; i<128; ++i) ret += fmt::Format("GPR[%d] = 0x%s\n", i, GPR[i].ToString().c_str()); + for(uint i=0; i<128; ++i) ret += fmt::Format("GPR[%d] = 0x%s\n", i, GPR[i].to_hex().c_str()); return ret; } @@ -1299,6 +560,7 @@ public: public: virtual void InitRegs(); virtual u64 GetFreeStackSize() const; + virtual void Task(); protected: virtual void DoReset(); diff --git a/rpcs3/Emu/DbgCommand.cpp b/rpcs3/Emu/DbgCommand.cpp new file mode 100644 index 0000000000..8be005e73c --- /dev/null +++ b/rpcs3/Emu/DbgCommand.cpp @@ -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; +} \ No newline at end of file diff --git a/rpcs3/Emu/DbgCommand.h b/rpcs3/Emu/DbgCommand.h new file mode 100644 index 0000000000..f3e7f03943 --- /dev/null +++ b/rpcs3/Emu/DbgCommand.h @@ -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); \ No newline at end of file diff --git a/rpcs3/Emu/DbgConsole.cpp b/rpcs3/Emu/DbgConsole.cpp deleted file mode 100644 index bfd84fcfcc..0000000000 --- a/rpcs3/Emu/DbgConsole.cpp +++ /dev/null @@ -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(); -} diff --git a/rpcs3/Emu/DbgConsole.h b/rpcs3/Emu/DbgConsole.h deleted file mode 100644 index c4417b3880..0000000000 --- a/rpcs3/Emu/DbgConsole.h +++ /dev/null @@ -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 -{ - _DbgBuffer() : MTPacketBuffer(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(&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(); -}; diff --git a/rpcs3/Emu/Event.cpp b/rpcs3/Emu/Event.cpp index a1fee9d086..5dce5b6884 100644 --- a/rpcs3/Emu/Event.cpp +++ b/rpcs3/Emu/Event.cpp @@ -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 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 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 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 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 lock(m_lock); auto f = key_map.find(key); if (f == key_map.end()) diff --git a/rpcs3/Emu/Event.h b/rpcs3/Emu/Event.h new file mode 100644 index 0000000000..31a33e3db5 --- /dev/null +++ b/rpcs3/Emu/Event.h @@ -0,0 +1,18 @@ +#pragma once +#include "Emu/SysCalls/lv2/sys_event.h" +#include + +class EventManager +{ + std::mutex m_lock; + std::unordered_map key_map; + +public: + void Init(); + void Clear(); + bool CheckKey(u64 key); + bool RegisterKey(EventQueue* data, u64 key); + bool GetEventQueue(u64 key, EventQueue*& data); + bool UnregisterKey(u64 key); + bool SendEvent(u64 key, u64 source, u64 d1, u64 d2, u64 d3); +}; diff --git a/rpcs3/Emu/FS/VFS.cpp b/rpcs3/Emu/FS/VFS.cpp index 0833c471b9..7007955899 100644 --- a/rpcs3/Emu/FS/VFS.cpp +++ b/rpcs3/Emu/FS/VFS.cpp @@ -1,7 +1,11 @@ #include "stdafx.h" #include "VFS.h" +#include "vfsDirBase.h" #include "Emu/HDD/HDD.h" #include "vfsDeviceLocalFile.h" +#include "Ini.h" + +#undef CreateFile // TODO: what's wrong with it? int sort_devices(const void* _a, const void* _b) { @@ -241,9 +245,9 @@ vfsDevice* VFS::GetDeviceLocal(const std::string& local_path, std::string& path) u32 max_eq; s32 max_i=-1; - wxFileName file_path(fmt::FromUTF8(local_path)); + rFileName file_path(local_path); file_path.Normalize(); - std::string mormalized_path = fmt::ToUTF8(file_path.GetFullPath()); + std::string mormalized_path = file_path.GetFullPath(); for(u32 i=0; i& res, bool is_load) } else { - count = res.size(); - entries_count.SaveValue(res.size()); + count = (int)res.size(); + entries_count.SaveValue(count); } for(int i=0; i arr0 = fmt::rSplit(path0.GetFullPath(), DL); + std::vector arr1 = fmt::rSplit(local_path, DL); - const u32 lim = min(arr0.GetCount(), arr1.GetCount()); + const u32 lim = (u32)std::min(arr0.size(), arr1.size()); u32 ret = 0; - for(u32 i=0; i= 0; --i) + for(int i = (int)path.length() - 1, dir = 0; i >= 0; --i) { if(path[i] == '\\' || path[i] == '/' || i == 0) { @@ -108,9 +109,9 @@ std::string vfsDevice::GetRoot(const std::string& path) //return fmt::ToUTF8(wxFileName(fmt::FromUTF8(path), wxPATH_UNIX).GetPath()); if(path.empty()) return ""; - u32 first_dir = path.length() - 1; + u32 first_dir = (u32)path.length() - 1; - for(int i = path.length() - 1, dir = 0, li = path.length() - 1; i >= 0 && dir < 2; --i) + for(int i = (int)path.length() - 1, dir = 0, li = (int)path.length() - 1; i >= 0 && dir < 2; --i) { if(path[i] == '\\' || path[i] == '/' || i == 0) { @@ -138,9 +139,9 @@ std::string vfsDevice::GetRootPs3(const std::string& path) static const std::string home = "/dev_hdd0/game/"; u32 last_dir = 0; - u32 first_dir = path.length() - 1; + u32 first_dir = (u32)path.length() - 1; - for(int i = path.length() - 1, dir = 0; i >= 0; --i) + for(int i = (int)path.length() - 1, dir = 0; i >= 0; --i) { if(path[i] == '\\' || path[i] == '/' || i == 0) { @@ -187,9 +188,9 @@ std::string vfsDevice::GetWinPath(const std::string& p, bool is_dir) if(is_dir && ret[ret.length() - 1] != '/' && ret[ret.length() - 1] != '\\') ret += '/'; // ??? - wxFileName res(fmt::FromUTF8(ret)); + rFileName res(ret); res.Normalize(); - return fmt::ToUTF8(res.GetFullPath()); + return res.GetFullPath(); } std::string vfsDevice::GetWinPath(const std::string& l, const std::string& r) diff --git a/rpcs3/Emu/FS/vfsDevice.h b/rpcs3/Emu/FS/vfsDevice.h index 2be4c108ff..d3921a529a 100644 --- a/rpcs3/Emu/FS/vfsDevice.h +++ b/rpcs3/Emu/FS/vfsDevice.h @@ -1,6 +1,7 @@ #pragma once -#include "vfsFileBase.h" -#include "vfsDirBase.h" + +struct vfsFileBase; +class vfsDirBase; class vfsDevice { diff --git a/rpcs3/Emu/FS/vfsDir.cpp b/rpcs3/Emu/FS/vfsDir.cpp index 5df20734a5..94ed07096a 100644 --- a/rpcs3/Emu/FS/vfsDir.cpp +++ b/rpcs3/Emu/FS/vfsDir.cpp @@ -1,10 +1,16 @@ #include "stdafx.h" +#include "Emu/System.h" + +#include "VFS.h" #include "vfsDir.h" vfsDir::vfsDir() : vfsDirBase(nullptr) , m_stream(nullptr) { + // TODO: proper implementation + // m_stream is nullptr here. So open root until a proper dir is given + Open("/"); } vfsDir::vfsDir(const std::string& path) @@ -30,7 +36,7 @@ bool vfsDir::Create(const std::string& path) bool vfsDir::IsExists(const std::string& path) const { - return m_stream->IsExists(path); // Crash (Access violation reading location 0x0000000000000000) + return m_stream->IsExists(path); } const std::vector& vfsDir::GetEntries() const diff --git a/rpcs3/Emu/FS/vfsDirBase.cpp b/rpcs3/Emu/FS/vfsDirBase.cpp index a7e212019e..e5bda0eded 100644 --- a/rpcs3/Emu/FS/vfsDirBase.cpp +++ b/rpcs3/Emu/FS/vfsDirBase.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "Utilities/rFile.h" #include "vfsDirBase.h" vfsDirBase::vfsDirBase(vfsDevice* device) @@ -31,7 +32,7 @@ bool vfsDirBase::IsOpened() const bool vfsDirBase::IsExists(const std::string& path) const { - return wxDirExists(fmt::FromUTF8(path)); + return rExists(path); } const std::vector& vfsDirBase::GetEntries() const diff --git a/rpcs3/Emu/FS/vfsDirBase.h b/rpcs3/Emu/FS/vfsDirBase.h index c888f60cab..7251862976 100644 --- a/rpcs3/Emu/FS/vfsDirBase.h +++ b/rpcs3/Emu/FS/vfsDirBase.h @@ -1,5 +1,7 @@ #pragma once +class vfsDevice; + enum DirEntryFlags { DirEntry_TypeDir = 0x1, diff --git a/rpcs3/Emu/FS/vfsFile.cpp b/rpcs3/Emu/FS/vfsFile.cpp index 96bcbdd483..8d0bfb1ebb 100644 --- a/rpcs3/Emu/FS/vfsFile.cpp +++ b/rpcs3/Emu/FS/vfsFile.cpp @@ -1,4 +1,7 @@ #include "stdafx.h" +#include "Emu/System.h" + +#include "VFS.h" #include "vfsFile.h" vfsFile::vfsFile() diff --git a/rpcs3/Emu/FS/vfsFileBase.h b/rpcs3/Emu/FS/vfsFileBase.h index a74e05e251..ff7a56e349 100644 --- a/rpcs3/Emu/FS/vfsFileBase.h +++ b/rpcs3/Emu/FS/vfsFileBase.h @@ -1,7 +1,7 @@ #pragma once #include "vfsStream.h" -enum vfsOpenMode +enum vfsOpenMode : u8 { vfsRead = 0x1, vfsWrite = 0x2, diff --git a/rpcs3/Emu/FS/vfsLocalDir.cpp b/rpcs3/Emu/FS/vfsLocalDir.cpp index f7e0901807..0c44144ab9 100644 --- a/rpcs3/Emu/FS/vfsLocalDir.cpp +++ b/rpcs3/Emu/FS/vfsLocalDir.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "vfsDevice.h" #include "vfsLocalDir.h" vfsLocalDir::vfsLocalDir(vfsDevice* device) : vfsDirBase(device) @@ -14,24 +15,27 @@ bool vfsLocalDir::Open(const std::string& path) if(!vfsDirBase::Open(path)) return false; - wxDir dir; - if(!dir.Open(path)) return false; - wxString name; + std::string name; for(bool is_ok = dir.GetFirst(&name); is_ok; is_ok = dir.GetNext(&name)) { - wxString dir_path = fmt::FromUTF8(path) + name; + std::string dir_path = path + name; m_entries.emplace_back(); + // TODO: Use same info structure as fileinfo? DirEntryInfo& info = m_entries.back(); - info.name = fmt::ToUTF8(name); + info.name = name; - info.flags |= dir.Exists(dir_path) ? DirEntry_TypeDir : DirEntry_TypeFile; - if(wxIsWritable(dir_path)) info.flags |= DirEntry_PermWritable; - if(wxIsReadable(dir_path)) info.flags |= DirEntry_PermReadable; - if(wxIsExecutable(dir_path)) info.flags |= DirEntry_PermExecutable; + FileInfo fileinfo; + getFileInfo(dir_path.c_str(), &fileinfo); + + // Not sure of purpose for below. I hope these don't need to be correct + info.flags |= rIsDir(dir_path) ? DirEntry_TypeDir : DirEntry_TypeFile; + if(fileinfo.isWritable) info.flags |= DirEntry_PermWritable; + info.flags |= DirEntry_PermReadable; // Always? + info.flags |= DirEntry_PermExecutable; // Always? } return true; @@ -39,7 +43,7 @@ bool vfsLocalDir::Open(const std::string& path) bool vfsLocalDir::Create(const std::string& path) { - return wxFileName::Mkdir(fmt::FromUTF8(path), 0777, wxPATH_MKDIR_FULL); + return rMkpath(path); } bool vfsLocalDir::Rename(const std::string& from, const std::string& to) @@ -49,5 +53,10 @@ bool vfsLocalDir::Rename(const std::string& from, const std::string& to) bool vfsLocalDir::Remove(const std::string& path) { - return wxRmdir(fmt::FromUTF8(path)); + return rRmdir(path); +} + +bool vfsLocalDir::IsOpened() const +{ + return dir.IsOpened() && vfsDirBase::IsOpened(); } diff --git a/rpcs3/Emu/FS/vfsLocalDir.h b/rpcs3/Emu/FS/vfsLocalDir.h index 4120b12f41..f4b41509d2 100644 --- a/rpcs3/Emu/FS/vfsLocalDir.h +++ b/rpcs3/Emu/FS/vfsLocalDir.h @@ -1,10 +1,12 @@ #pragma once #include "vfsDirBase.h" +#include "Utilities/rFile.h" class vfsLocalDir : public vfsDirBase { private: u32 m_pos; + rDir dir; public: vfsLocalDir(vfsDevice* device); @@ -15,4 +17,5 @@ public: virtual bool Create(const std::string& path) override; virtual bool Rename(const std::string& from, const std::string& to) override; virtual bool Remove(const std::string& path) override; + virtual bool IsOpened() const override; }; \ No newline at end of file diff --git a/rpcs3/Emu/FS/vfsLocalFile.cpp b/rpcs3/Emu/FS/vfsLocalFile.cpp index 0dbf878987..aea1e02e0c 100644 --- a/rpcs3/Emu/FS/vfsLocalFile.cpp +++ b/rpcs3/Emu/FS/vfsLocalFile.cpp @@ -1,30 +1,31 @@ #include "stdafx.h" +#include "Utilities/Log.h" #include "vfsLocalFile.h" -static const wxFile::OpenMode vfs2wx_mode(vfsOpenMode mode) +static const rFile::OpenMode vfs2wx_mode(vfsOpenMode mode) { switch(mode) { - case vfsRead: return wxFile::read; - case vfsWrite: return wxFile::write; - case vfsReadWrite: return wxFile::read_write; - case vfsWriteExcl: return wxFile::write_excl; - case vfsWriteAppend: return wxFile::write_append; + case vfsRead: return rFile::read; + case vfsWrite: return rFile::write; + case vfsReadWrite: return rFile::read_write; + case vfsWriteExcl: return rFile::write_excl; + case vfsWriteAppend: return rFile::write_append; } - return wxFile::read; + return rFile::read; } -static const wxSeekMode vfs2wx_seek(vfsSeekMode mode) +static const rSeekMode vfs2wx_seek(vfsSeekMode mode) { switch(mode) { - case vfsSeekSet: return wxFromStart; - case vfsSeekCur: return wxFromCurrent; - case vfsSeekEnd: return wxFromEnd; + case vfsSeekSet: return rFromStart; + case vfsSeekCur: return rFromCurrent; + case vfsSeekEnd: return rFromEnd; } - return wxFromStart; + return rFromStart; } vfsLocalFile::vfsLocalFile(vfsDevice* device) : vfsFileBase(device) @@ -44,15 +45,15 @@ bool vfsLocalFile::Open(const std::string& path, vfsOpenMode mode) // } // else // { - if(!m_file.Access(fmt::FromUTF8(path), vfs2wx_mode(mode))) return false; + if(!m_file.Access(path, vfs2wx_mode(mode))) return false; - return m_file.Open(fmt::FromUTF8(path), vfs2wx_mode(mode)) && vfsFileBase::Open(path, mode); + return m_file.Open(path, vfs2wx_mode(mode)) && vfsFileBase::Open(path, mode); // } } bool vfsLocalFile::Create(const std::string& path) { - ConLog.Warning("vfsLocalFile::Create('%s')", path.c_str()); + LOG_WARNING(HLE, "vfsLocalFile::Create('%s')", path.c_str()); for(uint p=1; p < path.length() && path[p] != '\0' ; p++) { for(; p < path.length() && path[p] != '\0'; p++) @@ -62,19 +63,19 @@ bool vfsLocalFile::Create(const std::string& path) break; const std::string& dir = path.substr(0, p); - if(!wxDirExists(fmt::FromUTF8(dir))) + if(!rExists(dir)) { - ConLog.Write("create dir: %s", dir.c_str()); - wxMkdir(fmt::FromUTF8(dir)); + LOG_NOTICE(HLE, "create dir: %s", dir.c_str()); + rMkdir(dir); } } //create file const char m = path[path.length() - 1]; - if(m != '/' && m != '\\' && !wxFileExists(fmt::FromUTF8(path))) // ??? + if(m != '/' && m != '\\' && !rExists(path)) // ??? { - wxFile f; - return f.Create(fmt::FromUTF8(path)); + rFile f; + return f.Create(path); } return true; @@ -114,3 +115,8 @@ bool vfsLocalFile::IsOpened() const { return m_file.IsOpened() && vfsFileBase::IsOpened(); } + +bool vfsLocalFile::Exists(const std::string& path) +{ + return rExists(path); +} \ No newline at end of file diff --git a/rpcs3/Emu/FS/vfsLocalFile.h b/rpcs3/Emu/FS/vfsLocalFile.h index ec0c12d72a..7395eb519a 100644 --- a/rpcs3/Emu/FS/vfsLocalFile.h +++ b/rpcs3/Emu/FS/vfsLocalFile.h @@ -1,10 +1,11 @@ #pragma once #include "vfsFileBase.h" +#include "Utilities/rFile.h" class vfsLocalFile : public vfsFileBase { private: - wxFile m_file; + rFile m_file; public: vfsLocalFile(vfsDevice* device); @@ -12,6 +13,7 @@ public: virtual bool Open(const std::string& path, vfsOpenMode mode = vfsRead) override; virtual bool Create(const std::string& path) override; virtual bool Close() override; + virtual bool Exists(const std::string& path) override; virtual u64 GetSize() override; diff --git a/rpcs3/Emu/FS/vfsStreamMemory.cpp b/rpcs3/Emu/FS/vfsStreamMemory.cpp index feecb51330..f385a4ecb3 100644 --- a/rpcs3/Emu/FS/vfsStreamMemory.cpp +++ b/rpcs3/Emu/FS/vfsStreamMemory.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "Emu/Memory/Memory.h" #include "vfsStreamMemory.h" vfsStreamMemory::vfsStreamMemory() : vfsStream() @@ -30,9 +31,7 @@ u64 vfsStreamMemory::Write(const void* src, u64 size) size = GetSize() - Tell(); } - if(!size || !Memory.IsGoodAddr(m_addr + Tell(), size)) return 0; - - Memory.CopyFromReal(m_addr + Tell(), (void*)src, size); + memcpy(vm::get_ptr(m_addr + Tell()), src, size); return vfsStream::Write(src, size); } @@ -44,9 +43,7 @@ u64 vfsStreamMemory::Read(void* dst, u64 size) size = GetSize() - Tell(); } - if(!size || !Memory.IsGoodAddr(m_addr + Tell(), size)) return 0; - - Memory.CopyToReal(dst, m_addr + Tell(), size); + memcpy(dst, vm::get_ptr(m_addr + Tell()), size); return vfsStream::Read(dst, size); } diff --git a/rpcs3/Emu/GS/GCM.h b/rpcs3/Emu/GS/GCM.h deleted file mode 100644 index 62bf689097..0000000000 --- a/rpcs3/Emu/GS/GCM.h +++ /dev/null @@ -1,1250 +0,0 @@ -#pragma once -#include "rpcs3.h" - -enum -{ - CELL_GCM_DISPLAY_HSYNC = 1, - CELL_GCM_DISPLAY_VSYNC = 2, - CELL_GCM_DISPLAY_HSYNC_WITH_NOISE = 3, -}; - -enum -{ - CELL_GCM_DEBUG_LEVEL0 = 1, - CELL_GCM_DEBUG_LEVEL1 = 2, - CELL_GCM_DEBUG_LEVEL2 = 3, -}; - -enum -{ - CELL_GCM_DISPLAY_FREQUENCY_59_94HZ = 1, - CELL_GCM_DISPLAY_FREQUENCY_SCANOUT = 2, - CELL_GCM_DISPLAY_FREQUENCY_DISABLE = 3, -}; - -enum -{ - CELL_GCM_VERTEX_S1 = 1, - CELL_GCM_VERTEX_F = 2, - CELL_GCM_VERTEX_S = 3, - CELL_GCM_VERTEX_UB = 4, - CELL_GCM_VERTEX_S32K = 5, - CELL_GCM_VERTEX_CMP = 6, - CELL_GCM_VERTEX_UB256 = 7, -}; - -enum -{ - CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32 = 0, - CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16 = 1, -}; - -// GCM Texture -enum -{ - // Color Flag - CELL_GCM_TEXTURE_B8 = 0x81, - CELL_GCM_TEXTURE_A1R5G5B5 = 0x82, - CELL_GCM_TEXTURE_A4R4G4B4 = 0x83, - CELL_GCM_TEXTURE_R5G6B5 = 0x84, - CELL_GCM_TEXTURE_A8R8G8B8 = 0x85, - CELL_GCM_TEXTURE_COMPRESSED_DXT1 = 0x86, - CELL_GCM_TEXTURE_COMPRESSED_DXT23 = 0x87, - CELL_GCM_TEXTURE_COMPRESSED_DXT45 = 0x88, - CELL_GCM_TEXTURE_G8B8 = 0x8B, - CELL_GCM_TEXTURE_R6G5B5 = 0x8F, - CELL_GCM_TEXTURE_DEPTH24_D8 = 0x90, - CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT = 0x91, - CELL_GCM_TEXTURE_DEPTH16 = 0x92, - CELL_GCM_TEXTURE_DEPTH16_FLOAT = 0x93, - CELL_GCM_TEXTURE_X16 = 0x94, - CELL_GCM_TEXTURE_Y16_X16 = 0x95, - CELL_GCM_TEXTURE_R5G5B5A1 = 0x97, - CELL_GCM_TEXTURE_COMPRESSED_HILO8 = 0x98, - CELL_GCM_TEXTURE_COMPRESSED_HILO_S8 = 0x99, - CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT = 0x9A, - CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT = 0x9B, - CELL_GCM_TEXTURE_X32_FLOAT = 0x9C, - CELL_GCM_TEXTURE_D1R5G5B5 = 0x9D, - CELL_GCM_TEXTURE_D8R8G8B8 = 0x9E, - CELL_GCM_TEXTURE_Y16_X16_FLOAT = 0x9F, - CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8 = 0xAD, - CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8 = 0xAE, - - // Swizzle Flag - CELL_GCM_TEXTURE_SZ = 0x00, - CELL_GCM_TEXTURE_LN = 0x20, - - // Normalization Flag - CELL_GCM_TEXTURE_NR = 0x00, - CELL_GCM_TEXTURE_UN = 0x40, -}; - -// GCM Surface -enum -{ - // Target - CELL_GCM_SURFACE_TARGET_NONE = 0, - CELL_GCM_SURFACE_TARGET_0 = 1, - CELL_GCM_SURFACE_TARGET_1 = 2, - CELL_GCM_SURFACE_TARGET_MRT1 = 0x13, - CELL_GCM_SURFACE_TARGET_MRT2 = 0x17, - CELL_GCM_SURFACE_TARGET_MRT3 = 0x1f, - - // Depth - CELL_GCM_SURFACE_Z16 = 1, - CELL_GCM_SURFACE_Z24S8 = 2, - - // Antialias - CELL_GCM_SURFACE_CENTER_1 = 2, - CELL_GCM_SURFACE_DIAGONAL_CENTERED_2 = 3, - CELL_GCM_SURFACE_SQUARE_CENTERED_4 = 4, - CELL_GCM_SURFACE_SQUARE_ROTATED_4 = 5, -}; - -// GCM Reports -enum -{ - CELL_GCM_ZPASS_PIXEL_CNT = 1, - CELL_GCM_ZCULL_STATS = 2, - CELL_GCM_ZCULL_STATS1 = 3, - CELL_GCM_ZCULL_STATS2 = 4, - CELL_GCM_ZCULL_STATS3 = 5, -}; - -struct CellGcmControl -{ - be_t put; - be_t get; - be_t ref; -}; - -struct CellGcmConfig -{ - be_t localAddress; - be_t ioAddress; - be_t localSize; - be_t ioSize; - be_t memoryFrequency; - be_t coreFrequency; -}; - -struct CellGcmContextData -{ - be_t begin; - be_t end; - be_t current; - be_t callback; -}; - -struct gcmInfo -{ - u32 config_addr; - u32 context_addr; - u32 control_addr; -}; - -struct CellGcmSurface -{ - u8 type; - u8 antialias; - - u8 color_format; - u8 color_target; - u8 color_location[4]; - u32 color_offset[4]; - u32 color_pitch[4]; - - u8 depth_format; - u8 depth_location; - u16 pad; - u32 depth_offset; - u32 depth_pitch; - - u16 width; - u16 height; - u16 x; - u16 y; -}; - -struct CellGcmReportData -{ - u64 timer; - u32 value; - u32 pad; -}; - -struct CellGcmZcullInfo -{ - u32 region; - u32 size; - u32 start; - u32 offset; - u32 status0; - u32 status1; -}; - -struct CellGcmTileInfo -{ - be_t tile; - be_t limit; - be_t pitch; - be_t format; -}; - -struct GcmZcullInfo -{ - u32 m_offset; - u32 m_width; - u32 m_height; - u32 m_cullStart; - u32 m_zFormat; - u32 m_aaFormat; - u32 m_zCullDir; - u32 m_zCullFormat; - u32 m_sFunc; - u32 m_sRef; - u32 m_sMask; - bool m_binded; - - GcmZcullInfo() - { - memset(this, 0, sizeof(*this)); - } -}; - -struct GcmTileInfo -{ - u8 m_location; - u32 m_offset; - u32 m_size; - u32 m_pitch; - u8 m_comp; - u16 m_base; - u8 m_bank; - bool m_binded; - - GcmTileInfo() - { - memset(this, 0, sizeof(*this)); - } - - CellGcmTileInfo Pack() - { - CellGcmTileInfo ret; - - ret.tile = (m_location + 1) | (m_bank << 4) | ((m_offset / 0x10000) << 16) | (m_location << 31); - ret.limit = ((m_offset + m_size - 1) / 0x10000) << 16 | (m_location << 31); - ret.pitch = (m_pitch / 0x100) << 8; - ret.format = m_base | ((m_base + ((m_size - 1) / 0x10000)) << 13) | (m_comp << 26) | (1 << 30); - - return ret; - } -}; - -enum -{ - CELL_GCM_LOCATION_LOCAL, - CELL_GCM_LOCATION_MAIN, -}; - -enum -{ -// NV406E - NV406E_SET_REFERENCE = 0x00000050, - NV406E_SET_CONTEXT_DMA_SEMAPHORE = 0x00000060, - NV406E_SEMAPHORE_OFFSET = 0x00000064, - NV406E_SEMAPHORE_ACQUIRE = 0x00000068, - NV406E_SEMAPHORE_RELEASE = 0x0000006c, - -// NV4097 - NV4097_SET_OBJECT = 0x00000000, - NV4097_NO_OPERATION = 0x00000100, - NV4097_NOTIFY = 0x00000104, - NV4097_WAIT_FOR_IDLE = 0x00000110, - NV4097_PM_TRIGGER = 0x00000140, - NV4097_SET_CONTEXT_DMA_NOTIFIES = 0x00000180, - NV4097_SET_CONTEXT_DMA_A = 0x00000184, - NV4097_SET_CONTEXT_DMA_B = 0x00000188, - NV4097_SET_CONTEXT_DMA_COLOR_B = 0x0000018c, - NV4097_SET_CONTEXT_DMA_STATE = 0x00000190, - NV4097_SET_CONTEXT_DMA_COLOR_A = 0x00000194, - NV4097_SET_CONTEXT_DMA_ZETA = 0x00000198, - NV4097_SET_CONTEXT_DMA_VERTEX_A = 0x0000019c, - NV4097_SET_CONTEXT_DMA_VERTEX_B = 0x000001a0, - NV4097_SET_CONTEXT_DMA_SEMAPHORE = 0x000001a4, - NV4097_SET_CONTEXT_DMA_REPORT = 0x000001a8, - NV4097_SET_CONTEXT_DMA_CLIP_ID = 0x000001ac, - NV4097_SET_CONTEXT_DMA_CULL_DATA = 0x000001b0, - NV4097_SET_CONTEXT_DMA_COLOR_C = 0x000001b4, - NV4097_SET_CONTEXT_DMA_COLOR_D = 0x000001b8, - NV4097_SET_SURFACE_CLIP_HORIZONTAL = 0x00000200, - NV4097_SET_SURFACE_CLIP_VERTICAL = 0x00000204, - NV4097_SET_SURFACE_FORMAT = 0x00000208, - NV4097_SET_SURFACE_PITCH_A = 0x0000020c, - NV4097_SET_SURFACE_COLOR_AOFFSET = 0x00000210, - NV4097_SET_SURFACE_ZETA_OFFSET = 0x00000214, - NV4097_SET_SURFACE_COLOR_BOFFSET = 0x00000218, - NV4097_SET_SURFACE_PITCH_B = 0x0000021c, - NV4097_SET_SURFACE_COLOR_TARGET = 0x00000220, - NV4097_SET_SURFACE_PITCH_Z = 0x0000022c, - NV4097_INVALIDATE_ZCULL = 0x00000234, - NV4097_SET_CYLINDRICAL_WRAP = 0x00000238, - NV4097_SET_CYLINDRICAL_WRAP1 = 0x0000023c, - NV4097_SET_SURFACE_PITCH_C = 0x00000280, - NV4097_SET_SURFACE_PITCH_D = 0x00000284, - NV4097_SET_SURFACE_COLOR_COFFSET = 0x00000288, - NV4097_SET_SURFACE_COLOR_DOFFSET = 0x0000028c, - NV4097_SET_WINDOW_OFFSET = 0x000002b8, - NV4097_SET_WINDOW_CLIP_TYPE = 0x000002bc, - NV4097_SET_WINDOW_CLIP_HORIZONTAL = 0x000002c0, - NV4097_SET_WINDOW_CLIP_VERTICAL = 0x000002c4, - NV4097_SET_DITHER_ENABLE = 0x00000300, - NV4097_SET_ALPHA_TEST_ENABLE = 0x00000304, - NV4097_SET_ALPHA_FUNC = 0x00000308, - NV4097_SET_ALPHA_REF = 0x0000030c, - NV4097_SET_BLEND_ENABLE = 0x00000310, - NV4097_SET_BLEND_FUNC_SFACTOR = 0x00000314, - NV4097_SET_BLEND_FUNC_DFACTOR = 0x00000318, - NV4097_SET_BLEND_COLOR = 0x0000031c, - NV4097_SET_BLEND_EQUATION = 0x00000320, - NV4097_SET_COLOR_MASK = 0x00000324, - NV4097_SET_STENCIL_TEST_ENABLE = 0x00000328, - NV4097_SET_STENCIL_MASK = 0x0000032c, - NV4097_SET_STENCIL_FUNC = 0x00000330, - NV4097_SET_STENCIL_FUNC_REF = 0x00000334, - NV4097_SET_STENCIL_FUNC_MASK = 0x00000338, - NV4097_SET_STENCIL_OP_FAIL = 0x0000033c, - NV4097_SET_STENCIL_OP_ZFAIL = 0x00000340, - NV4097_SET_STENCIL_OP_ZPASS = 0x00000344, - NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE = 0x00000348, - NV4097_SET_BACK_STENCIL_MASK = 0x0000034c, - NV4097_SET_BACK_STENCIL_FUNC = 0x00000350, - NV4097_SET_BACK_STENCIL_FUNC_REF = 0x00000354, - NV4097_SET_BACK_STENCIL_FUNC_MASK = 0x00000358, - NV4097_SET_BACK_STENCIL_OP_FAIL = 0x0000035c, - NV4097_SET_BACK_STENCIL_OP_ZFAIL = 0x00000360, - NV4097_SET_BACK_STENCIL_OP_ZPASS = 0x00000364, - NV4097_SET_SHADE_MODE = 0x00000368, - NV4097_SET_BLEND_ENABLE_MRT = 0x0000036c, - NV4097_SET_COLOR_MASK_MRT = 0x00000370, - NV4097_SET_LOGIC_OP_ENABLE = 0x00000374, - NV4097_SET_LOGIC_OP = 0x00000378, - NV4097_SET_BLEND_COLOR2 = 0x0000037c, - NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE = 0x00000380, - NV4097_SET_DEPTH_BOUNDS_MIN = 0x00000384, - NV4097_SET_DEPTH_BOUNDS_MAX = 0x00000388, - NV4097_SET_CLIP_MIN = 0x00000394, - NV4097_SET_CLIP_MAX = 0x00000398, - NV4097_SET_CONTROL0 = 0x000003b0, - NV4097_SET_LINE_WIDTH = 0x000003b8, - NV4097_SET_LINE_SMOOTH_ENABLE = 0x000003bc, - NV4097_SET_ANISO_SPREAD = 0x000003c0, - NV4097_SET_SCISSOR_HORIZONTAL = 0x000008c0, - NV4097_SET_SCISSOR_VERTICAL = 0x000008c4, - NV4097_SET_FOG_MODE = 0x000008cc, - NV4097_SET_FOG_PARAMS = 0x000008d0, - NV4097_SET_SHADER_PROGRAM = 0x000008e4, - NV4097_SET_VERTEX_TEXTURE_OFFSET = 0x00000900, - NV4097_SET_VERTEX_TEXTURE_FORMAT = 0x00000904, - NV4097_SET_VERTEX_TEXTURE_ADDRESS = 0x00000908, - NV4097_SET_VERTEX_TEXTURE_CONTROL0 = 0x0000090c, - NV4097_SET_VERTEX_TEXTURE_CONTROL3 = 0x00000910, - NV4097_SET_VERTEX_TEXTURE_FILTER = 0x00000914, - NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT = 0x00000918, - NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR = 0x0000091c, - NV4097_SET_VIEWPORT_HORIZONTAL = 0x00000a00, - NV4097_SET_VIEWPORT_VERTICAL = 0x00000a04, - NV4097_SET_POINT_CENTER_MODE = 0x00000a0c, - NV4097_ZCULL_SYNC = 0x00000a1c, - NV4097_SET_VIEWPORT_OFFSET = 0x00000a20, - NV4097_SET_VIEWPORT_SCALE = 0x00000a30, - NV4097_SET_POLY_OFFSET_POINT_ENABLE = 0x00000a60, - NV4097_SET_POLY_OFFSET_LINE_ENABLE = 0x00000a64, - NV4097_SET_POLY_OFFSET_FILL_ENABLE = 0x00000a68, - NV4097_SET_DEPTH_FUNC = 0x00000a6c, - NV4097_SET_DEPTH_MASK = 0x00000a70, - NV4097_SET_DEPTH_TEST_ENABLE = 0x00000a74, - NV4097_SET_POLYGON_OFFSET_SCALE_FACTOR = 0x00000a78, - NV4097_SET_POLYGON_OFFSET_BIAS = 0x00000a7c, - NV4097_SET_VERTEX_DATA_SCALED4S_M = 0x00000a80, - NV4097_SET_TEXTURE_CONTROL2 = 0x00000b00, - NV4097_SET_TEX_COORD_CONTROL = 0x00000b40, - NV4097_SET_TRANSFORM_PROGRAM = 0x00000b80, - NV4097_SET_SPECULAR_ENABLE = 0x00001428, - NV4097_SET_TWO_SIDE_LIGHT_EN = 0x0000142c, - NV4097_CLEAR_ZCULL_SURFACE = 0x00001438, - NV4097_SET_PERFORMANCE_PARAMS = 0x00001450, - NV4097_SET_FLAT_SHADE_OP = 0x00001454, - NV4097_SET_EDGE_FLAG = 0x0000145c, - NV4097_SET_USER_CLIP_PLANE_CONTROL = 0x00001478, - NV4097_SET_POLYGON_STIPPLE = 0x0000147c, - NV4097_SET_POLYGON_STIPPLE_PATTERN = 0x00001480, - NV4097_SET_VERTEX_DATA3F_M = 0x00001500, - NV4097_SET_VERTEX_DATA_ARRAY_OFFSET = 0x00001680, - NV4097_INVALIDATE_VERTEX_CACHE_FILE = 0x00001710, - NV4097_INVALIDATE_VERTEX_FILE = 0x00001714, - NV4097_PIPE_NOP = 0x00001718, - NV4097_SET_VERTEX_DATA_BASE_OFFSET = 0x00001738, - NV4097_SET_VERTEX_DATA_BASE_INDEX = 0x0000173c, - NV4097_SET_VERTEX_DATA_ARRAY_FORMAT = 0x00001740, - NV4097_CLEAR_REPORT_VALUE = 0x000017c8, - NV4097_SET_ZPASS_PIXEL_COUNT_ENABLE = 0x000017cc, - NV4097_GET_REPORT = 0x00001800, - NV4097_SET_ZCULL_STATS_ENABLE = 0x00001804, - NV4097_SET_BEGIN_END = 0x00001808, - NV4097_ARRAY_ELEMENT16 = 0x0000180c, - NV4097_ARRAY_ELEMENT32 = 0x00001810, - NV4097_DRAW_ARRAYS = 0x00001814, - NV4097_INLINE_ARRAY = 0x00001818, - NV4097_SET_INDEX_ARRAY_ADDRESS = 0x0000181c, - NV4097_SET_INDEX_ARRAY_DMA = 0x00001820, - NV4097_DRAW_INDEX_ARRAY = 0x00001824, - NV4097_SET_FRONT_POLYGON_MODE = 0x00001828, - NV4097_SET_BACK_POLYGON_MODE = 0x0000182c, - NV4097_SET_CULL_FACE = 0x00001830, - NV4097_SET_FRONT_FACE = 0x00001834, - NV4097_SET_POLY_SMOOTH_ENABLE = 0x00001838, - NV4097_SET_CULL_FACE_ENABLE = 0x0000183c, - NV4097_SET_TEXTURE_CONTROL3 = 0x00001840, - NV4097_SET_VERTEX_DATA2F_M = 0x00001880, - NV4097_SET_VERTEX_DATA2S_M = 0x00001900, - NV4097_SET_VERTEX_DATA4UB_M = 0x00001940, - NV4097_SET_VERTEX_DATA4S_M = 0x00001980, - NV4097_SET_TEXTURE_OFFSET = 0x00001a00, - NV4097_SET_TEXTURE_FORMAT = 0x00001a04, - NV4097_SET_TEXTURE_ADDRESS = 0x00001a08, - NV4097_SET_TEXTURE_CONTROL0 = 0x00001a0c, - NV4097_SET_TEXTURE_CONTROL1 = 0x00001a10, - NV4097_SET_TEXTURE_FILTER = 0x00001a14, - NV4097_SET_TEXTURE_IMAGE_RECT = 0x00001a18, - NV4097_SET_TEXTURE_BORDER_COLOR = 0x00001a1c, - NV4097_SET_VERTEX_DATA4F_M = 0x00001c00, - NV4097_SET_COLOR_KEY_COLOR = 0x00001d00, - NV4097_SET_SHADER_CONTROL = 0x00001d60, - NV4097_SET_INDEXED_CONSTANT_READ_LIMITS = 0x00001d64, - NV4097_SET_SEMAPHORE_OFFSET = 0x00001d6c, - NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE = 0x00001d70, - NV4097_TEXTURE_READ_SEMAPHORE_RELEASE = 0x00001d74, - NV4097_SET_ZMIN_MAX_CONTROL = 0x00001d78, - NV4097_SET_ANTI_ALIASING_CONTROL = 0x00001d7c, - NV4097_SET_SURFACE_COMPRESSION = 0x00001d80, - NV4097_SET_ZCULL_EN = 0x00001d84, - NV4097_SET_SHADER_WINDOW = 0x00001d88, - NV4097_SET_ZSTENCIL_CLEAR_VALUE = 0x00001d8c, - NV4097_SET_COLOR_CLEAR_VALUE = 0x00001d90, - NV4097_CLEAR_SURFACE = 0x00001d94, - NV4097_SET_CLEAR_RECT_HORIZONTAL = 0x00001d98, - NV4097_SET_CLEAR_RECT_VERTICAL = 0x00001d9c, - NV4097_SET_CLIP_ID_TEST_ENABLE = 0x00001da4, - NV4097_SET_RESTART_INDEX_ENABLE = 0x00001dac, - NV4097_SET_RESTART_INDEX = 0x00001db0, - NV4097_SET_LINE_STIPPLE = 0x00001db4, - NV4097_SET_LINE_STIPPLE_PATTERN = 0x00001db8, - NV4097_SET_VERTEX_DATA1F_M = 0x00001e40, - NV4097_SET_TRANSFORM_EXECUTION_MODE = 0x00001e94, - NV4097_SET_RENDER_ENABLE = 0x00001e98, - NV4097_SET_TRANSFORM_PROGRAM_LOAD = 0x00001e9c, - NV4097_SET_TRANSFORM_PROGRAM_START = 0x00001ea0, - NV4097_SET_ZCULL_CONTROL0 = 0x00001ea4, - NV4097_SET_ZCULL_CONTROL1 = 0x00001ea8, - NV4097_SET_SCULL_CONTROL = 0x00001eac, - NV4097_SET_POINT_SIZE = 0x00001ee0, - NV4097_SET_POINT_PARAMS_ENABLE = 0x00001ee4, - NV4097_SET_POINT_SPRITE_CONTROL = 0x00001ee8, - NV4097_SET_TRANSFORM_TIMEOUT = 0x00001ef8, - NV4097_SET_TRANSFORM_CONSTANT_LOAD = 0x00001efc, - NV4097_SET_TRANSFORM_CONSTANT = 0x00001f00, - NV4097_SET_FREQUENCY_DIVIDER_OPERATION = 0x00001fc0, - NV4097_SET_ATTRIB_COLOR = 0x00001fc4, - NV4097_SET_ATTRIB_TEX_COORD = 0x00001fc8, - NV4097_SET_ATTRIB_TEX_COORD_EX = 0x00001fcc, - NV4097_SET_ATTRIB_UCLIP0 = 0x00001fd0, - NV4097_SET_ATTRIB_UCLIP1 = 0x00001fd4, - NV4097_INVALIDATE_L2 = 0x00001fd8, - NV4097_SET_REDUCE_DST_COLOR = 0x00001fe0, - NV4097_SET_NO_PARANOID_TEXTURE_FETCHES = 0x00001fe8, - NV4097_SET_SHADER_PACKER = 0x00001fec, - NV4097_SET_VERTEX_ATTRIB_INPUT_MASK = 0x00001ff0, - NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK = 0x00001ff4, - NV4097_SET_TRANSFORM_BRANCH_BITS = 0x00001ff8, - NV4097_SET_FLIP = 0x00003fead, - -// NV0039 - NV0039_SET_OBJECT = 0x00002000, - NV0039_SET_CONTEXT_DMA_NOTIFIES = 0x00002180, - NV0039_SET_CONTEXT_DMA_BUFFER_IN = 0x00002184, - NV0039_SET_CONTEXT_DMA_BUFFER_OUT = 0x00002188, - NV0039_OFFSET_IN = 0x0000230C, - NV0039_OFFSET_OUT = 0x00002310, - NV0039_PITCH_IN = 0x00002314, - NV0039_PITCH_OUT = 0x00002318, - NV0039_LINE_LENGTH_IN = 0x0000231C, - NV0039_LINE_COUNT = 0x00002320, - NV0039_FORMAT = 0x00002324, - NV0039_BUFFER_NOTIFY = 0x00002328, - -// NV3062 - NV3062_SET_OBJECT = 0x00006000, - NV3062_SET_CONTEXT_DMA_NOTIFIES = 0x00006180, - NV3062_SET_CONTEXT_DMA_IMAGE_SOURCE = 0x00006184, - NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN = 0x00006188, - NV3062_SET_COLOR_FORMAT = 0x00006300, - NV3062_SET_PITCH = 0x00006304, - NV3062_SET_OFFSET_SOURCE = 0x00006308, - NV3062_SET_OFFSET_DESTIN = 0x0000630C, - -// NV309E - NV309E_SET_OBJECT = 0x00008000, - NV309E_SET_CONTEXT_DMA_NOTIFIES = 0x00008180, - NV309E_SET_CONTEXT_DMA_IMAGE = 0x00008184, - NV309E_SET_FORMAT = 0x00008300, - NV309E_SET_OFFSET = 0x00008304, - -// NV308A - NV308A_SET_OBJECT = 0x0000A000, - NV308A_SET_CONTEXT_DMA_NOTIFIES = 0x0000A180, - NV308A_SET_CONTEXT_COLOR_KEY = 0x0000A184, - NV308A_SET_CONTEXT_CLIP_RECTANGLE = 0x0000A188, - NV308A_SET_CONTEXT_PATTERN = 0x0000A18C, - NV308A_SET_CONTEXT_ROP = 0x0000A190, - NV308A_SET_CONTEXT_BETA1 = 0x0000A194, - NV308A_SET_CONTEXT_BETA4 = 0x0000A198, - NV308A_SET_CONTEXT_SURFACE = 0x0000A19C, - NV308A_SET_COLOR_CONVERSION = 0x0000A2F8, - NV308A_SET_OPERATION = 0x0000A2FC, - NV308A_SET_COLOR_FORMAT = 0x0000A300, - NV308A_POINT = 0x0000A304, - NV308A_SIZE_OUT = 0x0000A308, - NV308A_SIZE_IN = 0x0000A30C, - NV308A_COLOR = 0x0000A400, - -// NV3089 - NV3089_SET_OBJECT = 0x0000C000, - NV3089_SET_CONTEXT_DMA_NOTIFIES = 0x0000C180, - NV3089_SET_CONTEXT_DMA_IMAGE = 0x0000C184, - NV3089_SET_CONTEXT_PATTERN = 0x0000C188, - NV3089_SET_CONTEXT_ROP = 0x0000C18C, - NV3089_SET_CONTEXT_BETA1 = 0x0000C190, - NV3089_SET_CONTEXT_BETA4 = 0x0000C194, - NV3089_SET_CONTEXT_SURFACE = 0x0000C198, - NV3089_SET_COLOR_CONVERSION = 0x0000C2FC, - NV3089_SET_COLOR_FORMAT = 0x0000C300, - NV3089_SET_OPERATION = 0x0000C304, - NV3089_CLIP_POINT = 0x0000C308, - NV3089_CLIP_SIZE = 0x0000C30C, - NV3089_IMAGE_OUT_POINT = 0x0000C310, - NV3089_IMAGE_OUT_SIZE = 0x0000C314, - NV3089_DS_DX = 0x0000C318, - NV3089_DT_DY = 0x0000C31C, - NV3089_IMAGE_IN_SIZE = 0x0000C400, - NV3089_IMAGE_IN_FORMAT = 0x0000C404, - NV3089_IMAGE_IN_OFFSET = 0x0000C408, - NV3089_IMAGE_IN = 0x0000C40C, -}; - -static const std::string GetMethodName(const u32 id) -{ - struct MethodName - { - const u32 id; - const std::string& name; - } static const METHOD_NAME_LIST[] = { - { NV4097_NO_OPERATION , "NoOperation" } , - { NV4097_NOTIFY , "Notify" } , - { NV4097_WAIT_FOR_IDLE , "WaitForIdle" } , - { NV4097_PM_TRIGGER , "PmTrigger" } , - { NV4097_SET_CONTEXT_DMA_NOTIFIES , "SetContextDmaNotifies" } , - { NV4097_SET_CONTEXT_DMA_A , "SetContextDmaA" } , - { NV4097_SET_CONTEXT_DMA_B , "SetContextDmaB" } , - { NV4097_SET_CONTEXT_DMA_COLOR_B , "SetContextDmaColorB" } , - { NV4097_SET_CONTEXT_DMA_STATE , "SetContextDmaState" } , - { NV4097_SET_CONTEXT_DMA_COLOR_A , "SetContextDmaColorA" } , - { NV4097_SET_CONTEXT_DMA_ZETA , "SetContextDmaZeta" } , - { NV4097_SET_CONTEXT_DMA_VERTEX_A , "SetContextDmaVertexA" } , - { NV4097_SET_CONTEXT_DMA_VERTEX_B , "SetContextDmaVertexB" } , - { NV4097_SET_CONTEXT_DMA_SEMAPHORE , "SetContextDmaSemaphore" } , - { NV4097_SET_CONTEXT_DMA_REPORT , "SetContextDmaReport" } , - { NV4097_SET_CONTEXT_DMA_CLIP_ID , "SetContextDmaClipId" } , - { NV4097_SET_CONTEXT_DMA_CULL_DATA , "SetContextDmaCullData" } , - { NV4097_SET_CONTEXT_DMA_COLOR_C , "SetContextDmaColorC" } , - { NV4097_SET_CONTEXT_DMA_COLOR_D , "SetContextDmaColorD" } , - { NV4097_SET_SURFACE_CLIP_HORIZONTAL , "SetSurfaceClipHorizontal" } , - { NV4097_SET_SURFACE_CLIP_VERTICAL , "SetSurfaceClipVertical" } , - { NV4097_SET_SURFACE_FORMAT , "SetSurfaceFormat" } , - { NV4097_SET_SURFACE_PITCH_A , "SetSurfacePitchA" } , - { NV4097_SET_SURFACE_COLOR_AOFFSET , "SetSurfaceColorAOffset" } , - { NV4097_SET_SURFACE_ZETA_OFFSET , "SetSurfaceZetaOffset" } , - { NV4097_SET_SURFACE_COLOR_BOFFSET , "SetSurfaceColorBOffset" } , - { NV4097_SET_SURFACE_PITCH_B , "SetSurfacePitchB" } , - { NV4097_SET_SURFACE_COLOR_TARGET , "SetSurfaceColorTarget" } , - { NV4097_SET_SURFACE_PITCH_Z , "SetSurfacePitchZ" } , - { NV4097_INVALIDATE_ZCULL , "InvalidateZcull" } , - { NV4097_SET_CYLINDRICAL_WRAP , "SetCylindricalWrap" } , - { NV4097_SET_CYLINDRICAL_WRAP1 , "SetCylindricalWrap1" } , - { NV4097_SET_SURFACE_PITCH_C , "SetSurfacePitchC" } , - { NV4097_SET_SURFACE_PITCH_D , "SetSurfacePitchD" } , - { NV4097_SET_SURFACE_COLOR_COFFSET , "SetSurfaceColorCOffset" } , - { NV4097_SET_SURFACE_COLOR_DOFFSET , "SetSurfaceColorDOffset" } , - { NV4097_SET_WINDOW_OFFSET , "SetWindowOffset" } , - { NV4097_SET_DITHER_ENABLE , "SetDitherEnable" } , - { NV4097_SET_ALPHA_TEST_ENABLE , "SetAlphaTestEnable" } , - { NV4097_SET_ALPHA_FUNC , "SetAlphaFunc" } , - { NV4097_SET_ALPHA_REF , "SetAlphaRef" } , - { NV4097_SET_BLEND_ENABLE , "SetBlendEnable" } , - { NV4097_SET_BLEND_FUNC_SFACTOR , "SetBlendFuncSfactor" } , - { NV4097_SET_BLEND_FUNC_DFACTOR , "SetBlendFuncDfactor" } , - { NV4097_SET_BLEND_COLOR , "SetBlendColor" } , - { NV4097_SET_BLEND_EQUATION , "SetBlendEquation" } , - { NV4097_SET_COLOR_MASK , "SetColorMask" } , - { NV4097_SET_STENCIL_TEST_ENABLE , "SetStencilTestEnable" } , - { NV4097_SET_STENCIL_MASK , "SetStencilMask" } , - { NV4097_SET_STENCIL_FUNC , "SetStencilFunc" } , - { NV4097_SET_STENCIL_FUNC_REF , "SetStencilFuncRef" } , - { NV4097_SET_STENCIL_FUNC_MASK , "SetStencilFuncMask" } , - { NV4097_SET_STENCIL_OP_FAIL , "SetStencilOpFail" } , - { NV4097_SET_STENCIL_OP_ZFAIL , "SetStencilOpZfail" } , - { NV4097_SET_STENCIL_OP_ZPASS , "SetStencilOpZpass" } , - { NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE , "SetTwoSidedStencilTestEnable" } , - { NV4097_SET_BACK_STENCIL_MASK , "SetBackStencilMask" } , - { NV4097_SET_BACK_STENCIL_FUNC , "SetBackStencilFunc" } , - { NV4097_SET_BACK_STENCIL_FUNC_REF , "SetBackStencilFuncRef" } , - { NV4097_SET_BACK_STENCIL_FUNC_MASK , "SetBackStencilFuncMask" } , - { NV4097_SET_BACK_STENCIL_OP_FAIL , "SetBackStencilOpFail" } , - { NV4097_SET_BACK_STENCIL_OP_ZFAIL , "SetBackStencilOpZfail" } , - { NV4097_SET_BACK_STENCIL_OP_ZPASS , "SetBackStencilOpZpass" } , - { NV4097_SET_SHADE_MODE , "SetShadeMode" } , - { NV4097_SET_BLEND_ENABLE_MRT , "SetBlendEnableMRT" } , - { NV4097_SET_COLOR_MASK_MRT , "SetColorMaskMRT" } , - { NV4097_SET_LOGIC_OP_ENABLE , "SetLogicOpEnable" } , - { NV4097_SET_LOGIC_OP , "SetLogicOp" } , - { NV4097_SET_BLEND_COLOR2 , "SetBlendColor2" } , - { NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE , "SetDepthBoundsTestEnable" } , - { NV4097_SET_DEPTH_BOUNDS_MIN , "SetDepthBoundsMin" } , - { NV4097_SET_DEPTH_BOUNDS_MAX , "SetDepthBoundsMax" } , - { NV4097_SET_CLIP_MIN , "SetClipMin" } , - { NV4097_SET_CLIP_MAX , "SetClipMax" } , - { NV4097_SET_CONTROL0 , "SetControl0" } , - { NV4097_SET_LINE_WIDTH , "SetLineWidth" } , - { NV4097_SET_LINE_SMOOTH_ENABLE , "SetLineSmoothEnable" } , - { NV4097_SET_ANISO_SPREAD , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 4 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 8 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 12 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 16 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 20 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 24 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 28 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 32 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 36 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 40 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 44 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 48 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 52 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 56 , "SetAnisoSpread" } , - { NV4097_SET_ANISO_SPREAD + 60 , "SetAnisoSpread" } , - { NV4097_SET_SCISSOR_HORIZONTAL , "SetScissorHorizontal" } , - { NV4097_SET_SCISSOR_VERTICAL , "SetScissorVertical" } , - { NV4097_SET_FOG_MODE , "SetFogMode" } , - { NV4097_SET_FOG_PARAMS , "SetFogParams" } , - { NV4097_SET_FOG_PARAMS + 4 , "SetFogParams" } , - { NV4097_SET_FOG_PARAMS + 8 , "SetFogParams" } , - { NV4097_SET_SHADER_PROGRAM , "SetShaderProgram" } , - { NV4097_SET_VERTEX_TEXTURE_OFFSET , "SetVertexTexture_Offset" } , - { NV4097_SET_VERTEX_TEXTURE_FORMAT , "SetVertexTexture_Format" } , - { NV4097_SET_VERTEX_TEXTURE_ADDRESS , "SetVertexTexture_Address" } , - { NV4097_SET_VERTEX_TEXTURE_CONTROL0 , "SetVertexTexture_Control0" } , - { NV4097_SET_VERTEX_TEXTURE_CONTROL3 , "SetVertexTexture_Control3" } , - { NV4097_SET_VERTEX_TEXTURE_FILTER , "SetVertexTexture_Filter" } , - { NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT , "SetVertexTexture_ImageRect" } , - { NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR , "SetVertexTexture_BorderColor" } , - { NV4097_SET_VERTEX_TEXTURE_OFFSET + 0x20, "SetVertexTexture_Offset" } , - { NV4097_SET_VERTEX_TEXTURE_FORMAT + 0x20, "SetVertexTexture_Format" } , - { NV4097_SET_VERTEX_TEXTURE_ADDRESS + 0x20, "SetVertexTexture_Address" } , - { NV4097_SET_VERTEX_TEXTURE_CONTROL0 + 0x20, "SetVertexTexture_Control0" } , - { NV4097_SET_VERTEX_TEXTURE_CONTROL3 + 0x20, "SetVertexTexture_Control3" } , - { NV4097_SET_VERTEX_TEXTURE_FILTER + 0x20, "SetVertexTexture_Filter" } , - { NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT + 0x20, "SetVertexTexture_ImageRect" } , - { NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR + 0x20, "SetVertexTexture_BorderColor" } , - { NV4097_SET_VERTEX_TEXTURE_OFFSET + 0x40, "SetVertexTexture_Offset" } , - { NV4097_SET_VERTEX_TEXTURE_FORMAT + 0x40, "SetVertexTexture_Format" } , - { NV4097_SET_VERTEX_TEXTURE_ADDRESS + 0x40, "SetVertexTexture_Address" } , - { NV4097_SET_VERTEX_TEXTURE_CONTROL0 + 0x40, "SetVertexTexture_Control0" } , - { NV4097_SET_VERTEX_TEXTURE_CONTROL3 + 0x40, "SetVertexTexture_Control3" } , - { NV4097_SET_VERTEX_TEXTURE_FILTER + 0x40, "SetVertexTexture_Filter" } , - { NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT + 0x40, "SetVertexTexture_ImageRect" } , - { NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR + 0x40, "SetVertexTexture_BorderColor" } , - { NV4097_SET_VERTEX_TEXTURE_OFFSET + 0x60, "SetVertexTexture_Offset" } , - { NV4097_SET_VERTEX_TEXTURE_FORMAT + 0x60, "SetVertexTexture_Format" } , - { NV4097_SET_VERTEX_TEXTURE_ADDRESS + 0x60, "SetVertexTexture_Address" } , - { NV4097_SET_VERTEX_TEXTURE_CONTROL0 + 0x60, "SetVertexTexture_Control0" } , - { NV4097_SET_VERTEX_TEXTURE_CONTROL3 + 0x60, "SetVertexTexture_Control3" } , - { NV4097_SET_VERTEX_TEXTURE_FILTER + 0x60, "SetVertexTexture_Filter" } , - { NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT + 0x60, "SetVertexTexture_ImageRect" } , - { NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR + 0x60, "SetVertexTexture_BorderColor" } , - { NV4097_SET_VIEWPORT_HORIZONTAL , "SetViewportHorizontal" } , - { NV4097_SET_VIEWPORT_VERTICAL , "SetViewportVertical" } , - { NV4097_SET_VIEWPORT_OFFSET , "SetViewportOffset" } , - { NV4097_SET_VIEWPORT_SCALE , "SetViewportScale" } , - { NV4097_SET_POLY_OFFSET_LINE_ENABLE , "SetPolyOffsetLineEnable" } , - { NV4097_SET_POLY_OFFSET_FILL_ENABLE , "SetPolyOffsetFillEnable" } , - { NV4097_SET_DEPTH_FUNC , "SetDepthFunc" } , - { NV4097_SET_DEPTH_MASK , "SetDepthMask" } , - { NV4097_SET_DEPTH_TEST_ENABLE , "SetDepthTestEnable" } , - { NV4097_SET_POLYGON_OFFSET_SCALE_FACTOR , "SetPolygonOffsetScaleFactor" } , - { NV4097_SET_POLYGON_OFFSET_BIAS , "SetPolygonOffsetBias" } , - { NV4097_SET_VERTEX_DATA_SCALED4S_M , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 4 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 8 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 12 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 16 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 20 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 24 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 28 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 32 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 36 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 40, "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 44 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 48 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 52 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 56 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 60 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 64 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 68 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 72 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 76 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 80 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 84 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 88 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 92 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 96 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 100 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 104 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 108 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 112 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 116 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 120 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_VERTEX_DATA_SCALED4S_M + 124 , "SetVertexDataScaled4s_M"}, - { NV4097_SET_TEXTURE_CONTROL2 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 4 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 8 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 12 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 16 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 20 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 24 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 28 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 32 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 36 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 40 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 44 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 48 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 52 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 56 , "SetTextureControl2" } , - { NV4097_SET_TEXTURE_CONTROL2 + 60 , "SetTextureControl2" } , - { NV4097_SET_TEX_COORD_CONTROL , "SetTexCoordControl" } , - { NV4097_SET_TEX_COORD_CONTROL + 4 , "SetTexCoordControl" } , - { NV4097_SET_TEX_COORD_CONTROL + 8 , "SetTexCoordControl" } , - { NV4097_SET_TEX_COORD_CONTROL + 12 , "SetTexCoordControl" } , - { NV4097_SET_TEX_COORD_CONTROL + 16 , "SetTexCoordControl" } , - { NV4097_SET_TEX_COORD_CONTROL + 20 , "SetTexCoordControl" } , - { NV4097_SET_TEX_COORD_CONTROL + 24 , "SetTexCoordControl" } , - { NV4097_SET_TEX_COORD_CONTROL + 28 , "SetTexCoordControl" } , - { NV4097_SET_TEX_COORD_CONTROL + 32 , "SetTexCoordControl" } , - { NV4097_SET_TEX_COORD_CONTROL + 36 , "SetTexCoordControl" } , - { NV4097_SET_TRANSFORM_PROGRAM , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 4 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 8 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 12 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 16 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 20 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 24 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 28 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 32 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 36 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 40 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 44 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 48 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 52 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 56 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 60 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 64 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 68 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 72 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 76 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 80 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 84 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 88 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 92 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 96 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 100 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 104 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 108 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 112 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 116 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 120 , "SetTransformProgram"}, - { NV4097_SET_TRANSFORM_PROGRAM + 124 , "SetTransformProgram"}, - { NV4097_SET_TWO_SIDE_LIGHT_EN , "SetTwoSideLightEn" } , - { NV4097_CLEAR_ZCULL_SURFACE , "ClearZcullSurface" } , - { NV4097_SET_USER_CLIP_PLANE_CONTROL , "SetUserClipPlaneControl" } , - { NV4097_SET_POLYGON_STIPPLE , "SetPolygonStipple" } , - { NV4097_SET_POLYGON_STIPPLE_PATTERN , "SetPolygonStipplePattern" } , - { NV4097_SET_VERTEX_DATA3F_M , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 4 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 8 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 12 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 16 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 20 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 24 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 28 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 32 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 36 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 40 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 44 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 48 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 52 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 56 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 60 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 64 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 68 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 72 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 76 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 80 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 84 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 88 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 92 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 96 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 100 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 104 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 108 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 112 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 116 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 120 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 124 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 128 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 132 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 136 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 140 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 144 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 148 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 152 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 156 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 160 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 164 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 168 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 172 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 176 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 180 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 184 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA3F_M + 188 , "SetVertexData3f_M"}, - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 4 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 8 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 12 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 16 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 20 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 24 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 28 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 32 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 36 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 40 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 44 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 48 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 52 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 56 , "SetVertexDataArrayOffset" } , - { NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 60 , "SetVertexDataArrayOffset" } , - { NV4097_INVALIDATE_VERTEX_CACHE_FILE , "InvalidateVertexCacheFile" } , - { NV4097_INVALIDATE_VERTEX_FILE , "InvalidateVertexFile" } , - { NV4097_SET_VERTEX_DATA_BASE_OFFSET , "SetVertexDataBaseOffset" } , - { NV4097_SET_VERTEX_DATA_BASE_INDEX , "SetVertexDataBaseIndex" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 4 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 8 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 12 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 16 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 20 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 24 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 28 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 32 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 36 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 40 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 44 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 48 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 52 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 56 , "SetVertexDataArrayFormat" } , - { NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 60 , "SetVertexDataArrayFormat" } , - { NV4097_CLEAR_REPORT_VALUE , "ClearReportValue" } , - { NV4097_SET_ZPASS_PIXEL_COUNT_ENABLE , "SetZpassPixelCountEnable" } , - { NV4097_GET_REPORT , "GetReport" } , - { NV4097_SET_ZCULL_STATS_ENABLE , "SetZcullStatsEnable" } , - { NV4097_SET_BEGIN_END , "SetBeginEnd" } , - { NV4097_ARRAY_ELEMENT16 , "ArrayElement16" } , - { NV4097_ARRAY_ELEMENT32 , "ArrayElement32" } , - { NV4097_DRAW_ARRAYS , "DrawArrays" } , - { NV4097_INLINE_ARRAY , "InlineArray" } , - { NV4097_SET_INDEX_ARRAY_ADDRESS , "SetIndexArrayAddress" } , - { NV4097_SET_INDEX_ARRAY_DMA , "SetIndexArrayDMA" } , - { NV4097_DRAW_INDEX_ARRAY , "DrawIndexArray" } , - { NV4097_SET_FRONT_POLYGON_MODE , "SetFrontPolygonMode" } , - { NV4097_SET_BACK_POLYGON_MODE , "SetBackPolygonMode" } , - { NV4097_SET_CULL_FACE , "SetCullFace" } , - { NV4097_SET_FRONT_FACE , "SetFrontFace" } , - { NV4097_SET_POLY_SMOOTH_ENABLE , "SetPolySmoothEnable" } , - { NV4097_SET_CULL_FACE_ENABLE , "SetCullFaceEnable" } , - { NV4097_SET_TEXTURE_CONTROL3 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 4 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 8 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 12 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 16 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 20 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 24 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 28 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 32 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 36 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 40 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 44 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 48 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 52 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 56 , "SetTextureControl3"}, - { NV4097_SET_TEXTURE_CONTROL3 + 60 , "SetTextureControl3"}, - { NV4097_SET_VERTEX_DATA2F_M , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 4 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 8 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 12 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 16 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 20 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 24 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 28 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 32 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 36 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 40 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 44 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 48 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 52 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 56 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 60 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 64 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 68 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 72 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 76 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 80 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 84 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 88 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 92 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 96 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 100 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 104 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 108 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 112 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 116 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 120 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2F_M + 124 , "SetVertexData2f_M"}, - { NV4097_SET_VERTEX_DATA2S_M , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 4 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 8 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 12 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 16 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 20 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 24 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 28 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 32 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 36 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 40 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 44 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 48 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 52 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 56 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA2S_M + 60 , "SetVertexData2s_M"}, - { NV4097_SET_VERTEX_DATA4UB_M , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 4 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 8 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 12 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 16 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 20 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 24 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 28 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 32 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 36 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 40 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 44 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 48 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 52 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 56 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4UB_M + 60 , "SetVertexData4ub_M"}, - { NV4097_SET_VERTEX_DATA4S_M , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 4 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 8 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 12 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 16 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 20 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 24 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 28 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 32 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 36 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 40 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 44 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 48 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 52 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 56 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 60 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 64 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 68 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 72 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 76 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 80 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 84 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 88 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 92 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 96 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 100 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 104 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 108 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 112 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 116 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 120 , "SetVertexData4s_M"}, - { NV4097_SET_VERTEX_DATA4S_M + 124 , "SetVertexData4s_M"}, - { NV4097_SET_TEXTURE_OFFSET , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0x20 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0x20 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0x20 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0x20 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0x20 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0x20 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0x20 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0x20 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0x40 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0x40 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0x40 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0x40 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0x40 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0x40 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0x40 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0x40 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0x60 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0x60 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0x60 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0x60 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0x60 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0x60 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0x60 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0x60 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0x80 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0x80 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0x80 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0x80 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0x80 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0x80 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0x80 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0x80 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0xa0 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0xa0 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0xa0 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0xa0 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0xa0 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0xa0 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0xa0 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0xa0 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0xc0 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0xc0 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0xc0 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0xc0 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0xc0 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0xc0 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0xc0 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0xc0 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0xe0 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0xe0 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0xe0 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0xe0 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0xe0 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0xe0 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0xe0 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0xe0 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0x100 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0x100 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0x100 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0x100 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0x100 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0x100 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0x100 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0x100 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0x120 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0x120 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0x120 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0x120 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0x120 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0x120 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0x120 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0x120 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0x140 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0x140 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0x140 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0x140 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0x140 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0x140 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0x140 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0x140 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0x160 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0x160 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0x160 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0x160 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0x160 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0x160 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0x160 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0x160 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0x180 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0x180 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0x180 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0x180 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0x180 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0x180 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0x180 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0x180 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0x1a0 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0x1a0 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0x1a0 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0x1a0 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0x1a0 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0x1a0 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0x1a0 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0x1a0 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0x1c0 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0x1c0 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0x1c0 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0x1c0 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0x1c0 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0x1c0 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0x1c0 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0x1c0 , "SetTexture_BorderColor" } , - { NV4097_SET_TEXTURE_OFFSET + 0x1e0 , "SetTexture_Offset" } , - { NV4097_SET_TEXTURE_FORMAT + 0x1e0 , "SetTexture_Format" } , - { NV4097_SET_TEXTURE_ADDRESS + 0x1e0 , "SetTexture_Address" } , - { NV4097_SET_TEXTURE_CONTROL0 + 0x1e0 , "SetTexture_Control0" } , - { NV4097_SET_TEXTURE_CONTROL1 + 0x1e0 , "SetTexture_Control1" } , - { NV4097_SET_TEXTURE_FILTER + 0x1e0 , "SetTexture_Filter" } , - { NV4097_SET_TEXTURE_IMAGE_RECT + 0x1e0 , "SetTexture_ImageRect" } , - { NV4097_SET_TEXTURE_BORDER_COLOR + 0x1e0 , "SetTexture_BorderColor" } , - { NV4097_SET_VERTEX_DATA4F_M , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 4 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 8 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 12 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 16 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 20 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 24 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 28 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 32 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 36 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 40 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 44 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 48 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 52 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 56 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 60 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 64 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 68 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 72 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 76 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 80 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 84 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 88 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 92 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 96 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 100 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 104 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 108 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 112 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 116 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 120 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 124 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 128 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 132 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 136 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 140 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 144 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 148 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 152 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 156 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 160 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 164 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 168 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 172 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 176 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 180 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 184 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 188 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 192 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 196 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 200 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 204 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 208 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 212 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 216 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 220 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 224 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 228 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 232 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 236 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 240 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 244 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 248 , "SetVertexData4f_M"}, - { NV4097_SET_VERTEX_DATA4F_M + 252 , "SetVertexData4f_M"}, - { NV4097_SET_SHADER_CONTROL , "SetShaderControl" } , - { NV4097_SET_SEMAPHORE_OFFSET , "SetSemaphoreOffset" } , - { NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE , "BackEndWriteSemaphoreRelease" } , - { NV4097_TEXTURE_READ_SEMAPHORE_RELEASE , "TextureReadSemaphoreRelease" } , - { NV4097_SET_ZMIN_MAX_CONTROL , "SetZMinMaxControl" } , - { NV4097_SET_ANTI_ALIASING_CONTROL , "SetAntiAliasingControl" } , - { NV4097_SET_ZCULL_EN , "SetZcullEn" } , - { NV4097_SET_SHADER_WINDOW , "SetShaderWindow" } , - { NV4097_SET_ZSTENCIL_CLEAR_VALUE , "SetZStencilClearValue" } , - { NV4097_SET_COLOR_CLEAR_VALUE , "SetColorClearValue" } , - { NV4097_CLEAR_SURFACE , "ClearSurface" } , - { NV4097_SET_RESTART_INDEX_ENABLE , "SetRestartIndexEnable" } , - { NV4097_SET_RESTART_INDEX , "SetRestartIndex" } , - { NV4097_SET_LINE_STIPPLE , "SetLineStipple" } , - { NV4097_SET_LINE_STIPPLE_PATTERN , "SetLineStipplePattern" } , - { NV4097_SET_VERTEX_DATA1F_M , "SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 4 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 8 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 12 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 16 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 20 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 24 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 28 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 32 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 36 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 40 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 44 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 48 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 52 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 56 ,"SetVertexData1f_M"}, - { NV4097_SET_VERTEX_DATA1F_M + 60 ,"SetVertexData1f_M"}, - { NV4097_SET_RENDER_ENABLE , "SetRenderEnable" } , - { NV4097_SET_TRANSFORM_PROGRAM_LOAD , "SetTransformProgramLoad" } , - { NV4097_SET_TRANSFORM_PROGRAM_START , "SetTransformProgramStart" } , - { NV4097_SET_ZCULL_CONTROL0 , "SetZcullControl0" } , - { NV4097_SET_ZCULL_CONTROL1 , "SetZcullControl1" } , - { NV4097_SET_SCULL_CONTROL , "SetScullControl" } , - { NV4097_SET_POINT_SIZE , "SetPointSize" } , - { NV4097_SET_POINT_PARAMS_ENABLE , "SetPointParamsEnable" } , - { NV4097_SET_POINT_SPRITE_CONTROL , "SetPointSpriteControl" } , - { NV4097_SET_TRANSFORM_TIMEOUT , "SetTransformTimeout" } , - { NV4097_SET_TRANSFORM_CONSTANT_LOAD , "SetTransformConstantLoad" } , - { NV4097_SET_FREQUENCY_DIVIDER_OPERATION , "SetFrequencyDividerOperation" } , - { NV4097_INVALIDATE_L2 , "InvalidateL2" } , - { NV4097_SET_TRANSFORM_BRANCH_BITS, "SetTransformBranchBits" } , - }; - - for(u32 i = 0; i < WXSIZEOF(METHOD_NAME_LIST); ++i) - { - if(METHOD_NAME_LIST[i].id == id) return "cellGcm" + METHOD_NAME_LIST[i].name; - } - - return fmt::Format("unknown/illegal method [0x%08x]", id); -} diff --git a/rpcs3/Emu/GS/GL/GLFragmentProgram.cpp b/rpcs3/Emu/GS/GL/GLFragmentProgram.cpp deleted file mode 100644 index 784b3a6aea..0000000000 --- a/rpcs3/Emu/GS/GL/GLFragmentProgram.cpp +++ /dev/null @@ -1,452 +0,0 @@ -#include "stdafx.h" -#include "GLFragmentProgram.h" - -void GLFragmentDecompilerThread::AddCode(std::string code, bool append_mask) -{ - if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) return; - - const std::string mask = GetMask(); - std::string cond; - - if(!src0.exec_if_gr || !src0.exec_if_lt || !src0.exec_if_eq) - { - static const char f[4] = {'x', 'y', 'z', 'w'}; - - std::string swizzle; - swizzle += f[src0.cond_swizzle_x]; - swizzle += f[src0.cond_swizzle_y]; - swizzle += f[src0.cond_swizzle_z]; - swizzle += f[src0.cond_swizzle_w]; - swizzle = swizzle == "xyzw" ? "" : "." + swizzle; - - if(src0.exec_if_gr && src0.exec_if_eq) - { - cond = "greaterThanEqual"; - } - else if(src0.exec_if_lt && src0.exec_if_eq) - { - cond = "lessThanEqual"; - } - else if(src0.exec_if_gr && src0.exec_if_lt) - { - cond = "notEqual"; - } - else if(src0.exec_if_gr) - { - cond = "greaterThan"; - } - else if(src0.exec_if_lt) - { - cond = "lessThan"; - } - else //if(src0.exec_if_eq) - { - cond = "equal"; - } - - cond = "if(all(" + cond + "(" + AddCond(dst.no_dest) + swizzle + ", vec4(0.0)))) "; - } - - if(src1.scale) - { - switch(src1.scale) - { - case 1: code = "(" + code + " * 2)"; break; - case 2: code = "(" + code + " * 4)"; break; - case 3: code = "(" + code + " * 8)"; break; - case 5: code = "(" + code + " / 2)"; break; - case 6: code = "(" + code + " / 4)"; break; - case 7: code = "(" + code + " / 8)"; break; - - default: - ConLog.Error("Bad scale: %d", fmt::by_value(src1.scale)); - Emu.Pause(); - break; - } - } - - if(dst.saturate) - { - code = "clamp(" + code + ", 0.0, 1.0)"; - } - - std::string dest; - - if(dst.no_dest) - { - if(dst.set_cond) - { - dest = m_parr.AddParam(PARAM_NONE , "vec4", std::string(dst.fp16 ? "hc" : "rc") + std::to_string(src0.cond_reg_index)); - } - } - else - { - dest = AddReg(dst.dest_reg, dst.fp16); - } - - code = cond + (dest.length() ? dest + mask + " = " : "") + code + (append_mask ? mask : ""); - - main += "\t" + code + ";\n"; -} - -std::string GLFragmentDecompilerThread::GetMask() -{ - std::string ret; - - static const char dst_mask[4] = - { - 'x', 'y', 'z', 'w', - }; - - if(dst.mask_x) ret += dst_mask[0]; - if(dst.mask_y) ret += dst_mask[1]; - if(dst.mask_z) ret += dst_mask[2]; - if(dst.mask_w) ret += dst_mask[3]; - - return ret.empty() || strncmp(ret.c_str(), dst_mask, 4) == 0 ? "" : ("." + ret); -} - -std::string GLFragmentDecompilerThread::AddReg(u32 index, int fp16) -{ - if(index >= 2 && index <= 4) - { - return m_parr.AddParam(PARAM_OUT, "vec4", std::string(fp16 ? "h" : "r") + std::to_string(index), - (fp16) ? -1 : (index - 1)); - } - - return m_parr.AddParam(PARAM_NONE, "vec4", std::string(fp16 ? "h" : "r") + std::to_string(index), "vec4(0.0, 0.0, 0.0, 0.0)"); - - //return m_parr.AddParam((index >= 2 && index <= 4) ? PARAM_OUT : PARAM_NONE, "vec4", - // std::string(fp16 ? "h" : "r") + std::to_string(index), (fp16 || !index) ? -1 : ((index >= 2 && index <= 4) ? (index - 1) : -1)); -} - -bool GLFragmentDecompilerThread::HasReg(u32 index, int fp16) -{ - return m_parr.HasParam((index >= 2 && index <= 4) ? PARAM_OUT : PARAM_NONE, "vec4", - std::string(fp16 ? "h" : "r") + std::to_string(index)); -} - -std::string GLFragmentDecompilerThread::AddCond(int fp16) -{ - return m_parr.AddParam(PARAM_NONE , "vec4", std::string(fp16 ? "hc" : "rc") + std::to_string(src0.cond_mod_reg_index)); -} - -std::string GLFragmentDecompilerThread::AddConst() -{ - std::string name = std::string("fc") + std::to_string(m_size + 4 * 4); - if(m_parr.HasParam(PARAM_UNIFORM, "vec4", name)) - { - return name; - } - - mem32_ptr_t data(m_addr + m_size + m_offset); - - m_offset += 4 * 4; - u32 x = GetData(data[0]); - u32 y = GetData(data[1]); - u32 z = GetData(data[2]); - u32 w = GetData(data[3]); - return m_parr.AddParam(PARAM_UNIFORM, "vec4", name, - std::string("vec4(") + std::to_string((float&)x) + ", " + std::to_string((float&)y) - + ", " + std::to_string((float&)z) + ", " + std::to_string((float&)w) + ")"); -} - -std::string GLFragmentDecompilerThread::AddTex() -{ - return m_parr.AddParam(PARAM_UNIFORM, "sampler2D", std::string("tex") + std::to_string(dst.tex_num)); -} - -template std::string GLFragmentDecompilerThread::GetSRC(T src) -{ - std::string ret = ""; - - switch(src.reg_type) - { - case 0: //tmp - ret += AddReg(src.tmp_reg_index, src.fp16); - break; - - case 1: //input - { - static const std::string reg_table[] = - { - "gl_Position", - "col0", "col1", - "fogc", - "tc0", "tc1", "tc2", "tc3", "tc4", "tc5", "tc6", "tc7" - }; - - switch(dst.src_attr_reg_num) - { - case 0x00: ret += reg_table[0]; break; - default: - if(dst.src_attr_reg_num < sizeof(reg_table)/sizeof(reg_table[0])) - { - ret += m_parr.AddParam(PARAM_IN, "vec4", reg_table[dst.src_attr_reg_num]); - } - else - { - ConLog.Error("Bad src reg num: %d", fmt::by_value(dst.src_attr_reg_num)); - ret += m_parr.AddParam(PARAM_IN, "vec4", "unk"); - Emu.Pause(); - } - break; - } - } - break; - - case 2: //const - ret += AddConst(); - break; - - default: - ConLog.Error("Bad src type %d", fmt::by_value(src.reg_type)); - Emu.Pause(); - break; - } - - static const char f[4] = {'x', 'y', 'z', 'w'}; - - std::string swizzle = ""; - swizzle += f[src.swizzle_x]; - swizzle += f[src.swizzle_y]; - swizzle += f[src.swizzle_z]; - swizzle += f[src.swizzle_w]; - - if(strncmp(swizzle.c_str(), f, 4) != 0) ret += "." + swizzle; - - if(src.abs) ret = "abs(" + ret + ")"; - if(src.neg) ret = "-" + ret; - - return ret; -} - -std::string GLFragmentDecompilerThread::BuildCode() -{ - //main += fmt::Format("\tgl_FragColor = %c0;\n", m_ctrl & 0x40 ? 'r' : 'h'); - main += "\t" + m_parr.AddParam(PARAM_OUT, "vec4", "ocol", 0) + " = " + (m_ctrl & 0x40 ? "r0" : "h0") + ";\n"; - if(m_ctrl & 0xe) main += "\tgl_FragDepth = r1.z;\n"; - - std::string p; - - for(u32 i=0; iIsAlive()) - { - m_decompiler_thread->Stop(); - } - - delete m_decompiler_thread; - m_decompiler_thread = nullptr; - } - - Delete(); -} - -void GLShaderProgram::Wait() -{ - if(m_decompiler_thread && m_decompiler_thread->IsAlive()) - { - m_decompiler_thread->Join(); - } -} - -void GLShaderProgram::Decompile(RSXShaderProgram& prog) -{ - GLFragmentDecompilerThread decompiler(m_shader, m_parr, prog.addr, prog.size, prog.ctrl); - decompiler.Task(); -} - -void GLShaderProgram::DecompileAsync(RSXShaderProgram& prog) -{ - if(m_decompiler_thread) - { - Wait(); - if(m_decompiler_thread->IsAlive()) - { - m_decompiler_thread->Stop(); - } - - delete m_decompiler_thread; - m_decompiler_thread = nullptr; - } - - m_decompiler_thread = new GLFragmentDecompilerThread(m_shader, m_parr, prog.addr, prog.size, prog.ctrl); - m_decompiler_thread->Start(); -} - -void GLShaderProgram::Compile() -{ - if (m_id) glDeleteShader(m_id); - - m_id = glCreateShader(GL_FRAGMENT_SHADER); - - const char* str = m_shader.c_str(); - const int strlen = m_shader.length(); - - glShaderSource(m_id, 1, &str, &strlen); - glCompileShader(m_id); - - GLint compileStatus = GL_FALSE; - glGetShaderiv(m_id, GL_COMPILE_STATUS, &compileStatus); // Determine the result of the glCompileShader call - if (compileStatus != GL_TRUE) // If the shader failed to compile... - { - GLint infoLength; - glGetShaderiv(m_id, GL_INFO_LOG_LENGTH, &infoLength); // Retrieve the length in bytes (including trailing NULL) of the shader info log - - if (infoLength > 0) - { - GLsizei len; - char* buf = new char[infoLength]; // Buffer to store infoLog - - glGetShaderInfoLog(m_id, infoLength, &len, buf); // Retrieve the shader info log into our buffer - ConLog.Error("Failed to compile shader: %s", buf); // Write log to the console - - delete[] buf; - } - - ConLog.Write(m_shader.c_str()); // Log the text of the shader that failed to compile - Emu.Pause(); // Pause the emulator, we can't really continue from here - } -} - -void GLShaderProgram::Delete() -{ - for (u32 i = 0; iSetSize(GetClientSize()); - - canvas->Bind(wxEVT_LEFT_DCLICK, &GSFrame::OnLeftDclick, this); -} - -void GLGSFrame::Flip(wxGLContext *context) -{ - if(!canvas) return; - canvas->SetCurrent(*context); - - static Timer fps_t; - canvas->SwapBuffers(); - m_frames++; - - if(fps_t.GetElapsedTimeInSec() >= 0.5) - { - SetTitle(wxString::Format("FPS: %.2f", (double)m_frames / fps_t.GetElapsedTimeInSec())); - m_frames = 0; - fps_t.Start(); - } -} - -void GLGSFrame::OnSize(wxSizeEvent& event) -{ - if(canvas) canvas->SetSize(GetClientSize()); - event.Skip(); -} - -void GLGSFrame::SetViewport(int x, int y, u32 w, u32 h) -{ - /* - //ConLog.Warning("SetViewport(x=%d, y=%d, w=%d, h=%d)", x, y, w, h); - - const wxSize client = GetClientSize(); - const wxSize viewport = AspectRatio(client, wxSize(w, h)); - - const int vx = (client.GetX() - viewport.GetX()) / 2; - const int vy = (client.GetY() - viewport.GetY()) / 2; - - glViewport(vx + x, vy + y, viewport.GetWidth(), viewport.GetHeight()); - */ -} - -GLGSRender::GLGSRender() - : GSRender() - , m_frame(nullptr) - , m_fp_buf_num(-1) - , m_vp_buf_num(-1) - , m_context(nullptr) -{ - m_frame = new GLGSFrame(); -} - -GLGSRender::~GLGSRender() -{ - m_frame->Close(); - delete m_context; -} - -void GLGSRender::Enable(bool enable, const u32 cap) -{ - if(enable) - { - glEnable(cap); - } - else - { - glDisable(cap); - } -} - -extern CellGcmContextData current_context; - -void GLGSRender::Close() -{ - Stop(); - - if(m_frame->IsShown()) m_frame->Hide(); - m_ctrl = nullptr; -} - -void GLGSRender::EnableVertexData(bool indexed_draw) -{ - static u32 offset_list[m_vertex_count]; - u32 cur_offset = 0; - - const u32 data_offset = indexed_draw ? 0 : m_draw_array_first; - - for(u32 i=0; i= 1 && m_vertex_data[i].type <= 7) - { - if(!m_vertex_data[i].addr) - { - switch(m_vertex_data[i].type) - { - case CELL_GCM_VERTEX_S32K: - case CELL_GCM_VERTEX_S1: - switch(m_vertex_data[i].size) - { - case 1: glVertexAttrib1s(i, (GLshort&)m_vertex_data[i].data[0]); break; - case 2: glVertexAttrib2sv(i, (GLshort*)&m_vertex_data[i].data[0]); break; - case 3: glVertexAttrib3sv(i, (GLshort*)&m_vertex_data[i].data[0]); break; - case 4: glVertexAttrib4sv(i, (GLshort*)&m_vertex_data[i].data[0]); break; - } - break; - - case CELL_GCM_VERTEX_F: - switch(m_vertex_data[i].size) - { - case 1: glVertexAttrib1f(i, (GLfloat&)m_vertex_data[i].data[0]); break; - case 2: glVertexAttrib2fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break; - case 3: glVertexAttrib3fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break; - case 4: glVertexAttrib4fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break; - } - break; - - case CELL_GCM_VERTEX_CMP: - case CELL_GCM_VERTEX_UB: - glVertexAttrib4ubv(i, (GLubyte*)&m_vertex_data[i].data[0]); - break; - } - - checkForGlError("glVertexAttrib"); - } - else - { - u32 gltype = gl_types[m_vertex_data[i].type - 1]; - bool normalized = gl_normalized[m_vertex_data[i].type - 1]; - - glEnableVertexAttribArray(i); - checkForGlError("glEnableVertexAttribArray"); - glVertexAttribPointer(i, m_vertex_data[i].size, gltype, normalized, 0, (void*)offset_list[i]); - checkForGlError("glVertexAttribPointer"); - } - } - } -} - -void GLGSRender::DisableVertexData() -{ - m_vdata.clear(); - for(u32 i=0; ioffset; - - //ConLog.Warning("fc%u[0x%x - 0x%x] = (%f, %f, %f, %f)", id, c.id, m_cur_shader_prog->offset, c.x, c.y, c.z, c.w); - - const std::string name = fmt::Format("fc%u", id); - const int l = m_program.GetLocation(name); - checkForGlError("glGetUniformLocation " + name); - - glUniform4f(l, c.x, c.y, c.z, c.w); - checkForGlError("glUniform4f " + name + fmt::Format(" %d [%f %f %f %f]", l, c.x, c.y, c.z, c.w)); - } - - //if(m_fragment_constants.GetCount()) - // ConLog.SkipLn(); -} - -bool GLGSRender::LoadProgram() -{ - if(!m_cur_shader_prog) - { - ConLog.Warning("LoadProgram: m_cur_shader_prog == NULL"); - return false; - } - - if(!m_cur_vertex_prog) - { - ConLog.Warning("LoadProgram: m_cur_vertex_prog == NULL"); - return false; - } - - m_fp_buf_num = m_prog_buffer.SearchFp(*m_cur_shader_prog, m_shader_prog); - m_vp_buf_num = m_prog_buffer.SearchVp(*m_cur_vertex_prog, m_vertex_prog); - - //ConLog.Write("Create program"); - - if(m_fp_buf_num == -1) - { - ConLog.Warning("FP not found in buffer!"); - m_shader_prog.DecompileAsync(*m_cur_shader_prog); - m_shader_prog.Wait(); - m_shader_prog.Compile(); - checkForGlError("m_shader_prog.Compile"); - - wxFile f(wxGetCwd() + "/FragmentProgram.txt", wxFile::write); - f.Write(m_shader_prog.GetShaderText()); - } - - if(m_vp_buf_num == -1) - { - ConLog.Warning("VP not found in buffer!"); - m_vertex_prog.DecompileAsync(*m_cur_vertex_prog); - m_vertex_prog.Wait(); - m_vertex_prog.Compile(); - checkForGlError("m_vertex_prog.Compile"); - - wxFile f(wxGetCwd() + "/VertexProgram.txt", wxFile::write); - f.Write(m_vertex_prog.shader); - } - - if(m_fp_buf_num != -1 && m_vp_buf_num != -1) - { - m_program.id = m_prog_buffer.GetProg(m_fp_buf_num, m_vp_buf_num); - } - - if(m_program.id) - { - // RSX Debugger: Check if this program was modified and update it - if (Ini.GSLogPrograms.GetValue()) - { - for(auto& program : m_debug_programs) - { - if (program.id == m_program.id && program.modified) - { - // TODO: This isn't working perfectly. Is there any better/shorter way to update the program - m_vertex_prog.shader = program.vp_shader; - m_shader_prog.SetShaderText(program.fp_shader); - m_vertex_prog.Wait(); - m_vertex_prog.Compile(); - checkForGlError("m_vertex_prog.Compile"); - m_shader_prog.Wait(); - m_shader_prog.Compile(); - checkForGlError("m_shader_prog.Compile"); - glAttachShader(m_program.id, m_vertex_prog.id); - glAttachShader(m_program.id, m_shader_prog.GetId()); - glLinkProgram(m_program.id); - checkForGlError("glLinkProgram"); - glDetachShader(m_program.id, m_vertex_prog.id); - glDetachShader(m_program.id, m_shader_prog.GetId()); - program.vp_id = m_vertex_prog.id; - program.fp_id = m_shader_prog.GetId(); - program.modified = false; - } - } - } - m_program.Use(); - } - else - { - m_program.Create(m_vertex_prog.id, m_shader_prog.GetId()); - checkForGlError("m_program.Create"); - m_prog_buffer.Add(m_program, m_shader_prog, *m_cur_shader_prog, m_vertex_prog, *m_cur_vertex_prog); - checkForGlError("m_prog_buffer.Add"); - m_program.Use(); - - // RSX Debugger - if (Ini.GSLogPrograms.GetValue()) - { - RSXDebuggerProgram program; - program.id = m_program.id; - program.vp_id = m_vertex_prog.id; - program.fp_id = m_shader_prog.GetId(); - program.vp_shader = m_vertex_prog.shader; - program.fp_shader = m_shader_prog.GetShaderText(); - m_debug_programs.push_back(program); - } - } - - return true; -} - -void GLGSRender::WriteDepthBuffer() -{ - if(!m_set_context_dma_z) - { - return; - } - - // Reset the flag - m_set_context_dma_z = false; - - u32 address = GetAddress(m_surface_offset_z, m_context_dma_z - 0xfeed0000); - if(!Memory.IsGoodAddr(address)) - { - ConLog.Warning("Bad depth address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_z, m_context_dma_z); - return; - } - - glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, &Memory[address]); - checkForGlError("glReadPixels"); - - glBindTexture(GL_TEXTURE_2D, g_depth_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, RSXThread::m_width, RSXThread::m_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &Memory[address]); - checkForGlError("glTexImage2D"); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]); - checkForGlError("glGetTexImage"); -} - -void GLGSRender::WriteColourBufferA() -{ - if(!m_set_context_dma_color_a) - { - return; - } - - // Reset the flag - m_set_context_dma_color_a = false; - - u32 address = GetAddress(m_surface_offset_a, m_context_dma_color_a - 0xfeed0000); - if(!Memory.IsGoodAddr(address)) - { - ConLog.Warning("Bad colour buffer a address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_a, m_context_dma_color_a); - return; - } - - glReadBuffer(GL_COLOR_ATTACHMENT0); - checkForGlError("glReadBuffer(GL_COLOR_ATTACHMENT0)"); - glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]); - checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)"); -} - -void GLGSRender::WriteColourBufferB() -{ - if(!m_set_context_dma_color_b) - { - return; - } - - // Reset the flag - m_set_context_dma_color_b = false; - - u32 address = GetAddress(m_surface_offset_b, m_context_dma_color_b - 0xfeed0000); - if(!Memory.IsGoodAddr(address)) - { - ConLog.Warning("Bad colour buffer b address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_b, m_context_dma_color_b); - return; - } - - glReadBuffer(GL_COLOR_ATTACHMENT1); - checkForGlError("glReadBuffer(GL_COLOR_ATTACHMENT1)"); - glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]); - checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)"); -} - -void GLGSRender::WriteColourBufferC() -{ - if(!m_set_context_dma_color_c) - { - return; - } - - // Reset the flag - m_set_context_dma_color_c = false; - - u32 address = GetAddress(m_surface_offset_c, m_context_dma_color_c - 0xfeed0000); - if(!Memory.IsGoodAddr(address)) - { - ConLog.Warning("Bad colour buffer c address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_c, m_context_dma_color_c); - return; - } - - glReadBuffer(GL_COLOR_ATTACHMENT2); - checkForGlError("glReadBuffer(GL_COLOR_ATTACHMENT2)"); - glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]); - checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)"); -} - -void GLGSRender::WriteColourBufferD() -{ - if(!m_set_context_dma_color_d) - { - return; - } - - // Reset the flag - m_set_context_dma_color_d = false; - - u32 address = GetAddress(m_surface_offset_d, m_context_dma_color_d - 0xfeed0000); - if(!Memory.IsGoodAddr(address)) - { - ConLog.Warning("Bad colour buffer d address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_d, m_context_dma_color_d); - return; - } - - glReadBuffer(GL_COLOR_ATTACHMENT3); - checkForGlError("glReadBuffer(GL_COLOR_ATTACHMENT3)"); - glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]); - checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)"); -} - -void GLGSRender::WriteColorBuffers() -{ - glPixelStorei(GL_PACK_ROW_LENGTH, 0); - glPixelStorei(GL_PACK_ALIGNMENT, 4); - - switch(m_surface_colour_target) - { - case CELL_GCM_SURFACE_TARGET_NONE: - return; - - case CELL_GCM_SURFACE_TARGET_0: - WriteColourBufferA(); - break; - - case CELL_GCM_SURFACE_TARGET_1: - WriteColourBufferB(); - break; - - case CELL_GCM_SURFACE_TARGET_MRT1: - WriteColourBufferA(); - WriteColourBufferB(); - break; - - case CELL_GCM_SURFACE_TARGET_MRT2: - WriteColourBufferA(); - WriteColourBufferB(); - WriteColourBufferC(); - break; - - case CELL_GCM_SURFACE_TARGET_MRT3: - WriteColourBufferA(); - WriteColourBufferB(); - WriteColourBufferC(); - WriteColourBufferD(); - break; - } -} - -void GLGSRender::OnInit() -{ - m_draw_frames = 1; - m_skip_frames = 0; - RSXThread::m_width = 720; - RSXThread::m_height = 576; - - last_width = 0; - last_height = 0; - last_depth_format = 0; - - m_frame->Show(); -} - -void GLGSRender::OnInitThread() -{ - m_context = new wxGLContext(m_frame->GetCanvas()); - - m_frame->GetCanvas()->SetCurrent(*m_context); - InitProcTable(); - - glEnable(GL_TEXTURE_2D); - -#ifdef _WIN32 - glSwapInterval(Ini.GSVSyncEnable.GetValue() ? 1 : 0); -// Undefined reference: glXSwapIntervalEXT -/*#else - if (GLXDrawable drawable = glXGetCurrentDrawable()){ - glXSwapIntervalEXT(glXGetCurrentDisplay(), drawable, Ini.GSVSyncEnable.GetValue() ? 1 : 0); - }*/ -#endif - glGenTextures(1, &g_depth_tex); - glGenTextures(1, &g_flip_tex); -} - -void GLGSRender::OnExitThread() -{ - glDeleteTextures(1, &g_flip_tex); - glDeleteTextures(1, &g_depth_tex); - - m_program.Delete(); - m_rbo.Delete(); - m_fbo.Delete(); - m_vbo.Delete(); - m_vao.Delete(); - m_prog_buffer.Clear(); -} - -void GLGSRender::OnReset() -{ - m_program.UnUse(); - - //m_shader_prog.id = 0; - //m_vertex_prog.id = 0; - - if(m_vbo.IsCreated()) - { - m_vbo.UnBind(); - m_vbo.Delete(); - } - - m_vao.Delete(); -} - -void GLGSRender::ExecCMD() -{ - //return; - if(!LoadProgram()) - { - ConLog.Error("LoadProgram failed."); - Emu.Pause(); - return; - } - - if(!m_fbo.IsCreated() || RSXThread::m_width != last_width || RSXThread::m_height != last_height || last_depth_format != m_surface_depth_format) - { - ConLog.Warning("New FBO (%dx%d)", RSXThread::m_width, RSXThread::m_height); - last_width = RSXThread::m_width; - last_height = RSXThread::m_height; - last_depth_format = m_surface_depth_format; - - m_fbo.Create(); - checkForGlError("m_fbo.Create"); - m_fbo.Bind(); - - m_rbo.Create(4 + 1); - checkForGlError("m_rbo.Create"); - - for(int i=0; i<4; ++i) - { - m_rbo.Bind(i); - m_rbo.Storage(GL_RGBA, RSXThread::m_width, RSXThread::m_height); - checkForGlError("m_rbo.Storage(GL_RGBA)"); - } - - m_rbo.Bind(4); - - switch(m_surface_depth_format) - { - // case 0 found in BLJM60410-[Suzukaze no Melt - Days in the Sanctuary] - // [E : RSXThread]: Bad depth format! (0) - // [E : RSXThread]: glEnable: opengl error 0x0506 - // [E : RSXThread]: glDrawArrays: opengl error 0x0506 - case 0: - m_rbo.Storage(GL_DEPTH_COMPONENT, RSXThread::m_width, RSXThread::m_height); - checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT)"); - break; - - case CELL_GCM_SURFACE_Z16: - m_rbo.Storage(GL_DEPTH_COMPONENT16, RSXThread::m_width, RSXThread::m_height); - checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT16)"); - break; - - case CELL_GCM_SURFACE_Z24S8: - m_rbo.Storage(GL_DEPTH24_STENCIL8, RSXThread::m_width, RSXThread::m_height); - checkForGlError("m_rbo.Storage(GL_DEPTH24_STENCIL8)"); - break; - - default: - ConLog.Error("Bad depth format! (%d)", m_surface_depth_format); - assert(0); - break; - } - - for(int i=0; i<4; ++i) - { - m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0 + i, m_rbo.GetId(i)); - checkForGlError(fmt::Format("m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT%d)", i)); - } - - m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT, m_rbo.GetId(4)); - checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT)"); - - if(m_surface_depth_format == 2) - { - m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT, m_rbo.GetId(4)); - checkForGlError("m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT)"); - } - } - - if(!m_set_surface_clip_horizontal) - { - m_surface_clip_x = 0; - m_surface_clip_w = RSXThread::m_width; - } - - if(!m_set_surface_clip_vertical) - { - m_surface_clip_y = 0; - m_surface_clip_h = RSXThread::m_height; - } - - m_fbo.Bind(); - - if(Ini.GSDumpDepthBuffer.GetValue()) - WriteDepthBuffer(); - - static const GLenum draw_buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; - - switch(m_surface_colour_target) - { - case CELL_GCM_SURFACE_TARGET_NONE: - break; - - case CELL_GCM_SURFACE_TARGET_0: - glDrawBuffer(draw_buffers[0]); - break; - - case CELL_GCM_SURFACE_TARGET_1: - glDrawBuffer(draw_buffers[1]); - break; - - case CELL_GCM_SURFACE_TARGET_MRT1: - glDrawBuffers(2, draw_buffers); - break; - - case CELL_GCM_SURFACE_TARGET_MRT2: - glDrawBuffers(3, draw_buffers); - break; - - case CELL_GCM_SURFACE_TARGET_MRT3: - glDrawBuffers(4, draw_buffers); - break; - - default: - ConLog.Error("Bad surface colour target: %d", m_surface_colour_target); - break; - } - - if(m_set_color_mask) - { - glColorMask(m_color_mask_r, m_color_mask_g, m_color_mask_b, m_color_mask_a); - checkForGlError("glColorMask"); - } - - if(m_set_viewport_horizontal && m_set_viewport_vertical) - { - //glViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h); - //checkForGlError("glViewport"); - } - - if(m_clear_surface_mask) - { - GLbitfield f = 0; - - if (m_clear_surface_mask & 0x1) - { - glClearDepth(m_clear_surface_z / (float)0xffffff); - - f |= GL_DEPTH_BUFFER_BIT; - } - - if (m_clear_surface_mask & 0x2) - { - glClearStencil(m_clear_surface_s); - - f |= GL_STENCIL_BUFFER_BIT; - } - - if (m_clear_surface_mask & 0xF0) - { - glClearColor( - m_clear_surface_color_r / 255.0f, - m_clear_surface_color_g / 255.0f, - m_clear_surface_color_b / 255.0f, - m_clear_surface_color_a / 255.0f); - - f |= GL_COLOR_BUFFER_BIT; - } - - glClear(f); - } - - Enable(m_set_depth_test, GL_DEPTH_TEST); - Enable(m_set_alpha_test, GL_ALPHA_TEST); - Enable(m_set_depth_bounds_test, GL_DEPTH_BOUNDS_TEST_EXT); - Enable(m_set_blend, GL_BLEND); - Enable(m_set_logic_op, GL_LOGIC_OP); - Enable(m_set_cull_face, GL_CULL_FACE); - Enable(m_set_dither, GL_DITHER); - Enable(m_set_stencil_test, GL_STENCIL_TEST); - Enable(m_set_scissor_horizontal && m_set_scissor_vertical, GL_SCISSOR_TEST); - Enable(m_set_line_smooth, GL_LINE_SMOOTH); - Enable(m_set_poly_smooth, GL_POLYGON_SMOOTH); - Enable(m_set_point_sprite_control, GL_POINT_SPRITE); - Enable(m_set_specular, GL_LIGHTING); - Enable(m_set_poly_offset_fill, GL_POLYGON_OFFSET_FILL); - Enable(m_set_poly_offset_line, GL_POLYGON_OFFSET_LINE); - Enable(m_set_poly_offset_point, GL_POLYGON_OFFSET_POINT); - Enable(m_set_restart_index, GL_PRIMITIVE_RESTART); // Requires OpenGL 3.1+ - - if(m_set_clip_plane) - { - Enable(m_clip_plane_0, GL_CLIP_PLANE0); - Enable(m_clip_plane_1, GL_CLIP_PLANE1); - Enable(m_clip_plane_2, GL_CLIP_PLANE2); - Enable(m_clip_plane_3, GL_CLIP_PLANE3); - Enable(m_clip_plane_4, GL_CLIP_PLANE4); - Enable(m_clip_plane_5, GL_CLIP_PLANE5); - - checkForGlError("m_set_clip_plane"); - } - - checkForGlError("glEnable"); - - - if (m_set_front_polygon_mode) - { - glPolygonMode(GL_FRONT, m_front_polygon_mode); - checkForGlError("glPolygonMode(Front)"); - } - - if (m_set_back_polygon_mode) - { - glPolygonMode(GL_BACK, m_back_polygon_mode); - checkForGlError("glPolygonMode(Back)"); - } - - if (m_set_point_size) - { - glPointSize(m_point_size); - checkForGlError("glPointSize"); - } - - if (m_set_poly_offset_mode) - { - glPolygonOffset(m_poly_offset_scale_factor, m_poly_offset_bias); - checkForGlError("glPolygonOffset"); - } - - if (m_set_logic_op) - { - glLogicOp(m_logic_op); - checkForGlError("glLogicOp"); - } - - if (m_set_scissor_horizontal && m_set_scissor_vertical) - { - glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); - checkForGlError("glScissor"); - } - - if(m_set_two_sided_stencil_test_enable) - { - if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) - { - glStencilOpSeparate(GL_FRONT, m_stencil_fail, m_stencil_zfail, m_stencil_zpass); - checkForGlError("glStencilOpSeparate"); - } - - if(m_set_stencil_mask) - { - glStencilMaskSeparate(GL_FRONT, m_stencil_mask); - checkForGlError("glStencilMaskSeparate"); - } - - if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) - { - glStencilFuncSeparate(GL_FRONT, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); - checkForGlError("glStencilFuncSeparate"); - } - - if(m_set_back_stencil_fail && m_set_back_stencil_zfail && m_set_back_stencil_zpass) - { - glStencilOpSeparate(GL_BACK, m_back_stencil_fail, m_back_stencil_zfail, m_back_stencil_zpass); - checkForGlError("glStencilOpSeparate(GL_BACK)"); - } - - if(m_set_back_stencil_mask) - { - glStencilMaskSeparate(GL_BACK, m_back_stencil_mask); - checkForGlError("glStencilMaskSeparate(GL_BACK)"); - } - - if(m_set_back_stencil_func && m_set_back_stencil_func_ref && m_set_back_stencil_func_mask) - { - glStencilFuncSeparate(GL_BACK, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask); - checkForGlError("glStencilFuncSeparate(GL_BACK)"); - } - } - else - { - if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) - { - glStencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass); - checkForGlError("glStencilOp"); - } - - if(m_set_stencil_mask) - { - glStencilMask(m_stencil_mask); - checkForGlError("glStencilMask"); - } - - if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) - { - glStencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); - checkForGlError("glStencilFunc"); - } - } - - if(m_set_shade_mode) - { - glShadeModel(m_shade_mode); - checkForGlError("glShadeModel"); - } - - if(m_set_depth_mask) - { - glDepthMask(m_depth_mask); - checkForGlError("glDepthMask"); - } - - if(m_set_depth_func) - { - glDepthFunc(m_depth_func); - //ConLog.Warning("glDepthFunc(0x%x)", m_depth_func); - checkForGlError("glDepthFunc"); - } - - if(m_set_depth_bounds) - { - //ConLog.Warning("glDepthBounds(%f, %f)", m_depth_bounds_min, m_depth_bounds_max); - glDepthBoundsEXT(m_depth_bounds_min, m_depth_bounds_max); - checkForGlError("glDepthBounds"); - } - - if(m_set_clip) - { - //ConLog.Warning("glDepthRangef(%f, %f)", m_clip_min, m_clip_max); - glDepthRangef(m_clip_min, m_clip_max); - checkForGlError("glDepthRangef"); - } - - if(m_set_line_width) - { - glLineWidth(m_line_width / 255.f); - checkForGlError("glLineWidth"); - } - - if(m_set_blend_equation) - { - glBlendEquationSeparate(m_blend_equation_rgb, m_blend_equation_alpha); - checkForGlError("glBlendEquationSeparate"); - } - - if(m_set_blend_sfactor && m_set_blend_dfactor) - { - glBlendFuncSeparate(m_blend_sfactor_rgb, m_blend_dfactor_rgb, m_blend_sfactor_alpha, m_blend_dfactor_alpha); - checkForGlError("glBlendFuncSeparate"); - } - - if(m_set_blend_color) - { - glBlendColor(m_blend_color_r, m_blend_color_g, m_blend_color_b, m_blend_color_a); - checkForGlError("glBlendColor"); - } - - if(m_set_cull_face) - { - glCullFace(m_cull_face); - checkForGlError("glCullFace"); - } - - if (m_set_front_face) - { - // Sanity check . Disgaea 3 return 0x1d0 here and cause openGL 0x0500 - if (m_front_face == GL_CW || m_front_face == GL_CCW) - { - glFrontFace(m_front_face); - checkForGlError("glFrontFace"); - } - } - - if(m_set_alpha_func && m_set_alpha_ref) - { - glAlphaFunc(m_alpha_func, m_alpha_ref/255.0f); - checkForGlError("glAlphaFunc"); - } - - if(m_set_fog_mode) - { - glFogi(GL_FOG_MODE, m_fog_mode); - checkForGlError("glFogi(GL_FOG_MODE)"); - } - - if(m_set_fog_params) - { - glFogf(GL_FOG_START, m_fog_param0); - checkForGlError("glFogf(GL_FOG_START)"); - glFogf(GL_FOG_END, m_fog_param1); - checkForGlError("glFogf(GL_FOG_END)"); - } - - if(m_set_restart_index) - { - glPrimitiveRestartIndex(m_restart_index); // Requires OpenGL 3.1+ - checkForGlError("glPrimitiveRestartIndex"); - } - - if(m_indexed_array.m_count && m_draw_array_count) - { - ConLog.Warning("m_indexed_array.m_count && draw_array_count"); - } - - for(u32 i=0; i pixels; - pixels.resize(RSXThread::m_width * RSXThread::m_height * 4); - m_fbo.Bind(GL_READ_FRAMEBUFFER); - glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, pixels.data()); - - src_buffer = pixels.data(); - width = RSXThread::m_width; - height = RSXThread::m_height; - } - else - src_buffer = nullptr; - - if (src_buffer) - { - glDisable(GL_STENCIL_TEST); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CLIP_PLANE0); - glDisable(GL_CLIP_PLANE1); - glDisable(GL_CLIP_PLANE2); - glDisable(GL_CLIP_PLANE3); - glDisable(GL_CLIP_PLANE4); - glDisable(GL_CLIP_PLANE5); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, g_flip_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_INT_8_8_8_8, src_buffer); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, 1, 0, 1, 0, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0); - - m_program.UnUse(); - m_program.Use(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_ACCUM_BUFFER_BIT); - - glColor3f(1, 1, 1); - glBegin(GL_QUADS); - glTexCoord2i(0, 1); - glVertex2i(0, 0); - - glTexCoord2i(1, 1); - glVertex2i(1, 0); - - glTexCoord2i(1, 0); - glVertex2i(1, 1); - - glTexCoord2i(0, 0); - glVertex2i(0, 1); - glEnd(); - } - - if (m_set_scissor_horizontal && m_set_scissor_vertical) - { - glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); - checkForGlError("glScissor"); - } - } - break; - } - - // Draw Objects - for (uint i = 0; iFlip(m_context); - -} - -u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, u32 log2_depth) -{ - u32 offset = 0; - u32 shift_count = 0; - while(log2_width | log2_height | log2_depth){ - if(log2_width){ - offset |= (x & 0x01) << shift_count; - x >>= 1; - ++shift_count; - --log2_width; - } - if(log2_height){ - offset |= (y & 0x01) << shift_count; - y >>= 1; - ++shift_count; - --log2_height; - } - if(log2_depth){ - offset |= (z & 0x01) << shift_count; - z >>= 1; - ++shift_count; - --log2_depth; - } - } - return offset; -} diff --git a/rpcs3/Emu/GS/GL/GLGSRender.h b/rpcs3/Emu/GS/GL/GLGSRender.h deleted file mode 100644 index 8839d578ea..0000000000 --- a/rpcs3/Emu/GS/GL/GLGSRender.h +++ /dev/null @@ -1,845 +0,0 @@ -#pragma once -#include "Emu/GS/GSRender.h" -#include "Emu/GS/RSXThread.h" -#include "GLBuffers.h" -#include "GLProgramBuffer.h" -#include - -#pragma comment(lib, "opengl32.lib") - -#define RSX_DEBUG 1 - -extern GLenum g_last_gl_error; -void printGlError(GLenum err, const char* situation); -void printGlError(GLenum err, const std::string& situation); -u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, u32 log2_depth); - -#if RSX_DEBUG -#define checkForGlError(sit) if((g_last_gl_error = glGetError()) != GL_NO_ERROR) printGlError(g_last_gl_error, sit) -#else -#define checkForGlError(sit) -#endif - -class GLTexture -{ - u32 m_id; - -public: - GLTexture() : m_id(0) - { - } - - void Create() - { - if(m_id) - { - Delete(); - } - - if(!m_id) - { - glGenTextures(1, &m_id); - checkForGlError("GLTexture::Init() -> glGenTextures"); - Bind(); - } - } - - int GetGlWrap(int wrap) - { - switch(wrap) - { - case 1: return GL_REPEAT; - case 2: return GL_MIRRORED_REPEAT; - case 3: return GL_CLAMP_TO_EDGE; - case 4: return GL_CLAMP_TO_BORDER; - case 5: return GL_CLAMP_TO_EDGE; - case 6: return GL_MIRROR_CLAMP_TO_EDGE_EXT; - case 7: return GL_MIRROR_CLAMP_TO_BORDER_EXT; - case 8: return GL_MIRROR_CLAMP_EXT; - } - - ConLog.Error("Texture wrap error: bad wrap (%d).", wrap); - return GL_REPEAT; - } - - inline static u8 Convert4To8(u8 v) - { - // Swizzle bits: 00001234 -> 12341234 - return (v << 4) | (v); - } - - inline static u8 Convert5To8(u8 v) - { - // Swizzle bits: 00012345 -> 12345123 - return (v << 3) | (v >> 2); - } - - inline static u8 Convert6To8(u8 v) - { - // Swizzle bits: 00123456 -> 12345612 - return (v << 2) | (v >> 4); - } - - void Init(RSXTexture& tex) - { - Bind(); - - const u64 texaddr = GetAddress(tex.GetOffset(), tex.GetLocation()); - if (!Memory.IsGoodAddr(texaddr)) - { - ConLog.Error("Bad texture address=0x%x", texaddr); - return; - } - //ConLog.Warning("texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x", - // m_offset, m_width, m_height, m_maxaniso, m_mipmap, m_remap, m_zfunc, m_wraps, m_wrapt, m_wrapr, m_minlod, m_maxlod); - //TODO: safe init - checkForGlError("GLTexture::Init() -> glBindTexture"); - - int format = tex.GetFormat() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); - bool is_swizzled = !(tex.GetFormat() & CELL_GCM_TEXTURE_LN); - - const u8 *pixels = const_cast(Memory.GetMemFromAddr(texaddr)); - u8 *unswizzledPixels; - static const GLint glRemapStandard[4] = {GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE}; - // NOTE: This must be in ARGB order in all forms below. - const GLint *glRemap = glRemapStandard; - - switch(format) - { - case CELL_GCM_TEXTURE_B8: // One 8-bit fixed-point number - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - static const GLint swizzleMaskB8[] = { GL_BLUE, GL_BLUE, GL_BLUE, GL_BLUE }; - glRemap = swizzleMaskB8; - } - break; - - case CELL_GCM_TEXTURE_A1R5G5B5: - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - - // TODO: texture swizzling - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - break; - - case CELL_GCM_TEXTURE_A4R4G4B4: - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - // We read it in as R4G4B4A4, so we need to remap each component. - static const GLint swizzleMaskA4R4G4B4[] = { GL_BLUE, GL_ALPHA, GL_RED, GL_GREEN }; - glRemap = swizzleMaskA4R4G4B4; - } - break; - - case CELL_GCM_TEXTURE_R5G6B5: - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex.GetWidth(), tex.GetHeight(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - } - break; - - case CELL_GCM_TEXTURE_A8R8G8B8: - if(is_swizzled) - { - u32 *src, *dst; - u32 log2width, log2height; - - unswizzledPixels = (u8*)malloc(tex.GetWidth() * tex.GetHeight() * 4); - src = (u32*)pixels; - dst = (u32*)unswizzledPixels; - - log2width = log(tex.GetWidth())/log(2); - log2height = log(tex.GetHeight())/log(2); - - for(int i=0; i glTexImage2D"); - break; - - case CELL_GCM_TEXTURE_COMPRESSED_DXT1: // Compressed 4x4 pixels into 8 bytes - { - u32 size = ((tex.GetWidth() + 3) / 4) * ((tex.GetHeight() + 3) / 4) * 8; - - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, tex.GetWidth(), tex.GetHeight(), 0, size, pixels); - checkForGlError("GLTexture::Init() -> glCompressedTexImage2D"); - } - break; - - case CELL_GCM_TEXTURE_COMPRESSED_DXT23: // Compressed 4x4 pixels into 16 bytes - { - u32 size = ((tex.GetWidth() + 3) / 4) * ((tex.GetHeight() + 3) / 4) * 16; - - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, tex.GetWidth(), tex.GetHeight(), 0, size, pixels); - checkForGlError("GLTexture::Init() -> glCompressedTexImage2D"); - } - break; - - case CELL_GCM_TEXTURE_COMPRESSED_DXT45: // Compressed 4x4 pixels into 16 bytes - { - u32 size = ((tex.GetWidth() + 3) / 4) * ((tex.GetHeight() + 3) / 4) * 16; - - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, tex.GetWidth(), tex.GetHeight(), 0, size, pixels); - checkForGlError("GLTexture::Init() -> glCompressedTexImage2D"); - } - break; - - case CELL_GCM_TEXTURE_G8B8: - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RG, GL_UNSIGNED_BYTE, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - static const GLint swizzleMaskG8B8[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN }; - glRemap = swizzleMaskG8B8; - } - break; - - case CELL_GCM_TEXTURE_R6G5B5: - { - // TODO: Probably need to actually unswizzle if is_swizzled. - const u32 numPixels = tex.GetWidth() * tex.GetHeight(); - unswizzledPixels = (u8 *)malloc(numPixels * 4); - // TODO: Speed. - for (u32 i = 0; i < numPixels; ++i) { - u16 c = reinterpret_cast *>(pixels)[i]; - unswizzledPixels[i * 4 + 0] = Convert6To8((c >> 10) & 0x3F); - unswizzledPixels[i * 4 + 1] = Convert5To8((c >> 5) & 0x1F); - unswizzledPixels[i * 4 + 2] = Convert5To8((c >> 0) & 0x1F); - unswizzledPixels[i * 4 + 3] = 255; - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - free(unswizzledPixels); - } - break; - - case CELL_GCM_TEXTURE_DEPTH24_D8: // 24-bit unsigned fixed-point number and 8 bits of garbage - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - break; - - case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: // 24-bit unsigned float and 8 bits of garbage - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - break; - - case CELL_GCM_TEXTURE_DEPTH16: // 16-bit unsigned fixed-point number - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_SHORT, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - break; - - case CELL_GCM_TEXTURE_DEPTH16_FLOAT: // 16-bit unsigned float - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - break; - - case CELL_GCM_TEXTURE_X16: // A 16-bit fixed-point number - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RED, GL_UNSIGNED_SHORT, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - - static const GLint swizzleMaskX16[] = { GL_RED, GL_ONE, GL_RED, GL_ONE }; - glRemap = swizzleMaskX16; - } - break; - - case CELL_GCM_TEXTURE_Y16_X16: // Two 16-bit fixed-point numbers - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RG, GL_UNSIGNED_SHORT, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - - static const GLint swizzleMaskX32_Y16_X16[] = { GL_GREEN, GL_RED, GL_GREEN, GL_RED }; - glRemap = swizzleMaskX32_Y16_X16; - } - break; - - case CELL_GCM_TEXTURE_R5G5B5A1: - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - break; - - case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: // Four fp16 values - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_HALF_FLOAT, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - break; - - case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: // Four fp32 values - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_FLOAT, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - break; - - case CELL_GCM_TEXTURE_X32_FLOAT: // One 32-bit floating-point number - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RED, GL_FLOAT, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - static const GLint swizzleMaskX32_FLOAT[] = { GL_RED, GL_ONE, GL_ONE, GL_ONE }; - glRemap = swizzleMaskX32_FLOAT; - } - break; - - case CELL_GCM_TEXTURE_D1R5G5B5: - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - - // TODO: Texture swizzling - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - static const GLint swizzleMaskX32_D1R5G5B5[] = { GL_ONE, GL_RED, GL_GREEN, GL_BLUE }; - glRemap = swizzleMaskX32_D1R5G5B5; - - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - } - break; - - case CELL_GCM_TEXTURE_D8R8G8B8: // 8 bits of garbage and three unsigned 8-bit fixed-point numbers - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - static const GLint swizzleMaskX32_D8R8G8B8[] = { GL_ONE, GL_RED, GL_GREEN, GL_BLUE }; - glRemap = swizzleMaskX32_D8R8G8B8; - } - break; - - case CELL_GCM_TEXTURE_Y16_X16_FLOAT: // Two fp16 values - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RG, GL_HALF_FLOAT, pixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - checkForGlError("GLTexture::Init() -> glPixelStorei"); - - static const GLint swizzleMaskX32_Y16_X16_FLOAT[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN }; - glRemap = swizzleMaskX32_Y16_X16_FLOAT; - } - break; - - case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN): - { - const u32 numPixels = tex.GetWidth() * tex.GetHeight(); - unswizzledPixels = (u8 *)malloc(numPixels * 4); - // TODO: Speed. - for (u32 i = 0; i < numPixels; i += 2) { - unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 3]; - unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 2]; - unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 0]; - unswizzledPixels[i * 4 + 0 + 3] = 255; - - // The second pixel is the same, except for red. - unswizzledPixels[i * 4 + 4 + 0] = pixels[i * 2 + 1]; - unswizzledPixels[i * 4 + 4 + 1] = pixels[i * 2 + 2]; - unswizzledPixels[i * 4 + 4 + 2] = pixels[i * 2 + 0]; - unswizzledPixels[i * 4 + 4 + 3] = 255; - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - free(unswizzledPixels); - } - break; - - case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN): - { - const u32 numPixels = tex.GetWidth() * tex.GetHeight(); - unswizzledPixels = (u8 *)malloc(numPixels * 4); - // TODO: Speed. - for (u32 i = 0; i < numPixels; i += 2) { - unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 2]; - unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 3]; - unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 1]; - unswizzledPixels[i * 4 + 0 + 3] = 255; - - // The second pixel is the same, except for red. - unswizzledPixels[i * 4 + 4 + 0] = pixels[i * 2 + 0]; - unswizzledPixels[i * 4 + 4 + 1] = pixels[i * 2 + 3]; - unswizzledPixels[i * 4 + 4 + 2] = pixels[i * 2 + 1]; - unswizzledPixels[i * 4 + 4 + 3] = 255; - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels); - checkForGlError("GLTexture::Init() -> glTexImage2D"); - - free(unswizzledPixels); - } - break; - - default: ConLog.Error("Init tex error: Bad tex format (0x%x | %s | 0x%x)", format, - (is_swizzled ? "swizzled" : "linear"), tex.GetFormat() & 0x40); break; - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, tex.GetMipmap() - 1); - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, tex.GetMipmap() > 1); - - if (format != CELL_GCM_TEXTURE_B8 && format != CELL_GCM_TEXTURE_X16 && format != CELL_GCM_TEXTURE_X32_FLOAT) - { - u8 remap_a = tex.GetRemap() & 0x3; - u8 remap_r = (tex.GetRemap() >> 2) & 0x3; - u8 remap_g = (tex.GetRemap() >> 4) & 0x3; - u8 remap_b = (tex.GetRemap() >> 6) & 0x3; - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]); - } - else - { - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, glRemap[0]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, glRemap[1]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, glRemap[2]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, glRemap[3]); - } - - checkForGlError("GLTexture::Init() -> remap"); - - static const int gl_tex_zfunc[] = - { - GL_NEVER, - GL_LESS, - GL_EQUAL, - GL_LEQUAL, - GL_GREATER, - GL_NOTEQUAL, - GL_GEQUAL, - GL_ALWAYS, - }; - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GetGlWrap(tex.GetWrapS())); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GetGlWrap(tex.GetWrapT())); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GetGlWrap(tex.GetWrapR())); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[tex.GetZfunc()]); - - checkForGlError("GLTexture::Init() -> parameters1"); - - glTexEnvi(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, tex.GetBias()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, (tex.GetMinLOD() >> 8)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (tex.GetMaxLOD() >> 8)); - - checkForGlError("GLTexture::Init() -> parameters2"); - - static const int gl_tex_filter[] = - { - GL_NEAREST, - GL_NEAREST, - GL_LINEAR, - GL_NEAREST_MIPMAP_NEAREST, - GL_LINEAR_MIPMAP_NEAREST, - GL_NEAREST_MIPMAP_LINEAR, - GL_LINEAR_MIPMAP_LINEAR, - GL_NEAREST, - }; - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_filter[tex.GetMinFilter()]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter[tex.GetMagFilter()]); - - checkForGlError("GLTexture::Init() -> filters"); - - //Unbind(); - - if(is_swizzled && format == CELL_GCM_TEXTURE_A8R8G8B8) - { - free(unswizzledPixels); - } - } - - void Save(RSXTexture& tex, const wxString& name) - { - if(!m_id || !tex.GetOffset() || !tex.GetWidth() || !tex.GetHeight()) return; - - const u32 texPixelCount = tex.GetWidth() * tex.GetHeight(); - - u32* alldata = new u32[texPixelCount]; - - Bind(); - - switch(tex.GetFormat() & ~(0x20 | 0x40)) - { - case CELL_GCM_TEXTURE_B8: - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, alldata); - break; - - case CELL_GCM_TEXTURE_A8R8G8B8: - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, alldata); - break; - - default: - delete[] alldata; - return; - } - - { - wxFile f(name + ".raw", wxFile::write); - f.Write(alldata, texPixelCount * 4); - } - u8* data = new u8[texPixelCount * 3]; - u8* alpha = new u8[texPixelCount]; - - u8* src = (u8*)alldata; - u8* dst_d = data; - u8* dst_a = alpha; - for (u32 i = 0; i < texPixelCount; i++) - { - *dst_d++ = *src++; - *dst_d++ = *src++; - *dst_d++ = *src++; - *dst_a++ = *src++; - } - - wxImage out; - out.Create(tex.GetWidth(), tex.GetHeight(), data, alpha); - out.SaveFile(name, wxBITMAP_TYPE_PNG); - - delete[] alldata; - //free(data); - //free(alpha); - } - - void Save(RSXTexture& tex) - { - static const wxString& dir_path = "textures"; - static const wxString& file_fmt = dir_path + "/" + "tex[%d].png"; - - if(!wxDirExists(dir_path)) wxMkdir(dir_path); - - u32 count = 0; - while(wxFileExists(wxString::Format(file_fmt, count))) count++; - Save(tex, wxString::Format(file_fmt, count)); - } - - void Bind() - { - glBindTexture(GL_TEXTURE_2D, m_id); - } - - void Unbind() - { - glBindTexture(GL_TEXTURE_2D, 0); - } - - void Delete() - { - if(m_id) - { - glDeleteTextures(1, &m_id); - m_id = 0; - } - } -}; - -struct GLGSFrame : public GSFrame -{ - wxGLCanvas* canvas; - u32 m_frames; - - GLGSFrame(); - ~GLGSFrame() {} - - void Flip(wxGLContext *context); - - wxGLCanvas* GetCanvas() const { return canvas; } - - virtual void SetViewport(int x, int y, u32 w, u32 h); - -private: - virtual void OnSize(wxSizeEvent& event); -}; - -class PostDrawObj -{ -protected: - GLShaderProgram m_fp; - GLVertexProgram m_vp; - GLProgram m_program; - GLfbo m_fbo; - GLrbo m_rbo; - -public: - virtual void Draw() - { - static bool s_is_initialized = false; - - if(!s_is_initialized) - { - s_is_initialized = true; - Initialize(); - } - else - { - m_program.Use(); - } - } - - virtual void InitializeShaders() = 0; - virtual void InitializeLocations() = 0; - - void Initialize() - { - InitializeShaders(); - m_fp.Compile(); - m_vp.Compile(); - m_program.Create(m_vp.id, m_fp.GetId()); - m_program.Use(); - InitializeLocations(); - } -}; - -class DrawCursorObj : public PostDrawObj -{ - u32 m_tex_id; - void* m_pixels; - u32 m_width, m_height; - double m_pos_x, m_pos_y, m_pos_z; - bool m_update_texture, m_update_pos; - -public: - DrawCursorObj() : PostDrawObj() - , m_tex_id(0) - , m_update_texture(false) - , m_update_pos(false) - { - } - - virtual void Draw() - { - checkForGlError("PostDrawObj : Unknown error."); - - PostDrawObj::Draw(); - checkForGlError("PostDrawObj::Draw"); - - if(!m_fbo.IsCreated()) - { - m_fbo.Create(); - checkForGlError("DrawCursorObj : m_fbo.Create"); - m_fbo.Bind(); - checkForGlError("DrawCursorObj : m_fbo.Bind"); - - m_rbo.Create(); - checkForGlError("DrawCursorObj : m_rbo.Create"); - m_rbo.Bind(); - checkForGlError("DrawCursorObj : m_rbo.Bind"); - m_rbo.Storage(GL_RGBA, m_width, m_height); - checkForGlError("DrawCursorObj : m_rbo.Storage"); - - m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0, m_rbo.GetId()); - checkForGlError("DrawCursorObj : m_fbo.Renderbuffer"); - } - - m_fbo.Bind(); - checkForGlError("DrawCursorObj : m_fbo.Bind"); - glDrawBuffer(GL_COLOR_ATTACHMENT0); - checkForGlError("DrawCursorObj : glDrawBuffer"); - - m_program.Use(); - checkForGlError("DrawCursorObj : m_program.Use"); - - if(m_update_texture) - { - //m_update_texture = false; - - glUniform2f(m_program.GetLocation("in_tc"), m_width, m_height); - checkForGlError("DrawCursorObj : glUniform2f"); - if(!m_tex_id) - { - glGenTextures(1, &m_tex_id); - checkForGlError("DrawCursorObj : glGenTextures"); - } - - glActiveTexture(GL_TEXTURE0); - checkForGlError("DrawCursorObj : glActiveTexture"); - glBindTexture(GL_TEXTURE_2D, m_tex_id); - checkForGlError("DrawCursorObj : glBindTexture"); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels); - checkForGlError("DrawCursorObj : glTexImage2D"); - m_program.SetTex(0); - } - - if(m_update_pos) - { - //m_update_pos = false; - - glUniform4f(m_program.GetLocation("in_pos"), m_pos_x, m_pos_y, m_pos_z, 1.0f); - checkForGlError("DrawCursorObj : glUniform4f"); - } - - glDrawArrays(GL_QUADS, 0, 4); - checkForGlError("DrawCursorObj : glDrawArrays"); - - m_fbo.Bind(GL_READ_FRAMEBUFFER); - checkForGlError("DrawCursorObj : m_fbo.Bind(GL_READ_FRAMEBUFFER)"); - GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0); - checkForGlError("DrawCursorObj : GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0)"); - GLfbo::Blit( - 0, 0, m_width, m_height, - 0, 0, m_width, m_height, - GL_COLOR_BUFFER_BIT, GL_NEAREST); - checkForGlError("DrawCursorObj : GLfbo::Blit"); - m_fbo.Bind(); - checkForGlError("DrawCursorObj : m_fbo.Bind"); - } - - virtual void InitializeShaders() - { - m_vp.shader = - "#version 330\n" - "\n" - "uniform vec4 in_pos;\n" - "uniform vec2 in_tc;\n" - "out vec2 tc;\n" - "\n" - "void main()\n" - "{\n" - " tc = in_tc;\n" - " gl_Position = in_pos;\n" - "}\n"; - - m_fp.SetShaderText( - "#version 330\n" - "\n" - "in vec2 tc;\n" - "uniform sampler2D tex0;\n" - "layout (location = 0) out vec4 res;\n" - "\n" - "void main()\n" - "{\n" - " res = texture(tex0, tc);\n" - "}\n"); - } - - void SetTexture(void* pixels, int width, int height) - { - m_pixels = pixels; - m_width = width; - m_height = height; - - m_update_texture = true; - } - - void SetPosition(float x, float y, float z = 0.0f) - { - m_pos_x = x; - m_pos_y = y; - m_pos_z = z; - m_update_pos = true; - } - - void InitializeLocations() - { - //ConLog.Warning("tex0 location = 0x%x", m_program.GetLocation("tex0")); - } -}; - -class GLGSRender - : public wxWindow - , public GSRender -{ -private: - std::vector m_vdata; - std::vector m_post_draw_objs; - - GLProgram m_program; - int m_fp_buf_num; - int m_vp_buf_num; - GLProgramBuffer m_prog_buffer; - - GLShaderProgram m_shader_prog; - GLVertexProgram m_vertex_prog; - - GLTexture m_gl_textures[m_textures_count]; - - GLvao m_vao; - GLvbo m_vbo; - GLrbo m_rbo; - GLfbo m_fbo; - - wxGLContext* m_context; - -public: - GLGSFrame* m_frame; - u32 m_draw_frames; - u32 m_skip_frames; - - GLGSRender(); - virtual ~GLGSRender(); - -private: - void EnableVertexData(bool indexed_draw=false); - void DisableVertexData(); - void InitVertexData(); - void InitFragmentData(); - - void Enable(bool enable, const u32 cap); - virtual void Close(); - bool LoadProgram(); - void WriteDepthBuffer(); - void WriteColorBuffers(); - void WriteColourBufferA(); - void WriteColourBufferB(); - void WriteColourBufferC(); - void WriteColourBufferD(); - - void DrawObjects(); - -protected: - virtual void OnInit(); - virtual void OnInitThread(); - virtual void OnExitThread(); - virtual void OnReset(); - virtual void ExecCMD(); - virtual void Flip(); -}; diff --git a/rpcs3/Emu/GS/GL/GLVertexProgram.cpp b/rpcs3/Emu/GS/GL/GLVertexProgram.cpp deleted file mode 100644 index e1ce95c65c..0000000000 --- a/rpcs3/Emu/GS/GL/GLVertexProgram.cpp +++ /dev/null @@ -1,546 +0,0 @@ -#include "stdafx.h" -#include "GLVertexProgram.h" - -std::string GLVertexDecompilerThread::GetMask(bool is_sca) -{ - std::string ret; - - if(is_sca) - { - if(d3.sca_writemask_x) ret += "x"; - if(d3.sca_writemask_y) ret += "y"; - if(d3.sca_writemask_z) ret += "z"; - if(d3.sca_writemask_w) ret += "w"; - } - else - { - if(d3.vec_writemask_x) ret += "x"; - if(d3.vec_writemask_y) ret += "y"; - if(d3.vec_writemask_z) ret += "z"; - if(d3.vec_writemask_w) ret += "w"; - } - - return ret.empty() || ret == "xyzw" ? "" : ("." + ret); -} - -std::string GLVertexDecompilerThread::GetVecMask() -{ - return GetMask(false); -} - -std::string GLVertexDecompilerThread::GetScaMask() -{ - return GetMask(true); -} - -std::string GLVertexDecompilerThread::GetDST(bool isSca) -{ - static const std::string reg_table[] = - { - "gl_Position", - "col0", "col1", - "bfc0", "bfc1", - "gl_ClipDistance[%d]", - "gl_ClipDistance[%d]", - "tc0", "tc1", "tc2", "tc3", "tc4", "tc5", "tc6", "tc7" - }; - - std::string ret; - - switch(isSca ? 0x1f : d3.dst) - { - case 0x0: case 0x5: case 0x6: - ret += reg_table[d3.dst]; - break; - - case 0x1f: - ret += m_parr.AddParam(PARAM_NONE, "vec4", std::string("tmp") + std::to_string(isSca ? d3.sca_dst_tmp : d0.dst_tmp)); - break; - - default: - if(d3.dst < WXSIZEOF(reg_table)) - { - ret += m_parr.AddParam(PARAM_OUT, "vec4", reg_table[d3.dst]); - } - else - { - ConLog.Error("Bad dst reg num: %d", fmt::by_value(d3.dst)); - ret += m_parr.AddParam(PARAM_OUT, "vec4", "unk"); - } - break; - } - - return ret; -} - -std::string GLVertexDecompilerThread::GetSRC(const u32 n, bool isSca) -{ - static const std::string reg_table[] = - { - "in_pos", "in_weight", "in_normal", - "in_col0", "in_col1", - "in_fogc", - "in_6", "in_7", - "in_tc0", "in_tc1", "in_tc2", "in_tc3", - "in_tc4", "in_tc5", "in_tc6", "in_tc7" - }; - - std::string ret; - - switch(src[n].reg_type) - { - case 1: //temp - ret += m_parr.AddParam(PARAM_NONE, "vec4", std::string("tmp") + std::to_string(src[n].tmp_src)); - break; - case 2: //input - if(d1.input_src < WXSIZEOF(reg_table)) - { - ret += m_parr.AddParam(PARAM_IN, "vec4", reg_table[d1.input_src], d1.input_src); - } - else - { - ConLog.Error("Bad input src num: %d", fmt::by_value(d1.input_src)); - ret += m_parr.AddParam(PARAM_IN, "vec4", "in_unk", d1.input_src); - } - break; - case 3: //const - ret += m_parr.AddParam(PARAM_UNIFORM, "vec4", std::string("vc") + std::to_string(d1.const_src)); - break; - - default: - ConLog.Error("Bad src%u reg type: %d", n, fmt::by_value(src[n].reg_type)); - Emu.Pause(); - break; - } - - static const std::string f = "xyzw"; - - if (isSca) - { - assert(src[n].swz_x == src[n].swz_y); - assert(src[n].swz_z == src[n].swz_w); - assert(src[n].swz_x == src[n].swz_z); - - ret += '.'; - ret += f[src[n].swz_x]; - } - else - { - std::string swizzle; - - swizzle += f[src[n].swz_x]; - swizzle += f[src[n].swz_y]; - swizzle += f[src[n].swz_z]; - swizzle += f[src[n].swz_w]; - - if(swizzle != f) ret += '.' + swizzle; - } - - bool abs; - - switch(n) - { - case 0: abs = d0.src0_abs; break; - case 1: abs = d0.src1_abs; break; - case 2: abs = d0.src2_abs; break; - } - - if(abs) ret = "abs(" + ret + ")"; - if(src[n].neg) ret = "-" + ret; - - return ret; -} - -void GLVertexDecompilerThread::AddCode(bool is_sca, const std::string& pCode, bool src_mask, bool set_dst, bool set_cond) -{ - std::string code = pCode; - if(d0.cond == 0) return; - enum - { - lt = 0x1, - eq = 0x2, - gt = 0x4, - }; - - static const char* cond_string_table[(lt | gt | eq) + 1] = - { - "error", - "lessThan", - "equal", - "lessThanEqual", - "greaterThan", - "notEqual", - "greaterThanEqual", - "error" - }; - - std::string cond; - - if((set_cond || d0.cond_test_enable) && d0.cond != (lt | gt | eq)) - { - static const char f[4] = {'x', 'y', 'z', 'w'}; - - std::string swizzle; - swizzle += f[d0.mask_x]; - swizzle += f[d0.mask_y]; - swizzle += f[d0.mask_z]; - swizzle += f[d0.mask_w]; - - swizzle = swizzle == "xyzw" ? "" : "." + swizzle; - - cond = fmt::Format("if(all(%s(rc%s, vec4(0.0)%s))) ", cond_string_table[d0.cond], swizzle.c_str(), swizzle.c_str()); - } - - std::string mask = GetMask(is_sca); - std::string value = src_mask ? code + mask : code; - - if(is_sca && d0.vec_result) - { - value = "vec4(" + value + ")" + mask; - } - - if(d0.staturate) - { - value = "clamp(" + value + ", 0.0, 1.0)"; - } - - if(set_dst) - { - std::string dest; - if(d0.cond_update_enable_0) - { - dest = m_parr.AddParam(PARAM_NONE, "vec4", "rc", "vec4(0.0)") + mask; - } - else if(d3.dst == 5 || d3.dst == 6) - { - if(d3.vec_writemask_x) - { - dest = m_parr.AddParam(PARAM_OUT, "vec4", "fogc") + mask; - } - else - { - int num = d3.dst == 5 ? 0 : 3; - - //if(d3.vec_writemask_y) num += 0; - if(d3.vec_writemask_z) num += 1; - else if(d3.vec_writemask_w) num += 2; - - dest = fmt::Format(GetDST(is_sca) + "/*" + mask + "*/", num); - } - } - else - { - dest = GetDST(is_sca) + mask; - } - - code = cond + dest + " = " + value; - } - else - { - code = cond + value; - } - - m_body.push_back(code + ";"); -} - -std::string GLVertexDecompilerThread::GetFunc() -{ - u32 offset = (d2.iaddrh << 3) | d3.iaddrl; - std::string name = fmt::Format("func%u", offset); - - for(uint i=0; i0; --i) - { - fp += fmt::Format("void %s();\n", m_funcs[i].name.c_str()); - } - - std::string f; - - f += fmt::Format("void %s()\n{\n\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n\t%s();\n\tgl_Position = gl_Position * scaleOffsetMat;\n}\n", - m_funcs[0].name.c_str(), m_funcs[1].name.c_str()); - - for(uint i=1; i 2) - { - m_funcs.erase(m_funcs.begin()+2, m_funcs.end()); - } -} - -GLVertexProgram::GLVertexProgram() - : m_decompiler_thread(nullptr) - , id(0) -{ -} - -GLVertexProgram::~GLVertexProgram() -{ - if(m_decompiler_thread) - { - Wait(); - if(m_decompiler_thread->IsAlive()) - { - m_decompiler_thread->Stop(); - } - - delete m_decompiler_thread; - m_decompiler_thread = nullptr; - } - - Delete(); -} - -void GLVertexProgram::Wait() -{ - if(m_decompiler_thread && m_decompiler_thread->IsAlive()) - { - m_decompiler_thread->Join(); - } -} - -void GLVertexProgram::Decompile(RSXVertexProgram& prog) -{ - GLVertexDecompilerThread(prog.data, shader, parr); -} - -void GLVertexProgram::DecompileAsync(RSXVertexProgram& prog) -{ - if (m_decompiler_thread) - { - Wait(); - if (m_decompiler_thread->IsAlive()) - { - m_decompiler_thread->Stop(); - } - - delete m_decompiler_thread; - m_decompiler_thread = nullptr; - } - - m_decompiler_thread = new GLVertexDecompilerThread(prog.data, shader, parr); - m_decompiler_thread->Start(); -} - -void GLVertexProgram::Compile() -{ - if(id) glDeleteShader(id); - - id = glCreateShader(GL_VERTEX_SHADER); - - const char* str = shader.c_str(); - const int strlen = shader.length(); - - glShaderSource(id, 1, &str, &strlen); - glCompileShader(id); - - GLint r = GL_FALSE; - glGetShaderiv(id, GL_COMPILE_STATUS, &r); - if(r != GL_TRUE) - { - glGetShaderiv(id, GL_INFO_LOG_LENGTH, &r); - - if(r) - { - char* buf = new char[r+1]; - GLsizei len; - memset(buf, 0, r+1); - glGetShaderInfoLog(id, r, &len, buf); - ConLog.Error("Failed to compile vertex shader: %s", buf); - delete[] buf; - } - - ConLog.Write(shader); - Emu.Pause(); - } - //else ConLog.Write("Vertex shader compiled successfully!"); - -} - -void GLVertexProgram::Delete() -{ - parr.params.clear(); - shader.clear(); - - if(id) - { - glDeleteShader(id); - id = 0; - } -} diff --git a/rpcs3/Emu/GS/GL/GLVertexProgram.h b/rpcs3/Emu/GS/GL/GLVertexProgram.h deleted file mode 100644 index a74a2cd066..0000000000 --- a/rpcs3/Emu/GS/GL/GLVertexProgram.h +++ /dev/null @@ -1,193 +0,0 @@ -#pragma once -#include "GLShaderParam.h" -#include "Emu/GS/RSXVertexProgram.h" - -struct GLVertexDecompilerThread : public ThreadBase -{ - union D0 - { - u32 HEX; - - struct - { - u32 addr_swz : 2; - u32 mask_w : 2; - u32 mask_z : 2; - u32 mask_y : 2; - u32 mask_x : 2; - u32 cond : 3; - u32 cond_test_enable : 1; - u32 cond_update_enable_0 : 1; - u32 dst_tmp : 6; - u32 src0_abs : 1; - u32 src1_abs : 1; - u32 src2_abs : 1; - u32 addr_reg_sel_1 : 1; - u32 cond_reg_sel_1 : 1; - u32 staturate : 1; - u32 index_input : 1; - u32 : 1; - u32 cond_update_enable_1 : 1; - u32 vec_result : 1; - u32 : 1; - }; - } d0; - - union D1 - { - u32 HEX; - - struct - { - u32 src0h : 8; - u32 input_src : 4; - u32 const_src : 10; - u32 vec_opcode : 5; - u32 sca_opcode : 5; - }; - } d1; - - union D2 - { - u32 HEX; - - struct - { - u32 src2h : 6; - u32 src1 : 17; - u32 src0l : 9; - }; - struct - { - u32 iaddrh : 6; - u32 : 26; - }; - } d2; - - union D3 - { - u32 HEX; - - struct - { - u32 end : 1; - u32 index_const : 1; - u32 dst : 5; - u32 sca_dst_tmp : 6; - u32 vec_writemask_w : 1; - u32 vec_writemask_z : 1; - u32 vec_writemask_y : 1; - u32 vec_writemask_x : 1; - u32 sca_writemask_w : 1; - u32 sca_writemask_z : 1; - u32 sca_writemask_y : 1; - u32 sca_writemask_x : 1; - u32 src2l : 11; - }; - struct - { - u32 : 29; - u32 iaddrl : 3; - }; - } d3; - - union SRC - { - union - { - u32 HEX; - - struct - { - u32 src0l : 9; - u32 src0h : 8; - }; - - struct - { - u32 src1 : 17; - }; - - struct - { - u32 src2l : 11; - u32 src2h : 6; - }; - }; - - struct - { - u32 reg_type : 2; - u32 tmp_src : 6; - u32 swz_w : 2; - u32 swz_z : 2; - u32 swz_y : 2; - u32 swz_x : 2; - u32 neg : 1; - }; - } src[3]; - - struct FuncInfo - { - u32 offset; - std::string name; - }; - - std::vector m_body; - - std::vector m_funcs; - - //wxString main; - std::string& m_shader; - std::vector& m_data; - GLParamArray& m_parr; - - GLVertexDecompilerThread(std::vector& data, std::string& shader, GLParamArray& parr) - : ThreadBase("Vertex Shader Decompiler Thread") - , m_data(data) - , m_shader(shader) - , m_parr(parr) - { - m_funcs.emplace_back(); - m_funcs[0].offset = 0; - m_funcs[0].name = "main"; - m_funcs.emplace_back(); - m_funcs[1].offset = 0; - m_funcs[1].name = "func0"; - //m_cur_func->body = "\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n"; - } - - std::string GetMask(bool is_sca); - std::string GetVecMask(); - std::string GetScaMask(); - std::string GetDST(bool is_sca = false); - std::string GetSRC(const u32 n, bool is_sca = false); - std::string GetFunc(); - void AddCode(bool is_sca, const std::string& code, bool src_mask = true, bool set_dst = true, bool set_cond = true); - void AddVecCode(const std::string& code, bool src_mask = true, bool set_dst = true); - void AddScaCode(const std::string& code, bool set_dst = true, bool set_cond = true); - std::string BuildFuncBody(const FuncInfo& func); - std::string BuildCode(); - - virtual void Task(); -}; - -class GLVertexProgram -{ -public: - GLVertexProgram(); - ~GLVertexProgram(); - - GLParamArray parr; - u32 id; - std::string shader; - - void Decompile(RSXVertexProgram& prog); - void DecompileAsync(RSXVertexProgram& prog); - void Wait(); - void Compile(); - -private: - GLVertexDecompilerThread* m_decompiler_thread; - void Delete(); -}; diff --git a/rpcs3/Emu/GS/GSRender.h b/rpcs3/Emu/GS/GSRender.h deleted file mode 100644 index 3ae017cb39..0000000000 --- a/rpcs3/Emu/GS/GSRender.h +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once -#include "Emu/GS/GCM.h" -#include "Emu/GS/RSXThread.h" - -wxSize AspectRatio(wxSize rs, const wxSize as); - -class GSFrame : public wxFrame -{ -protected: - GSFrame(wxWindow* parent, const wxString& title); - - virtual void SetViewport(int x, int y, u32 w, u32 h) {} - virtual void OnPaint(wxPaintEvent& event); - virtual void OnClose(wxCloseEvent& event); - - //virtual void OnSize(wxSizeEvent&); - - void OnKeyDown(wxKeyEvent& event); - void OnFullScreen(); - -public: - void OnLeftDclick(wxMouseEvent&) - { - OnFullScreen(); - } - - //void SetSize(int width, int height); - -private: - DECLARE_EVENT_TABLE(); -}; - -struct GSRender : public RSXThread -{ - virtual ~GSRender() - { - } - - virtual void Close()=0; -}; - -enum GSLockType -{ - GS_LOCK_NOT_WAIT, - GS_LOCK_WAIT_FLUSH, - GS_LOCK_WAIT_FLIP, -}; - -struct GSLock -{ -private: - GSRender& m_renderer; - GSLockType m_type; - -public: - GSLock(GSRender& renderer, GSLockType type) - : m_renderer(renderer) - , m_type(type) - { - switch(m_type) - { - case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.Enter(); break; - case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.Wait(); break; - case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.Wait(); break; - } - } - - ~GSLock() - { - switch(m_type) - { - case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.Leave(); break; - case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.Post(); break; - case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.Post(); break; - } - } -}; - -struct GSLockCurrent : GSLock -{ - GSLockCurrent(GSLockType type); -}; \ No newline at end of file diff --git a/rpcs3/Emu/GS/Null/NullGSRender.h b/rpcs3/Emu/GS/Null/NullGSRender.h deleted file mode 100644 index aaba2ec398..0000000000 --- a/rpcs3/Emu/GS/Null/NullGSRender.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once -#include "Emu/GS/GSRender.h" - -struct NullGSFrame : public GSFrame -{ - NullGSFrame() : GSFrame(nullptr, "GSFrame[Null]") - { - Bind(wxEVT_LEFT_DCLICK, &GSFrame::OnLeftDclick, this); - } - - void Draw() - { - wxClientDC dc(this); - Draw(&dc); - } - -private: - virtual void OnPaint(wxPaintEvent& event) - { - wxPaintDC dc(this); - Draw(&dc); - } - virtual void OnSize(wxSizeEvent& event) - { - GSFrame::OnSize(event); - Draw(); - } - - void Draw(wxDC* dc) - { - dc->DrawText("Null GS output", 0, 0); - } -}; - -class NullGSRender - : public wxWindow - , public GSRender -{ -public: - NullGSFrame* m_frame; - - NullGSRender() : m_frame(nullptr) - { - m_frame = new NullGSFrame(); - } - - virtual ~NullGSRender() - { - m_frame->Close(); - } - -private: - virtual void OnInit() - { - m_frame->Show(); - } - - virtual void OnInitThread() - { - } - - virtual void OnExitThread() - { - } - - virtual void OnReset() - { - } - - virtual void ExecCMD() - { - } - - virtual void Flip() - { - } - - virtual void Close() - { - Stop(); - - if(m_frame->IsShown()) m_frame->Hide(); - } -}; diff --git a/rpcs3/Emu/GS/RSXFragmentProgram.h b/rpcs3/Emu/GS/RSXFragmentProgram.h deleted file mode 100644 index 53eb25990c..0000000000 --- a/rpcs3/Emu/GS/RSXFragmentProgram.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -struct RSXShaderProgram -{ - u32 size; - u32 addr; - u32 offset; - u32 ctrl; - - RSXShaderProgram() - : size(0) - , addr(0) - , offset(0) - , ctrl(0) - { - } -}; \ No newline at end of file diff --git a/rpcs3/Emu/HDD/HDD.cpp b/rpcs3/Emu/HDD/HDD.cpp index 4d8937b4b5..80eda63429 100644 --- a/rpcs3/Emu/HDD/HDD.cpp +++ b/rpcs3/Emu/HDD/HDD.cpp @@ -1,6 +1,338 @@ #include "stdafx.h" +#include "Utilities/Log.h" #include "HDD.h" +void vfsHDDManager::CreateBlock(vfsHDD_Block& block) +{ + block.is_used = true; + block.next_block = 0; +} + +void vfsHDDManager::CreateEntry(vfsHDD_Entry& entry) +{ + memset(&entry, 0, sizeof(vfsHDD_Entry)); + u64 ctime = time(nullptr); + entry.atime = ctime; + entry.ctime = ctime; + entry.mtime = ctime; + entry.access = vfsReadWrite; + CreateBlock(entry); +} + +void vfsHDDManager::CreateHDD(const std::string& path, u64 size, u64 block_size) +{ + rFile f(path, rFile::write); + + static const u64 cur_dir_block = 1; + + vfsHDD_Hdr hdr; + CreateBlock(hdr); + hdr.next_block = cur_dir_block; + hdr.magic = g_hdd_magic; + hdr.version = g_hdd_version; + hdr.block_count = (size + block_size) / block_size; + hdr.block_size = block_size; + f.Write(&hdr, sizeof(vfsHDD_Hdr)); + + { + vfsHDD_Entry entry; + CreateEntry(entry); + entry.type = vfsHDD_Entry_Dir; + entry.data_block = hdr.next_block; + entry.next_block = 0; + + f.Seek(cur_dir_block * hdr.block_size); + f.Write(&entry, sizeof(vfsHDD_Entry)); + f.Write("."); + } + + u8 null = 0; + f.Seek(hdr.block_count * hdr.block_size - sizeof(null)); + f.Write(&null, sizeof(null)); +} + +void vfsHDDManager::Format() +{ +} + +void vfsHDDManager::AppendEntry(vfsHDD_Entry entry) +{ +} + +bool vfsHDDFile::goto_block(u64 n) +{ + vfsHDD_Block block_info; + + if (m_info.data_block >= m_hdd_info.block_count) + { + return false; + } + + m_hdd.Seek(m_info.data_block * m_hdd_info.block_size); + block_info.next_block = m_info.data_block; + + for (u64 i = 0; i= m_hdd_info.block_count) + { + return false; + } + + m_hdd.Seek(block_info.next_block * m_hdd_info.block_size); + m_hdd.Read(&block_info, sizeof(vfsHDD_Block)); + } + + return true; +} + +void vfsHDDFile::RemoveBlocks(u64 start_block) +{ + vfsHDD_Block block_info; + block_info.next_block = start_block; + + while (block_info.next_block && block_info.is_used) + { + u64 offset = block_info.next_block * m_hdd_info.block_size; + + ReadBlock(offset, block_info); + WriteBlock(offset, g_null_block); + } +} + +void vfsHDDFile::WriteBlock(u64 block, const vfsHDD_Block& data) +{ + m_hdd.Seek(block * m_hdd_info.block_size); + m_hdd.Write(&data, sizeof(vfsHDD_Block)); +} + +void vfsHDDFile::ReadBlock(u64 block, vfsHDD_Block& data) +{ + m_hdd.Seek(block * m_hdd_info.block_size); + m_hdd.Read(&data, sizeof(vfsHDD_Block)); +} + +void vfsHDDFile::WriteEntry(u64 block, const vfsHDD_Entry& data) +{ + m_hdd.Seek(block * m_hdd_info.block_size); + m_hdd.Write(&data, sizeof(vfsHDD_Entry)); +} + +void vfsHDDFile::ReadEntry(u64 block, vfsHDD_Entry& data) +{ + m_hdd.Seek(block * m_hdd_info.block_size); + m_hdd.Read(&data, sizeof(vfsHDD_Entry)); +} + +void vfsHDDFile::ReadEntry(u64 block, vfsHDD_Entry& data, std::string& name) +{ + m_hdd.Seek(block * m_hdd_info.block_size); + m_hdd.Read(&data, sizeof(vfsHDD_Entry)); + name.resize(GetMaxNameLen()); + m_hdd.Read(&name.front(), GetMaxNameLen()); +} + +void vfsHDDFile::ReadEntry(u64 block, std::string& name) +{ + m_hdd.Seek(block * m_hdd_info.block_size + sizeof(vfsHDD_Entry)); + name.resize(GetMaxNameLen()); + m_hdd.Read(&name.front(), GetMaxNameLen()); +} + +void vfsHDDFile::WriteEntry(u64 block, const vfsHDD_Entry& data, const std::string& name) +{ + m_hdd.Seek(block * m_hdd_info.block_size); + m_hdd.Write(&data, sizeof(vfsHDD_Entry)); + m_hdd.Write(name.c_str(), std::min(GetMaxNameLen() - 1, name.length() + 1)); +} + +void vfsHDDFile::Open(u64 info_block) +{ + m_info_block = info_block; + ReadEntry(m_info_block, m_info); + m_position = 0; + m_cur_block = m_info.data_block; +} + +u64 vfsHDDFile::FindFreeBlock() +{ + vfsHDD_Block block_info; + + for (u64 i = 0; i(block_size - m_position, size); + + vfsHDD_Block cur_block_info; + m_hdd.Seek(m_cur_block * m_hdd_info.block_size); + m_hdd.Read(&cur_block_info, sizeof(vfsHDD_Block)); + m_hdd.Seek(m_cur_block * m_hdd_info.block_size + sizeof(vfsHDD_Block)+m_position); + m_hdd.Read(dst, rsize); + size -= rsize; + m_position += rsize; + if (!size) + { + return rsize; + } + + u64 offset = rsize; + + for (; size; size -= rsize, offset += rsize) + { + if (!cur_block_info.is_used || !cur_block_info.next_block || cur_block_info.next_block >= m_hdd_info.block_count) + { + return offset; + } + + m_cur_block = cur_block_info.next_block; + rsize = std::min(block_size, size); + + m_hdd.Seek(cur_block_info.next_block * m_hdd_info.block_size); + m_hdd.Read(&cur_block_info, sizeof(vfsHDD_Block)); + + if (m_hdd.Read((u8*)dst + offset, rsize) != rsize) + { + return offset; + } + } + + m_position = rsize; + + return offset; +} + +u64 vfsHDDFile::Write(const void* src, u64 size) +{ + if (!size) + return 0; + + //vfsDeviceLocker lock(m_hdd); + + const u32 block_size = m_hdd_info.block_size - sizeof(vfsHDD_Block); + + if (!m_cur_block) + { + if (!m_info.data_block) + { + u64 new_block = FindFreeBlock(); + + if (!new_block) + { + return 0; + } + + WriteBlock(new_block, g_used_block); + m_info.data_block = new_block; + m_info.size = 0; + SaveInfo(); + } + + m_cur_block = m_info.data_block; + m_position = 0; + } + + u64 wsize = std::min(block_size - m_position, size); + + vfsHDD_Block block_info; + ReadBlock(m_cur_block, block_info); + + if (wsize) + { + m_hdd.Seek(m_cur_block * m_hdd_info.block_size + sizeof(vfsHDD_Block)+m_position); + m_hdd.Write(src, wsize); + size -= wsize; + m_info.size += wsize; + m_position += wsize; + SaveInfo(); + + if (!size) + return wsize; + } + + u64 last_block = m_cur_block; + block_info.is_used = true; + u64 offset = wsize; + + for (; size; size -= wsize, offset += wsize, m_info.size += wsize) + { + u64 new_block = FindFreeBlock(); + + if (!new_block) + { + m_position = 0; + SaveInfo(); + return offset; + } + + m_cur_block = new_block; + wsize = std::min(block_size, size); + + block_info.next_block = m_cur_block; + m_hdd.Seek(last_block * m_hdd_info.block_size); + if (m_hdd.Write(&block_info, sizeof(vfsHDD_Block)) != sizeof(vfsHDD_Block)) + { + m_position = 0; + SaveInfo(); + return offset; + } + + block_info.next_block = 0; + m_hdd.Seek(m_cur_block * m_hdd_info.block_size); + if (m_hdd.Write(&block_info, sizeof(vfsHDD_Block)) != sizeof(vfsHDD_Block)) + { + m_position = 0; + SaveInfo(); + return offset; + } + if ((m_position = m_hdd.Write((u8*)src + offset, wsize)) != wsize) + { + m_info.size += wsize; + SaveInfo(); + return offset; + } + + last_block = m_cur_block; + } + + SaveInfo(); + m_position = wsize; + return offset; +} + vfsDeviceHDD::vfsDeviceHDD(const std::string& hdd_path) : m_hdd_path(hdd_path) { } @@ -14,3 +346,438 @@ vfsDirBase* vfsDeviceHDD::GetNewDirStream() { return nullptr; } + +vfsHDD::vfsHDD(vfsDevice* device, const std::string& hdd_path) + : m_hdd_file(device) + , m_file(m_hdd_file, m_hdd_info) + , m_hdd_path(hdd_path) + , vfsFileBase(device) +{ + m_hdd_file.Open(hdd_path, vfsReadWrite); + m_hdd_file.Read(&m_hdd_info, sizeof(vfsHDD_Hdr)); + m_cur_dir_block = m_hdd_info.next_block; + if (!m_hdd_info.block_size) + { + LOG_ERROR(HLE, "Bad block size!"); + m_hdd_info.block_size = 2048; + } + m_hdd_file.Seek(m_cur_dir_block * m_hdd_info.block_size); + m_hdd_file.Read(&m_cur_dir, sizeof(vfsHDD_Entry)); +} + +bool vfsHDD::SearchEntry(const std::string& name, u64& entry_block, u64* parent_block) +{ + u64 last_block = 0; + u64 block = m_cur_dir_block; + vfsHDD_Entry entry; + std::string buf; + + while (block) + { + ReadEntry(block, entry, buf); + + if (fmt::CmpNoCase(name, buf) == 0) + { + entry_block = block; + if (parent_block) + *parent_block = last_block; + + return true; + } + + last_block = block; + block = entry.is_used ? entry.next_block : 0ULL; + } + + return false; +} + +int vfsHDD::OpenDir(const std::string& name) +{ + LOG_WARNING(HLE, "OpenDir(%s)", name.c_str()); + u64 entry_block; + if (!SearchEntry(name, entry_block)) + return -1; + + m_hdd_file.Seek(entry_block * m_hdd_info.block_size); + vfsHDD_Entry entry; + m_hdd_file.Read(&entry, sizeof(vfsHDD_Entry)); + if (entry.type == vfsHDD_Entry_File) + return 1; + + m_cur_dir_block = entry.data_block; + ReadEntry(m_cur_dir_block, m_cur_dir); + + return 0; +} + +bool vfsHDD::Rename(const std::string& from, const std::string& to) +{ + u64 entry_block; + if (!SearchEntry(from, entry_block)) + { + return false; + } + + vfsHDD_Entry entry; + ReadEntry(entry_block, entry); + WriteEntry(entry_block, entry, to); + + return true; +} + +u64 vfsHDD::FindFreeBlock() +{ + vfsHDD_Block block_info; + + for (u64 i = 0; i(GetMaxNameLen() - 1, name.length() + 1)); +} + +bool vfsHDD::Create(vfsHDD_EntryType type, const std::string& name) +{ + if (HasEntry(name)) + { + return false; + } + + u64 new_block = FindFreeBlock(); + if (!new_block) + { + return false; + } + + LOG_NOTICE(HLE, "CREATING ENTRY AT 0x%llx", new_block); + WriteBlock(new_block, g_used_block); + + { + vfsHDD_Entry new_entry; + vfsHDDManager::CreateEntry(new_entry); + new_entry.next_block = 0; + new_entry.type = type; + + if (type == vfsHDD_Entry_Dir) + { + u64 block_cur = FindFreeBlock(); + + if (!block_cur) + { + return false; + } + + WriteBlock(block_cur, g_used_block); + + u64 block_last = FindFreeBlock(); + + if (!block_last) + { + return false; + } + + WriteBlock(block_last, g_used_block); + + vfsHDD_Entry entry_cur, entry_last; + vfsHDDManager::CreateEntry(entry_cur); + vfsHDDManager::CreateEntry(entry_last); + + entry_cur.type = vfsHDD_Entry_Dir; + entry_cur.data_block = block_cur; + entry_cur.next_block = block_last; + + entry_last.type = vfsHDD_Entry_Dir; + entry_last.data_block = m_cur_dir_block; + entry_last.next_block = 0; + + new_entry.data_block = block_cur; + + WriteEntry(block_cur, entry_cur, "."); + WriteEntry(block_last, entry_last, ".."); + } + + WriteEntry(new_block, new_entry, name); + } + + { + u64 block = m_cur_dir_block; + + vfsHDD_Block tmp; + while (block) + { + ReadBlock(block, tmp); + + if (!tmp.next_block) + break; + + block = tmp.next_block; + } + + tmp.next_block = new_block; + WriteBlock(block, tmp); + } + + return true; +} + +bool vfsHDD::GetFirstEntry(u64& block, vfsHDD_Entry& entry, std::string& name) +{ + if (!m_cur_dir_block) + { + return false; + } + + ReadEntry(m_cur_dir_block, entry, name); + block = entry.is_used ? entry.next_block : 0; + + return true; +} + +bool vfsHDD::GetNextEntry(u64& block, vfsHDD_Entry& entry, std::string& name) +{ + if (!block) + { + return false; + } + + ReadEntry(block, entry, name); + + block = entry.is_used ? entry.next_block : 0; + return true; +} + +bool vfsHDD::Open(const std::string& path, vfsOpenMode mode) +{ + const char* s = path.c_str(); + u64 from = 0; + u64 pos = 0; + u64 file_pos = -1; + + do + { + if (s[pos] == '\\' || s[pos] == '/' || s[pos] == '\0') // ??? + { + if (file_pos != -1) + { + return false; + } + + if (from != -1) + { + if (pos - from > 1) + { + int res = OpenDir(std::string(s + from, pos)); + if (res == -1) + { + return false; + } + + if (res == 1) + { + file_pos = from; + } + } + + from = pos; + } + else + { + from = pos; + } + } + } while (s[pos++] != '\0'); + + if (file_pos == -1) + { + return false; + } + + u64 file_block; + if (!SearchEntry(std::string(s + file_pos), file_block)) + { + return false; + } + + LOG_NOTICE(HLE, "ENTRY FOUND AT 0x%llx", file_block); + m_file.Open(file_block); + + return vfsFileBase::Open(path, mode); +} + +bool vfsHDD::HasEntry(const std::string& name) +{ + u64 file_block; + if (!SearchEntry(name, file_block)) + { + return false; + } + + return true; +} + +void vfsHDD::RemoveBlocksDir(u64 start_block) +{ + std::string name; + u64 block = start_block; + vfsHDD_Entry entry; + + while (block) + { + ReadEntry(block, entry, name); + WriteBlock(block, g_null_block); + + if (entry.type == vfsHDD_Entry_Dir && name != "." && name != "..") + { + LOG_WARNING(HLE, "Removing sub folder '%s'", name.c_str()); + RemoveBlocksDir(entry.data_block); + } + else if (entry.type == vfsHDD_Entry_File) + { + RemoveBlocksFile(entry.data_block); + } + + block = entry.next_block; + } +} + +void vfsHDD::RemoveBlocksFile(u64 start_block) +{ + u64 block = start_block; + vfsHDD_Block block_data; + + while (block) + { + ReadBlock(block, block_data); + WriteBlock(block, g_null_block); + + block = block_data.next_block; + } +} + +bool vfsHDD::RemoveEntry(const std::string& name) +{ + u64 entry_block, parent_entry; + if (!SearchEntry(name, entry_block, &parent_entry)) + { + return false; + } + + vfsHDD_Entry entry; + ReadEntry(entry_block, entry); + if (entry.type == vfsHDD_Entry_Dir) + { + RemoveBlocksDir(entry.data_block); + } + else if (entry.type == vfsHDD_Entry_File) + { + RemoveBlocksFile(entry.data_block); + } + + if (parent_entry) + { + u64 next = entry.next_block; + ReadEntry(parent_entry, entry); + entry.next_block = next; + WriteEntry(parent_entry, entry); + } + WriteBlock(entry_block, g_null_block); + return true; +} + +bool vfsHDD::Create(const std::string& path) +{ + return false; +} + +u32 vfsHDD::Write(const void* src, u32 size) +{ + return vfsFileBase::Write(src, m_file.Write(src, size)); +} + +u32 vfsHDD::Read(void* dst, u32 size) +{ + return vfsFileBase::Read(dst, m_file.Read(dst, size)); +} + +u64 vfsHDD::Seek(s64 offset, vfsSeekMode mode) +{ + switch (mode) + { + case vfsSeekCur: + m_file.Seek(Tell() + offset); + break; + + case vfsSeekSet: + m_file.Seek(offset); + break; + + case vfsSeekEnd: + m_file.Seek(m_file.GetSize() + offset); + break; + } + + return vfsFileBase::Seek(offset, mode); +} + +bool vfsHDD::Eof() +{ + return m_file.Eof(); +} + +u64 vfsHDD::GetSize() +{ + return m_file.GetSize(); +} \ No newline at end of file diff --git a/rpcs3/Emu/HDD/HDD.h b/rpcs3/Emu/HDD/HDD.h index 8dc3767f68..f71fa77f35 100644 --- a/rpcs3/Emu/HDD/HDD.h +++ b/rpcs3/Emu/HDD/HDD.h @@ -1,5 +1,6 @@ #pragma once #include "Emu/FS/vfsDevice.h" +#include "Emu/FS/vfsLocalFile.h" static const u64 g_hdd_magic = *(u64*)"PS3eHDD\0"; static const u16 g_hdd_version = 0x0001; @@ -42,62 +43,15 @@ struct vfsHDD_Entry : public vfsHDD_Block class vfsHDDManager { public: - static void CreateBlock(vfsHDD_Block& block) - { - block.is_used = true; - block.next_block = 0; - } + static void CreateBlock(vfsHDD_Block& block); - static void CreateEntry(vfsHDD_Entry& entry) - { - memset(&entry, 0, sizeof(vfsHDD_Entry)); - u64 ctime = time(nullptr); - entry.atime = ctime; - entry.ctime = ctime; - entry.mtime = ctime; - entry.access = vfsReadWrite; - CreateBlock(entry); - } + static void CreateEntry(vfsHDD_Entry& entry); - static void CreateHDD(const std::string& path, u64 size, u64 block_size) - { - wxFile f(fmt::FromUTF8(path), wxFile::write); + static void CreateHDD(const std::string& path, u64 size, u64 block_size); - static const u64 cur_dir_block = 1; + void Format(); - vfsHDD_Hdr hdr; - CreateBlock(hdr); - hdr.next_block = cur_dir_block; - hdr.magic = g_hdd_magic; - hdr.version = g_hdd_version; - hdr.block_count = (size + block_size) / block_size; - hdr.block_size = block_size; - f.Write(&hdr, sizeof(vfsHDD_Hdr)); - - { - vfsHDD_Entry entry; - CreateEntry(entry); - entry.type = vfsHDD_Entry_Dir; - entry.data_block = hdr.next_block; - entry.next_block = 0; - - f.Seek(cur_dir_block * hdr.block_size); - f.Write(&entry, sizeof(vfsHDD_Entry)); - f.Write("."); - } - - u8 null = 0; - f.Seek(hdr.block_count * hdr.block_size - sizeof(null)); - f.Write(&null, sizeof(null)); - } - - void Format() - { - } - - void AppendEntry(vfsHDD_Entry entry) - { - } + void AppendEntry(vfsHDD_Entry entry); }; @@ -110,91 +64,23 @@ class vfsHDDFile u32 m_position; u64 m_cur_block; - bool goto_block(u64 n) - { - vfsHDD_Block block_info; + bool goto_block(u64 n); - if(m_info.data_block >= m_hdd_info.block_count) - { - return false; - } + void RemoveBlocks(u64 start_block); - m_hdd.Seek(m_info.data_block * m_hdd_info.block_size); - block_info.next_block = m_info.data_block; + void WriteBlock(u64 block, const vfsHDD_Block& data); - for(u64 i=0; i= m_hdd_info.block_count) - { - return false; - } + void ReadBlock(u64 block, vfsHDD_Block& data); - m_hdd.Seek(block_info.next_block * m_hdd_info.block_size); - m_hdd.Read(&block_info, sizeof(vfsHDD_Block)); - } + void WriteEntry(u64 block, const vfsHDD_Entry& data); - return true; - } + void ReadEntry(u64 block, vfsHDD_Entry& data); - void RemoveBlocks(u64 start_block) - { - vfsHDD_Block block_info; - block_info.next_block = start_block; + void ReadEntry(u64 block, vfsHDD_Entry& data, std::string& name); - while(block_info.next_block && block_info.is_used) - { - u64 offset = block_info.next_block * m_hdd_info.block_size; + void ReadEntry(u64 block, std::string& name); - ReadBlock(offset, block_info); - WriteBlock(offset, g_null_block); - } - } - - void WriteBlock(u64 block, const vfsHDD_Block& data) - { - m_hdd.Seek(block * m_hdd_info.block_size); - m_hdd.Write(&data, sizeof(vfsHDD_Block)); - } - - void ReadBlock(u64 block, vfsHDD_Block& data) - { - m_hdd.Seek(block * m_hdd_info.block_size); - m_hdd.Read(&data, sizeof(vfsHDD_Block)); - } - - void WriteEntry(u64 block, const vfsHDD_Entry& data) - { - m_hdd.Seek(block * m_hdd_info.block_size); - m_hdd.Write(&data, sizeof(vfsHDD_Entry)); - } - - void ReadEntry(u64 block, vfsHDD_Entry& data) - { - m_hdd.Seek(block * m_hdd_info.block_size); - m_hdd.Read(&data, sizeof(vfsHDD_Entry)); - } - - void ReadEntry(u64 block, vfsHDD_Entry& data, std::string& name) - { - m_hdd.Seek(block * m_hdd_info.block_size); - m_hdd.Read(&data, sizeof(vfsHDD_Entry)); - name.resize(GetMaxNameLen()); - m_hdd.Read(&name.front(), GetMaxNameLen()); - } - - void ReadEntry(u64 block, std::string& name) - { - m_hdd.Seek(block * m_hdd_info.block_size + sizeof(vfsHDD_Entry)); - name.resize(GetMaxNameLen()); - m_hdd.Read(&name.front(), GetMaxNameLen()); - } - - void WriteEntry(u64 block, const vfsHDD_Entry& data, const std::string& name) - { - m_hdd.Seek(block * m_hdd_info.block_size); - m_hdd.Write(&data, sizeof(vfsHDD_Entry)); - m_hdd.Write(name.c_str(), min(GetMaxNameLen() - 1, name.length() + 1)); - } + void WriteEntry(u64 block, const vfsHDD_Entry& data, const std::string& name); __forceinline u32 GetMaxNameLen() const { @@ -212,198 +98,22 @@ public: { } - void Open(u64 info_block) - { - m_info_block = info_block; - ReadEntry(m_info_block, m_info); - m_position = 0; - m_cur_block = m_info.data_block; - } + void Open(u64 info_block); - u64 FindFreeBlock() - { - vfsHDD_Block block_info; - - for(u64 i = 0; i(block_size - m_position, size); - - vfsHDD_Block cur_block_info; - m_hdd.Seek(m_cur_block * m_hdd_info.block_size); - m_hdd.Read(&cur_block_info, sizeof(vfsHDD_Block)); - m_hdd.Seek(m_cur_block * m_hdd_info.block_size + sizeof(vfsHDD_Block) + m_position); - m_hdd.Read(dst, rsize); - size -= rsize; - m_position += rsize; - if(!size) - { - return rsize; - } - - u64 offset = rsize; - - for(; size; size -= rsize, offset += rsize) - { - if(!cur_block_info.is_used || !cur_block_info.next_block || cur_block_info.next_block >= m_hdd_info.block_count) - { - return offset; - } - - m_cur_block = cur_block_info.next_block; - rsize = min(block_size, size); - - m_hdd.Seek(cur_block_info.next_block * m_hdd_info.block_size); - m_hdd.Read(&cur_block_info, sizeof(vfsHDD_Block)); - - if(m_hdd.Read((u8*)dst + offset, rsize) != rsize) - { - return offset; - } - } - - m_position = rsize; - - return offset; - } - - u64 Write(const void* src, u64 size) - { - if(!size) - return 0; - - //vfsDeviceLocker lock(m_hdd); - - const u32 block_size = m_hdd_info.block_size - sizeof(vfsHDD_Block); - - if(!m_cur_block) - { - if(!m_info.data_block) - { - u64 new_block = FindFreeBlock(); - - if(!new_block) - { - return 0; - } - - WriteBlock(new_block, g_used_block); - m_info.data_block = new_block; - m_info.size = 0; - SaveInfo(); - } - - m_cur_block = m_info.data_block; - m_position = 0; - } - - u64 wsize = min(block_size - m_position, size); - - vfsHDD_Block block_info; - ReadBlock(m_cur_block, block_info); - - if(wsize) - { - m_hdd.Seek(m_cur_block * m_hdd_info.block_size + sizeof(vfsHDD_Block) + m_position); - m_hdd.Write(src, wsize); - size -= wsize; - m_info.size += wsize; - m_position += wsize; - SaveInfo(); - - if(!size) - return wsize; - } - - u64 last_block = m_cur_block; - block_info.is_used = true; - u64 offset = wsize; - - for(; size; size -= wsize, offset += wsize, m_info.size += wsize) - { - u64 new_block = FindFreeBlock(); - - if(!new_block) - { - m_position = 0; - SaveInfo(); - return offset; - } - - m_cur_block = new_block; - wsize = min(block_size, size); - - block_info.next_block = m_cur_block; - m_hdd.Seek(last_block * m_hdd_info.block_size); - if(m_hdd.Write(&block_info, sizeof(vfsHDD_Block)) != sizeof(vfsHDD_Block)) - { - m_position = 0; - SaveInfo(); - return offset; - } - - block_info.next_block = 0; - m_hdd.Seek(m_cur_block * m_hdd_info.block_size); - if(m_hdd.Write(&block_info, sizeof(vfsHDD_Block)) != sizeof(vfsHDD_Block)) - { - m_position = 0; - SaveInfo(); - return offset; - } - if((m_position = m_hdd.Write((u8*)src + offset, wsize)) != wsize) - { - m_info.size += wsize; - SaveInfo(); - return offset; - } - - last_block = m_cur_block; - } - - SaveInfo(); - m_position = wsize; - return offset; - } + u64 Write(const void* src, u64 size); bool Eof() const { @@ -432,444 +142,60 @@ class vfsHDD : public vfsFileBase vfsHDDFile m_file; public: - vfsHDD(vfsDevice* device, const std::string& hdd_path) - : m_hdd_file(device) - , m_file(m_hdd_file, m_hdd_info) - , m_hdd_path(hdd_path) - , vfsFileBase(device) - { - m_hdd_file.Open(hdd_path, vfsReadWrite); - m_hdd_file.Read(&m_hdd_info, sizeof(vfsHDD_Hdr)); - m_cur_dir_block = m_hdd_info.next_block; - if(!m_hdd_info.block_size) - { - ConLog.Error("Bad block size!"); - m_hdd_info.block_size = 2048; - } - m_hdd_file.Seek(m_cur_dir_block * m_hdd_info.block_size); - m_hdd_file.Read(&m_cur_dir, sizeof(vfsHDD_Entry)); - } + vfsHDD(vfsDevice* device, const std::string& hdd_path); __forceinline u32 GetMaxNameLen() const { return m_hdd_info.block_size - sizeof(vfsHDD_Entry); } - bool SearchEntry(const std::string& name, u64& entry_block, u64* parent_block = nullptr) - { - u64 last_block = 0; - u64 block = m_cur_dir_block; - vfsHDD_Entry entry; - std::string buf; + bool SearchEntry(const std::string& name, u64& entry_block, u64* parent_block = nullptr); - while(block) - { - ReadEntry(block, entry, buf); + int OpenDir(const std::string& name); - if (fmt::CmpNoCase(name,buf) == 0) - { - entry_block = block; - if(parent_block) - *parent_block = last_block; + bool Rename(const std::string& from, const std::string& to); - return true; - } + u64 FindFreeBlock(); - last_block = block; - block = entry.is_used ? entry.next_block : 0ULL; - } + void WriteBlock(u64 block, const vfsHDD_Block& data); - return false; - } + void ReadBlock(u64 block, vfsHDD_Block& data); - int OpenDir(const std::string& name) - { - ConLog.Warning("OpenDir(%s)", name.c_str()); - u64 entry_block; - if(!SearchEntry(name, entry_block)) - return -1; + void WriteEntry(u64 block, const vfsHDD_Entry& data); - m_hdd_file.Seek(entry_block * m_hdd_info.block_size); - vfsHDD_Entry entry; - m_hdd_file.Read(&entry, sizeof(vfsHDD_Entry)); - if(entry.type == vfsHDD_Entry_File) - return 1; + void ReadEntry(u64 block, vfsHDD_Entry& data); - m_cur_dir_block = entry.data_block; - ReadEntry(m_cur_dir_block, m_cur_dir); + void ReadEntry(u64 block, vfsHDD_Entry& data, std::string& name); - return 0; - } + void ReadEntry(u64 block, std::string& name); - bool Rename(const std::string& from, const std::string& to) - { - u64 entry_block; - if(!SearchEntry(from, entry_block)) - { - return false; - } + void WriteEntry(u64 block, const vfsHDD_Entry& data, const std::string& name); - vfsHDD_Entry entry; - ReadEntry(entry_block, entry); - WriteEntry(entry_block, entry, to); + bool Create(vfsHDD_EntryType type, const std::string& name); - return true; - } + bool GetFirstEntry(u64& block, vfsHDD_Entry& entry, std::string& name); - u64 FindFreeBlock() - { - vfsHDD_Block block_info; + bool GetNextEntry(u64& block, vfsHDD_Entry& entry, std::string& name); - for(u64 i = 0; i(GetMaxNameLen() - 1, name.length() + 1)); - } + virtual bool Eof(); - bool Create(vfsHDD_EntryType type, const std::string& name) - { - if(HasEntry(name)) - { - return false; - } - - u64 new_block = FindFreeBlock(); - if(!new_block) - { - return false; - } - - ConLog.Write("CREATING ENTRY AT 0x%llx", new_block); - WriteBlock(new_block, g_used_block); - - { - vfsHDD_Entry new_entry; - vfsHDDManager::CreateEntry(new_entry); - new_entry.next_block = 0; - new_entry.type = type; - - if(type == vfsHDD_Entry_Dir) - { - u64 block_cur = FindFreeBlock(); - - if(!block_cur) - { - return false; - } - - WriteBlock(block_cur, g_used_block); - - u64 block_last = FindFreeBlock(); - - if(!block_last) - { - return false; - } - - WriteBlock(block_last, g_used_block); - - vfsHDD_Entry entry_cur, entry_last; - vfsHDDManager::CreateEntry(entry_cur); - vfsHDDManager::CreateEntry(entry_last); - - entry_cur.type = vfsHDD_Entry_Dir; - entry_cur.data_block = block_cur; - entry_cur.next_block = block_last; - - entry_last.type = vfsHDD_Entry_Dir; - entry_last.data_block = m_cur_dir_block; - entry_last.next_block = 0; - - new_entry.data_block = block_cur; - - WriteEntry(block_cur, entry_cur, "."); - WriteEntry(block_last, entry_last, ".."); - } - - WriteEntry(new_block, new_entry, name); - } - - { - u64 block = m_cur_dir_block; - - vfsHDD_Block tmp; - while(block) - { - ReadBlock(block, tmp); - - if(!tmp.next_block) - break; - - block = tmp.next_block; - } - - tmp.next_block = new_block; - WriteBlock(block, tmp); - } - - return true; - } - - bool GetFirstEntry(u64& block, vfsHDD_Entry& entry, std::string& name) - { - if(!m_cur_dir_block) - { - return false; - } - - ReadEntry(m_cur_dir_block, entry, name); - block = entry.is_used ? entry.next_block : 0; - - return true; - } - - bool GetNextEntry(u64& block, vfsHDD_Entry& entry, std::string& name) - { - if(!block) - { - return false; - } - - ReadEntry(block, entry, name); - - block = entry.is_used ? entry.next_block : 0; - return true; - } - - virtual bool Open(const std::string& path, vfsOpenMode mode = vfsRead) - { - const char* s = path.c_str(); - u64 from = 0; - u64 pos = 0; - u64 file_pos = -1; - - do - { - if(s[pos] == '\\' || s[pos] == '/' || s[pos] == '\0') // ??? - { - if(file_pos != -1) - { - return false; - } - - if(from != -1) - { - if(pos - from > 1) - { - int res = OpenDir(std::string(s + from, pos)); - if(res == -1) - { - return false; - } - - if(res == 1) - { - file_pos = from; - } - } - - from = pos; - } - else - { - from = pos; - } - } - } - while(s[pos++] != '\0'); - - if(file_pos == -1) - { - return false; - } - - u64 file_block; - if(!SearchEntry(std::string(s + file_pos), file_block)) - { - return false; - } - - ConLog.Write("ENTRY FOUND AT 0x%llx", file_block); - m_file.Open(file_block); - - return vfsFileBase::Open(path, mode); - } - - bool HasEntry(const std::string& name) - { - u64 file_block; - if(!SearchEntry(name, file_block)) - { - return false; - } - - return true; - } - - void RemoveBlocksDir(u64 start_block) - { - std::string name; - u64 block = start_block; - vfsHDD_Entry entry; - - while(block) - { - ReadEntry(block, entry, name); - WriteBlock(block, g_null_block); - - if(entry.type == vfsHDD_Entry_Dir && name != "." && name != "..") - { - ConLog.Warning("Removing sub folder '%s'", name.c_str()); - RemoveBlocksDir(entry.data_block); - } - else if(entry.type == vfsHDD_Entry_File) - { - RemoveBlocksFile(entry.data_block); - } - - block = entry.next_block; - } - } - - void RemoveBlocksFile(u64 start_block) - { - u64 block = start_block; - vfsHDD_Block block_data; - - while(block) - { - ReadBlock(block, block_data); - WriteBlock(block, g_null_block); - - block = block_data.next_block; - } - } - - bool RemoveEntry(const std::string& name) - { - u64 entry_block, parent_entry; - if(!SearchEntry(name, entry_block, &parent_entry)) - { - return false; - } - - vfsHDD_Entry entry; - ReadEntry(entry_block, entry); - if(entry.type == vfsHDD_Entry_Dir) - { - RemoveBlocksDir(entry.data_block); - } - else if(entry.type == vfsHDD_Entry_File) - { - RemoveBlocksFile(entry.data_block); - } - - if(parent_entry) - { - u64 next = entry.next_block; - ReadEntry(parent_entry, entry); - entry.next_block = next; - WriteEntry(parent_entry, entry); - } - WriteBlock(entry_block, g_null_block); - return true; - } - - virtual bool Create(const std::string& path) - { - return false; - } - - virtual u32 Write(const void* src, u32 size) - { - return vfsFileBase::Write(src, m_file.Write(src, size)); - } - - virtual u32 Read(void* dst, u32 size) - { - return vfsFileBase::Read(dst, m_file.Read(dst, size)); - } - - virtual u64 Seek(s64 offset, vfsSeekMode mode = vfsSeekSet) - { - switch(mode) - { - case vfsSeekCur: - m_file.Seek(Tell() + offset); - break; - - case vfsSeekSet: - m_file.Seek(offset); - break; - - case vfsSeekEnd: - m_file.Seek(m_file.GetSize() + offset); - break; - } - - return vfsFileBase::Seek(offset, mode); - } - - virtual bool Eof() - { - return m_file.Eof(); - } - - virtual u64 GetSize() - { - return m_file.GetSize(); - } + virtual u64 GetSize(); }; diff --git a/Utilities/IdManager.h b/rpcs3/Emu/IdManager.h similarity index 55% rename from Utilities/IdManager.h rename to rpcs3/Emu/IdManager.h index c56fefd061..b81c8678cd 100644 --- a/Utilities/IdManager.h +++ b/rpcs3/Emu/IdManager.h @@ -1,7 +1,34 @@ #pragma once #include -typedef u32 ID_TYPE; +#define rID_ANY -1 // was wxID_ANY + +enum IDType +{ + // Special objects + TYPE_MEM, + TYPE_MUTEX, + TYPE_COND, + TYPE_RWLOCK, + TYPE_INTR_TAG, + TYPE_INTR_SERVICE_HANDLE, + TYPE_EVENT_QUEUE, + TYPE_EVENT_PORT, + TYPE_TRACE, + TYPE_SPUIMAGE, + TYPE_PRX, + TYPE_SPUPORT, + TYPE_LWMUTEX, + TYPE_TIMER, + TYPE_SEMAPHORE, + TYPE_FS_FILE, + TYPE_FS_DIR, + TYPE_LWCOND, + TYPE_EVENT_FLAG, + + // Any other objects + TYPE_OTHER, +}; class IDData { @@ -35,13 +62,13 @@ public: struct ID { std::string m_name; - u32 m_attr; IDData* m_data; + IDType m_type; template - ID(const std::string& name, T* data, const u32 attr) + ID(const std::string& name, T* data, const IDType type) : m_name(name) - , m_attr(attr) + , m_type(type) { m_data = new IDData(data, [](void *ptr) -> void { delete (T*)ptr; }); } @@ -53,14 +80,14 @@ struct ID ID(ID&& other) { m_name = other.m_name; - m_attr = other.m_attr; + m_type = other.m_type; m_data = other.m_data; other.m_data = nullptr; } ID& operator=(ID&& other) { std::swap(m_name,other.m_name); - std::swap(m_attr,other.m_attr); + std::swap(m_type,other.m_type); std::swap(m_data,other.m_data); return *this; } @@ -73,13 +100,14 @@ struct ID class IdManager { - static const ID_TYPE s_first_id = 1; - static const ID_TYPE s_max_id = -1; + static const u32 s_first_id = 1; + static const u32 s_max_id = -1; - std::unordered_map m_id_map; + std::unordered_map m_id_map; + std::set m_types[TYPE_OTHER]; std::mutex m_mtx_main; - ID_TYPE m_cur_id; + u32 m_cur_id; public: IdManager() : m_cur_id(s_first_id) @@ -91,7 +119,7 @@ public: Clear(); } - bool CheckID(const ID_TYPE id) + bool CheckID(const u32 id) { std::lock_guard lock(m_mtx_main); @@ -102,8 +130,7 @@ public: { std::lock_guard lock(m_mtx_main); - for(auto& i : m_id_map) - { + for(auto& i : m_id_map) { i.second.Kill(); } @@ -116,16 +143,19 @@ public: = char #endif > - ID_TYPE GetNewID(const std::string& name = "", T* data = nullptr, const u32 attr = 0) + u32 GetNewID(const std::string& name = "", T* data = nullptr, const IDType type = TYPE_OTHER) { std::lock_guard lock(m_mtx_main); - m_id_map[m_cur_id] = ID(name, data, attr); + m_id_map[m_cur_id] = ID(name, data, type); + if (type < TYPE_OTHER) { + m_types[type].insert(m_cur_id); + } return m_cur_id++; } - ID& GetID(const ID_TYPE id) + ID& GetID(const u32 id) { std::lock_guard lock(m_mtx_main); @@ -133,14 +163,12 @@ public: } template - bool GetIDData(const ID_TYPE id, T*& result) + bool GetIDData(const u32 id, T*& result) { std::lock_guard lock(m_mtx_main); auto f = m_id_map.find(id); - - if(f == m_id_map.end()) - { + if (f == m_id_map.end()) { return false; } @@ -149,29 +177,48 @@ public: return true; } - bool HasID(const s64 id) + bool HasID(const u32 id) { { std::lock_guard lock(m_mtx_main); - if(id == wxID_ANY) + if(id == rID_ANY) { return m_id_map.begin() != m_id_map.end(); + } } - return CheckID(id); } - bool RemoveID(const ID_TYPE id) + bool RemoveID(const u32 id) { std::lock_guard lock(m_mtx_main); auto item = m_id_map.find(id); - if(item == m_id_map.end()) return false; + if (item == m_id_map.end()) { + return false; + } + if (item->second.m_type < TYPE_OTHER) { + m_types[item->second.m_type].erase(id); + } item->second.Kill(); m_id_map.erase(item); return true; } + + u32 GetTypeCount(IDType type) + { + if (type < TYPE_OTHER) { + return (u32)m_types[type].size(); + } + return 1; + } + + const std::set& GetTypeIDs(IDType type) + { + assert(type < TYPE_OTHER); + return m_types[type]; + } }; diff --git a/rpcs3/Emu/Io/Keyboard.cpp b/rpcs3/Emu/Io/Keyboard.cpp index b14ca37530..e23f325b87 100644 --- a/rpcs3/Emu/Io/Keyboard.cpp +++ b/rpcs3/Emu/Io/Keyboard.cpp @@ -1,7 +1,27 @@ #include "stdafx.h" -#include "Keyboard.h" +#include "rpcs3/Ini.h" #include "Null/NullKeyboardHandler.h" -#include "Windows/WindowsKeyboardHandler.h" +#include "Keyboard.h" + +GetKeyboardHandlerCountCb GetKeyboardHandlerCount = []() +{ + return 1; +}; + +GetKeyboardHandlerCb GetKeyboardHandler = [](int i) -> KeyboardHandlerBase* +{ + return new NullKeyboardHandler; +}; + +void SetGetKeyboardHandlerCountCallback(GetKeyboardHandlerCountCb cb) +{ + GetKeyboardHandlerCount = cb; +} + +void SetGetKeyboardHandlerCallback(GetKeyboardHandlerCb cb) +{ + GetKeyboardHandler = cb; +} KeyboardManager::KeyboardManager() : m_keyboard_handler(nullptr) @@ -19,17 +39,13 @@ void KeyboardManager::Init(const u32 max_connect) return; // NOTE: Change these to std::make_unique assignments when C++14 comes out. - switch(Ini.KeyboardHandlerMode.GetValue()) + int numHandlers = GetKeyboardHandlerCount(); + int selectedHandler = Ini.KeyboardHandlerMode.GetValue(); + if (selectedHandler > numHandlers) { - case 1: - m_keyboard_handler.reset(new WindowsKeyboardHandler()); - break; - - default: - case 0: - m_keyboard_handler.reset(new NullKeyboardHandler()); - break; + selectedHandler = 0; } + m_keyboard_handler.reset(GetKeyboardHandler(selectedHandler)); m_keyboard_handler->Init(max_connect); m_inited = true; @@ -41,4 +57,4 @@ void KeyboardManager::Close() m_keyboard_handler = nullptr; m_inited = false; -} \ No newline at end of file +} diff --git a/rpcs3/Emu/Io/Keyboard.h b/rpcs3/Emu/Io/Keyboard.h index 1674b185de..bbcd8561b6 100644 --- a/rpcs3/Emu/Io/Keyboard.h +++ b/rpcs3/Emu/Io/Keyboard.h @@ -1,10 +1,7 @@ #pragma once - -#include -#include #include "KeyboardHandler.h" -class KeyboardManager //: public wxWindow +class KeyboardManager { bool m_inited; std::unique_ptr m_keyboard_handler; @@ -19,11 +16,14 @@ public: std::vector& GetKeyboards() { return m_keyboard_handler->GetKeyboards(); } KbInfo& GetInfo() { return m_keyboard_handler->GetInfo(); } std::vector& GetButtons(const u32 keyboard) { return m_keyboard_handler->GetButtons(keyboard); } - CellKbData& GetData(const u32 keyboard) { return m_keyboard_handler->GetData(keyboard); } - CellKbConfig& GetConfig(const u32 keyboard) { return m_keyboard_handler->GetConfig(keyboard); } + KbData& GetData(const u32 keyboard) { return m_keyboard_handler->GetData(keyboard); } + KbConfig& GetConfig(const u32 keyboard) { return m_keyboard_handler->GetConfig(keyboard); } bool IsInited() const { return m_inited; } +}; -//private: - //DECLARE_EVENT_TABLE(); -}; \ No newline at end of file +typedef int(*GetKeyboardHandlerCountCb)(); +typedef KeyboardHandlerBase*(*GetKeyboardHandlerCb)(int i); + +void SetGetKeyboardHandlerCountCallback(GetKeyboardHandlerCountCb cb); +void SetGetKeyboardHandlerCallback(GetKeyboardHandlerCb cb); \ No newline at end of file diff --git a/rpcs3/Emu/Io/KeyboardHandler.h b/rpcs3/Emu/Io/KeyboardHandler.h index 9eff36490b..c2acaa3941 100644 --- a/rpcs3/Emu/Io/KeyboardHandler.h +++ b/rpcs3/Emu/Io/KeyboardHandler.h @@ -1,7 +1,5 @@ #pragma once -#include - extern u16 cellKbCnvRawCode(u32 arrange, u32 mkey, u32 led, u16 rawcode); // (TODO: Can it be problematic to place SysCalls in middle of nowhere?) enum KbPortStatus @@ -191,26 +189,25 @@ enum CellKbMappingType CELL_KB_MAPPING_PORTUGUESE_BRAZIL, }; -static const u32 CELL_KB_MAX_KEYBOARDS = 127; -static const u32 CELL_KB_MAX_PORT_NUM = 7; -static const u32 CELL_KB_MAX_KEYCODES = 62; +static const u32 KB_MAX_KEYBOARDS = 127; +static const u32 KB_MAX_KEYCODES = 62; struct KbInfo { u32 max_connect; u32 now_connect; u32 info; - u8 status[CELL_KB_MAX_KEYBOARDS]; + u8 status[KB_MAX_KEYBOARDS]; }; -struct CellKbData +struct KbData { u32 led; u32 mkey; s32 len; - u16 keycode[CELL_KB_MAX_KEYCODES]; + u16 keycode[KB_MAX_KEYCODES]; - CellKbData() + KbData() : led(0) , mkey(0) , len(0) @@ -218,13 +215,13 @@ struct CellKbData } }; -struct CellKbConfig +struct KbConfig { u32 arrange; u32 read_mode; u32 code_type; - CellKbConfig() + KbConfig() : arrange(CELL_KB_MAPPING_106) , read_mode(CELL_KB_RMODE_INPUTCHAR) , code_type(CELL_KB_CODETYPE_ASCII) @@ -248,8 +245,8 @@ struct KbButton struct Keyboard { - CellKbData m_data; - CellKbConfig m_config; + KbData m_data; + KbConfig m_config; std::vector m_buttons; Keyboard() @@ -278,8 +275,8 @@ public: if(button.m_keyCode != code) continue; - CellKbData& data = keyboard.m_data; - CellKbConfig& config = keyboard.m_config; + KbData& data = keyboard.m_data; + KbConfig& config = keyboard.m_config; if (pressed) { @@ -305,7 +302,7 @@ public: { kcode = cellKbCnvRawCode(config.arrange, data.mkey, data.led, button.m_outKeyCode); } - data.keycode[data.len % CELL_KB_MAX_KEYCODES] = kcode; + data.keycode[data.len % KB_MAX_KEYCODES] = kcode; data.len++; } } @@ -327,6 +324,6 @@ public: KbInfo& GetInfo() { return m_info; } std::vector& GetKeyboards() { return m_keyboards; } std::vector& GetButtons(const u32 keyboard) { return m_keyboards[keyboard].m_buttons; } - CellKbData& GetData(const u32 keyboard) { return m_keyboards[keyboard].m_data; } - CellKbConfig& GetConfig(const u32 keyboard) { return m_keyboards[keyboard].m_config; } + KbData& GetData(const u32 keyboard) { return m_keyboards[keyboard].m_data; } + KbConfig& GetConfig(const u32 keyboard) { return m_keyboards[keyboard].m_config; } }; \ No newline at end of file diff --git a/rpcs3/Emu/Io/Mouse.cpp b/rpcs3/Emu/Io/Mouse.cpp index 80d8cb4b97..5a0f191dae 100644 --- a/rpcs3/Emu/Io/Mouse.cpp +++ b/rpcs3/Emu/Io/Mouse.cpp @@ -1,7 +1,27 @@ #include "stdafx.h" -#include "Mouse.h" +#include "rpcs3/Ini.h" #include "Null/NullMouseHandler.h" -#include "Windows/WindowsMouseHandler.h" +#include "Mouse.h" + +GetMouseHandlerCountCb GetMouseHandlerCount = []() +{ + return 1; +}; + +GetMouseHandlerCb GetMouseHandler = [](int i) -> MouseHandlerBase* +{ + return new NullMouseHandler; +}; + +void SetGetMouseHandlerCountCallback(GetMouseHandlerCountCb cb) +{ + GetMouseHandlerCount = cb; +} + +void SetGetMouseHandlerCallback(GetMouseHandlerCb cb) +{ + GetMouseHandler = cb; +} MouseManager::MouseManager() : m_mouse_handler(nullptr) @@ -19,17 +39,13 @@ void MouseManager::Init(const u32 max_connect) return; // NOTE: Change these to std::make_unique assignments when C++14 is available. - switch(Ini.MouseHandlerMode.GetValue()) + int numHandlers = GetMouseHandlerCount(); + int selectedHandler = Ini.MouseHandlerMode.GetValue(); + if (selectedHandler > numHandlers) { - case 1: - m_mouse_handler.reset(new WindowsMouseHandler()); - break; - - default: - case 0: - m_mouse_handler.reset(new NullMouseHandler()); - break; + selectedHandler = 0; } + m_mouse_handler.reset(GetMouseHandler(selectedHandler)); m_mouse_handler->Init(max_connect); m_inited = true; @@ -41,4 +57,4 @@ void MouseManager::Close() m_mouse_handler = nullptr; m_inited = false; -} \ No newline at end of file +} diff --git a/rpcs3/Emu/Io/Mouse.h b/rpcs3/Emu/Io/Mouse.h index aa3c546117..c6dbdd61dd 100644 --- a/rpcs3/Emu/Io/Mouse.h +++ b/rpcs3/Emu/Io/Mouse.h @@ -1,10 +1,7 @@ #pragma once - -#include -#include #include "MouseHandler.h" -class MouseManager //: public wxWindow +class MouseManager { bool m_inited; std::unique_ptr m_mouse_handler; @@ -18,11 +15,14 @@ public: std::vector& GetMice() { return m_mouse_handler->GetMice(); } MouseInfo& GetInfo() { return m_mouse_handler->GetInfo(); } - CellMouseData& GetData(const u32 mouse) { return m_mouse_handler->GetData(mouse); } - CellMouseRawData& GetRawData(const u32 mouse) { return m_mouse_handler->GetRawData(mouse); } + MouseData& GetData(const u32 mouse) { return m_mouse_handler->GetData(mouse); } + MouseRawData& GetRawData(const u32 mouse) { return m_mouse_handler->GetRawData(mouse); } bool IsInited() const { return m_inited; } +}; -//private: - //DECLARE_EVENT_TABLE(); -}; \ No newline at end of file +typedef int(*GetMouseHandlerCountCb)(); +typedef MouseHandlerBase*(*GetMouseHandlerCb)(int i); + +void SetGetMouseHandlerCountCallback(GetMouseHandlerCountCb cb); +void SetGetMouseHandlerCallback(GetMouseHandlerCb cb); \ No newline at end of file diff --git a/rpcs3/Emu/Io/MouseHandler.h b/rpcs3/Emu/Io/MouseHandler.h index c081ae2f7e..a2aeeede32 100644 --- a/rpcs3/Emu/Io/MouseHandler.h +++ b/rpcs3/Emu/Io/MouseHandler.h @@ -1,7 +1,5 @@ #pragma once -#include - enum MousePortStatus { CELL_MOUSE_STATUS_DISCONNECTED = 0x00000000, @@ -26,32 +24,32 @@ enum MouseButtonCodes CELL_MOUSE_BUTTON_8 = 0x00000080, }; -static const u32 CELL_MAX_MICE = 127; -static const u32 CELL_MOUSE_MAX_DATA_LIST_NUM = 8; -static const u32 CELL_MOUSE_MAX_CODES = 64; +static const u32 MAX_MICE = 127; +static const u32 MOUSE_MAX_DATA_LIST_NUM = 8; +static const u32 MOUSE_MAX_CODES = 64; struct MouseInfo { u32 max_connect; u32 now_connect; u32 info; - u16 vendor_id[CELL_MAX_MICE]; - u16 product_id[CELL_MAX_MICE]; - u8 status[CELL_MAX_MICE]; + u16 vendor_id[MAX_MICE]; + u16 product_id[MAX_MICE]; + u8 status[MAX_MICE]; }; -struct CellMouseRawData +struct MouseRawData { s32 len; - u8 data[CELL_MOUSE_MAX_CODES]; + u8 data[MOUSE_MAX_CODES]; - CellMouseRawData() + MouseRawData() : len(0) { } }; -struct CellMouseData +struct MouseData { u8 update; u8 buttons; @@ -60,7 +58,7 @@ struct CellMouseData s8 wheel; s8 tilt; // (TODO) - CellMouseData() + MouseData() : update(0) , buttons(0) , x_axis(0) @@ -71,12 +69,12 @@ struct CellMouseData } }; -struct CellMouseDataList +struct MouseDataList { u32 list_num; - CellMouseData list[CELL_MOUSE_MAX_DATA_LIST_NUM]; + MouseData list[MOUSE_MAX_DATA_LIST_NUM]; - CellMouseDataList() + MouseDataList() : list_num(0) { } @@ -87,8 +85,8 @@ struct Mouse s16 x_pos; s16 y_pos; - CellMouseData m_data; - CellMouseRawData m_rawdata; + MouseData m_data; + MouseRawData m_rawdata; Mouse() : m_data() @@ -109,11 +107,11 @@ public: void Button(u8 button, bool pressed) { - for(u64 p=0; p < m_mice.size(); ++p) + for(u32 p=0; p < (u32)m_mice.size(); ++p) { if (m_info.status[p] == CELL_MOUSE_STATUS_CONNECTED) { - CellMouseData& data = GetData(p); + MouseData& data = GetData(p); data.update = CELL_MOUSE_DATA_UPDATE; if (pressed) data.buttons |= button; else data.buttons &= ~button; @@ -123,11 +121,11 @@ public: void Scroll(const s8 rotation) { - for(u64 p=0; p < m_mice.size(); ++p) + for(u32 p=0; p < (u32)m_mice.size(); ++p) { if (m_info.status[p] == CELL_MOUSE_STATUS_CONNECTED) { - CellMouseData& data = GetData(p); + MouseData& data = GetData(p); data.update = CELL_MOUSE_DATA_UPDATE; data.wheel = rotation/120; //120=event.GetWheelDelta() } @@ -136,11 +134,11 @@ public: void Move(const s16 x_pos_new, const s16 y_pos_new) { - for(u64 p=0; p< m_mice.size(); ++p) + for(u32 p=0; p < (u32)m_mice.size(); ++p) { if (m_info.status[p] == CELL_MOUSE_STATUS_CONNECTED) { - CellMouseData& data = GetData(p); + MouseData& data = GetData(p); data.update = CELL_MOUSE_DATA_UPDATE; data.x_axis += x_pos_new - m_mice[p].x_pos; data.y_axis += y_pos_new - m_mice[p].y_pos; @@ -157,6 +155,6 @@ public: MouseInfo& GetInfo() { return m_info; } std::vector& GetMice() { return m_mice; } - CellMouseData& GetData(const u32 mouse) { return m_mice[mouse].m_data; } - CellMouseRawData& GetRawData(const u32 mouse) { return m_mice[mouse].m_rawdata; } + MouseData& GetData(const u32 mouse) { return m_mice[mouse].m_data; } + MouseRawData& GetRawData(const u32 mouse) { return m_mice[mouse].m_rawdata; } }; \ No newline at end of file diff --git a/rpcs3/Emu/Io/Pad.cpp b/rpcs3/Emu/Io/Pad.cpp index 48e9e67f46..72efc937bd 100644 --- a/rpcs3/Emu/Io/Pad.cpp +++ b/rpcs3/Emu/Io/Pad.cpp @@ -1,10 +1,27 @@ #include "stdafx.h" -#include "Pad.h" +#include "rpcs3/Ini.h" #include "Null/NullPadHandler.h" -#include "Windows/WindowsPadHandler.h" -#if defined(_WIN32) -#include "XInput/XInputPadHandler.h" -#endif +#include "Pad.h" + +GetPadHandlerCountCb GetPadHandlerCount = []() +{ + return 1; +}; + +GetPadHandlerCb GetPadHandler = [](int i) -> PadHandlerBase* +{ + return new NullPadHandler; +}; + +void SetGetPadHandlerCountCallback(GetPadHandlerCountCb cb) +{ + GetPadHandlerCount = cb; +} + +void SetGetPadHandlerCallback(GetPadHandlerCb cb) +{ + GetPadHandler = cb; +} PadManager::PadManager() : m_pad_handler(nullptr) @@ -22,23 +39,13 @@ void PadManager::Init(const u32 max_connect) return; // NOTE: Change these to std::make_unique assignments when C++14 is available. - switch(Ini.PadHandlerMode.GetValue()) + int numHandlers = GetPadHandlerCount(); + int selectedHandler = Ini.PadHandlerMode.GetValue(); + if (selectedHandler > numHandlers) { - case 1: - m_pad_handler.reset(new WindowsPadHandler()); - break; - -#if defined(_WIN32) - case 2: - m_pad_handler.reset(new XInputPadHandler()); - break; -#endif - - default: - case 0: - m_pad_handler.reset(new NullPadHandler()); - break; + selectedHandler = 0; } + m_pad_handler.reset(GetPadHandler(selectedHandler)); m_pad_handler->Init(max_connect); m_inited = true; diff --git a/rpcs3/Emu/Io/Pad.h b/rpcs3/Emu/Io/Pad.h index 27b049cea4..e6a3260464 100644 --- a/rpcs3/Emu/Io/Pad.h +++ b/rpcs3/Emu/Io/Pad.h @@ -1,10 +1,7 @@ #pragma once - -#include -#include #include "PadHandler.h" -class PadManager //: public wxWindow +class PadManager { bool m_inited; std::unique_ptr m_pad_handler; @@ -21,7 +18,10 @@ public: std::vector