Merge pull request #1252 from DHrpcs3/master

Implemented new config system. Minor improvements
This commit is contained in:
DHrpcs3 2015-10-13 23:09:22 +03:00
commit d8d09b5472
23 changed files with 1584 additions and 250 deletions

View File

@ -208,6 +208,16 @@ std::vector<std::string> 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);

View File

@ -300,6 +300,7 @@ namespace fmt
std::vector<std::string> rSplit(const std::string& source, const std::string& delim);
std::vector<std::string> split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty = true);
std::string trim(const std::string& source, const std::string& values = " \t");
template<typename T>
std::string merge(const T& source, const std::string& separator)

View File

@ -0,0 +1,145 @@
#include "stdafx.h"
#include "config_context.h"
#include "StrFmt.h"
#include <iostream>
#include <sstream>
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();
}

128
Utilities/config_context.h Normal file
View File

@ -0,0 +1,128 @@
#pragma once
#include <unordered_map>
#include <string>
#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<std::string, entry_base *> 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<typename T>
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<std::string>(value());
}
void string_value(const std::string &new_value) override
{
value(convert::to<T>(new_value));
}
void value_from(const entry_base* rhs)
{
value(static_cast<const entry*>(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<std::string, group*> 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;
};

240
Utilities/convert.h Normal file
View File

@ -0,0 +1,240 @@
#pragma once
#include <string>
namespace convert
{
template<typename ReturnType, typename FromType>
struct to_impl_t;
template<typename Type>
struct to_impl_t<Type, Type>
{
static Type func(const Type& value)
{
return value;
}
};
template<>
struct to_impl_t<std::string, bool>
{
static std::string func(bool value)
{
return value ? "true" : "false";
}
};
template<>
struct to_impl_t<bool, std::string>
{
static bool func(const std::string& value)
{
return value == "true" ? true : false;
}
};
template<>
struct to_impl_t<std::string, char>
{
static std::string func(char value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, unsigned char>
{
static std::string func(unsigned char value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, short>
{
static std::string func(short value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, unsigned short>
{
static std::string func(unsigned short value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, int>
{
static std::string func(int value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, unsigned int>
{
static std::string func(unsigned int value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, long>
{
static std::string func(long value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, unsigned long>
{
static std::string func(unsigned long value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, long long>
{
static std::string func(long long value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, unsigned long long>
{
static std::string func(unsigned long long value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, float>
{
static std::string func(float value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, double>
{
static std::string func(double value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<std::string, long double>
{
static std::string func(long double value)
{
return std::to_string(value);
}
};
template<>
struct to_impl_t<int, std::string>
{
static int func(const std::string& value)
{
return std::stoi(value);
}
};
template<>
struct to_impl_t<unsigned int, std::string>
{
static unsigned int func(const std::string& value)
{
return (unsigned long)std::stoul(value);
}
};
template<>
struct to_impl_t<long, std::string>
{
static long func(const std::string& value)
{
return std::stol(value);
}
};
template<>
struct to_impl_t<unsigned long, std::string>
{
static unsigned long func(const std::string& value)
{
return std::stoul(value);
}
};
template<>
struct to_impl_t<long long, std::string>
{
static long long func(const std::string& value)
{
return std::stoll(value);
}
};
template<>
struct to_impl_t<unsigned long long, std::string>
{
static unsigned long long func(const std::string& value)
{
return std::stoull(value);
}
};
template<>
struct to_impl_t<float, std::string>
{
static float func(const std::string& value)
{
return std::stof(value);
}
};
template<>
struct to_impl_t<double, std::string>
{
static double func(const std::string& value)
{
return std::stod(value);
}
};
template<>
struct to_impl_t<long double, std::string>
{
static long double func(const std::string& value)
{
return std::stold(value);
}
};
template<typename ReturnType, typename FromType>
ReturnType to(FromType value)
{
return to_impl_t<std::remove_all_extents_t<ReturnType>, std::remove_all_extents_t<FromType>>::func(value);
}
}

420
Utilities/event.h Normal file
View File

@ -0,0 +1,420 @@
#pragma once
#include <functional>
#include <deque>
#include <list>
enum class event_result
{
skip,
handled
};
class events_queue
{
std::deque<std::function<void()>> m_queue;
public:
/*template<typename Type>
events_queue& operator += (event<Type> &evt)
{
evt.set_queue(this);
return *this;
}
*/
void invoke(std::function<void()> function)
{
m_queue.push_back(function);
}
void flush()
{
while (!m_queue.empty())
{
std::function<void()> function = m_queue.front();
function();
m_queue.pop_front();
}
}
};
template<typename ...AT>
class event
{
using func_t = std::function<event_result(AT...)>;
using entry_t = typename std::list<func_t>::iterator;
std::list<func_t> 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<typename T>
entry_t bind(T *caller, event_result(T::*callback)(AT...))
{
return bind([=](AT... args) { return (caller->*callback)(args...); });
}
template<typename T>
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<void>
{
using func_t = std::function<event_result()>;
using entry_t = std::list<func_t>::iterator;
std::list<func_t> 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<typename T>
entry_t bind(T *caller, event_result(T::*callback)())
{
return bind([=]() { return (caller->*callback)(); });
}
template<typename T>
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<typename Type>
class binder_impl_t
{
event_binder_t *m_binder;
event<Type> *m_event;
public:
binder_impl_t(event_binder_t *binder, event<Type> *evt)
: m_binder(binder)
, m_event(evt)
{
}
};
public:
template<typename Type>
binder_impl_t<Type> operator()(event<Type>& evt) const
{
return{ this, &evt };
}
};
template<typename T>
class combined_data;
template<typename T>
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<T>;
};
template<typename T>
class combined_data
{
public:
using type = T;
protected:
local_data<type> m_local_data;
std::function<void(type)> m_invoke_event_function;
std::function<type()> 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<void(type)> function)
{
m_invoke_event_function = function;
}
void get_function(std::function<type()> function)
{
m_get_function = function;
}
};
template<typename T, typename base_type_ = local_data<T>>
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<type> onchange;
event<type> 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<typename aType> auto operator + (aType value) const { return get() + value; }
template<typename aType> auto operator - (aType value) const { return get() - value; }
template<typename aType> auto operator * (aType value) const { return get() * value; }
template<typename aType> auto operator / (aType value) const { return get() / value; }
template<typename aType> auto operator % (aType value) const { return get() % value; }
template<typename aType> auto operator & (aType value) const { return get() & value; }
template<typename aType> auto operator | (aType value) const { return get() | value; }
template<typename aType> auto operator ^ (aType value) const { return get() ^ value; }
template<typename aType> data_event& operator += (aType value) { return *this = get() + value; }
template<typename aType> data_event& operator -= (aType value) { return *this = get() - value; }
template<typename aType> data_event& operator *= (aType value) { return *this = get() * value; }
template<typename aType> data_event& operator /= (aType value) { return *this = get() / value; }
template<typename aType> data_event& operator %= (aType value) { return *this = get() % value; }
template<typename aType> data_event& operator &= (aType value) { return *this = get() & value; }
template<typename aType> data_event& operator |= (aType value) { return *this = get() | value; }
template<typename aType> 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<int> i;
auto it = i.bind(this, &test_obj::test);
i(5);
i.unbind(it);
i(6);
}
};

View File

@ -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/*"

View File

@ -8,6 +8,7 @@
#include <chrono>
#include "d3dx12.h"
#include <d3d11on12.h>
#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<void>(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

View File

@ -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();

View File

@ -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<u32, rsx_method_impl_t> 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;
/*

View File

@ -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<u32 index>
force_inline void set_vertex_data4ub_m(thread* rsx, u32 arg)
struct set_vertex_data4ub_m
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA4UB_M, index, 4, u8>(rsx, arg);
}
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA4UB_M, index, 4, u8>(rsx, arg);
}
};
template<u32 index>
force_inline void set_vertex_data1f_m(thread* rsx, u32 arg)
struct set_vertex_data1f_m
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA1F_M, index, 1, f32>(rsx, arg);
}
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA1F_M, index, 1, f32>(rsx, arg);
}
};
template<u32 index>
force_inline void set_vertex_data2f_m(thread* rsx, u32 arg)
struct set_vertex_data2f_m
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA2F_M, index, 2, f32>(rsx, arg);
}
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA2F_M, index, 2, f32>(rsx, arg);
}
};
template<u32 index>
force_inline void set_vertex_data3f_m(thread* rsx, u32 arg)
struct set_vertex_data3f_m
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA3F_M, index, 3, f32>(rsx, arg);
}
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA3F_M, index, 3, f32>(rsx, arg);
}
};
template<u32 index>
force_inline void set_vertex_data4f_m(thread* rsx, u32 arg)
struct set_vertex_data4f_m
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA4F_M, index, 4, f32>(rsx, arg);
}
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA4F_M, index, 4, f32>(rsx, arg);
}
};
template<u32 index>
force_inline void set_vertex_data2s_m(thread* rsx, u32 arg)
struct set_vertex_data2s_m
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA2S_M, index, 2, u16>(rsx, arg);
}
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA2S_M, index, 2, u16>(rsx, arg);
}
};
template<u32 index>
force_inline void set_vertex_data4s_m(thread* rsx, u32 arg)
struct set_vertex_data4s_m
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA4S_M, index, 4, u16>(rsx, arg);
}
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA4S_M, index, 4, u16>(rsx, arg);
}
};
template<u32 index>
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<u32 index>
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<u32 index>
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<u32 index>
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<s32>(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<s32>(std::max<s32>(method_registers[NV3089_CLIP_POINT] & 0xffff, 0), method_registers[NV3089_CLIP_SIZE] & 0xffff);
size_t src_max = std::min<s32>(
std::max<s32>((s32)(method_registers[NV3089_CLIP_SIZE] & 0xffff) - (method_registers[NV3089_CLIP_POINT] & 0xffff), 0),
@ -584,23 +618,30 @@ namespace rsx
call_impl_func<impl_func>(rsx, arg);
}
/*
template<int id, int step, template<u32> class T, T impl_func = nullptr, int limit = 0>
static void bind_impl()
template<int id, int step, int count, template<u32> class T, int index = 0>
struct bind_range_impl_t
{
bind<id, impl_func<id>>();
force_inline static void impl()
{
bind_range_impl_t<id + step, step, count, T, index + 1>::impl();
bind<id, T<index>::impl>();
}
};
if (id + step < limit)
bind_impl<id + step, step, T, impl_func, limit>();
template<int id, int step, int count, template<u32> class T>
struct bind_range_impl_t<id, step, count, T, count>
{
force_inline static void impl()
{
}
};
template<int id, int step, int count, template<u32> class T, int index = 0>
force_inline static void bind_range()
{
bind_range_impl_t<id, step, count, T, index>::impl();
}
template<int id, int step, int count, template<u32> class rsx_impl_method_t impl_func = nullptr>
static void bind() { bind_impl<id, step, rsx_impl_method_t, impl_func, id + step * count>(); }
template<int id, int step, int count, template<u32> class rsx_method_t impl_func = nullptr>
static void bind() { bind_impl<id, step, rsx_method_t, impl_func, id + step * count>(); }
*/
template<int id, typename T, T impl_func>
static void bind_impl()
{
@ -631,42 +672,6 @@ namespace rsx
//do not try process on gpu
template<int id, rsx_method_t impl_func = nullptr> static void bind_cpu_only() { bind_cpu_only_impl<id, rsx_method_t, impl_func>(); }
#define bind_2(index, offset, step, func) \
bind<offset, func<index>>(); \
bind<offset + step, func<index + 1>>()
#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<NV4097_CLEAR_SURFACE>();
bind<NV4097_DRAW_ARRAYS, nv4097::draw_arrays>();
bind<NV4097_DRAW_INDEX_ARRAY, nv4097::draw_index_array>();
//bind<NV4097_SET_VERTEX_DATA4UB_M, 1, 16, nv4097::set_vertex_data4ub_m>();
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<NV4097_SET_VERTEX_DATA_ARRAY_FORMAT, 1, 16, nv4097::set_vertex_data_array_format>();
bind_range<NV4097_SET_VERTEX_DATA4UB_M, 1, 16, nv4097::set_vertex_data4ub_m>();
bind_range<NV4097_SET_VERTEX_DATA1F_M, 1, 16, nv4097::set_vertex_data1f_m>();
bind_range<NV4097_SET_VERTEX_DATA2F_M + 1, 2, 16, nv4097::set_vertex_data2f_m>();
bind_range<NV4097_SET_VERTEX_DATA3F_M + 2, 3, 16, nv4097::set_vertex_data3f_m>();
bind_range<NV4097_SET_VERTEX_DATA4F_M + 3, 4, 16, nv4097::set_vertex_data4f_m>();
bind_range<NV4097_SET_VERTEX_DATA2S_M, 1, 16, nv4097::set_vertex_data2s_m>();
bind_range<NV4097_SET_VERTEX_DATA4S_M + 1, 2, 16, nv4097::set_vertex_data4s_m>();
bind_range<NV4097_SET_TRANSFORM_CONSTANT + 3, 4, 8, nv4097::set_transform_constant>();
bind_range<NV4097_SET_TRANSFORM_PROGRAM + 3, 4, 128, nv4097::set_transform_program>();
bind_cpu_only<NV4097_GET_REPORT, nv4097::get_report>();
bind_cpu_only<NV4097_CLEAR_REPORT_VALUE, nv4097::clear_report_value>();
//NV308A
bind_512(0, NV308A_COLOR, 1, nv308a::color);
bind_range<NV308A_COLOR, 1, 512, nv308a::color>();
//NV3089
bind<NV3089_IMAGE_IN, nv3089::image_in>();

View File

@ -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);
{

10
rpcs3/Emu/events.cpp Normal file
View File

@ -0,0 +1,10 @@
#include "stdafx.h"
#include "events.h"
namespace rpcs3
{
event<void> oninit;
event<void> onstart;
event<void> onstop;
event<void> onpause;
}

10
rpcs3/Emu/events.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "Utilities/event.h"
namespace rpcs3
{
extern event<void> oninit;
extern event<void> onstart;
extern event<void> onstop;
extern event<void> onpause;
}

9
rpcs3/Emu/state.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "stdafx.h"
#include "state.h"
#include <sstream>
#include <type_traits>
namespace rpcs3
{
state_t state;
}

15
rpcs3/Emu/state.h Normal file
View File

@ -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;
}

View File

@ -7,6 +7,22 @@
#include "Utilities/Log.h"
#include <wx/radiobox.h>
#ifdef _WIN32
#include <windows.h>
#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")
#else
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#endif
#if defined(DX12_SUPPORT)
#undef GetHwnd
#include <d3d12.h>
@ -14,7 +30,66 @@
#include <dxgi1_4.h>
#endif
SettingsDialog::SettingsDialog(wxWindow *parent)
std::vector<std::string> GetAdapters()
{
std::vector<std::string> 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();
}

View File

@ -1,82 +1,11 @@
#pragma once
#include "Utilities/Log.h"
#include "config.h"
#ifdef _WIN32
#include <windows.h>
#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")
#else
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#endif
std::vector<std::string> GetAdapters();
class SettingsDialog : public wxDialog
{
public:
SettingsDialog(wxWindow *parent);
SettingsDialog(wxWindow *parent, rpcs3::config_t* cfg = &rpcs3::config);
};
static std::vector<std::string> GetAdapters()
{
std::vector<std::string> 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;
}

View File

@ -109,10 +109,6 @@ public:
IniEntry<u8> GSAspectRatio;
IniEntry<u8> GSFrameLimit;
IniEntry<bool> GSLogPrograms;
IniEntry<bool> GSDumpColorBuffers;
IniEntry<bool> GSDumpDepthBuffer;
IniEntry<bool> GSReadColorBuffers;
IniEntry<bool> GSReadDepthBuffer;
IniEntry<bool> GSVSyncEnable;
IniEntry<bool> GS3DTV;
IniEntry<bool> 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();

53
rpcs3/config.cpp Normal file
View File

@ -0,0 +1,53 @@
#include "stdafx.h"
#include "config.h"
#include <fstream>
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" };
}

253
rpcs3/config.h Normal file
View File

@ -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<std::string, audio_output_type>
{
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<audio_output_type, std::string>
{
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<std::string, rsx_renderer_type>
{
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<rsx_renderer_type, std::string>
{
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<std::string, ppu_decoder_type>
{
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<ppu_decoder_type, std::string>
{
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<std::string, spu_decoder_type>
{
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<spu_decoder_type, std::string>
{
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_type> ppu_decoder{ this, "PPU Decoder", ppu_decoder_type::interpreter };
entry<spu_decoder_type> spu_decoder{ this, "SPU Decoder", spu_decoder_type::interpreter_precise };
entry<bool> 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<bool> write_color_buffers{ this, "Write Color Buffers", true };
entry<bool> write_depth_buffer{ this, "Write Depth Buffer", true };
entry<bool> read_color_buffers{ this, "Read Color Buffers", true };
entry<bool> read_depth_buffer{ this, "Read Depth Buffer", true };
} opengl{ this };
rsx_group(config_context_t *cfg) : group{ cfg, "rsx" } {}
entry<rsx_renderer_type> renderer{ this, "Renderer", rsx_renderer_type::OpenGL };
} rsx{ this };
struct audio_group : protected group
{
audio_group(config_context_t *cfg) : group{ cfg, "audio" } {}
entry<audio_output_type> 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;
}

View File

@ -40,6 +40,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\Utilities\AutoPause.cpp" />
<ClCompile Include="..\Utilities\config_context.cpp" />
<ClCompile Include="..\Utilities\Log.cpp" />
<ClCompile Include="..\Utilities\File.cpp" />
<ClCompile Include="..\Utilities\rMsgBox.cpp" />
@ -52,11 +53,13 @@
<ClCompile Include="..\Utilities\StrFmt.cpp" />
<ClCompile Include="..\Utilities\Thread.cpp" />
<ClCompile Include="..\Utilities\VirtualMemory.cpp" />
<ClCompile Include="config.cpp" />
<ClCompile Include="Emu\Cell\PPUInterpreter.cpp" />
<ClCompile Include="Emu\Cell\PPULLVMRecompilerCore.cpp" />
<ClCompile Include="Emu\Cell\SPUAnalyser.cpp" />
<ClCompile Include="Emu\Cell\SPUASMJITRecompiler.cpp" />
<ClCompile Include="Emu\Cell\SPUInterpreter.cpp" />
<ClCompile Include="Emu\events.cpp" />
<ClCompile Include="Emu\IdManager.cpp" />
<ClCompile Include="Emu\RSX\CgBinaryFragmentProgram.cpp" />
<ClCompile Include="Emu\RSX\CgBinaryVertexProgram.cpp" />
@ -78,6 +81,7 @@
<ClCompile Include="Emu\RSX\GL\GLCommonDecompiler.cpp" />
<ClCompile Include="Emu\RSX\GL\gl_helpers.cpp" />
<ClCompile Include="Emu\RSX\Null\NullGSRender.cpp" />
<ClCompile Include="Emu\state.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\sys_dbg.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\sys_fs.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\cellAtracMulti.cpp" />
@ -379,6 +383,9 @@
<ClInclude Include="..\Utilities\Atomic.h" />
<ClInclude Include="..\Utilities\AutoPause.h" />
<ClInclude Include="..\Utilities\BEType.h" />
<ClInclude Include="..\Utilities\config_context.h" />
<ClInclude Include="..\Utilities\convert.h" />
<ClInclude Include="..\Utilities\event.h" />
<ClInclude Include="..\Utilities\GNU.h" />
<ClInclude Include="..\Utilities\MTRingbuffer.h" />
<ClInclude Include="..\Utilities\Log.h" />
@ -397,6 +404,7 @@
<ClInclude Include="..\Utilities\Timer.h" />
<ClInclude Include="..\Utilities\types.h" />
<ClInclude Include="..\Utilities\VirtualMemory.h" />
<ClInclude Include="config.h" />
<ClInclude Include="Crypto\aes.h" />
<ClInclude Include="Crypto\ec.h" />
<ClInclude Include="Crypto\key_vault.h" />
@ -508,6 +516,7 @@
<ClInclude Include="Emu\CPU\CPUThreadManager.h" />
<ClInclude Include="Emu\DbgCommand.h" />
<ClInclude Include="Emu\Event.h" />
<ClInclude Include="Emu\events.h" />
<ClInclude Include="Emu\FS\VFS.h" />
<ClInclude Include="Emu\FS\vfsDevice.h" />
<ClInclude Include="Emu\FS\vfsDeviceLocalFile.h" />
@ -572,6 +581,7 @@
<ClInclude Include="Emu\Memory\vm_ptr.h" />
<ClInclude Include="Emu\Memory\vm_ref.h" />
<ClInclude Include="Emu\Memory\vm_var.h" />
<ClInclude Include="Emu\state.h" />
<ClInclude Include="Emu\SysCalls\Callback.h" />
<ClInclude Include="Emu\SysCalls\CB_FUNC.h" />
<ClInclude Include="Emu\SysCalls\ErrorCodes.h" />

View File

@ -1001,6 +1001,16 @@
<ClCompile Include="Emu\RSX\GL\gl_helpers.cpp">
<Filter>Emu\GPU\RSX\GL</Filter>
</ClCompile>
<ClCompile Include="..\Utilities\config_context.cpp">
<Filter>Utilities</Filter>
</ClCompile>
<ClCompile Include="config.cpp" />
<ClCompile Include="Emu\events.cpp">
<Filter>Emu</Filter>
</ClCompile>
<ClCompile Include="Emu\state.cpp">
<Filter>Emu</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Crypto\aes.h">
@ -1906,5 +1916,21 @@
<ClInclude Include="Emu\RSX\GL\gl_helpers.h">
<Filter>Emu\GPU\RSX\GL</Filter>
</ClInclude>
<ClInclude Include="..\Utilities\config_context.h">
<Filter>Utilities</Filter>
</ClInclude>
<ClInclude Include="..\Utilities\convert.h">
<Filter>Utilities</Filter>
</ClInclude>
<ClInclude Include="..\Utilities\event.h">
<Filter>Utilities</Filter>
</ClInclude>
<ClInclude Include="config.h" />
<ClInclude Include="Emu\events.h">
<Filter>Emu</Filter>
</ClInclude>
<ClInclude Include="Emu\state.h">
<Filter>Emu</Filter>
</ClInclude>
</ItemGroup>
</Project>