Improved GS Renderer.

This commit is contained in:
DH 2013-11-09 23:29:49 +02:00
parent 6ea2c7d6a8
commit 521244b0e0
28 changed files with 2568 additions and 2702 deletions

View File

@ -1,4 +1,5 @@
#pragma once
#include "rpcs3.h"
enum
{
@ -39,6 +40,104 @@ struct gcmInfo
u32 control_addr;
};
struct CellGcmSurface
{
u8 type;
u8 antialias;
u8 color_format;
u8 color_target;
u8 color_location[4];
u32 color_offset[4];
u32 color_pitch[4];
u8 depth_format;
u8 depth_location;
u16 pad;
u32 depth_offset;
u32 depth_pitch;
u16 width;
u16 height;
u16 x;
u16 y;
};
struct CellGcmReportData
{
u64 timer;
u32 value;
u32 pad;
};
struct CellGcmZcullInfo
{
u32 region;
u32 size;
u32 start;
u32 offset;
u32 status0;
u32 status1;
};
struct CellGcmTileInfo
{
u32 tile;
u32 limit;
u32 pitch;
u32 format;
};
struct GcmZcullInfo
{
u32 m_offset;
u32 m_width;
u32 m_height;
u32 m_cullStart;
u32 m_zFormat;
u32 m_aaFormat;
u32 m_zCullDir;
u32 m_zCullFormat;
u32 m_sFunc;
u32 m_sRef;
u32 m_sMask;
bool m_binded;
GcmZcullInfo()
{
memset(this, 0, sizeof(*this));
}
};
struct GcmTileInfo
{
u8 m_location;
u32 m_offset;
u32 m_size;
u32 m_pitch;
u8 m_comp;
u16 m_base;
u8 m_bank;
bool m_binded;
GcmTileInfo()
{
memset(this, 0, sizeof(*this));
}
CellGcmTileInfo Pack()
{
CellGcmTileInfo ret;
re(ret.tile, (m_location + 1) | (m_bank << 4) | ((m_offset / 0x10000) << 16) | (m_location << 31));
re(ret.limit, ((m_offset + m_size - 1) / 0x10000) << 16 | (m_location << 31));
re(ret.pitch, (m_pitch / 0x100) << 8);
re(ret.format, m_base | ((m_base + ((m_size - 1) / 0x10000)) << 13) | (m_comp << 26) | (1 << 30));
return ret;
}
};
enum
{
CELL_GCM_LOCATION_LOCAL,

View File

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "FragmentProgram.h"
#include "GLFragmentProgram.h"
void FragmentDecompilerThread::AddCode(wxString code, bool append_mask)
void GLFragmentDecompilerThread::AddCode(wxString code, bool append_mask)
{
if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) return;
@ -79,7 +79,7 @@ void FragmentDecompilerThread::AddCode(wxString code, bool append_mask)
main += "\t" + code + ";\n";
}
wxString FragmentDecompilerThread::GetMask()
wxString GLFragmentDecompilerThread::GetMask()
{
wxString ret = wxEmptyString;
@ -96,7 +96,7 @@ wxString FragmentDecompilerThread::GetMask()
return ret.IsEmpty() || strncmp(ret, dst_mask, 4) == 0 ? wxEmptyString : ("." + ret);
}
wxString FragmentDecompilerThread::AddReg(u32 index, int fp16)
wxString GLFragmentDecompilerThread::AddReg(u32 index, int fp16)
{
/*
if(HasReg(index, fp16))
@ -110,18 +110,18 @@ wxString FragmentDecompilerThread::AddReg(u32 index, int fp16)
wxString::Format((fp16 ? "h%u" : "r%u"), index), fp16 ? -1 : index);
}
bool FragmentDecompilerThread::HasReg(u32 index, int fp16)
bool GLFragmentDecompilerThread::HasReg(u32 index, int fp16)
{
return m_parr.HasParam(PARAM_OUT, "vec4",
wxString::Format((fp16 ? "h%u" : "r%u"), index));
}
wxString FragmentDecompilerThread::AddCond(int fp16)
wxString GLFragmentDecompilerThread::AddCond(int fp16)
{
return m_parr.AddParam(PARAM_NONE , "vec4", wxString::Format(fp16 ? "hc%d" : "rc%d", src0.cond_mod_reg_index));
}
wxString FragmentDecompilerThread::AddConst()
wxString GLFragmentDecompilerThread::AddConst()
{
mem32_ptr_t data(m_addr + m_size + m_offset);
@ -134,12 +134,12 @@ wxString FragmentDecompilerThread::AddConst()
wxString::Format("vec4(%f, %f, %f, %f)", (float&)x, (float&)y, (float&)z, (float&)w));
}
wxString FragmentDecompilerThread::AddTex()
wxString GLFragmentDecompilerThread::AddTex()
{
return m_parr.AddParam(PARAM_UNIFORM, "sampler2D", wxString::Format("tex%d", dst.tex_num));
}
template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
template<typename T> wxString GLFragmentDecompilerThread::GetSRC(T src)
{
wxString ret = wxEmptyString;
@ -204,7 +204,7 @@ template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
return ret;
}
wxString FragmentDecompilerThread::BuildCode()
wxString GLFragmentDecompilerThread::BuildCode()
{
wxString p = wxEmptyString;
@ -222,7 +222,7 @@ wxString FragmentDecompilerThread::BuildCode()
return wxString::Format(prot, p, main);
}
void FragmentDecompilerThread::Task()
void GLFragmentDecompilerThread::Task()
{
mem32_ptr_t data(m_addr);
m_size = 0;
@ -322,13 +322,13 @@ void FragmentDecompilerThread::Task()
main.Clear();
}
ShaderProgram::ShaderProgram()
GLShaderProgram::GLShaderProgram()
: m_decompiler_thread(nullptr)
, id(0)
{
}
ShaderProgram::~ShaderProgram()
GLShaderProgram::~GLShaderProgram()
{
if(m_decompiler_thread)
{
@ -345,7 +345,7 @@ ShaderProgram::~ShaderProgram()
Delete();
}
void ShaderProgram::Decompile()
void GLShaderProgram::Decompile(RSXShaderProgram& prog)
{
#if 0
FragmentDecompilerThread(shader, parr, addr).Entry();
@ -362,12 +362,12 @@ void ShaderProgram::Decompile()
m_decompiler_thread = nullptr;
}
m_decompiler_thread = new FragmentDecompilerThread(shader, parr, addr, size);
m_decompiler_thread = new GLFragmentDecompilerThread(shader, parr, prog.addr, prog.size);
m_decompiler_thread->Start();
#endif
}
void ShaderProgram::Compile()
void GLShaderProgram::Compile()
{
if(id) glDeleteShader(id);
@ -401,7 +401,7 @@ void ShaderProgram::Compile()
//else ConLog.Write("Shader compiled successfully!");
}
void ShaderProgram::Delete()
void GLShaderProgram::Delete()
{
for(u32 i=0; i<parr.params.GetCount(); ++i)
{

View File

@ -1,7 +1,8 @@
#pragma once
#include "ShaderParam.h"
#include "GLShaderParam.h"
#include "Emu/GS/RSXFragmentProgram.h"
struct FragmentDecompilerThread : public ThreadBase
struct GLFragmentDecompilerThread : public ThreadBase
{
union OPDEST
{
@ -99,14 +100,14 @@ struct FragmentDecompilerThread : public ThreadBase
wxString main;
wxString& m_shader;
ParamArray& m_parr;
GLParamArray& m_parr;
u32 m_addr;
u32& m_size;
u32 m_const_index;
u32 m_offset;
u32 m_location;
FragmentDecompilerThread(wxString& shader, ParamArray& parr, u32 addr, u32& size)
GLFragmentDecompilerThread(wxString& shader, GLParamArray& parr, u32 addr, u32& size)
: ThreadBase(false, "Fragment Shader Decompiler Thread")
, m_shader(shader)
, m_parr(parr)
@ -135,18 +136,15 @@ struct FragmentDecompilerThread : public ThreadBase
u32 GetData(const u32 d) const { return d << 16 | d >> 16; }
};
struct ShaderProgram
struct GLShaderProgram
{
ShaderProgram();
~ShaderProgram();
GLShaderProgram();
~GLShaderProgram();
FragmentDecompilerThread* m_decompiler_thread;
GLFragmentDecompilerThread* m_decompiler_thread;
ParamArray parr;
GLParamArray parr;
u32 size;
u32 addr;
u32 offset;
wxString shader;
u32 id;
@ -158,7 +156,7 @@ struct ShaderProgram
m_decompiler_thread->Wait();
}
}
void Decompile();
void Decompile(RSXShaderProgram& prog);
void Compile();
void Delete();

File diff suppressed because it is too large Load Diff

View File

@ -3,9 +3,9 @@
#include "Emu/GS/RSXThread.h"
#include "wx/glcanvas.h"
#include "GLBuffers.h"
#include "Program.h"
#include "GLProgram.h"
#include "OpenGL.h"
#include "ProgramBuffer.h"
#include "GLProgramBuffer.h"
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "gl.lib")
@ -15,57 +15,10 @@ void checkForGlError(const char* situation);
class GLTexture
{
u32 m_width, m_height;
u32 m_id;
u32 m_offset;
bool m_enabled;
bool m_cubemap;
u8 m_dimension;
u32 m_format;
u16 m_mipmap;
u32 m_pitch;
u16 m_depth;
u16 m_minlod;
u16 m_maxlod;
u8 m_maxaniso;
u8 m_wraps;
u8 m_wrapt;
u8 m_wrapr;
u8 m_unsigned_remap;
u8 m_zfunc;
u8 m_gamma;
u8 m_aniso_bias;
u8 m_signed_remap;
u16 m_bias;
u8 m_min_filter;
u8 m_mag_filter;
u8 m_conv;
u8 m_a_signed;
u8 m_r_signed;
u8 m_g_signed;
u8 m_b_signed;
u32 m_remap;
public:
GLTexture()
: m_width(0), m_height(0)
, m_id(0)
, m_offset(0)
, m_enabled(false)
, m_cubemap(false)
, m_dimension(0)
, m_format(0)
, m_mipmap(0)
, m_minlod(0)
, m_maxlod(1000)
, m_maxaniso(0)
GLTexture() : m_id(0)
{
}
@ -81,85 +34,9 @@ public:
glGenTextures(1, &m_id);
checkForGlError("GLTexture::Init() -> glGenTextures");
Bind();
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
}
}
void SetRect(const u32 width, const u32 height)
{
m_width = width;
m_height = height;
}
u32 GetOffset() const { return m_offset; }
void SetFormat(const bool cubemap, const u8 dimension, const u32 format, const u16 mipmap)
{
m_cubemap = cubemap;
m_dimension = dimension;
m_format = format;
m_mipmap = mipmap;
}
void SetAddress(u8 wraps, u8 wrapt, u8 wrapr, u8 unsigned_remap, u8 zfunc, u8 gamma, u8 aniso_bias, u8 signed_remap)
{
m_wraps = wraps;
m_wrapt = wrapt;
m_wrapr = wrapr;
m_unsigned_remap = unsigned_remap;
m_zfunc = zfunc;
m_gamma = gamma;
m_aniso_bias = aniso_bias;
m_signed_remap = signed_remap;
}
void SetControl0(const bool enable, const u16 minlod, const u16 maxlod, const u8 maxaniso)
{
m_enabled = enable;
m_minlod = minlod;
m_maxlod = maxlod;
m_maxaniso = maxaniso;
}
void SetControl1(u32 remap)
{
m_remap = remap;
}
void SetControl3(u16 depth, u32 pitch)
{
m_depth = depth;
m_pitch = pitch;
}
void SetFilter(u16 bias, u8 min, u8 mag, u8 conv, u8 a_signed, u8 r_signed, u8 g_signed, u8 b_signed)
{
m_bias = bias;
m_min_filter = min;
m_mag_filter = mag;
m_conv = conv;
m_a_signed = a_signed;
m_r_signed = r_signed;
m_g_signed = g_signed;
m_b_signed = b_signed;
}
u32 GetFormat() const { return m_format; }
void SetOffset(const u32 offset)
{
m_offset = offset;
}
wxSize GetRect() const
{
return wxSize(m_width, m_height);
}
int GetGlWrap(int wrap)
{
switch(wrap)
@ -176,12 +53,12 @@ public:
return GL_REPEAT;
}
void Init()
void Init(RSXTexture& tex)
{
Bind();
if(!Memory.IsGoodAddr(m_offset))
if(!Memory.IsGoodAddr(tex.GetOffset()))
{
ConLog.Error("Bad texture address=0x%x", m_offset);
ConLog.Error("Bad texture address=0x%x", tex.GetOffset());
return;
}
//ConLog.Warning("texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x",
@ -189,16 +66,16 @@ public:
//TODO: safe init
checkForGlError("GLTexture::Init() -> glBindTexture");
int format = m_format & ~(0x20 | 0x40);
bool is_swizzled = (m_format & 0x20) == 0;
int format = tex.GetFormat() & ~(0x20 | 0x40);
bool is_swizzled = (tex.GetFormat() & 0x20) == 0;
glPixelStorei(GL_PACK_ALIGNMENT, m_pitch);
char* pixels = (char*)Memory.GetMemFromAddr(m_offset);
glPixelStorei(GL_PACK_ALIGNMENT, tex.m_pitch);
char* pixels = (char*)Memory.GetMemFromAddr(tex.GetOffset());
switch(format)
{
case 0x81:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.m_width, tex.m_height, 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
@ -210,39 +87,39 @@ public:
break;
case 0x85:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.m_width, tex.m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
break;
case 0x86:
{
u32 size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 8;
u32 size = ((tex.m_width + 3) / 4) * ((tex.m_height + 3) / 4) * 8;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, m_width, m_height, 0, size, pixels);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, tex.m_width, tex.m_height, 0, size, pixels);
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D");
}
break;
case 0x87:
{
u32 size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 16;
u32 size = ((tex.m_width + 3) / 4) * ((tex.m_height + 3) / 4) * 16;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, m_width, m_height, 0, size, pixels);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, tex.m_width, tex.m_height, 0, size, pixels);
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D");
}
break;
case 0x88:
{
u32 size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 16;
u32 size = ((tex.m_width + 3) / 4) * ((tex.m_height + 3) / 4) * 16;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, m_width, m_height, 0, size, pixels);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, tex.m_width, tex.m_height, 0, size, pixels);
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D");
}
break;
case 0x94:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RED, GL_SHORT, pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.m_width, tex.m_height, 0, GL_RED, GL_SHORT, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ONE);
@ -251,30 +128,30 @@ public:
break;
case 0x9a:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_HALF_FLOAT, pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.m_width, tex.m_height, 0, GL_BGRA, GL_HALF_FLOAT, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
break;
case 0x9e:
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.m_width, tex.m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
}
break;
default: ConLog.Error("Init tex error: Bad tex format (0x%x | 0x%x | 0x%x)", format, m_format & 0x20, m_format & 0x40); break;
default: ConLog.Error("Init tex error: Bad tex format (0x%x | 0x%x | 0x%x)", format, tex.GetFormat() & 0x20, tex.GetFormat() & 0x40); break;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, m_mipmap - 1);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, m_mipmap > 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, tex.m_mipmap - 1);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, tex.m_mipmap > 1);
if(format != 0x81 && format != 0x94)
{
u8 remap_a = m_remap & 0x3;
u8 remap_r = (m_remap >> 2) & 0x3;
u8 remap_g = (m_remap >> 4) & 0x3;
u8 remap_b = (m_remap >> 6) & 0x3;
u8 remap_a = tex.m_remap & 0x3;
u8 remap_r = (tex.m_remap >> 2) & 0x3;
u8 remap_g = (tex.m_remap >> 4) & 0x3;
u8 remap_b = (tex.m_remap >> 6) & 0x3;
static const int gl_remap[] =
{
@ -302,14 +179,14 @@ public:
GL_ALWAYS,
};
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GetGlWrap(m_wraps));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GetGlWrap(m_wrapt));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GetGlWrap(m_wrapr));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[m_zfunc]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GetGlWrap(tex.m_wraps));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GetGlWrap(tex.m_wrapt));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GetGlWrap(tex.m_wrapr));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[tex.m_zfunc]);
glTexEnvi(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, m_bias);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, m_minlod);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, m_maxlod);
glTexEnvi(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, tex.m_bias);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, tex.m_minlod);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, tex.m_maxlod);
static const int gl_tex_filter[] =
{
@ -323,20 +200,20 @@ public:
GL_NEAREST,
};
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_filter[m_min_filter]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter[m_mag_filter]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_filter[tex.m_min_filter]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter[tex.m_mag_filter]);
//Unbind();
}
void Save(const wxString& name)
void Save(RSXTexture& tex, const wxString& name)
{
if(!m_id || !m_offset || !m_width || !m_height) return;
if(!m_id || !tex.m_offset || !tex.m_width || !tex.m_height) return;
u32* alldata = new u32[m_width * m_height];
u32* alldata = new u32[tex.m_width * tex.m_height];
Bind();
switch(m_format & ~(0x20 | 0x40))
switch(tex.m_format & ~(0x20 | 0x40))
{
case 0x81:
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, alldata);
@ -353,15 +230,15 @@ public:
{
wxFile f(name + ".raw", wxFile::write);
f.Write(alldata, m_width * m_height * 4);
f.Write(alldata, tex.m_width * tex.m_height * 4);
}
u8* data = new u8[m_width * m_height * 3];
u8* alpha = new u8[m_width * m_height];
u8* data = new u8[tex.m_width * tex.m_height * 3];
u8* alpha = new u8[tex.m_width * tex.m_height];
u8* src = (u8*)alldata;
u8* dst_d = data;
u8* dst_a = alpha;
for(u32 i=0; i<m_width*m_height;i++)
for(u32 i=0; i<tex.m_width*tex.m_height;i++)
{
*dst_d++ = *src++;
*dst_d++ = *src++;
@ -370,7 +247,7 @@ public:
}
wxImage out;
out.Create(m_width, m_height, data, alpha);
out.Create(tex.m_width, tex.m_height, data, alpha);
out.SaveFile(name, wxBITMAP_TYPE_PNG);
free(alldata);
@ -378,7 +255,7 @@ public:
//free(alpha);
}
void Save()
void Save(RSXTexture& tex)
{
static const wxString& dir_path = "textures";
static const wxString& file_fmt = dir_path + "\\" + "tex[%d].png";
@ -387,7 +264,7 @@ public:
u32 count = 0;
while(wxFileExists(wxString::Format(file_fmt, count))) count++;
Save(wxString::Format(file_fmt, count));
Save(tex, wxString::Format(file_fmt, count));
}
void Bind()
@ -408,64 +285,11 @@ public:
m_id = 0;
}
}
bool IsEnabled() const { return m_enabled; }
};
struct TransformConstant
{
u32 id;
float x, y, z, w;
TransformConstant()
: x(0.0f)
, y(0.0f)
, z(0.0f)
, w(0.0f)
{
}
TransformConstant(u32 id, float x, float y, float z, float w)
: id(id)
, x(x)
, y(y)
, z(z)
, w(w)
{
}
};
struct IndexArrayData
{
Array<u8> m_data;
int m_type;
u32 m_first;
u32 m_count;
u32 m_addr;
u32 index_max;
u32 index_min;
IndexArrayData()
{
Reset();
}
void Reset()
{
m_type = 0;
m_first = ~0;
m_count = 0;
m_addr = 0;
index_min = ~0;
index_max = 0;
m_data.Clear();
}
};
struct GLGSFrame : public GSFrame
{
wxGLCanvas* canvas;
GLTexture m_textures[16];
u32 m_frames;
GLGSFrame();
@ -474,7 +298,6 @@ struct GLGSFrame : public GSFrame
void Flip();
wxGLCanvas* GetCanvas() const { return canvas; }
GLTexture& GetTexture(const u32 index) { return m_textures[index]; }
virtual void SetViewport(int x, int y, u32 w, u32 h);
@ -482,22 +305,12 @@ private:
virtual void OnSize(wxSizeEvent& event);
};
struct GLRSXThread : public ThreadBase
{
wxWindow* m_parent;
Stack<u32> call_stack;
GLRSXThread(wxWindow* parent);
virtual void Task();
};
class PostDrawObj
{
protected:
ShaderProgram m_fp;
VertexProgram m_vp;
Program m_program;
GLShaderProgram m_fp;
GLVertexProgram m_vp;
GLProgram m_program;
GLfbo m_fbo;
GLrbo m_rbo;
@ -594,51 +407,35 @@ public:
class GLGSRender
: public wxWindow
, public GSRender
, public ExecRSXCMDdata
{
public:
static const uint m_vertex_count = 16;
static const uint m_fragment_count = 16;
static const uint m_textures_count = 16;
private:
GLRSXThread* m_rsx_thread;
IndexArrayData m_indexed_array;
ShaderProgram m_shader_progs[m_fragment_count];
ShaderProgram* m_cur_shader_prog;
int m_cur_shader_prog_num;
VertexData m_vertex_data[m_vertex_count];
Array<u8> m_vdata;
VertexProgram m_vertex_progs[m_vertex_count];
VertexProgram* m_cur_vertex_prog;
Array<TransformConstant> m_transform_constants;
Array<TransformConstant> m_fragment_constants;
ArrayF<PostDrawObj> m_post_draw_objs;
Program m_program;
GLProgram m_program;
int m_fp_buf_num;
int m_vp_buf_num;
int m_draw_array_count;
int m_draw_mode;
ProgramBuffer m_prog_buffer;
GLProgramBuffer m_prog_buffer;
u32 m_width;
u32 m_height;
GLShaderProgram m_shader_prog;
GLVertexProgram m_vertex_prog;
GLTexture m_gl_textures[m_textures_count];
GLvao m_vao;
GLvbo m_vbo;
GLrbo m_rbo;
GLfbo m_fbo;
wxGLContext* m_context;
public:
GLGSFrame* m_frame;
u32 m_draw_frames;
u32 m_skip_frames;
GLGSRender();
~GLGSRender();
virtual ~GLGSRender();
private:
void EnableVertexData(bool indexed_draw=false);
@ -648,8 +445,6 @@ private:
void InitFragmentData();
void Enable(bool enable, const u32 cap);
virtual void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress);
virtual void Draw();
virtual void Close();
bool LoadProgram();
void WriteDepthBuffer();
@ -661,11 +456,11 @@ private:
void DrawObjects();
public:
void DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count);
void CloseOpenGL();
protected:
virtual void OnInit();
virtual void OnInitThread();
virtual void OnExitThread();
virtual void OnReset();
virtual void ExecCMD();
virtual void Reset();
void Init();
virtual void Flip();
};

View File

@ -1,12 +1,12 @@
#include "stdafx.h"
#include "Program.h"
#include "GLProgram.h"
#include "GLGSRender.h"
Program::Program() : id(0)
GLProgram::GLProgram() : id(0)
{
}
int Program::GetLocation(const wxString& name)
int GLProgram::GetLocation(const wxString& name)
{
for(u32 i=0; i<m_locations.GetCount(); ++i)
{
@ -24,12 +24,12 @@ int Program::GetLocation(const wxString& name)
return m_locations[pos].loc;
}
bool Program::IsCreated() const
bool GLProgram::IsCreated() const
{
return id > 0;
}
void Program::Create(const u32 vp, const u32 fp)
void GLProgram::Create(const u32 vp, const u32 fp)
{
if(IsCreated()) Delete();
id = glCreateProgram();
@ -74,19 +74,19 @@ void Program::Create(const u32 vp, const u32 fp)
}
}
void Program::UnUse()
void GLProgram::UnUse()
{
id = 0;
m_locations.Clear();
}
void Program::Use()
void GLProgram::Use()
{
glUseProgram(id);
checkForGlError("glUseProgram");
}
void Program::SetTex(u32 index)
void GLProgram::SetTex(u32 index)
{
int loc = GetLocation(wxString::Format("tex%u", index));
checkForGlError(wxString::Format("GetLocation(tex%u)", index));
@ -94,7 +94,7 @@ void Program::SetTex(u32 index)
checkForGlError(wxString::Format("SetTex(%u - %d - %d)", id, index, loc));
}
void Program::Delete()
void GLProgram::Delete()
{
if(!IsCreated()) return;
glDeleteProgram(id);

View File

@ -1,8 +1,8 @@
#pragma once
#include "VertexProgram.h"
#include "FragmentProgram.h"
#include "GLVertexProgram.h"
#include "GLFragmentProgram.h"
struct Program
struct GLProgram
{
private:
struct Location
@ -16,7 +16,7 @@ private:
public:
u32 id;
Program();
GLProgram();
int GetLocation(const wxString& name);
bool IsCreated() const;

View File

@ -1,14 +1,14 @@
#include "stdafx.h"
#include "ProgramBuffer.h"
#include "GLProgramBuffer.h"
int ProgramBuffer::SearchFp(ShaderProgram& fp)
int GLProgramBuffer::SearchFp(const RSXShaderProgram& rsx_fp, GLShaderProgram& gl_fp)
{
for(u32 i=0; i<m_buf.GetCount(); ++i)
{
if(memcmp(&m_buf[i].fp_data[0], &Memory[fp.addr], m_buf[i].fp_data.GetCount()) != 0) continue;
if(memcmp(&m_buf[i].fp_data[0], &Memory[rsx_fp.addr], m_buf[i].fp_data.GetCount()) != 0) continue;
fp.id = m_buf[i].fp_id;
fp.shader = m_buf[i].fp_shader.GetPtr();
gl_fp.id = m_buf[i].fp_id;
gl_fp.shader = m_buf[i].fp_shader.GetPtr();
return i;
}
@ -16,15 +16,15 @@ int ProgramBuffer::SearchFp(ShaderProgram& fp)
return -1;
}
int ProgramBuffer::SearchVp(VertexProgram& vp)
int GLProgramBuffer::SearchVp(const RSXVertexProgram& rsx_vp, GLVertexProgram& gl_vp)
{
for(u32 i=0; i<m_buf.GetCount(); ++i)
{
if(m_buf[i].vp_data.GetCount() != vp.data.GetCount()) continue;
if(memcmp(m_buf[i].vp_data.GetPtr(), vp.data.GetPtr(), vp.data.GetCount() * 4) != 0) continue;
if(m_buf[i].vp_data.GetCount() != rsx_vp.data.GetCount()) continue;
if(memcmp(m_buf[i].vp_data.GetPtr(), rsx_vp.data.GetPtr(), rsx_vp.data.GetCount() * 4) != 0) continue;
vp.id = m_buf[i].vp_id;
vp.shader = m_buf[i].vp_shader.GetPtr();
gl_vp.id = m_buf[i].vp_id;
gl_vp.shader = m_buf[i].vp_shader.GetPtr();
return i;
}
@ -32,19 +32,19 @@ int ProgramBuffer::SearchVp(VertexProgram& vp)
return -1;
}
bool ProgramBuffer::CmpVP(const u32 a, const u32 b) const
bool GLProgramBuffer::CmpVP(const u32 a, const u32 b) const
{
if(m_buf[a].vp_data.GetCount() != m_buf[b].vp_data.GetCount()) return false;
return memcmp(m_buf[a].vp_data.GetPtr(), m_buf[b].vp_data.GetPtr(), m_buf[a].vp_data.GetCount() * 4) == 0;
}
bool ProgramBuffer::CmpFP(const u32 a, const u32 b) const
bool GLProgramBuffer::CmpFP(const u32 a, const u32 b) const
{
if(m_buf[a].fp_data.GetCount() != m_buf[b].fp_data.GetCount()) return false;
return memcmp(m_buf[a].fp_data.GetPtr(), m_buf[b].fp_data.GetPtr(), m_buf[a].fp_data.GetCount()) == 0;
}
u32 ProgramBuffer::GetProg(u32 fp, u32 vp) const
u32 GLProgramBuffer::GetProg(u32 fp, u32 vp) const
{
if(fp == vp)
{
@ -82,34 +82,34 @@ u32 ProgramBuffer::GetProg(u32 fp, u32 vp) const
return 0;
}
void ProgramBuffer::Add(Program& prog, ShaderProgram& fp, VertexProgram& vp)
void GLProgramBuffer::Add(GLProgram& prog, GLShaderProgram& gl_fp, RSXShaderProgram& rsx_fp, GLVertexProgram& gl_vp, RSXVertexProgram& rsx_vp)
{
BufferInfo& new_buf = *new BufferInfo();
GLBufferInfo& new_buf = *new GLBufferInfo();
ConLog.Write("Add program (%d):", m_buf.GetCount());
ConLog.Write("*** prog id = %d", prog.id);
ConLog.Write("*** vp id = %d", vp.id);
ConLog.Write("*** fp id = %d", fp.id);
ConLog.Write("*** vp data size = %d", vp.data.GetCount() * 4);
ConLog.Write("*** fp data size = %d", fp.size);
ConLog.Write("*** vp id = %d", gl_vp.id);
ConLog.Write("*** fp id = %d", gl_fp.id);
ConLog.Write("*** vp data size = %d", rsx_vp.data.GetCount() * 4);
ConLog.Write("*** fp data size = %d", rsx_fp.size);
ConLog.Write("*** vp shader = \n%s", vp.shader);
ConLog.Write("*** fp shader = \n%s", fp.shader);
ConLog.Write("*** vp shader = \n%s", gl_vp.shader);
ConLog.Write("*** fp shader = \n%s", gl_fp.shader);
new_buf.prog_id = prog.id;
new_buf.vp_id = vp.id;
new_buf.fp_id = fp.id;
new_buf.vp_id = gl_vp.id;
new_buf.fp_id = gl_fp.id;
new_buf.fp_data.AddCpy(&Memory[fp.addr], fp.size);
new_buf.vp_data.CopyFrom(vp.data);
new_buf.fp_data.AddCpy(&Memory[rsx_fp.addr], rsx_fp.size);
new_buf.vp_data.CopyFrom(rsx_vp.data);
new_buf.vp_shader = vp.shader;
new_buf.fp_shader = fp.shader;
new_buf.vp_shader = gl_vp.shader;
new_buf.fp_shader = gl_fp.shader;
m_buf.Move(&new_buf);
}
void ProgramBuffer::Clear()
void GLProgramBuffer::Clear()
{
for(u32 i=0; i<m_buf.GetCount(); ++i)
{

View File

@ -0,0 +1,29 @@
#pragma once
#include "GLProgram.h"
struct GLBufferInfo
{
u32 prog_id;
u32 fp_id;
u32 vp_id;
Array<u8> fp_data;
Array<u32> vp_data;
ArrayString fp_shader;
ArrayString vp_shader;
};
struct GLProgramBuffer
{
Array<GLBufferInfo> m_buf;
int SearchFp(const RSXShaderProgram& rsx_fp, GLShaderProgram& gl_fp);
int SearchVp(const RSXVertexProgram& rsx_vp, GLVertexProgram& gl_vp);
bool CmpVP(const u32 a, const u32 b) const;
bool CmpFP(const u32 a, const u32 b) const;
u32 GetProg(u32 fp, u32 vp) const;
void Add(GLProgram& prog, GLShaderProgram& gl_fp, RSXShaderProgram& rsx_fp, GLVertexProgram& gl_vp, RSXVertexProgram& rsx_vp);
void Clear();
};

View File

@ -1,7 +1,7 @@
#pragma once
#include "OpenGL.h"
enum ParamFlag
enum GLParamFlag
{
PARAM_IN,
PARAM_OUT,
@ -10,13 +10,13 @@ enum ParamFlag
PARAM_NONE,
};
struct ParamItem
struct GLParamItem
{
ArrayString name;
ArrayString location;
ArrayString value;
ParamItem(const wxString& _name, int _location, const wxString& _value = wxEmptyString)
GLParamItem(const wxString& _name, int _location, const wxString& _value = wxEmptyString)
: name(_name)
, location(_location > -1 ? wxString::Format("layout (location = %d) ", _location) : "")
, value(_value)
@ -24,13 +24,13 @@ struct ParamItem
}
};
struct ParamType
struct GLParamType
{
const ParamFlag flag;
const GLParamFlag flag;
ArrayString type;
Array<ParamItem> items;
Array<GLParamItem> items;
ParamType(const ParamFlag _flag, const wxString& _type)
GLParamType(const GLParamFlag _flag, const wxString& _type)
: type(_type)
, flag(_flag)
{
@ -68,11 +68,11 @@ struct ParamType
}
};
struct ParamArray
struct GLParamArray
{
Array<ParamType> params;
Array<GLParamType> params;
ParamType* SearchParam(const wxString& type)
GLParamType* SearchParam(const wxString& type)
{
for(u32 i=0; i<params.GetCount(); ++i)
{
@ -82,7 +82,7 @@ struct ParamArray
return nullptr;
}
wxString GetParamFlag(const ParamFlag flag)
wxString GetParamFlag(const GLParamFlag flag)
{
switch(flag)
{
@ -95,46 +95,46 @@ struct ParamArray
return wxEmptyString;
}
bool HasParam(const ParamFlag flag, wxString type, const wxString& name)
bool HasParam(const GLParamFlag flag, wxString type, const wxString& name)
{
type = GetParamFlag(flag) + type;
ParamType* t = SearchParam(type);
GLParamType* t = SearchParam(type);
return t && t->SearchName(name);
}
wxString AddParam(const ParamFlag flag, wxString type, const wxString& name, const wxString& value)
wxString AddParam(const GLParamFlag flag, wxString type, const wxString& name, const wxString& value)
{
type = GetParamFlag(flag) + type;
ParamType* t = SearchParam(type);
GLParamType* t = SearchParam(type);
if(t)
{
if(!t->SearchName(name)) t->items.Move(new ParamItem(name, -1, value));
if(!t->SearchName(name)) t->items.Move(new GLParamItem(name, -1, value));
}
else
{
const u32 num = params.GetCount();
params.Move(new ParamType(flag, type));
params[num].items.Move(new ParamItem(name, -1, value));
params.Move(new GLParamType(flag, type));
params[num].items.Move(new GLParamItem(name, -1, value));
}
return name;
}
wxString AddParam(const ParamFlag flag, wxString type, const wxString& name, int location = -1)
wxString AddParam(const GLParamFlag flag, wxString type, const wxString& name, int location = -1)
{
type = GetParamFlag(flag) + type;
ParamType* t = SearchParam(type);
GLParamType* t = SearchParam(type);
if(t)
{
if(!t->SearchName(name)) t->items.Move(new ParamItem(name, location));
if(!t->SearchName(name)) t->items.Move(new GLParamItem(name, location));
}
else
{
const u32 num = params.GetCount();
params.Move(new ParamType(flag, type));
params[num].items.Move(new ParamItem(name, location));
params.Move(new GLParamType(flag, type));
params[num].items.Move(new GLParamItem(name, location));
}
return name;

View File

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "VertexProgram.h"
#include "GLVertexProgram.h"
wxString VertexDecompilerThread::GetMask(bool is_sca)
wxString GLVertexDecompilerThread::GetMask(bool is_sca)
{
wxString ret = wxEmptyString;
@ -23,17 +23,17 @@ wxString VertexDecompilerThread::GetMask(bool is_sca)
return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret);
}
wxString VertexDecompilerThread::GetVecMask()
wxString GLVertexDecompilerThread::GetVecMask()
{
return GetMask(false);
}
wxString VertexDecompilerThread::GetScaMask()
wxString GLVertexDecompilerThread::GetScaMask()
{
return GetMask(true);
}
wxString VertexDecompilerThread::GetDST(bool isSca)
wxString GLVertexDecompilerThread::GetDST(bool isSca)
{
static const wxString reg_table[] =
{
@ -73,7 +73,7 @@ wxString VertexDecompilerThread::GetDST(bool isSca)
return ret;
}
wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca)
wxString GLVertexDecompilerThread::GetSRC(const u32 n, bool isSca)
{
static const wxString reg_table[] =
{
@ -151,7 +151,7 @@ wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca)
return ret;
}
void VertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask)
void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask)
{
if(d0.cond == 0) return;
enum
@ -215,17 +215,17 @@ void VertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask)
main += "\t" + code + ";\n";
}
void VertexDecompilerThread::AddVecCode(const wxString& code, bool src_mask)
void GLVertexDecompilerThread::AddVecCode(const wxString& code, bool src_mask)
{
AddCode(false, code, src_mask);
}
void VertexDecompilerThread::AddScaCode(const wxString& code)
void GLVertexDecompilerThread::AddScaCode(const wxString& code)
{
AddCode(true, code, false);
}
wxString VertexDecompilerThread::BuildCode()
wxString GLVertexDecompilerThread::BuildCode()
{
wxString p = wxEmptyString;
@ -243,7 +243,7 @@ wxString VertexDecompilerThread::BuildCode()
return wxString::Format(prot, p, main);
}
void VertexDecompilerThread::Task()
void GLVertexDecompilerThread::Task()
{
for(u32 i=0;;)
{
@ -327,13 +327,13 @@ void VertexDecompilerThread::Task()
main = wxEmptyString;
}
VertexProgram::VertexProgram()
GLVertexProgram::GLVertexProgram()
: m_decompiler_thread(nullptr)
, id(0)
{
}
VertexProgram::~VertexProgram()
GLVertexProgram::~GLVertexProgram()
{
if(m_decompiler_thread)
{
@ -350,10 +350,10 @@ VertexProgram::~VertexProgram()
Delete();
}
void VertexProgram::Decompile()
void GLVertexProgram::Decompile(RSXVertexProgram& prog)
{
#if 0
VertexDecompilerThread(data, shader, parr).Entry();
GLVertexDecompilerThread(data, shader, parr).Entry();
#else
if(m_decompiler_thread)
{
@ -367,12 +367,12 @@ void VertexProgram::Decompile()
m_decompiler_thread = nullptr;
}
m_decompiler_thread = new VertexDecompilerThread(data, shader, parr);
m_decompiler_thread = new GLVertexDecompilerThread(prog.data, shader, parr);
m_decompiler_thread->Start();
#endif
}
void VertexProgram::Compile()
void GLVertexProgram::Compile()
{
if(id) glDeleteShader(id);
@ -407,9 +407,8 @@ void VertexProgram::Compile()
}
void VertexProgram::Delete()
void GLVertexProgram::Delete()
{
data.Clear();
parr.params.Clear();
shader.Clear();
@ -419,79 +418,3 @@ void VertexProgram::Delete()
id = 0;
}
}
VertexData::VertexData()
: frequency(0)
, stride(0)
, size(0)
, type(0)
, addr(0)
, data()
{
}
void VertexData::Reset()
{
frequency = 0;
stride = 0;
size = 0;
type = 0;
addr = 0;
data.ClearF();
}
void VertexData::Load(u32 start, u32 count)
{
if(!addr) return;
const u32 tsize = GetTypeSize();
data.SetCount((start + count) * tsize * size);
for(u32 i=start; i<start + count; ++i)
{
const u8* src = Memory.GetMemFromAddr(addr) + stride * i;
u8* dst = &data[i * tsize * size];
switch(tsize)
{
case 1:
{
memcpy(dst, src, size);
}
break;
case 2:
{
const u16* c_src = (const u16*)src;
u16* c_dst = (u16*)dst;
for(u32 j=0; j<size; ++j) *c_dst++ = re(*c_src++);
}
break;
case 4:
{
const u32* c_src = (const u32*)src;
u32* c_dst = (u32*)dst;
for(u32 j=0; j<size; ++j) *c_dst++ = re(*c_src++);
}
break;
}
}
}
u32 VertexData::GetTypeSize()
{
switch (type)
{
case 1: return 2;
case 2: return 4;
case 3: return 2;
case 4: return 1;
case 5: return 2;
case 7: return 1;
}
ConLog.Error("Bad vertex data type! %d", type);
return 1;
}

View File

@ -1,7 +1,8 @@
#pragma once
#include "ShaderParam.h"
#include "GLShaderParam.h"
#include "Emu/GS/RSXVertexProgram.h"
struct VertexDecompilerThread : public ThreadBase
struct GLVertexDecompilerThread : public ThreadBase
{
union D0
{
@ -129,9 +130,9 @@ struct VertexDecompilerThread : public ThreadBase
wxString main;
wxString& m_shader;
Array<u32>& m_data;
ParamArray& m_parr;
GLParamArray& m_parr;
VertexDecompilerThread(Array<u32>& data, wxString& shader, ParamArray& parr)
GLVertexDecompilerThread(Array<u32>& data, wxString& shader, GLParamArray& parr)
: ThreadBase(false, "Vertex Shader Decompiler Thread")
, m_data(data)
, m_shader(shader)
@ -152,17 +153,16 @@ struct VertexDecompilerThread : public ThreadBase
virtual void Task();
};
struct VertexProgram
struct GLVertexProgram
{
wxString shader;
GLVertexDecompilerThread* m_decompiler_thread;
GLVertexProgram();
~GLVertexProgram();
GLParamArray parr;
u32 id;
VertexDecompilerThread* m_decompiler_thread;
VertexProgram();
~VertexProgram();
Array<u32> data;
ParamArray parr;
wxString shader;
void Wait()
{
@ -171,27 +171,8 @@ struct VertexProgram
m_decompiler_thread->Wait();
}
}
void Decompile();
void Decompile(RSXVertexProgram& prog);
void Compile();
void Delete();
};
struct VertexData
{
u32 frequency;
u32 stride;
u32 size;
u32 type;
u32 addr;
u32 constant_count;
Array<u8> data;
VertexData();
void Reset();
bool IsEnabled() { return size > 0; }
void Load(u32 start, u32 count);
u32 GetTypeSize();
};

View File

@ -1,29 +0,0 @@
#pragma once
#include "Program.h"
struct BufferInfo
{
u32 prog_id;
u32 fp_id;
u32 vp_id;
Array<u8> fp_data;
Array<u32> vp_data;
ArrayString fp_shader;
ArrayString vp_shader;
};
struct ProgramBuffer
{
Array<BufferInfo> m_buf;
int SearchFp(ShaderProgram& fp);
int SearchVp(VertexProgram& vp);
bool CmpVP(const u32 a, const u32 b) const;
bool CmpFP(const u32 a, const u32 b) const;
u32 GetProg(u32 fp, u32 vp) const;
void Add(Program& prog, ShaderProgram& fp, VertexProgram& vp);
void Clear();
};

View File

@ -32,6 +32,7 @@ void GSManager::Close()
if(m_render)
{
m_render->Close();
delete m_render;
m_render = nullptr;
}
}

View File

@ -76,28 +76,6 @@ void GSFrame::SetSize(int width, int height)
}
*/
GSRender::GSRender()
: m_ctrl(nullptr)
, m_flip_status(0)
, m_flip_mode(CELL_GCM_DISPLAY_VSYNC)
, m_main_mem_addr(0)
{
}
u32 GSRender::GetAddress(u32 offset, u8 location)
{
switch(location)
{
case CELL_GCM_LOCATION_LOCAL: return m_local_mem_addr + offset;
case CELL_GCM_LOCATION_MAIN: return m_main_mem_addr + offset;
}
ConLog.Error("GetAddress(offset=0x%x, location=0x%x", location);
assert(0);
return 0;
}
GSLockCurrent::GSLockCurrent(GSLockType type) : GSLock(Emu.GetGSManager().GetRender(), type)
{
}

View File

@ -1,16 +1,6 @@
#pragma once
#include "Emu/GS/GCM.h"
#include "Emu/SysCalls/Callback.h"
#include "rpcs3.h"
enum Method
{
CELL_GCM_METHOD_FLAG_NON_INCREMENT = 0x40000000,
CELL_GCM_METHOD_FLAG_JUMP = 0x20000000,
CELL_GCM_METHOD_FLAG_CALL = 0x00000002,
CELL_GCM_METHOD_FLAG_RETURN = 0x00020000,
};
#include "Emu/GS/RSXThread.h"
wxSize AspectRatio(wxSize rs, const wxSize as);
@ -40,138 +30,13 @@ private:
DECLARE_EVENT_TABLE();
};
struct CellGcmSurface
struct GSRender : public RSXThread
{
u8 type;
u8 antialias;
u8 color_format;
u8 color_target;
u8 color_location[4];
u32 color_offset[4];
u32 color_pitch[4];
u8 depth_format;
u8 depth_location;
u16 pad;
u32 depth_offset;
u32 depth_pitch;
u16 width;
u16 height;
u16 x;
u16 y;
};
struct CellGcmReportData
{
u64 timer;
u32 value;
u32 pad;
};
struct CellGcmZcullInfo
{
u32 region;
u32 size;
u32 start;
u32 offset;
u32 status0;
u32 status1;
};
struct CellGcmTileInfo
{
u32 tile;
u32 limit;
u32 pitch;
u32 format;
};
struct GcmZcullInfo
{
u32 m_offset;
u32 m_width;
u32 m_height;
u32 m_cullStart;
u32 m_zFormat;
u32 m_aaFormat;
u32 m_zCullDir;
u32 m_zCullFormat;
u32 m_sFunc;
u32 m_sRef;
u32 m_sMask;
bool m_binded;
GcmZcullInfo()
virtual ~GSRender()
{
memset(this, 0, sizeof(*this));
}
};
struct GcmTileInfo
{
u8 m_location;
u32 m_offset;
u32 m_size;
u32 m_pitch;
u8 m_comp;
u16 m_base;
u8 m_bank;
bool m_binded;
GcmTileInfo()
{
memset(this, 0, sizeof(*this));
}
CellGcmTileInfo Pack()
{
CellGcmTileInfo ret;
re(ret.tile, (m_location + 1) | (m_bank << 4) | ((m_offset / 0x10000) << 16) | (m_location << 31));
re(ret.limit, ((m_offset + m_size - 1) / 0x10000) << 16 | (m_location << 31));
re(ret.pitch, (m_pitch / 0x100) << 8);
re(ret.format, m_base | ((m_base + ((m_size - 1) / 0x10000)) << 13) | (m_comp << 26) | (1 << 30));
return ret;
}
};
static const int g_tiles_count = 15;
struct GSRender
{
u32 m_ioAddress, m_ioSize, m_ctrlAddress;
CellGcmControl* m_ctrl;
wxCriticalSection m_cs_main;
wxSemaphore m_sem_flush;
wxSemaphore m_sem_flip;
int m_flip_status;
int m_flip_mode;
volatile bool m_draw;
Callback m_flip_handler;
GcmTileInfo m_tiles[g_tiles_count];
u32 m_tiles_addr;
u32 m_zculls_addr;
u32 m_gcm_buffers_addr;
u32 m_gcm_buffers_count;
u32 m_gcm_current_buffer;
u32 m_ctxt_addr;
u32 m_report_main_addr;
u32 m_local_mem_addr, m_main_mem_addr;
Array<MemInfo> m_main_mem_info;
GSRender();
virtual void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress)=0;
virtual void Draw()=0;
virtual void Close()=0;
u32 GetAddress(u32 offset, u8 location);
};
enum GSLockType

View File

@ -24,168 +24,53 @@ private:
}
};
struct NullRSXThread : public wxThread
{
wxWindow* m_parent;
Stack<u32> call_stack;
NullRSXThread(wxWindow* parent);
virtual void OnExit();
void Start();
ExitCode Entry();
};
class NullGSRender
: public wxWindow
, public GSRender
{
private:
NullRSXThread* m_rsx_thread;
public:
NullGSFrame* m_frame;
NullGSRender()
: m_frame(nullptr)
, m_rsx_thread(nullptr)
NullGSRender() : m_frame(nullptr)
{
m_draw = false;
m_frame = new NullGSFrame();
}
~NullGSRender()
virtual ~NullGSRender()
{
Close();
m_frame->Close();
}
private:
virtual void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress)
virtual void OnInit()
{
if(m_frame->IsShown()) return;
m_frame->SetSize(740, 480);
m_frame->Show();
m_ioAddress = ioAddress;
m_ctrlAddress = ctrlAddress;
m_ioSize = ioSize;
m_local_mem_addr = localAddress;
m_ctrl = (CellGcmControl*)Memory.GetMemFromAddr(m_ctrlAddress);
(m_rsx_thread = new NullRSXThread(this))->Start();
}
public:
void DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count)
virtual void OnInitThread()
{
switch(cmd)
{
case NV406E_SET_REFERENCE:
m_ctrl->ref = re32(args[0]);
break;
}
}
virtual void Draw()
virtual void OnExitThread()
{
}
virtual void OnReset()
{
}
virtual void ExecCMD()
{
}
virtual void Flip()
{
//if(m_frame && !m_frame->IsBeingDeleted()) m_frame->Draw();
m_draw = true;
}
virtual void Close()
{
if(m_rsx_thread) m_rsx_thread->Delete();
if(IsAlive()) Stop();
if(m_frame->IsShown()) m_frame->Hide();
m_ctrl = NULL;
}
};
NullRSXThread::NullRSXThread(wxWindow* parent)
: wxThread(wxTHREAD_DETACHED)
, m_parent(parent)
{
}
void NullRSXThread::OnExit()
{
call_stack.Clear();
}
void NullRSXThread::Start()
{
Create();
Run();
}
wxThread::ExitCode NullRSXThread::Entry()
{
ConLog.Write("Null RSX thread entry");
NullGSRender& p = *(NullGSRender*)m_parent;
while(!TestDestroy() && p.m_frame && !p.m_frame->IsBeingDeleted())
{
wxCriticalSectionLocker lock(p.m_cs_main);
if(p.m_ctrl->get == p.m_ctrl->put || !Emu.IsRunning())
{
SemaphorePostAndWait(p.m_sem_flush);
if(p.m_draw)
{
p.m_draw = false;
p.m_flip_status = 0;
if(SemaphorePostAndWait(p.m_sem_flip)) continue;
}
Sleep(1);
continue;
}
const u32 get = re(p.m_ctrl->get);
const u32 cmd = Memory.Read32(p.m_ioAddress + get);
const u32 count = (cmd >> 18) & 0x7ff;
if(cmd & CELL_GCM_METHOD_FLAG_JUMP)
{
p.m_ctrl->get = re32(cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT));
ConLog.Warning("rsx jump!");
continue;
}
if(cmd & CELL_GCM_METHOD_FLAG_CALL)
{
call_stack.Push(get + 4);
p.m_ctrl->get = re32(cmd & ~CELL_GCM_METHOD_FLAG_CALL);
ConLog.Warning("rsx call!");
continue;
}
if(cmd & CELL_GCM_METHOD_FLAG_RETURN)
{
p.m_ctrl->get = re32(call_stack.Pop());
ConLog.Warning("rsx return!");
continue;
}
if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
{
//ConLog.Warning("non increment cmd! 0x%x", cmd);
}
if(cmd == 0)
{
ConLog.Warning("null cmd: addr=0x%x, put=0x%x, get=0x%x", p.m_ioAddress + get, re(p.m_ctrl->put), get);
Emu.Pause();
continue;
}
p.DoCmd(cmd, cmd & 0x3ffff, mem32_ptr_t(p.m_ioAddress + get + 4), count);
re(p.m_ctrl->get, get + (count + 1) * 4);
}
ConLog.Write("Null RSX thread exit...");
call_stack.Clear();
return (ExitCode)0;
}

View File

@ -0,0 +1,15 @@
#pragma once
struct RSXShaderProgram
{
u32 size;
u32 addr;
u32 offset;
RSXShaderProgram()
: size(0)
, addr(0)
, offset(0)
{
}
};

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,281 @@
#pragma once
#include "GCM.h"
#include "RSXVertexProgram.h"
#include "RSXFragmentProgram.h"
#include "Emu/SysCalls/Callback.h"
class ExecRSXCMDdata
enum Method
{
CELL_GCM_METHOD_FLAG_NON_INCREMENT = 0x40000000,
CELL_GCM_METHOD_FLAG_JUMP = 0x20000000,
CELL_GCM_METHOD_FLAG_CALL = 0x00000002,
CELL_GCM_METHOD_FLAG_RETURN = 0x00020000,
};
class RSXTexture
{
public:
bool m_enabled;
u32 m_width, m_height;
u32 m_offset;
bool m_cubemap;
u8 m_dimension;
u32 m_format;
u16 m_mipmap;
u32 m_pitch;
u16 m_depth;
u16 m_minlod;
u16 m_maxlod;
u8 m_maxaniso;
u8 m_wraps;
u8 m_wrapt;
u8 m_wrapr;
u8 m_unsigned_remap;
u8 m_zfunc;
u8 m_gamma;
u8 m_aniso_bias;
u8 m_signed_remap;
u16 m_bias;
u8 m_min_filter;
u8 m_mag_filter;
u8 m_conv;
u8 m_a_signed;
u8 m_r_signed;
u8 m_g_signed;
u8 m_b_signed;
u32 m_remap;
public:
RSXTexture()
: m_width(0), m_height(0)
, m_offset(0)
, m_enabled(false)
, m_cubemap(false)
, m_dimension(0)
, m_format(0)
, m_mipmap(0)
, m_minlod(0)
, m_maxlod(1000)
, m_maxaniso(0)
{
}
void SetRect(const u32 width, const u32 height)
{
m_width = width;
m_height = height;
}
void SetFormat(const bool cubemap, const u8 dimension, const u32 format, const u16 mipmap)
{
m_cubemap = cubemap;
m_dimension = dimension;
m_format = format;
m_mipmap = mipmap;
}
void SetAddress(u8 wraps, u8 wrapt, u8 wrapr, u8 unsigned_remap, u8 zfunc, u8 gamma, u8 aniso_bias, u8 signed_remap)
{
m_wraps = wraps;
m_wrapt = wrapt;
m_wrapr = wrapr;
m_unsigned_remap = unsigned_remap;
m_zfunc = zfunc;
m_gamma = gamma;
m_aniso_bias = aniso_bias;
m_signed_remap = signed_remap;
}
void SetControl0(const bool enable, const u16 minlod, const u16 maxlod, const u8 maxaniso)
{
m_enabled = enable;
m_minlod = minlod;
m_maxlod = maxlod;
m_maxaniso = maxaniso;
}
void SetControl1(u32 remap)
{
m_remap = remap;
}
void SetControl3(u16 depth, u32 pitch)
{
m_depth = depth;
m_pitch = pitch;
}
void SetFilter(u16 bias, u8 min, u8 mag, u8 conv, u8 a_signed, u8 r_signed, u8 g_signed, u8 b_signed)
{
m_bias = bias;
m_min_filter = min;
m_mag_filter = mag;
m_conv = conv;
m_a_signed = a_signed;
m_r_signed = r_signed;
m_g_signed = g_signed;
m_b_signed = b_signed;
}
u32 GetFormat() const
{
return m_format;
}
void SetOffset(const u32 offset)
{
m_offset = offset;
}
wxSize GetRect() const
{
return wxSize(m_width, m_height);
}
bool IsEnabled() const
{
return m_enabled;
}
u32 GetOffset() const
{
return m_offset;
}
};
struct RSXVertexData
{
u32 frequency;
u32 stride;
u32 size;
u32 type;
u32 addr;
u32 constant_count;
Array<u8> data;
RSXVertexData();
void Reset();
bool IsEnabled() { return size > 0; }
void Load(u32 start, u32 count);
u32 GetTypeSize();
};
struct RSXIndexArrayData
{
Array<u8> m_data;
int m_type;
u32 m_first;
u32 m_count;
u32 m_addr;
u32 index_max;
u32 index_min;
RSXIndexArrayData()
{
Reset();
}
void Reset()
{
m_type = 0;
m_first = ~0;
m_count = 0;
m_addr = 0;
index_min = ~0;
index_max = 0;
m_data.Clear();
}
};
struct RSXTransformConstant
{
u32 id;
float x, y, z, w;
RSXTransformConstant()
: x(0.0f)
, y(0.0f)
, z(0.0f)
, w(0.0f)
{
}
RSXTransformConstant(u32 id, float x, float y, float z, float w)
: id(id)
, x(x)
, y(y)
, z(z)
, w(w)
{
}
};
class RSXThread : public ThreadBase
{
public:
static const uint m_textures_count = 16;
static const uint m_vertex_count = 16;
static const uint m_fragment_count = 16;
static const uint m_tiles_count = 15;
protected:
Stack<u32> m_call_stack;
CellGcmControl* m_ctrl;
public:
GcmTileInfo m_tiles[m_tiles_count];
RSXTexture m_textures[m_textures_count];
RSXVertexData m_vertex_data[m_vertex_count];
RSXIndexArrayData m_indexed_array;
Array<RSXTransformConstant> m_fragment_constants;
Array<RSXTransformConstant> m_transform_constants;
u32 m_cur_shader_prog_num;
RSXShaderProgram m_shader_progs[m_fragment_count];
RSXShaderProgram* m_cur_shader_prog;
RSXVertexProgram m_vertex_progs[m_vertex_count];
RSXVertexProgram* m_cur_vertex_prog;
public:
u32 m_ioAddress, m_ioSize, m_ctrlAddress;
int m_flip_status;
int m_flip_mode;
u32 m_tiles_addr;
u32 m_zculls_addr;
u32 m_gcm_buffers_addr;
u32 m_gcm_buffers_count;
u32 m_gcm_current_buffer;
u32 m_ctxt_addr;
u32 m_report_main_addr;
u32 m_local_mem_addr, m_main_mem_addr;
Array<MemInfo> m_main_mem_info;
protected:
uint m_draw_mode;
u32 m_width, m_height;
u32 m_draw_array_count;
public:
wxCriticalSection m_cs_main;
wxSemaphore m_sem_flush;
wxSemaphore m_sem_flip;
Callback m_flip_handler;
public:
bool m_set_color_mask;
bool m_color_mask_r;
@ -229,8 +502,16 @@ public:
u8 m_begin_end;
public:
ExecRSXCMDdata()
protected:
RSXThread()
: ThreadBase(false, "RSXThread")
, m_ctrl(nullptr)
, m_flip_status(0)
, m_flip_mode(CELL_GCM_DISPLAY_VSYNC)
, m_main_mem_addr(0)
, m_local_mem_addr(0)
, m_draw_mode(0)
, m_draw_array_count(0)
{
m_set_alpha_test = false;
m_set_blend = false;
@ -246,15 +527,18 @@ public:
m_set_surface_clip_horizontal = false;
m_set_surface_clip_vertical = false;
m_clear_surface_mask = 0;
m_clear_color_r = 0;
m_clear_color_g = 0;
m_clear_color_b = 0;
m_clear_color_a = 0;
m_clear_z = 0xffffff;
m_clear_s = 0;
Reset();
}
virtual void Reset()
void Reset()
{
m_set_color_mask = false;
m_set_clip = false;
@ -302,19 +586,57 @@ public:
m_begin_end = 0;
}
virtual void ExecCMD()=0;
};
void Begin(u32 draw_mode);
void End();
class RSXThread : public ThreadBase
{
Array<u32> call_stack;
CellGcmControl& m_ctrl;
u32 m_ioAddress;
void DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count);
protected:
RSXThread(CellGcmControl* ctrl, u32 ioAddress);
virtual void OnInit() = 0;
virtual void OnInitThread() = 0;
virtual void OnExitThread() = 0;
virtual void OnReset() = 0;
virtual void ExecCMD() = 0;
virtual void Flip() = 0;
u32 GetAddress(u32 offset, u8 location)
{
switch(location)
{
case CELL_GCM_LOCATION_LOCAL: return m_local_mem_addr + offset;
case CELL_GCM_LOCATION_MAIN: return m_main_mem_addr + offset;
}
ConLog.Error("GetAddress(offset=0x%x, location=0x%x)", location);
assert(0);
return 0;
}
void LoadVertexData(u32 first, u32 count)
{
for(u32 i=0; i<m_vertex_count; ++i)
{
if(!m_vertex_data[i].IsEnabled()) continue;
m_vertex_data[i].Load(first, count);
}
}
private:
virtual void Task();
virtual void OnExit();
public:
void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress)
{
m_ctrl = (CellGcmControl*)&Memory[ctrlAddress];
m_ioAddress = ioAddress;
m_ioSize = ioSize;
m_ctrlAddress = ctrlAddress;
m_local_mem_addr = localAddress;
m_cur_vertex_prog = nullptr;
m_cur_shader_prog = nullptr;
m_cur_shader_prog_num = 0;
OnInit();
ThreadBase::Start();
}
};

View File

@ -0,0 +1,6 @@
#pragma once
struct RSXVertexProgram
{
Array<u32> data;
};

View File

@ -219,7 +219,7 @@ public:
MemoryBlocks[i].Delete();
}
MemoryBlocks.Clear();
MemoryBlocks.ClearF();
}
void Write8(const u64 addr, const u8 data);

View File

@ -433,7 +433,7 @@ int cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u
cellGcmSys.Warning("cellGcmSetTileInfo(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)",
index, location, offset, size, pitch, comp, base, bank);
if(index >= g_tiles_count || base >= 800 || bank >= 4)
if(index >= RSXThread::m_tiles_count || base >= 800 || bank >= 4)
{
return CELL_GCM_ERROR_INVALID_VALUE;
}
@ -470,7 +470,7 @@ int cellGcmBindTile(u8 index)
{
cellGcmSys.Warning("cellGcmBindTile(index=%d)", index);
if(index >= g_tiles_count)
if(index >= RSXThread::m_tiles_count)
{
return CELL_GCM_ERROR_INVALID_VALUE;
}
@ -485,7 +485,7 @@ int cellGcmUnbindTile(u8 index)
{
cellGcmSys.Warning("cellGcmUnbindTile(index=%d)", index);
if(index >= g_tiles_count)
if(index >= RSXThread::m_tiles_count)
{
return CELL_GCM_ERROR_INVALID_VALUE;
}

View File

@ -9,7 +9,6 @@ Module cellRecs(0x001f, cellRecs_init);
int cellRescSetConvertAndFlip(s32 indx)
{
cellRecs.Log("cellRescSetConvertAndFlip(indx=0x%x)", indx);
Emu.GetGSManager().GetRender().Draw();
return CELL_OK;
}

View File

@ -312,13 +312,6 @@ void default_syscall()
case 23: RESULT(lv2ProcessWaitForChild2(CPU)); return;
case 25: RESULT(lv2ProcessGetSdkVersion(CPU)); return;
*/
//timer
case 141:
case 142:
std::this_thread::sleep_for(std::chrono::nanoseconds(SC_ARGS_1));
RESULT(0);
return;
//tty
case 988:
ConLog.Warning("SysCall 988! r3: 0x%llx, r4: 0x%llx, pc: 0x%llx",

View File

@ -219,13 +219,13 @@
<ClCompile Include="Emu\FS\vfsLocalFile.cpp" />
<ClCompile Include="Emu\FS\vfsStream.cpp" />
<ClCompile Include="Emu\FS\vfsStreamMemory.cpp" />
<ClCompile Include="Emu\GS\GL\FragmentProgram.cpp" />
<ClCompile Include="Emu\GS\GL\GLBuffers.cpp" />
<ClCompile Include="Emu\GS\GL\GLFragmentProgram.cpp" />
<ClCompile Include="Emu\GS\GL\GLGSRender.cpp" />
<ClCompile Include="Emu\GS\GL\GLProgram.cpp" />
<ClCompile Include="Emu\GS\GL\GLProgramBuffer.cpp" />
<ClCompile Include="Emu\GS\GL\GLVertexProgram.cpp" />
<ClCompile Include="Emu\GS\GL\OpenGL.cpp" />
<ClCompile Include="Emu\GS\GL\Program.cpp" />
<ClCompile Include="Emu\GS\GL\ProgramBuffer.cpp" />
<ClCompile Include="Emu\GS\GL\VertexProgram.cpp" />
<ClCompile Include="Emu\GS\GSManager.cpp" />
<ClCompile Include="Emu\GS\GSRender.cpp" />
<ClCompile Include="Emu\GS\RSXThread.cpp" />

View File

@ -160,30 +160,18 @@
<ClCompile Include="Emu\SysCalls\lv2\SC_Heap.cpp">
<Filter>Emu\SysCalls\lv2</Filter>
</ClCompile>
<ClCompile Include="Emu\GS\GL\FragmentProgram.cpp">
<Filter>Emu\GS\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\GS\GL\GLBuffers.cpp">
<Filter>Emu\GS\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\GS\GL\GLGSRender.cpp">
<Filter>Emu\GS\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\GS\GL\Program.cpp">
<Filter>Emu\GS\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\GS\GL\VertexProgram.cpp">
<Filter>Emu\GS\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\GS\GL\OpenGL.cpp">
<Filter>Emu\GS\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\GS\GSRender.cpp">
<Filter>Emu\GS</Filter>
</ClCompile>
<ClCompile Include="Emu\GS\GL\ProgramBuffer.cpp">
<Filter>Emu\GS\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\lv2\SC_SPU_Thread.cpp">
<Filter>Emu\SysCalls\lv2</Filter>
</ClCompile>
@ -343,6 +331,18 @@
<ClCompile Include="Emu\SysCalls\Modules\cellRtc.cpp">
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\GS\GL\GLFragmentProgram.cpp">
<Filter>Emu\GS\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\GS\GL\GLProgram.cpp">
<Filter>Emu\GS\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\GS\GL\GLProgramBuffer.cpp">
<Filter>Emu\GS\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\GS\GL\GLVertexProgram.cpp">
<Filter>Emu\GS\GL</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="rpcs3.rc" />

View File

@ -198,8 +198,8 @@ enum Status
#include "Ini.h"
#include "Gui/FrameBase.h"
#include "Gui/ConLog.h"
#include "Emu/System.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/FS/vfsFileBase.h"