diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index ebf966f2ad..74a571db55 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -208,6 +208,16 @@ std::vector fmt::split(const std::string& source, std::initializer_ return std::move(result); } +std::string fmt::trim(const std::string& source, const std::string& values) +{ + std::size_t begin = source.find_first_not_of(values); + + if (begin == source.npos) + return{}; + + return source.substr(begin, source.find_last_not_of(values) + 1); +} + std::string fmt::tolower(std::string source) { std::transform(source.begin(), source.end(), source.begin(), ::tolower); diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 02111b9db2..5f1376860c 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -300,6 +300,7 @@ namespace fmt std::vector rSplit(const std::string& source, const std::string& delim); std::vector split(const std::string& source, std::initializer_list separators, bool is_skip_empty = true); + std::string trim(const std::string& source, const std::string& values = " \t"); template std::string merge(const T& source, const std::string& separator) diff --git a/Utilities/config_context.cpp b/Utilities/config_context.cpp new file mode 100644 index 0000000000..921de6b6c7 --- /dev/null +++ b/Utilities/config_context.cpp @@ -0,0 +1,145 @@ +#include "stdafx.h" +#include "config_context.h" +#include "StrFmt.h" +#include +#include + +void config_context_t::group::init() +{ + m_cfg->m_groups[full_name()] = this; +} + +config_context_t::group::group(config_context_t* cfg, const std::string& name) + : m_cfg(cfg) + , m_name(name) + , m_parent(nullptr) +{ + init(); +} + +config_context_t::group::group(group* parent, const std::string& name) + : m_cfg(parent->m_cfg) + , m_name(name) + , m_parent(parent) +{ + init(); +} + +void config_context_t::group::set_parent(config_context_t* cfg) +{ + m_cfg = cfg; + init(); +} + +std::string config_context_t::group::name() const +{ + return m_name; +} + +std::string config_context_t::group::full_name() const +{ + if (m_parent) + return m_parent->full_name() + "/" + m_name; + + return m_name; +} + +void config_context_t::assign(const config_context_t& rhs) +{ + for (auto &rhs_g : rhs.m_groups) + { + auto g = m_groups.at(rhs_g.first); + + for (auto rhs_e : rhs_g.second->entries) + { + g->entries[rhs_e.first]->value_from(rhs_e.second); + } + } +} + +void config_context_t::deserialize(std::istream& stream) +{ + set_defaults(); + + uint line_index = 0; + std::string line; + group *current_group = nullptr; + + while (std::getline(stream, line)) + { + ++line_index; + line = fmt::trim(line); + + if (line.empty()) + continue; + + if (line.front() == '[' && line.back() == ']') + { + std::string group_name = line.substr(1, line.length() - 2); + + auto found = m_groups.find(group_name); + + if (found == m_groups.end()) + { + std::cerr << line_index << ": group '" << group_name << "' not exists. ignored" << std::endl; + current_group = nullptr; + continue; + } + + current_group = found->second; + continue; + } + + if (current_group == nullptr) + { + std::cerr << line_index << ": line '" << line << "' ignored, no group." << std::endl; + continue; + } + + auto name_value = fmt::split(line, { "=" }); + switch (name_value.size()) + { + case 1: current_group->entries[fmt::trim(name_value[0])]->string_value({}); break; + + default: + std::cerr << line_index << ": line '" << line << "' has more than one symbol '='. used only first" << std::endl; + case 2: current_group->entries[fmt::trim(name_value[0])]->string_value(fmt::trim(name_value[1])); break; + + } + } +} + +void config_context_t::serialize(std::ostream& stream) const +{ + for (auto &g : m_groups) + { + stream << "[" + g.first + "]" << std::endl; + + for (auto &e : g.second->entries) + { + stream << e.first << "=" << e.second->string_value() << std::endl; + } + + stream << std::endl; + } +} + +void config_context_t::set_defaults() +{ + for (auto &g : m_groups) + { + for (auto &e : g.second->entries) + { + e.second->to_default(); + } + } +} + +std::string config_context_t::to_string() const +{ + std::ostringstream result; + + serialize(result); + + return result.str(); +} \ No newline at end of file diff --git a/Utilities/config_context.h b/Utilities/config_context.h new file mode 100644 index 0000000000..fcbcfb17d7 --- /dev/null +++ b/Utilities/config_context.h @@ -0,0 +1,128 @@ +#pragma once +#include +#include +#include "convert.h" + +class config_context_t +{ +public: + class entry_base; + +protected: + class group + { + group* m_parent; + config_context_t* m_cfg; + std::string m_name; + + void init(); + + public: + std::unordered_map entries; + + group(config_context_t* cfg, const std::string& name); + group(group* parent, const std::string& name); + void set_parent(config_context_t* cfg); + + std::string name() const; + std::string full_name() const; + + friend config_context_t; + }; + +public: + class entry_base + { + public: + virtual std::string name() = 0; + virtual void to_default() = 0; + virtual std::string string_value() = 0; + virtual void string_value(const std::string& value) = 0; + virtual void value_from(const entry_base* rhs) = 0; + }; + + template + class entry : public entry_base + { + T m_default_value; + T m_value; + group* m_parent; + std::string m_name; + + public: + entry(group* parent, const std::string& name, const T& default_value) + : m_parent(parent) + , m_name(name) + , m_default_value(default_value) + , m_value(default_value) + { + parent->entries[name] = this; + } + + T default_value() const + { + return m_default_value; + } + + T value() const + { + return m_value; + } + + void value(const T& new_value) + { + m_value = new_value; + } + + std::string name() override + { + return m_name; + } + + void to_default() override + { + value(default_value()); + } + + std::string string_value() override + { + return convert::to(value()); + } + + void string_value(const std::string &new_value) override + { + value(convert::to(new_value)); + } + + void value_from(const entry_base* rhs) + { + value(static_cast(rhs)->value()); + } + + entry& operator = (const T& new_value) + { + value(new_value); + return *this; + } + + explicit operator const T&() const + { + return m_value; + } + }; + +private: + std::unordered_map m_groups; + +public: + config_context_t() = default; + + void assign(const config_context_t& rhs); + + void serialize(std::ostream& stream) const; + void deserialize(std::istream& stream); + + void set_defaults(); + + std::string to_string() const; +}; \ No newline at end of file diff --git a/Utilities/convert.h b/Utilities/convert.h new file mode 100644 index 0000000000..0a782c0347 --- /dev/null +++ b/Utilities/convert.h @@ -0,0 +1,240 @@ +#pragma once +#include + +namespace convert +{ + template + struct to_impl_t; + + template + struct to_impl_t + { + static Type func(const Type& value) + { + return value; + } + }; + + template<> + struct to_impl_t + { + static std::string func(bool value) + { + return value ? "true" : "false"; + } + }; + + template<> + struct to_impl_t + { + static bool func(const std::string& value) + { + return value == "true" ? true : false; + } + }; + + template<> + struct to_impl_t + { + static std::string func(char value) + { + return std::to_string(value); + } + }; + + template<> + struct to_impl_t + { + static std::string func(unsigned char value) + { + return std::to_string(value); + } + }; + + + template<> + struct to_impl_t + { + static std::string func(short value) + { + return std::to_string(value); + } + }; + + template<> + struct to_impl_t + { + static std::string func(unsigned short value) + { + return std::to_string(value); + } + }; + + template<> + struct to_impl_t + { + static std::string func(int value) + { + return std::to_string(value); + } + }; + + template<> + struct to_impl_t + { + static std::string func(unsigned int value) + { + return std::to_string(value); + } + }; + + template<> + struct to_impl_t + { + static std::string func(long value) + { + return std::to_string(value); + } + }; + + template<> + struct to_impl_t + { + static std::string func(unsigned long value) + { + return std::to_string(value); + } + }; + + template<> + struct to_impl_t + { + static std::string func(long long value) + { + return std::to_string(value); + } + }; + + template<> + struct to_impl_t + { + static std::string func(unsigned long long value) + { + return std::to_string(value); + } + }; + + template<> + struct to_impl_t + { + static std::string func(float value) + { + return std::to_string(value); + } + }; + + template<> + struct to_impl_t + { + static std::string func(double value) + { + return std::to_string(value); + } + }; + + template<> + struct to_impl_t + { + static std::string func(long double value) + { + return std::to_string(value); + } + }; + + template<> + struct to_impl_t + { + static int func(const std::string& value) + { + return std::stoi(value); + } + }; + + template<> + struct to_impl_t + { + static unsigned int func(const std::string& value) + { + return (unsigned long)std::stoul(value); + } + }; + + template<> + struct to_impl_t + { + static long func(const std::string& value) + { + return std::stol(value); + } + }; + + template<> + struct to_impl_t + { + static unsigned long func(const std::string& value) + { + return std::stoul(value); + } + }; + + template<> + struct to_impl_t + { + static long long func(const std::string& value) + { + return std::stoll(value); + } + }; + + template<> + struct to_impl_t + { + static unsigned long long func(const std::string& value) + { + return std::stoull(value); + } + }; + + template<> + struct to_impl_t + { + static float func(const std::string& value) + { + return std::stof(value); + } + }; + + template<> + struct to_impl_t + { + static double func(const std::string& value) + { + return std::stod(value); + } + }; + + template<> + struct to_impl_t + { + static long double func(const std::string& value) + { + return std::stold(value); + } + }; + + template + ReturnType to(FromType value) + { + return to_impl_t, std::remove_all_extents_t>::func(value); + } +} \ No newline at end of file diff --git a/Utilities/event.h b/Utilities/event.h new file mode 100644 index 0000000000..8078bfccf3 --- /dev/null +++ b/Utilities/event.h @@ -0,0 +1,420 @@ +#pragma once +#include +#include +#include + +enum class event_result +{ + skip, + handled +}; + +class events_queue +{ + std::deque> m_queue; + +public: + /*template + events_queue& operator += (event &evt) + { + evt.set_queue(this); + return *this; + } +*/ + void invoke(std::function function) + { + m_queue.push_back(function); + } + + void flush() + { + while (!m_queue.empty()) + { + std::function function = m_queue.front(); + function(); + m_queue.pop_front(); + } + } +}; + +template +class event +{ + using func_t = std::function; + using entry_t = typename std::list::iterator; + + std::list handlers; + events_queue& m_queue; + +public: + event(events_queue* queue = nullptr) : m_queue(*queue) + { + } + + void invoke(AT... args) + { + m_queue.invoke(std::bind([&](AT... eargs) + { + for (auto &&handler : handlers) + { + if (handler(eargs...) == event_result::handled) + break; + } + }, args...)); + } + + void operator()(AT... args) + { + invoke(args...); + } + + entry_t bind(func_t func) + { + handlers.push_front(func); + return handlers.begin(); + } + + template + entry_t bind(T *caller, event_result(T::*callback)(AT...)) + { + return bind([=](AT... args) { return (caller->*callback)(args...); }); + } + + template + entry_t bind(T *caller, void(T::*callback)(AT...)) + { + return bind([=](AT... args) { (caller->*callback)(args...); return event_result::skip; }); + } + + void unbind(entry_t entry) + { + handlers.erase(entry); + } + + entry_t operator +=(func_t func) + { + return bind(func); + } + + void operator -=(entry_t what) + { + return unbind(what); + } +}; + +template<> +class event +{ + using func_t = std::function; + using entry_t = std::list::iterator; + + std::list m_listeners; + events_queue* m_queue; + + void invoke_listeners() + { + for (auto &&listener : m_listeners) + { + if (listener() == event_result::handled) + break; + } + } + +public: + event(events_queue* queue = nullptr) : m_queue(queue) + { + } + + void invoke() + { + if (m_queue) + m_queue->invoke([=]() { invoke_listeners(); }); + else + invoke_listeners(); + } + + void operator()() + { + invoke(); + } + + entry_t bind(func_t func) + { + m_listeners.push_front(func); + return m_listeners.begin(); + } + + template + entry_t bind(T *caller, event_result(T::*callback)()) + { + return bind([=]() { return (caller->*callback)(); }); + } + + template + entry_t bind(T *caller, void(T::*callback)()) + { + return bind([=]() { (caller->*callback)(); return event_result::skip; }); + } + + void unbind(entry_t what) + { + m_listeners.erase(what); + } + + entry_t operator +=(func_t func) + { + return bind(func); + } + + void operator -=(entry_t what) + { + return unbind(what); + } +}; + +class event_binder_t +{ + template + class binder_impl_t + { + event_binder_t *m_binder; + event *m_event; + + public: + binder_impl_t(event_binder_t *binder, event *evt) + : m_binder(binder) + , m_event(evt) + { + } + }; + +public: + template + binder_impl_t operator()(event& evt) const + { + return{ this, &evt }; + } +}; + +template +class combined_data; + +template +class local_data +{ +public: + using type = T; + +protected: + type m_data; + + void set(type value) + { + m_data = value; + } + + type get() const + { + return m_data; + } + + bool equals(T value) const + { + return get() == value; + } + + bool invoke_event(type value) + { + return false; + } + + friend combined_data; +}; + +template +class combined_data +{ +public: + using type = T; + +protected: + local_data m_local_data; + std::function m_invoke_event_function; + std::function m_get_function; + + bool invoke_event(type value) + { + if (m_invoke_event_function) + { + m_invoke_event_function(value); + return true; + } + + return false; + } + + void set(type value) + { + m_local_data.set(value); + } + + type get() const + { + if (m_get_function) + { + return m_get_function(); + } + + return m_local_data.get(); + } + + type get_local() const + { + return m_local_data.get(); + } + + bool equals(T value) const + { + return get_local() == value; + } + +public: + void invoke_event_function(std::function function) + { + m_invoke_event_function = function; + } + + void get_function(std::function function) + { + m_get_function = function; + } +}; + +template> +class data_event : public base_type_ +{ +public: + using type = T; + using base_type = base_type_; + +protected: + event_result dochange(type new_value) + { + auto old_value = get(); + base_type::set(new_value); + onchanged(old_value); + return event_result::handled; + } + +public: + event onchange; + event onchanged; + + data_event(events_queue *queue = nullptr) + : onchange(queue) + , onchanged(queue) + { + onchange.bind(this, &data_event::dochange); + base_type::set({}); + } + + type get() const + { + return base_type::get(); + } + + type operator()() const + { + return get(); + } + + void change(type value, bool use_custom_invoke_event = true) + { + if (!base_type::equals(value)) + { + if (!use_custom_invoke_event || !base_type::invoke_event(value)) + { + onchange(value); + } + } + } + + operator const type() const + { + return get(); + } + + operator type() + { + return get(); + } + + data_event& operator = (type value) + { + change(value); + return *this; + } + + template auto operator + (aType value) const { return get() + value; } + template auto operator - (aType value) const { return get() - value; } + template auto operator * (aType value) const { return get() * value; } + template auto operator / (aType value) const { return get() / value; } + template auto operator % (aType value) const { return get() % value; } + template auto operator & (aType value) const { return get() & value; } + template auto operator | (aType value) const { return get() | value; } + template auto operator ^ (aType value) const { return get() ^ value; } + + template data_event& operator += (aType value) { return *this = get() + value; } + template data_event& operator -= (aType value) { return *this = get() - value; } + template data_event& operator *= (aType value) { return *this = get() * value; } + template data_event& operator /= (aType value) { return *this = get() / value; } + template data_event& operator %= (aType value) { return *this = get() % value; } + template data_event& operator &= (aType value) { return *this = get() & value; } + template data_event& operator |= (aType value) { return *this = get() | value; } + template data_event& operator ^= (aType value) { return *this = get() ^ value; } + + data_event& operator ++() + { + type value = get(); + return *this = ++value; + } + + type operator ++(int) + { + type value = get(); + type result = value; + *this = value++; + return result; + } + + data_event& operator --() + { + type value = get(); + return *this = --value; + } + + type operator --(int) + { + type value = get(); + type result = value; + *this = value--; + return result; + } +}; + +struct with_event_binder +{ + event_binder_t event_binder; +}; + +struct test_obj +{ + void test(int) + { + event i; + auto it = i.bind(this, &test_obj::test); + i(5); + i.unbind(it); + i(6); + } +}; diff --git a/rpcs3/CMakeLists.txt b/rpcs3/CMakeLists.txt index 30a99ecb0e..804cf49588 100644 --- a/rpcs3/CMakeLists.txt +++ b/rpcs3/CMakeLists.txt @@ -139,6 +139,7 @@ file( GLOB_RECURSE RPCS3_SRC "${RPCS3_SRC_DIR}/rpcs3.cpp" +"${RPCS3_SRC_DIR}/config.cpp" "${RPCS3_SRC_DIR}/Ini.cpp" "${RPCS3_SRC_DIR}/../Utilities/GNU.cpp" "${RPCS3_SRC_DIR}/Emu/*" diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 4604aa4903..51fd1cf814 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -8,6 +8,7 @@ #include #include "d3dx12.h" #include +#include "Emu/state.h" PFN_D3D12_CREATE_DEVICE wrapD3D12CreateDevice; PFN_D3D12_GET_DEBUG_INTERFACE wrapD3D12GetDebugInterface; @@ -299,12 +300,12 @@ bool D3D12GSRender::domethod(u32 cmd, u32 arg) clear_surface(arg); return true; case NV4097_TEXTURE_READ_SEMAPHORE_RELEASE: - semaphore_PGRAPH_texture_read_release(label_addr + rsx::method_registers[NV4097_SET_SEMAPHORE_OFFSET], arg); - return true; + semaphore_PGRAPH_texture_read_release(); + return false; //call rsx::thread method implementation case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE: - semaphore_PGRAPH_backend_release(label_addr + rsx::method_registers[NV4097_SET_SEMAPHORE_OFFSET], - (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff)); - return true;; + semaphore_PGRAPH_backend_release(); + return false; //call rsx::thread method implementation + default: return false; } @@ -897,12 +898,12 @@ void copyToCellRamAndRelease(void *dstAddress, ID3D12Resource *res, size_t dstPi res->Release(); } -void D3D12GSRender::semaphore_PGRAPH_texture_read_release(u32 offset, u32 value) +void D3D12GSRender::semaphore_PGRAPH_texture_read_release() { - semaphore_PGRAPH_backend_release(offset, value); + semaphore_PGRAPH_backend_release(); } -void D3D12GSRender::semaphore_PGRAPH_backend_release(u32 offset, u32 value) +void D3D12GSRender::semaphore_PGRAPH_backend_release() { // Add all buffer write // Cell can't make any assumption about readyness of color/depth buffer @@ -928,10 +929,10 @@ void D3D12GSRender::semaphore_PGRAPH_backend_release(u32 offset, u32 value) u32 m_context_dma_color_d = rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_D]; u32 m_context_dma_z = rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]; - bool needTransfer = (m_context_dma_z && Ini.GSDumpDepthBuffer.GetValue()) || - ((m_context_dma_color_a || m_context_dma_color_b || m_context_dma_color_c || m_context_dma_color_d) && Ini.GSDumpColorBuffers.GetValue()); + bool needTransfer = (m_context_dma_z && rpcs3::state.config.rsx.opengl.write_depth_buffer) || + ((m_context_dma_color_a || m_context_dma_color_b || m_context_dma_color_c || m_context_dma_color_d) && rpcs3::state.config.rsx.opengl.write_color_buffers); - if (m_context_dma_z && Ini.GSDumpDepthBuffer.GetValue()) + if (m_context_dma_z && rpcs3::state.config.rsx.opengl.write_depth_buffer) { size_t sizeInByte = clip_w * clip_h * 2; assert(m_UAVHeap.canAlloc(sizeInByte)); @@ -1016,7 +1017,7 @@ void D3D12GSRender::semaphore_PGRAPH_backend_release(u32 offset, u32 value) } ID3D12Resource *rtt0, *rtt1, *rtt2, *rtt3; - if (Ini.GSDumpColorBuffers.GetValue()) + if (rpcs3::state.config.rsx.opengl.write_color_buffers) { switch (rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]) { @@ -1067,7 +1068,7 @@ void D3D12GSRender::semaphore_PGRAPH_backend_release(u32 offset, u32 value) WaitForSingleObject(handle, INFINITE); CloseHandle(handle); - if (m_context_dma_z && Ini.GSDumpDepthBuffer.GetValue()) + if (m_context_dma_z && rpcs3::state.config.rsx.opengl.write_depth_buffer) { u32 address = rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], m_context_dma_z - 0xfeed0000); auto ptr = vm::get_ptr(address); @@ -1101,7 +1102,7 @@ void D3D12GSRender::semaphore_PGRAPH_backend_release(u32 offset, u32 value) break; } - if (Ini.GSDumpColorBuffers.GetValue()) + if (rpcs3::state.config.rsx.opengl.write_color_buffers) { switch (rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]) { @@ -1162,7 +1163,5 @@ void D3D12GSRender::semaphore_PGRAPH_backend_release(u32 offset, u32 value) break; } } - - vm::ps3::write32(offset, value); } #endif diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index 12957c1485..0d1018c419 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -456,8 +456,8 @@ public: D3D12GSRender(); virtual ~D3D12GSRender(); - void semaphore_PGRAPH_texture_read_release(u32 offset, u32 value); - void semaphore_PGRAPH_backend_release(u32 offset, u32 value); + void semaphore_PGRAPH_texture_read_release(); + void semaphore_PGRAPH_backend_release(); private: void InitD2DStructures(); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 2c9d4bb525..4c5928c4cc 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -6,6 +6,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "GLGSRender.h" +#include "Emu/state.h" #define DUMP_VERTEX_DATA 0 @@ -1161,23 +1162,11 @@ void nv4097_clear_surface(u32 arg, GLGSRender* renderer) renderer->draw_fbo.clear((gl::buffers)mask); } -static void nv4097_texture_read_semaphore_release(u32 arg, GLGSRender* render) -{ - vm::ps3::write32(render->label_addr + rsx::method_registers[NV4097_SET_SEMAPHORE_OFFSET], arg); -} - -static void nv4097_backend_write_semaphore_release(u32 arg, GLGSRender* render) -{ - vm::ps3::write32(render->label_addr + rsx::method_registers[NV4097_SET_SEMAPHORE_OFFSET], (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff)); -} - using rsx_method_impl_t = void(*)(u32, GLGSRender*); static const std::unordered_map g_gl_method_tbl = { - { NV4097_CLEAR_SURFACE, nv4097_clear_surface }, - { NV4097_TEXTURE_READ_SEMAPHORE_RELEASE, nv4097_texture_read_semaphore_release }, - { NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE, nv4097_backend_write_semaphore_release }, + { NV4097_CLEAR_SURFACE, nv4097_clear_surface } }; bool GLGSRender::domethod(u32 cmd, u32 arg) @@ -1536,7 +1525,7 @@ void GLGSRender::read_buffers() glDisable(GL_STENCIL_TEST); - if (Ini.GSReadColorBuffers.GetValue()) + if (rpcs3::state.config.rsx.opengl.read_color_buffers) { auto color_format = surface_color_format_to_gl(m_surface.color_format); @@ -1576,7 +1565,7 @@ void GLGSRender::read_buffers() } } - if (Ini.GSReadDepthBuffer.GetValue()) + if (rpcs3::state.config.rsx.opengl.read_depth_buffer) { auto depth_format = surface_depth_format_to_gl(m_surface.depth_format); @@ -1618,7 +1607,7 @@ void GLGSRender::write_buffers() if (!draw_fbo) return; - if (Ini.GSDumpColorBuffers.GetValue()) + if (rpcs3::state.config.rsx.opengl.write_color_buffers) { //gl::buffer pbo_color; //__glcheck pbo_color.create(m_draw_tex_color[0].width() * m_draw_tex_color[0].height() * 4); @@ -1678,7 +1667,7 @@ void GLGSRender::write_buffers() } } - if (Ini.GSDumpDepthBuffer.GetValue()) + if (rpcs3::state.config.rsx.opengl.write_depth_buffer) { auto depth_format = surface_depth_format_to_gl(m_surface.depth_format); @@ -1725,7 +1714,7 @@ void GLGSRender::flip(int buffer) u32 buffer_address = rsx::get_address(gcm_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL); bool skip_read = false; - if (draw_fbo && !Ini.GSDumpColorBuffers.GetValue()) + if (draw_fbo && !rpcs3::state.config.rsx.opengl.write_color_buffers) { skip_read = true; /* diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 3c0b143632..75d273f4ac 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -68,13 +68,14 @@ namespace rsx force_inline void texture_read_semaphore_release(thread* rsx, u32 arg) { //TODO: dma - rsx->domethod(NV4097_TEXTURE_READ_SEMAPHORE_RELEASE, arg); + vm::write32(rsx->label_addr + method_registers[NV4097_SET_SEMAPHORE_OFFSET], arg); } force_inline void back_end_write_semaphore_release(thread* rsx, u32 arg) { //TODO: dma - rsx->domethod(NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE, arg); + vm::write32(rsx->label_addr + method_registers[NV4097_SET_SEMAPHORE_OFFSET], + (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff)); } //fire only when all data passed to rsx cmd buffer @@ -104,54 +105,78 @@ namespace rsx } template - force_inline void set_vertex_data4ub_m(thread* rsx, u32 arg) + struct set_vertex_data4ub_m { - set_vertex_data_impl(rsx, arg); - } + force_inline static void impl(thread* rsx, u32 arg) + { + set_vertex_data_impl(rsx, arg); + } + }; template - force_inline void set_vertex_data1f_m(thread* rsx, u32 arg) + struct set_vertex_data1f_m { - set_vertex_data_impl(rsx, arg); - } + force_inline static void impl(thread* rsx, u32 arg) + { + set_vertex_data_impl(rsx, arg); + } + }; template - force_inline void set_vertex_data2f_m(thread* rsx, u32 arg) + struct set_vertex_data2f_m { - set_vertex_data_impl(rsx, arg); - } + force_inline static void impl(thread* rsx, u32 arg) + { + set_vertex_data_impl(rsx, arg); + } + }; template - force_inline void set_vertex_data3f_m(thread* rsx, u32 arg) + struct set_vertex_data3f_m { - set_vertex_data_impl(rsx, arg); - } + force_inline static void impl(thread* rsx, u32 arg) + { + set_vertex_data_impl(rsx, arg); + } + }; template - force_inline void set_vertex_data4f_m(thread* rsx, u32 arg) + struct set_vertex_data4f_m { - set_vertex_data_impl(rsx, arg); - } + force_inline static void impl(thread* rsx, u32 arg) + { + set_vertex_data_impl(rsx, arg); + } + }; template - force_inline void set_vertex_data2s_m(thread* rsx, u32 arg) + struct set_vertex_data2s_m { - set_vertex_data_impl(rsx, arg); - } + force_inline static void impl(thread* rsx, u32 arg) + { + set_vertex_data_impl(rsx, arg); + } + }; template - force_inline void set_vertex_data4s_m(thread* rsx, u32 arg) + struct set_vertex_data4s_m { - set_vertex_data_impl(rsx, arg); - } + force_inline static void impl(thread* rsx, u32 arg) + { + set_vertex_data_impl(rsx, arg); + } + }; template - force_inline void set_vertex_data_array_format(thread* rsx, u32 arg) + struct set_vertex_data_array_format { - auto& info = rsx->vertex_arrays_info[index]; - info.unpack(arg); - info.array = info.size > 0; - } + force_inline static void impl(thread* rsx, u32 arg) + { + auto& info = rsx->vertex_arrays_info[index]; + info.unpack(arg); + info.array = info.size > 0; + } + }; force_inline void draw_arrays(thread* rsx, u32 arg) { @@ -171,26 +196,32 @@ namespace rsx } template - force_inline void set_transform_constant(thread* rsxthr, u32 arg) + struct set_transform_constant { - u32& load = method_registers[NV4097_SET_TRANSFORM_CONSTANT_LOAD]; + force_inline static void impl(thread* rsxthr, u32 arg) + { + u32& load = method_registers[NV4097_SET_TRANSFORM_CONSTANT_LOAD]; - static const size_t count = 4; - static const size_t size = count * sizeof(f32); + static const size_t count = 4; + static const size_t size = count * sizeof(f32); - memcpy(rsxthr->transform_constants[load++].rgba, method_registers + NV4097_SET_TRANSFORM_CONSTANT + index * count, size); - } + memcpy(rsxthr->transform_constants[load++].rgba, method_registers + NV4097_SET_TRANSFORM_CONSTANT + index * count, size); + } + }; template - force_inline void set_transform_program(thread* rsx, u32 arg) + struct set_transform_program { - u32& load = method_registers[NV4097_SET_TRANSFORM_PROGRAM_LOAD]; + force_inline static void impl(thread* rsx, u32 arg) + { + u32& load = method_registers[NV4097_SET_TRANSFORM_PROGRAM_LOAD]; - static const size_t count = 4; - static const size_t size = count * sizeof(u32); + static const size_t count = 4; + static const size_t size = count * sizeof(u32); - memcpy(rsx->transform_program + load++ * count, method_registers + NV4097_SET_TRANSFORM_PROGRAM + index * count, size); - } + memcpy(rsx->transform_program + load++ * count, method_registers + NV4097_SET_TRANSFORM_PROGRAM + index * count, size); + } + }; force_inline void set_begin_end(thread* rsx, u32 arg) { @@ -290,20 +321,23 @@ namespace rsx namespace nv308a { template - force_inline void color(u32 arg) + struct color { - u32 point = method_registers[NV308A_POINT]; - u16 x = point; - u16 y = point >> 16; - - if (y) + force_inline static void impl(u32 arg) { - LOG_ERROR(RSX, "%s: y is not null (0x%x)", __FUNCTION__, y); - } + u32 point = method_registers[NV308A_POINT]; + u16 x = point; + u16 y = point >> 16; - u32 address = get_address(method_registers[NV3062_SET_OFFSET_DESTIN] + (x << 2) + index * 4, method_registers[NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN]); - vm::write32(address, arg); - } + if (y) + { + LOG_ERROR(RSX, "%s: y is not null (0x%x)", __FUNCTION__, y); + } + + u32 address = get_address(method_registers[NV3062_SET_OFFSET_DESTIN] + (x << 2) + index * 4, method_registers[NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN]); + vm::write32(address, arg); + } + }; } namespace nv3089 @@ -450,7 +484,7 @@ namespace rsx if (y >= 0 && y < std::min(method_registers[NV3089_CLIP_SIZE] >> 16, out_h)) { // source line - u8* src_line = pixels_src + y * out_bpp * out_w + + u8* src_line = pixels_src + y * out_bpp * out_w + std::min(std::max(method_registers[NV3089_CLIP_POINT] & 0xffff, 0), method_registers[NV3089_CLIP_SIZE] & 0xffff); size_t src_max = std::min( std::max((s32)(method_registers[NV3089_CLIP_SIZE] & 0xffff) - (method_registers[NV3089_CLIP_POINT] & 0xffff), 0), @@ -584,23 +618,30 @@ namespace rsx call_impl_func(rsx, arg); } - /* - template class T, T impl_func = nullptr, int limit = 0> - static void bind_impl() + template class T, int index = 0> + struct bind_range_impl_t { - bind>(); + force_inline static void impl() + { + bind_range_impl_t::impl(); + bind::impl>(); + } + }; - if (id + step < limit) - bind_impl(); + template class T> + struct bind_range_impl_t + { + force_inline static void impl() + { + } + }; + + template class T, int index = 0> + force_inline static void bind_range() + { + bind_range_impl_t::impl(); } - template class rsx_impl_method_t impl_func = nullptr> - static void bind() { bind_impl(); } - - template class rsx_method_t impl_func = nullptr> - static void bind() { bind_impl(); } - */ - template static void bind_impl() { @@ -631,42 +672,6 @@ namespace rsx //do not try process on gpu template static void bind_cpu_only() { bind_cpu_only_impl(); } -#define bind_2(index, offset, step, func) \ - bind>(); \ - bind>() - -#define bind_4(index, offset, step, func) \ - bind_2(index, offset, step, func); \ - bind_2(index + 2, offset + 2*step, step, func) - -#define bind_8(index, offset, step, func) \ - bind_4(index, offset, step, func); \ - bind_4(index + 4, offset + 4*step, step, func) - -#define bind_16(index, offset, step, func) \ - bind_8(index, offset, step, func); \ - bind_8(index + 8, offset + 8*step, step, func) - -#define bind_32(index, offset, step, func) \ - bind_16(index, offset, step, func); \ - bind_16(index + 16, offset + 16*step, step, func) - -#define bind_64(index, offset, step, func) \ - bind_32(index, offset, step, func); \ - bind_32(index + 32, offset + 32*step, step, func) - -#define bind_128(index, offset, step, func) \ - bind_64(index, offset, step, func); \ - bind_64(index + 64, offset + 64*step, step, func) - -#define bind_256(index, offset, step, func) \ - bind_128(index, offset, step, func); \ - bind_128(index + 128, offset + 128*step, step, func) - -#define bind_512(index, offset, step, func) \ - bind_256(index, offset, step, func); \ - bind_256(index + 256, offset + 256*step, step, func) - __rsx_methods_t() { // NV406E @@ -681,22 +686,21 @@ namespace rsx bind(); bind(); bind(); - //bind(); - bind_16(0, NV4097_SET_VERTEX_DATA_ARRAY_FORMAT, 1, nv4097::set_vertex_data_array_format); - bind_16(0, NV4097_SET_VERTEX_DATA4UB_M, 1, nv4097::set_vertex_data4ub_m); - bind_16(0, NV4097_SET_VERTEX_DATA1F_M, 1, nv4097::set_vertex_data1f_m); - bind_16(0, NV4097_SET_VERTEX_DATA2F_M + 1, 2, nv4097::set_vertex_data2f_m); - bind_16(0, NV4097_SET_VERTEX_DATA3F_M + 2, 3, nv4097::set_vertex_data3f_m); - bind_16(0, NV4097_SET_VERTEX_DATA4F_M + 3, 4, nv4097::set_vertex_data4f_m); - bind_16(0, NV4097_SET_VERTEX_DATA2S_M, 1, nv4097::set_vertex_data2s_m); - bind_16(0, NV4097_SET_VERTEX_DATA4S_M + 1, 2, nv4097::set_vertex_data4s_m); - bind_8(0, NV4097_SET_TRANSFORM_CONSTANT + 3, 4, nv4097::set_transform_constant); - bind_128(0, NV4097_SET_TRANSFORM_PROGRAM + 3, 4, nv4097::set_transform_program); + bind_range(); + bind_range(); + bind_range(); + bind_range(); + bind_range(); + bind_range(); + bind_range(); + bind_range(); + bind_range(); + bind_range(); bind_cpu_only(); bind_cpu_only(); //NV308A - bind_512(0, NV308A_COLOR, 1, nv308a::color); + bind_range(); //NV3089 bind(); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index dc7608d11c..92627a387d 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -1,4 +1,9 @@ #include "stdafx.h" + +#include "config.h" +#include "events.h" +#include "state.h" + #include "Utilities/Log.h" #include "Utilities/File.h" #include "rpcs3/Ini.h" @@ -61,6 +66,8 @@ Emulator::Emulator() void Emulator::Init() { + rpcs3::config.load(); + rpcs3::oninit(); } void Emulator::SetPath(const std::string& path, const std::string& elf_path) @@ -166,6 +173,9 @@ void Emulator::Load() } } + //TODO: load custom config if exists + rpcs3::state.config = rpcs3::config; + LOG_NOTICE(LOADER, "Loading '%s'...", m_path.c_str()); ResetInfo(); GetVFS().Init(elf_dir); @@ -213,14 +223,18 @@ void Emulator::Load() } LOG_NOTICE(LOADER, "Resolution: %s", Ini.ResolutionIdToString(Ini.GSResolution.GetValue())); - LOG_NOTICE(LOADER, "Write Depth Buffer: %s", Ini.GSDumpDepthBuffer.GetValue() ? "Yes" : "No"); + /*LOG_NOTICE(LOADER, "Write Depth Buffer: %s", Ini.GSDumpDepthBuffer.GetValue() ? "Yes" : "No"); LOG_NOTICE(LOADER, "Write Color Buffers: %s", Ini.GSDumpColorBuffers.GetValue() ? "Yes" : "No"); LOG_NOTICE(LOADER, "Read Color Buffers: %s", Ini.GSReadColorBuffers.GetValue() ? "Yes" : "No"); - LOG_NOTICE(LOADER, "Read Depth Buffer: %s", Ini.GSReadDepthBuffer.GetValue() ? "Yes" : "No"); + LOG_NOTICE(LOADER, "Read Depth Buffer: %s", Ini.GSReadDepthBuffer.GetValue() ? "Yes" : "No");*/ LOG_NOTICE(LOADER, "Audio Out: %s", Ini.AudioOutIdToString(Ini.AudioOutMode.GetValue())); LOG_NOTICE(LOADER, "Log Everything: %s", Ini.HLELogging.GetValue() ? "Yes" : "No"); LOG_NOTICE(LOADER, "RSX Logging: %s", Ini.RSXLogging.GetValue() ? "Yes" : "No"); + LOG_NOTICE(LOADER, ""); + + LOG_NOTICE(LOADER, rpcs3::config.to_string().c_str()); + LOG_NOTICE(LOADER, ""); f.Open("/app_home/../PARAM.SFO"); const PSFLoader psf(f); @@ -284,6 +298,8 @@ void Emulator::Run() return; } + rpcs3::onstart(); + SendDbgCommand(DID_START_EMU); m_pause_start_time = 0; @@ -304,6 +320,8 @@ bool Emulator::Pause() return false; } + rpcs3::onpause(); + // update pause start time if (m_pause_start_time.exchange(start)) { @@ -351,6 +369,8 @@ void Emulator::Resume() t->awake(); // untrigger status check and signal } + rpcs3::onstart(); + SendDbgCommand(DID_RESUMED_EMU); } @@ -365,6 +385,7 @@ void Emulator::Stop() return; } + rpcs3::onstop(); SendDbgCommand(DID_STOP_EMU); { diff --git a/rpcs3/Emu/events.cpp b/rpcs3/Emu/events.cpp new file mode 100644 index 0000000000..e02d4f56f4 --- /dev/null +++ b/rpcs3/Emu/events.cpp @@ -0,0 +1,10 @@ +#include "stdafx.h" +#include "events.h" + +namespace rpcs3 +{ + event oninit; + event onstart; + event onstop; + event onpause; +} \ No newline at end of file diff --git a/rpcs3/Emu/events.h b/rpcs3/Emu/events.h new file mode 100644 index 0000000000..0398698f52 --- /dev/null +++ b/rpcs3/Emu/events.h @@ -0,0 +1,10 @@ +#pragma once +#include "Utilities/event.h" + +namespace rpcs3 +{ + extern event oninit; + extern event onstart; + extern event onstop; + extern event onpause; +} \ No newline at end of file diff --git a/rpcs3/Emu/state.cpp b/rpcs3/Emu/state.cpp new file mode 100644 index 0000000000..f58020813a --- /dev/null +++ b/rpcs3/Emu/state.cpp @@ -0,0 +1,9 @@ +#include "stdafx.h" +#include "state.h" +#include +#include + +namespace rpcs3 +{ + state_t state; +} \ No newline at end of file diff --git a/rpcs3/Emu/state.h b/rpcs3/Emu/state.h new file mode 100644 index 0000000000..3abdbef957 --- /dev/null +++ b/rpcs3/Emu/state.h @@ -0,0 +1,15 @@ +#pragma once +#include "config.h" + +namespace rpcs3 +{ + struct state_t + { + config_t config; + + std::string path_to_elf; + std::string virtual_path_to_elf; + }; + + extern state_t state; +} \ No newline at end of file diff --git a/rpcs3/Gui/SettingsDialog.cpp b/rpcs3/Gui/SettingsDialog.cpp index a2c8f74aaf..0f39bfd2fe 100644 --- a/rpcs3/Gui/SettingsDialog.cpp +++ b/rpcs3/Gui/SettingsDialog.cpp @@ -7,6 +7,22 @@ #include "Utilities/Log.h" #include +#ifdef _WIN32 +#include +#include + +#pragma comment(lib, "iphlpapi.lib") +#else + +#include +#include +#include +#include +#include +#include +#include +#endif + #if defined(DX12_SUPPORT) #undef GetHwnd #include @@ -14,7 +30,66 @@ #include #endif -SettingsDialog::SettingsDialog(wxWindow *parent) +std::vector GetAdapters() +{ + std::vector adapters; +#ifdef _WIN32 + PIP_ADAPTER_INFO pAdapterInfo; + pAdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO)); + ULONG buflen = sizeof(IP_ADAPTER_INFO); + + if (GetAdaptersInfo(pAdapterInfo, &buflen) == ERROR_BUFFER_OVERFLOW) + { + free(pAdapterInfo); + pAdapterInfo = (IP_ADAPTER_INFO*)malloc(buflen); + } + + if (GetAdaptersInfo(pAdapterInfo, &buflen) == NO_ERROR) + { + PIP_ADAPTER_INFO pAdapter = pAdapterInfo; + while (pAdapter) + { + adapters.emplace_back(pAdapter->Description); + pAdapter = pAdapter->Next; + } + } + else + { + LOG_ERROR(HLE, "Call to GetAdaptersInfo failed."); + } +#else + struct ifaddrs *ifaddr, *ifa; + int family, s, n; + char host[NI_MAXHOST]; + + if (getifaddrs(&ifaddr) == -1) + { + LOG_ERROR(HLE, "Call to getifaddrs returned negative."); + } + + for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) + { + if (ifa->ifa_addr == NULL) + { + continue; + } + + family = ifa->ifa_addr->sa_family; + + if (family == AF_INET || family == AF_INET6) + { + adapters.emplace_back(ifa->ifa_name); + } + } + + freeifaddrs(ifaddr); +#endif + + return adapters; +} + + +SettingsDialog::SettingsDialog(wxWindow *parent, rpcs3::config_t* cfg) : wxDialog(parent, wxID_ANY, "Settings", wxDefaultPosition) { bool paused = false; @@ -203,6 +278,7 @@ SettingsDialog::SettingsDialog(wxWindow *parent) #if defined (_WIN32) cbox_pad_handler->Append("XInput"); #endif + //cbox_pad_handler->Append("DirectInput"); cbox_keyboard_handler->Append("Null"); @@ -255,10 +331,10 @@ SettingsDialog::SettingsDialog(wxWindow *parent) // Get values from .ini chbox_core_llvm_exclud->SetValue(Ini.LLVMExclusionRange.GetValue()); chbox_gs_log_prog->SetValue(Ini.GSLogPrograms.GetValue()); - chbox_gs_dump_depth->SetValue(Ini.GSDumpDepthBuffer.GetValue()); - chbox_gs_dump_color->SetValue(Ini.GSDumpColorBuffers.GetValue()); - chbox_gs_read_color->SetValue(Ini.GSReadColorBuffers.GetValue()); - chbox_gs_read_depth->SetValue(Ini.GSReadDepthBuffer.GetValue()); + chbox_gs_dump_depth->SetValue((bool)cfg->rsx.opengl.write_depth_buffer); + chbox_gs_dump_color->SetValue((bool)cfg->rsx.opengl.write_color_buffers); + chbox_gs_read_color->SetValue((bool)cfg->rsx.opengl.read_color_buffers); + chbox_gs_read_depth->SetValue((bool)cfg->rsx.opengl.read_depth_buffer); chbox_gs_vsync->SetValue(Ini.GSVSyncEnable.GetValue()); chbox_gs_debug_output->SetValue(Ini.GSDebugOutputEnable.GetValue()); chbox_gs_3dmonitor->SetValue(Ini.GS3DTV.GetValue()); @@ -438,10 +514,10 @@ SettingsDialog::SettingsDialog(wxWindow *parent) Ini.GSAspectRatio.SetValue(cbox_gs_aspect->GetSelection() + 1); Ini.GSFrameLimit.SetValue(cbox_gs_frame_limit->GetSelection()); Ini.GSLogPrograms.SetValue(chbox_gs_log_prog->GetValue()); - Ini.GSDumpDepthBuffer.SetValue(chbox_gs_dump_depth->GetValue()); - Ini.GSDumpColorBuffers.SetValue(chbox_gs_dump_color->GetValue()); - Ini.GSReadColorBuffers.SetValue(chbox_gs_read_color->GetValue()); - Ini.GSReadDepthBuffer.SetValue(chbox_gs_read_depth->GetValue()); + cfg->rsx.opengl.write_depth_buffer = chbox_gs_dump_depth->GetValue(); + cfg->rsx.opengl.write_color_buffers = chbox_gs_dump_color->GetValue(); + cfg->rsx.opengl.read_color_buffers = chbox_gs_read_color->GetValue(); + cfg->rsx.opengl.read_depth_buffer = chbox_gs_read_depth->GetValue(); Ini.GSVSyncEnable.SetValue(chbox_gs_vsync->GetValue()); Ini.GSDebugOutputEnable.SetValue(chbox_gs_debug_output->GetValue()); Ini.GS3DTV.SetValue(chbox_gs_3dmonitor->GetValue()); @@ -472,6 +548,7 @@ SettingsDialog::SettingsDialog(wxWindow *parent) Ini.SysEmulationDirPathEnable.SetValue(chbox_emulationdir_enable->GetValue()); Ini.SysEmulationDirPath.SetValue(txt_emulationdir_path->GetValue().ToStdString()); + cfg->save(); Ini.Save(); } diff --git a/rpcs3/Gui/SettingsDialog.h b/rpcs3/Gui/SettingsDialog.h index 8786a84850..21fcbfedd9 100644 --- a/rpcs3/Gui/SettingsDialog.h +++ b/rpcs3/Gui/SettingsDialog.h @@ -1,82 +1,11 @@ #pragma once -#include "Utilities/Log.h" +#include "config.h" -#ifdef _WIN32 -#include -#include - -#pragma comment(lib, "iphlpapi.lib") -#else - -#include -#include -#include -#include -#include -#include -#include -#endif +std::vector GetAdapters(); class SettingsDialog : public wxDialog { public: - SettingsDialog(wxWindow *parent); + SettingsDialog(wxWindow *parent, rpcs3::config_t* cfg = &rpcs3::config); }; -static std::vector GetAdapters() -{ - std::vector adapters; -#ifdef _WIN32 - PIP_ADAPTER_INFO pAdapterInfo; - pAdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO)); - ULONG buflen = sizeof(IP_ADAPTER_INFO); - - if (GetAdaptersInfo(pAdapterInfo, &buflen) == ERROR_BUFFER_OVERFLOW) - { - free(pAdapterInfo); - pAdapterInfo = (IP_ADAPTER_INFO*)malloc(buflen); - } - - if (GetAdaptersInfo(pAdapterInfo, &buflen) == NO_ERROR) - { - PIP_ADAPTER_INFO pAdapter = pAdapterInfo; - while (pAdapter) - { - adapters.emplace_back(pAdapter->Description); - pAdapter = pAdapter->Next; - } - } - else - { - LOG_ERROR(HLE, "Call to GetAdaptersInfo failed."); - } -#else - struct ifaddrs *ifaddr, *ifa; - int family, s, n; - char host[NI_MAXHOST]; - - if (getifaddrs(&ifaddr) == -1) - { - LOG_ERROR(HLE, "Call to getifaddrs returned negative."); - } - - for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) - { - if (ifa->ifa_addr == NULL) - { - continue; - } - - family = ifa->ifa_addr->sa_family; - - if (family == AF_INET || family == AF_INET6) - { - adapters.emplace_back(ifa->ifa_name); - } - } - - freeifaddrs(ifaddr); -#endif - - return adapters; -} diff --git a/rpcs3/Ini.h b/rpcs3/Ini.h index 197de5936d..139df08436 100644 --- a/rpcs3/Ini.h +++ b/rpcs3/Ini.h @@ -109,10 +109,6 @@ public: IniEntry GSAspectRatio; IniEntry GSFrameLimit; IniEntry GSLogPrograms; - IniEntry GSDumpColorBuffers; - IniEntry GSDumpDepthBuffer; - IniEntry GSReadColorBuffers; - IniEntry GSReadDepthBuffer; IniEntry GSVSyncEnable; IniEntry GS3DTV; IniEntry GSDebugOutputEnable; @@ -201,10 +197,6 @@ public: GSAspectRatio.Init("GS_AspectRatio", path); GSFrameLimit.Init("GS_FrameLimit", path); GSLogPrograms.Init("GS_LogPrograms", path); - GSDumpColorBuffers.Init("GS_DumpColorBuffers", path); - GSDumpDepthBuffer.Init("GS_DumpDepthBuffer", path); - GSReadColorBuffers.Init("GS_ReadColorBuffer", path); - GSReadDepthBuffer.Init("GS_ReadDepthBuffer", path); GSVSyncEnable.Init("GS_VSyncEnable", path); GSDebugOutputEnable.Init("GS_DebugOutputEnable", path); GS3DTV.Init("GS_3DTV", path); @@ -289,10 +281,6 @@ public: GSAspectRatio.Load(2); GSFrameLimit.Load(0); GSLogPrograms.Load(false); - GSDumpColorBuffers.Load(false); - GSDumpDepthBuffer.Load(false); - GSReadColorBuffers.Load(false); - GSReadDepthBuffer.Load(false); GSVSyncEnable.Load(false); GSDebugOutputEnable.Load(false); GS3DTV.Load(false); @@ -377,10 +365,6 @@ public: GSAspectRatio.Save(); GSFrameLimit.Save(); GSLogPrograms.Save(); - GSDumpColorBuffers.Save(); - GSDumpDepthBuffer.Save(); - GSReadColorBuffers.Save(); - GSReadDepthBuffer.Save(); GSVSyncEnable.Save(); GSDebugOutputEnable.Save(); GS3DTV.Save(); diff --git a/rpcs3/config.cpp b/rpcs3/config.cpp new file mode 100644 index 0000000000..cd38ad0e60 --- /dev/null +++ b/rpcs3/config.cpp @@ -0,0 +1,53 @@ +#include "stdafx.h" +#include "config.h" +#include + +namespace rpcs3 +{ + config_t::config_t(const std::string &path_) + { + path(path_); + } + config_t::config_t(const config_t& rhs) + { + assign(rhs); + } + + config_t& config_t::operator =(const config_t& rhs) + { + assign(rhs); + return *this; + } + + void config_t::path(const std::string &new_path) + { + m_path = new_path; + } + + std::string config_t::path() const + { + return m_path; + } + + void config_t::load() + { + if (!m_path.empty()) + { + std::ifstream stream{ m_path }; + if (stream) + deserialize(stream); + } + } + + void config_t::save() const + { + if (!m_path.empty()) + { + std::ofstream stream{ m_path }; + if (stream) + serialize(stream); + } + } + + config_t config{ "rpcs3.new.ini" }; +} \ No newline at end of file diff --git a/rpcs3/config.h b/rpcs3/config.h new file mode 100644 index 0000000000..9f14b95ac7 --- /dev/null +++ b/rpcs3/config.h @@ -0,0 +1,253 @@ +#pragma once +#include "Utilities/convert.h" +#include "Utilities/config_context.h" + +enum class audio_output_type +{ + Null, + OpenAL, + XAudio2 +}; + +namespace convert +{ + template<> + struct to_impl_t + { + static std::string func(audio_output_type value) + { + switch (value) + { + case audio_output_type::Null: return "Null"; + case audio_output_type::OpenAL: return "OpenAL"; + case audio_output_type::XAudio2: return "XAudio2"; + } + + return "Unknown"; + } + }; + + template<> + struct to_impl_t + { + static audio_output_type func(const std::string &value) + { + if (value == "Null") + return audio_output_type::Null; + + if (value == "OpenAL") + return audio_output_type::OpenAL; + + if (value == "XAudio2") + return audio_output_type::XAudio2; + + return audio_output_type::Null; + } + }; +} + +enum class rsx_renderer_type +{ + Null, + OpenGL, + DX12 +}; + +namespace convert +{ + template<> + struct to_impl_t + { + static std::string func(rsx_renderer_type value) + { + switch (value) + { + case rsx_renderer_type::Null: return "Null"; + case rsx_renderer_type::OpenGL: return "OpenGL"; + case rsx_renderer_type::DX12: return "DX12"; + } + + return "Unknown"; + } + }; + + template<> + struct to_impl_t + { + static rsx_renderer_type func(const std::string &value) + { + if (value == "Null") + return rsx_renderer_type::Null; + + if (value == "OpenGL") + return rsx_renderer_type::OpenGL; + + if (value == "DX12") + return rsx_renderer_type::DX12; + + return rsx_renderer_type::Null; + } + }; +} + +enum class ppu_decoder_type +{ + interpreter, + interpreter2, + recompiler_llvm +}; + +namespace convert +{ + template<> + struct to_impl_t + { + static std::string func(ppu_decoder_type value) + { + switch (value) + { + case ppu_decoder_type::interpreter: return "interpreter"; + case ppu_decoder_type::interpreter2: return "interpreter2"; + case ppu_decoder_type::recompiler_llvm: return "recompiler_llvm"; + } + + return "Unknown"; + } + }; + + template<> + struct to_impl_t + { + static ppu_decoder_type func(const std::string &value) + { + if (value == "interpreter") + return ppu_decoder_type::interpreter; + + if (value == "interpreter2") + return ppu_decoder_type::interpreter2; + + if (value == "DX12") + return ppu_decoder_type::recompiler_llvm; + + return ppu_decoder_type::interpreter; + } + }; +} + + +enum class spu_decoder_type +{ + interpreter_precise, + interpreter_fast, + recompiler_asmjit +}; + +namespace convert +{ + template<> + struct to_impl_t + { + static std::string func(spu_decoder_type value) + { + switch (value) + { + case spu_decoder_type::interpreter_precise: return "interpreter_precise"; + case spu_decoder_type::interpreter_fast: return "interpreter_fast"; + case spu_decoder_type::recompiler_asmjit: return "recompiler_asmjit"; + } + + return "Unknown"; + } + }; + + template<> + struct to_impl_t + { + static spu_decoder_type func(const std::string &value) + { + if (value == "interpreter_precise") + return spu_decoder_type::interpreter_precise; + + if (value == "interpreter_fast") + return spu_decoder_type::interpreter_fast; + + if (value == "recompiler_asmjit") + return spu_decoder_type::recompiler_asmjit; + + return spu_decoder_type::interpreter_precise; + } + }; +} + +namespace rpcs3 +{ + class config_t : public config_context_t + { + std::string m_path; + + public: + struct core_group : protected group + { + core_group(config_context_t *cfg) : group{ cfg, "core" } {} + + entry ppu_decoder{ this, "PPU Decoder", ppu_decoder_type::interpreter }; + entry spu_decoder{ this, "SPU Decoder", spu_decoder_type::interpreter_precise }; + entry load_liblv2{ this, "Load liblv2.sprx", false }; + } core{ this }; + + struct rsx_group : protected group + { + struct opengl_group : protected group + { + opengl_group(group *grp) : group{ grp, "opengl" } {} + + entry write_color_buffers{ this, "Write Color Buffers", true }; + entry write_depth_buffer{ this, "Write Depth Buffer", true }; + entry read_color_buffers{ this, "Read Color Buffers", true }; + entry read_depth_buffer{ this, "Read Depth Buffer", true }; + } opengl{ this }; + + rsx_group(config_context_t *cfg) : group{ cfg, "rsx" } {} + + entry renderer{ this, "Renderer", rsx_renderer_type::OpenGL }; + } rsx{ this }; + + struct audio_group : protected group + { + audio_group(config_context_t *cfg) : group{ cfg, "audio" } {} + + entry test{ this, "Audio Out", audio_output_type::OpenAL }; + } audio{ this }; + + struct io_group : protected group + { + io_group(config_context_t *cfg) : group{ cfg, "io" } {} + } io{ this }; + + struct misc_group : protected group + { + misc_group(config_context_t *cfg) : group{ cfg, "misc" } {} + } misc{ this }; + + struct system_group : protected group + { + system_group(config_context_t *cfg) : group{ cfg, "system" } {} + } system{ this }; + + config_t() = default; + config_t(const std::string &path); + config_t(const config_t& rhs); + config_t(config_t&& rhs) = delete; + + config_t& operator =(const config_t& rhs); + config_t& operator =(config_t&& rhs) = delete; + + void path(const std::string &new_path); + std::string path() const; + + void load(); + void save() const; + }; + + extern config_t config; +} \ No newline at end of file diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 9363293a30..f46a79b26c 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -40,6 +40,7 @@ + @@ -52,11 +53,13 @@ + + @@ -78,6 +81,7 @@ + @@ -379,6 +383,9 @@ + + + @@ -397,6 +404,7 @@ + @@ -508,6 +516,7 @@ + @@ -572,6 +581,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index e75f69456f..e0576323cf 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1001,6 +1001,16 @@ Emu\GPU\RSX\GL + + Utilities + + + + Emu + + + Emu + @@ -1906,5 +1916,21 @@ Emu\GPU\RSX\GL + + Utilities + + + Utilities + + + Utilities + + + + Emu + + + Emu + \ No newline at end of file