aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-x.travis-build.sh2
-rwxr-xr-x.travis-deps.sh1
-rw-r--r--src/citra_qt/CMakeLists.txt8
-rw-r--r--src/common/math_util.h2
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.cpp24
-rw-r--r--src/core/arm/skyeye_common/arm_regformat.h2
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp4
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h1
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp18
-rw-r--r--src/core/file_sys/archive_extsavedata.cpp9
-rw-r--r--src/core/hle/service/fs/archive.cpp23
-rw-r--r--src/core/hle/service/fs/archive.h4
-rw-r--r--src/core/hle/service/fs/fs_user.cpp16
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp154
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp36
-rw-r--r--src/video_core/renderer_opengl/gl_state.h7
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp6
17 files changed, 219 insertions, 98 deletions
diff --git a/.travis-build.sh b/.travis-build.sh
index 14dfd64d..422e1322 100755
--- a/.travis-build.sh
+++ b/.travis-build.sh
@@ -18,5 +18,5 @@ elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
export Qt5_DIR=$(brew --prefix)/opt/qt5
mkdir build && cd build
cmake .. -GXcode
- xcodebuild -configuration Release
+ xcodebuild -configuration Release | xcpretty -c && exit ${PIPESTATUS[0]}
fi
diff --git a/.travis-deps.sh b/.travis-deps.sh
index f8074fb9..b9561bb6 100755
--- a/.travis-deps.sh
+++ b/.travis-deps.sh
@@ -26,4 +26,5 @@ if [ "$TRAVIS_OS_NAME" = "linux" -o -z "$TRAVIS_OS_NAME" ]; then
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew tap homebrew/versions
brew install qt5 glfw3 pkgconfig
+ gem install xcpretty
fi
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt
index c0577938..c2d1ad24 100644
--- a/src/citra_qt/CMakeLists.txt
+++ b/src/citra_qt/CMakeLists.txt
@@ -91,10 +91,10 @@ if (Qt5_FOUND AND MSVC)
set(PLATFORMS ${DLL_DEST}platforms/)
# windows commandline expects the / to be \ so switch them
- string(REPLACE "/" "\\" Qt5_DLL_DIR ${Qt5_DLL_DIR})
- string(REPLACE "/" "\\" Qt5_PLATFORMS_DIR ${Qt5_PLATFORMS_DIR})
- string(REPLACE "/" "\\" DLL_DEST ${DLL_DEST})
- string(REPLACE "/" "\\" PLATFORMS ${PLATFORMS})
+ string(REPLACE "/" "\\\\" Qt5_DLL_DIR ${Qt5_DLL_DIR})
+ string(REPLACE "/" "\\\\" Qt5_PLATFORMS_DIR ${Qt5_PLATFORMS_DIR})
+ string(REPLACE "/" "\\\\" DLL_DEST ${DLL_DEST})
+ string(REPLACE "/" "\\\\" PLATFORMS ${PLATFORMS})
# /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output
# cmake adds an extra check for command success which doesn't work too well with robocopy
diff --git a/src/common/math_util.h b/src/common/math_util.h
index 4b091074..d44b06e7 100644
--- a/src/common/math_util.h
+++ b/src/common/math_util.h
@@ -12,7 +12,7 @@ namespace MathUtil
{
inline bool IntervalsIntersect(unsigned start0, unsigned length0, unsigned start1, unsigned length1) {
- return (std::max(start0, start1) <= std::min(start0 + length0, start1 + length1));
+ return (std::max(start0, start1) < std::min(start0 + length0, start1 + length1));
}
template<typename T>
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
index 83b532aa..3e79c44c 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
@@ -327,11 +327,25 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
case 24: // STMIA
case 25: // LDMIA
- *ainstr = ((tinstr & (1 << 11)) // base
- ? 0xE8B00000 // LDMIA
- : 0xE8A00000) // STMIA
- |((tinstr & 0x0700) << (16 - 8)) // Rb
- |(tinstr & 0x00FF); // mask8
+ if (tinstr & (1 << 11))
+ {
+ unsigned int base = 0xE8900000;
+ unsigned int rn = BITS(tinstr, 8, 10);
+
+ // Writeback
+ if ((tinstr & (1 << rn)) == 0)
+ base |= (1 << 21);
+
+ *ainstr = base // base (LDMIA)
+ | (rn << 16) // Rn
+ | (tinstr & 0x00FF); // Register list
+ }
+ else
+ {
+ *ainstr = 0xE8A00000 // base (STMIA)
+ | (BITS(tinstr, 8, 10) << 16) // Rn
+ | (tinstr & 0x00FF); // Register list
+ }
break;
case 26: // Bcc
diff --git a/src/core/arm/skyeye_common/arm_regformat.h b/src/core/arm/skyeye_common/arm_regformat.h
index 6c89774e..a92effbb 100644
--- a/src/core/arm/skyeye_common/arm_regformat.h
+++ b/src/core/arm/skyeye_common/arm_regformat.h
@@ -59,6 +59,8 @@ enum {
VFP_FPSID,
VFP_FPSCR,
VFP_FPEXC,
+ VFP_MVFR0,
+ VFP_MVFR1,
// Not an actual register.
// All VFP system registers should be defined above this.
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp
index b88d4775..571d6c2f 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -33,6 +33,10 @@ unsigned VFPInit(ARMul_State* state)
state->VFP[VFP_FPEXC] = 0;
state->VFP[VFP_FPSCR] = 0;
+ // ARM11 MPCore feature register values.
+ state->VFP[VFP_MVFR0] = 0x11111111;
+ state->VFP[VFP_MVFR1] = 0;
+
return 0;
}
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h
index 727350f1..acefae9b 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.h
+++ b/src/core/arm/skyeye_common/vfp/vfp.h
@@ -22,7 +22,6 @@
#include "core/arm/skyeye_common/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */
-#define VFP_DEBUG_UNIMPLEMENTED(x) LOG_ERROR(Core_ARM11, "in func %s, " #x " unimplemented\n", __FUNCTION__); exit(-1);
#define VFP_DEBUG_UNTESTED(x) LOG_TRACE(Core_ARM11, "in func %s, " #x " untested\n", __FUNCTION__);
#define CHECK_VFP_ENABLED
#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
index 3ed918a9..67fe63aa 100644
--- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
@@ -1068,10 +1068,12 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMOVBRC_INST:
{
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
- VFP_DEBUG_UNIMPLEMENTED(VMOVBRC);
+ vmovbrc_inst* const inst_cream = (vmovbrc_inst*)inst_base->component;
+
+ cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index] = cpu->Reg[inst_cream->t];
}
cpu->Reg[15] += GET_INST_SIZE(cpu);
INC_PC(sizeof(vmovbrc_inst));
@@ -1139,12 +1141,10 @@ VMRS_INST:
cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPSID];
break;
case 6:
- /* MVFR1, VFPv3 only ? */
- LOG_TRACE(Core_ARM11, "\tr%d <= MVFR1 unimplemented\n", inst_cream->Rt);
+ cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_MVFR1];
break;
case 7:
- /* MVFR0, VFPv3 only? */
- LOG_TRACE(Core_ARM11, "\tr%d <= MVFR0 unimplemented\n", inst_cream->Rt);
+ cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_MVFR0];
break;
case 8:
cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPEXC];
@@ -1195,10 +1195,12 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMOVBCR_INST:
{
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
- VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
+ vmovbcr_inst* const inst_cream = (vmovbcr_inst*) inst_base->component;
+
+ cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index];
}
cpu->Reg[15] += GET_INST_SIZE(cpu);
INC_PC(sizeof(vmovbcr_inst));
diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp
index 975aafb3..e50c58a5 100644
--- a/src/core/file_sys/archive_extsavedata.cpp
+++ b/src/core/file_sys/archive_extsavedata.cpp
@@ -71,7 +71,7 @@ bool ArchiveFactory_ExtSaveData::Initialize() {
}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(const Path& path) {
- std::string fullpath = GetExtSaveDataPath(mount_point, path);
+ std::string fullpath = GetExtSaveDataPath(mount_point, path) + "user/";
if (!FileUtil::Exists(fullpath)) {
// TODO(Subv): Check error code, this one is probably wrong
return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
@@ -82,8 +82,11 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(cons
}
ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path) {
- std::string fullpath = GetExtSaveDataPath(mount_point, path);
- FileUtil::CreateFullPath(fullpath);
+ // These folders are always created with the ExtSaveData
+ std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/";
+ std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/";
+ FileUtil::CreateFullPath(user_path);
+ FileUtil::CreateFullPath(boss_path);
return RESULT_SUCCESS;
}
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 7cab6802..4e275cb1 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -406,7 +406,7 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path) {
return archive_itr->second->Format(path);
}
-ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low) {
+ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size) {
// Construct the binary path to the archive first
FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low);
@@ -421,9 +421,25 @@ ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low) {
}
std::string base_path = FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND);
- std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path);
- if (!FileUtil::CreateFullPath(extsavedata_path))
+ std::string game_path = FileSys::GetExtSaveDataPath(base_path, path);
+ // These two folders are always created with the ExtSaveData
+ std::string user_path = game_path + "user/";
+ std::string boss_path = game_path + "boss/";
+ if (!FileUtil::CreateFullPath(user_path))
+ return ResultCode(-1); // TODO(Subv): Find the right error code
+ if (!FileUtil::CreateFullPath(boss_path))
+ return ResultCode(-1); // TODO(Subv): Find the right error code
+
+ u8* smdh_icon = Memory::GetPointer(icon_buffer);
+ if (!smdh_icon)
return ResultCode(-1); // TODO(Subv): Find the right error code
+
+ // Create the icon
+ FileUtil::IOFile icon_file(game_path + "icon", "wb+");
+ if (!icon_file.IsGood())
+ return ResultCode(-1); // TODO(Subv): Find the right error code
+
+ icon_file.WriteBytes(smdh_icon, icon_size);
return RESULT_SUCCESS;
}
@@ -441,6 +457,7 @@ ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) {
return ResultCode(-1); // TODO(Subv): Find the right error code
}
+ // Delete all directories (/user, /boss) and the icon file.
std::string base_path = FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND);
std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path);
if (!FileUtil::DeleteDirRecursively(extsavedata_path))
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h
index faab0cb7..357b6b09 100644
--- a/src/core/hle/service/fs/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -177,9 +177,11 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path = File
* @param media_type The media type of the archive to create (NAND / SDMC)
* @param high The high word of the extdata id to create
* @param low The low word of the extdata id to create
+ * @param icon_buffer VAddr of the SMDH icon for this ExtSaveData
+ * @param icon_size Size of the SMDH icon
* @return ResultCode 0 on success or the corresponding code on error
*/
-ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low);
+ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size);
/**
* Deletes the SharedExtSaveData archive for the specified extdata ID
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 32db773b..0ad44e55 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -504,9 +504,9 @@ static void FormatThisUserSaveData(Service::Interface* self) {
* 6 : Unknown
* 7 : Unknown
* 8 : Unknown
- * 9 : Unknown
- * 10: Unknown
- * 11: Unknown
+ * 9 : Size of the SMDH icon
+ * 10: (SMDH Size << 4) | 0x0000000A
+ * 11: Pointer to the SMDH icon for the new ExtSaveData
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
@@ -516,14 +516,16 @@ static void CreateExtSaveData(Service::Interface* self) {
MediaType media_type = static_cast<MediaType>(cmd_buff[1] & 0xFF);
u32 save_low = cmd_buff[2];
u32 save_high = cmd_buff[3];
+ u32 icon_size = cmd_buff[9];
+ VAddr icon_buffer = cmd_buff[11];
LOG_WARNING(Service_FS, "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X "
"cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X "
- "cmd_buff[9]=%08X cmd_buff[10]=%08X cmd_buff[11]=%08X", save_high, save_low,
- cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9],
- cmd_buff[10], cmd_buff[11]);
+ "icon_size=%08X icon_descriptor=%08X icon_buffer=%08X", save_high, save_low,
+ cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], icon_size,
+ cmd_buff[10], icon_buffer);
- cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low).raw;
+ cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low, icon_buffer, icon_size).raw;
}
/**
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index d31c46cc..518f7933 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -94,14 +94,27 @@ void RasterizerOpenGL::InitObjects() {
// Create textures for OGL framebuffer that will be rendered to, initially 1x1 to succeed in framebuffer creation
fb_color_texture.texture.Create();
ReconfigureColorTexture(fb_color_texture, Pica::Regs::ColorFormat::RGBA8, 1, 1);
+
+ state.texture_units[0].enabled_2d = true;
+ state.texture_units[0].texture_2d = fb_color_texture.texture.handle;
+ state.Apply();
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
+
fb_depth_texture.texture.Create();
ReconfigureDepthTexture(fb_depth_texture, Pica::Regs::DepthFormat::D16, 1, 1);
+
+ state.texture_units[0].enabled_2d = true;
+ state.texture_units[0].texture_2d = fb_depth_texture.texture.handle;
+ state.Apply();
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -110,14 +123,13 @@ void RasterizerOpenGL::InitObjects() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
+
// Configure OpenGL framebuffer
framebuffer.Create();
state.draw.framebuffer = framebuffer.handle;
-
- // Unbind texture to allow binding to framebuffer
- state.texture_units[0].enabled_2d = true;
- state.texture_units[0].texture_2d = 0;
state.Apply();
glActiveTexture(GL_TEXTURE0);
@@ -205,7 +217,19 @@ void RasterizerOpenGL::DrawTriangles() {
vertex_batch.clear();
- // TODO: Flush the resource cache at the current depth and color framebuffer addresses for render-to-texture
+ // Flush the resource cache at the current depth and color framebuffer addresses for render-to-texture
+ const auto& regs = Pica::g_state.regs;
+
+ PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
+ u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format)
+ * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
+
+ PAddr cur_fb_depth_addr = regs.framebuffer.GetDepthBufferPhysicalAddress();
+ u32 cur_fb_depth_size = Pica::Regs::BytesPerDepthPixel(regs.framebuffer.depth_format)
+ * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
+
+ res_cache.NotifyFlush(cur_fb_color_addr, cur_fb_color_size);
+ res_cache.NotifyFlush(cur_fb_depth_addr, cur_fb_depth_size);
}
void RasterizerOpenGL::CommitFramebuffer() {
@@ -472,6 +496,9 @@ void RasterizerOpenGL::ReconfigureColorTexture(TextureInfo& texture, Pica::Regs:
glActiveTexture(GL_TEXTURE0);
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0,
texture.gl_format, texture.gl_type, nullptr);
+
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
}
void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica::Regs::DepthFormat format, u32 width, u32 height) {
@@ -491,7 +518,7 @@ void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica::
case Pica::Regs::DepthFormat::D24:
internal_format = GL_DEPTH_COMPONENT24;
texture.gl_format = GL_DEPTH_COMPONENT;
- texture.gl_type = GL_UNSIGNED_INT_24_8;
+ texture.gl_type = GL_UNSIGNED_INT;
break;
case Pica::Regs::DepthFormat::D24S8:
@@ -513,6 +540,9 @@ void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica::
glActiveTexture(GL_TEXTURE0);
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0,
texture.gl_format, texture.gl_type, nullptr);
+
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
}
void RasterizerOpenGL::SyncFramebuffer() {
@@ -652,6 +682,10 @@ void RasterizerOpenGL::SyncDepthTest() {
const auto& regs = Pica::g_state.regs;
state.depth.test_enabled = (regs.output_merger.depth_test_enable == 1);
state.depth.test_func = PicaToGL::CompareFunc(regs.output_merger.depth_test_func);
+ state.color_mask.red_enabled = regs.output_merger.red_enable;
+ state.color_mask.green_enabled = regs.output_merger.green_enable;
+ state.color_mask.blue_enabled = regs.output_merger.blue_enable;
+ state.color_mask.alpha_enabled = regs.output_merger.alpha_enable;
state.depth.write_mask = regs.output_merger.depth_write_enable ? GL_TRUE : GL_FALSE;
}
@@ -759,10 +793,10 @@ void RasterizerOpenGL::ReloadColorBuffer() {
for (int x = 0; x < fb_color_texture.width; ++x) {
const u32 coarse_y = y & ~7;
u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_color_texture.width * bytes_per_pixel;
- u32 gl_px_idx = x * bytes_per_pixel + y * fb_color_texture.width * bytes_per_pixel;
+ u32 gl_pixel_index = (x + y * fb_color_texture.width) * bytes_per_pixel;
u8* pixel = color_buffer + dst_offset;
- memcpy(&temp_fb_color_buffer[gl_px_idx], pixel, bytes_per_pixel);
+ memcpy(&temp_fb_color_buffer[gl_pixel_index], pixel, bytes_per_pixel);
}
}
@@ -773,6 +807,9 @@ void RasterizerOpenGL::ReloadColorBuffer() {
glActiveTexture(GL_TEXTURE0);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb_color_texture.width, fb_color_texture.height,
fb_color_texture.gl_format, fb_color_texture.gl_type, temp_fb_color_buffer.get());
+
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
}
void RasterizerOpenGL::ReloadDepthBuffer() {
@@ -790,29 +827,29 @@ void RasterizerOpenGL::ReloadDepthBuffer() {
std::unique_ptr<u8[]> temp_fb_depth_buffer(new u8[fb_depth_texture.width * fb_depth_texture.height * gl_bpp]);
- for (int y = 0; y < fb_depth_texture.height; ++y) {
- for (int x = 0; x < fb_depth_texture.width; ++x) {
- const u32 coarse_y = y & ~7;
- u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
- u32 gl_px_idx = x + y * fb_depth_texture.width;
-
- switch (fb_depth_texture.format) {
- case Pica::Regs::DepthFormat::D16:
- ((u16*)temp_fb_depth_buffer.get())[gl_px_idx] = Color::DecodeD16(depth_buffer + dst_offset);
- break;
- case Pica::Regs::DepthFormat::D24:
- ((u32*)temp_fb_depth_buffer.get())[gl_px_idx] = Color::DecodeD24(depth_buffer + dst_offset);
- break;
- case Pica::Regs::DepthFormat::D24S8:
- {
- Math::Vec2<u32> depth_stencil = Color::DecodeD24S8(depth_buffer + dst_offset);
- ((u32*)temp_fb_depth_buffer.get())[gl_px_idx] = (depth_stencil.x << 8) | depth_stencil.y;
- break;
+ u8* temp_fb_depth_data = bytes_per_pixel == 3 ? (temp_fb_depth_buffer.get() + 1) : temp_fb_depth_buffer.get();
+
+ if (fb_depth_texture.format == Pica::Regs::DepthFormat::D24S8) {
+ for (int y = 0; y < fb_depth_texture.height; ++y) {
+ for (int x = 0; x < fb_depth_texture.width; ++x) {
+ const u32 coarse_y = y & ~7;
+ u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
+ u32 gl_pixel_index = (x + y * fb_depth_texture.width);
+
+ u8* pixel = depth_buffer + dst_offset;
+ u32 depth_stencil = *(u32*)pixel;
+ ((u32*)temp_fb_depth_data)[gl_pixel_index] = (depth_stencil << 8) | (depth_stencil >> 24);
}
- default:
- LOG_CRITICAL(Render_OpenGL, "Unknown memory framebuffer depth format %x", fb_depth_texture.format);
- UNIMPLEMENTED();
- break;
+ }
+ } else {
+ for (int y = 0; y < fb_depth_texture.height; ++y) {
+ for (int x = 0; x < fb_depth_texture.width; ++x) {
+ const u32 coarse_y = y & ~7;
+ u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
+ u32 gl_pixel_index = (x + y * fb_depth_texture.width) * gl_bpp;
+
+ u8* pixel = depth_buffer + dst_offset;
+ memcpy(&temp_fb_depth_data[gl_pixel_index], pixel, bytes_per_pixel);
}
}
}
@@ -824,6 +861,9 @@ void RasterizerOpenGL::ReloadDepthBuffer() {
glActiveTexture(GL_TEXTURE0);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb_depth_texture.width, fb_depth_texture.height,
fb_depth_texture.gl_format, fb_depth_texture.gl_type, temp_fb_depth_buffer.get());
+
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
}
void RasterizerOpenGL::CommitColorBuffer() {
@@ -842,15 +882,18 @@ void RasterizerOpenGL::CommitColorBuffer() {
glActiveTexture(GL_TEXTURE0);
glGetTexImage(GL_TEXTURE_2D, 0, fb_color_texture.gl_format, fb_color_texture.gl_type, temp_gl_color_buffer.get());
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
+
// Directly copy pixels. Internal OpenGL color formats are consistent so no conversion is necessary.
for (int y = 0; y < fb_color_texture.height; ++y) {
for (int x = 0; x < fb_color_texture.width; ++x) {
const u32 coarse_y = y & ~7;
u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_color_texture.width * bytes_per_pixel;
- u32 gl_px_idx = x * bytes_per_pixel + y * fb_color_texture.width * bytes_per_pixel;
+ u32 gl_pixel_index = x * bytes_per_pixel + y * fb_color_texture.width * bytes_per_pixel;
u8* pixel = color_buffer + dst_offset;
- memcpy(pixel, &temp_gl_color_buffer[gl_px_idx], bytes_per_pixel);
+ memcpy(pixel, &temp_gl_color_buffer[gl_pixel_index], bytes_per_pixel);
}
}
}
@@ -877,29 +920,32 @@ void RasterizerOpenGL::CommitDepthBuffer() {
glActiveTexture(GL_TEXTURE0);
glGetTexImage(GL_TEXTURE_2D, 0, fb_depth_texture.gl_format, fb_depth_texture.gl_type, temp_gl_depth_buffer.get());
- for (int y = 0; y < fb_depth_texture.height; ++y) {
- for (int x = 0; x < fb_depth_texture.width; ++x) {
- const u32 coarse_y = y & ~7;
- u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
- u32 gl_px_idx = x + y * fb_depth_texture.width;
-
- switch (fb_depth_texture.format) {
- case Pica::Regs::DepthFormat::D16:
- Color::EncodeD16(((u16*)temp_gl_depth_buffer.get())[gl_px_idx], depth_buffer + dst_offset);
- break;
- case Pica::Regs::DepthFormat::D24:
- Color::EncodeD24(((u32*)temp_gl_depth_buffer.get())[gl_px_idx], depth_buffer + dst_offset);
- break;
- case Pica::Regs::DepthFormat::D24S8:
- {
- u32 depth_stencil = ((u32*)temp_gl_depth_buffer.get())[gl_px_idx];
- Color::EncodeD24S8((depth_stencil >> 8), depth_stencil & 0xFF, depth_buffer + dst_offset);
- break;
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
+
+ u8* temp_gl_depth_data = bytes_per_pixel == 3 ? (temp_gl_depth_buffer.get() + 1) : temp_gl_depth_buffer.get();
+
+ if (fb_depth_texture.format == Pica::Regs::DepthFormat::D24S8) {
+ for (int y = 0; y < fb_depth_texture.height; ++y) {
+ for (int x = 0; x < fb_depth_texture.width; ++x) {
+ const u32 coarse_y = y & ~7;
+ u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
+ u32 gl_pixel_index = (x + y * fb_depth_texture.width);
+
+ u8* pixel = depth_buffer + dst_offset;
+ u32 depth_stencil = ((u32*)temp_gl_depth_data)[gl_pixel_index];
+ *(u32*)pixel = (depth_stencil >> 8) | (depth_stencil << 24);
}
- default:
- LOG_CRITICAL(Render_OpenGL, "Unknown framebuffer depth format %x", fb_depth_texture.format);
- UNIMPLEMENTED();
- break;
+ }
+ } else {
+ for (int y = 0; y < fb_depth_texture.height; ++y) {
+ for (int x = 0; x < fb_depth_texture.width; ++x) {
+ const u32 coarse_y = y & ~7;
+ u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
+ u32 gl_pixel_index = (x + y * fb_depth_texture.width) * gl_bpp;
+
+ u8* pixel = depth_buffer + dst_offset;
+ memcpy(pixel, &temp_gl_depth_data[gl_pixel_index], bytes_per_pixel);
}
}
}
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 9c5f38f9..3526e16d 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -16,6 +16,11 @@ OpenGLState::OpenGLState() {
depth.test_func = GL_LESS;
depth.write_mask = GL_TRUE;
+ color_mask.red_enabled = GL_TRUE;
+ color_mask.green_enabled = GL_TRUE;
+ color_mask.blue_enabled = GL_TRUE;
+ color_mask.alpha_enabled = GL_TRUE;
+
stencil.test_enabled = false;
stencil.test_func = GL_ALWAYS;
stencil.test_ref = 0;
@@ -77,6 +82,15 @@ void OpenGLState::Apply() {
glDepthMask(depth.write_mask);
}
+ // Color mask
+ if (color_mask.red_enabled != cur_state.color_mask.red_enabled ||
+ color_mask.green_enabled != cur_state.color_mask.green_enabled ||
+ color_mask.blue_enabled != cur_state.color_mask.blue_enabled ||
+ color_mask.alpha_enabled != cur_state.color_mask.alpha_enabled) {
+ glColorMask(color_mask.red_enabled, color_mask.green_enabled,
+ color_mask.blue_enabled, color_mask.alpha_enabled);
+ }
+
// Stencil test
if (stencil.test_enabled != cur_state.stencil.test_enabled) {
if (stencil.test_enabled) {
@@ -87,8 +101,8 @@ void OpenGLState::Apply() {
}
if (stencil.test_func != cur_state.stencil.test_func ||
- stencil.test_ref != cur_state.stencil.test_ref ||
- stencil.test_mask != cur_state.stencil.test_mask) {
+ stencil.test_ref != cur_state.stencil.test_ref ||
+ stencil.test_mask != cur_state.stencil.test_mask) {
glStencilFunc(stencil.test_func, stencil.test_ref, stencil.test_mask);
}
@@ -112,17 +126,19 @@ void OpenGLState::Apply() {
}
if (blend.color.red != cur_state.blend.color.red ||
- blend.color.green != cur_state.blend.color.green ||
- blend.color.blue != cur_state.blend.color.blue ||
- blend.color.alpha != cur_state.blend.color.alpha) {
- glBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha);
+ blend.color.green != cur_state.blend.color.green ||
+ blend.color.blue != cur_state.blend.color.blue ||
+ blend.color.alpha != cur_state.blend.color.alpha) {
+ glBlendColor(blend.color.red, blend.color.green,
+ blend.color.blue, blend.color.alpha);
}
if (blend.src_rgb_func != cur_state.blend.src_rgb_func ||
- blend.dst_rgb_func != cur_state.blend.dst_rgb_func ||
- blend.src_a_func != cur_state.blend.src_a_func ||
- blend.dst_a_func != cur_state.blend.dst_a_func) {
- glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func, blend.dst_a_func);
+ blend.dst_rgb_func != cur_state.blend.dst_rgb_func ||
+ blend.src_a_func != cur_state.blend.src_a_func ||
+ blend.dst_a_func != cur_state.blend.dst_a_func) {
+ glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func,
+ blend.src_a_func, blend.dst_a_func);
}
if (logic_op != cur_state.logic_op) {
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 6b97721d..26b91636 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -20,6 +20,13 @@ public:
} depth;
struct {
+ GLboolean red_enabled;
+ GLboolean green_enabled;
+ GLboolean blue_enabled;
+ GLboolean alpha_enabled;
+ } color_mask; // GL_COLOR_WRITEMASK
+
+ struct {
bool test_enabled; // GL_STENCIL_TEST
GLenum test_func; // GL_STENCIL_FUNC
GLint test_ref; // GL_STENCIL_REF
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 382aeaa0..058ad12c 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -170,6 +170,9 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig&
texture.gl_format, texture.gl_type, framebuffer_data);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
}
/**
@@ -239,6 +242,9 @@ void RendererOpenGL::InitOpenGLObjects() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
+
hw_rasterizer->InitObjects();
}