Skip to content

Instantly share code, notes, and snippets.

@Subv
Last active August 29, 2015 14:11
Show Gist options
  • Save Subv/294f4328bfc9c2d5f493 to your computer and use it in GitHub Desktop.
Save Subv/294f4328bfc9c2d5f493 to your computer and use it in GitHub Desktop.
diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp
index 93d7ac3..c21376f 100644
--- a/src/citra_qt/debugger/graphics_framebuffer.cpp
+++ b/src/citra_qt/debugger/graphics_framebuffer.cpp
@@ -242,6 +242,42 @@ void GraphicsFramebufferWidget::OnUpdate()
break;
}
+ case Format::RGB565:
+ {
+ QImage decoded_image(framebuffer_width, framebuffer_height, QImage::Format_ARGB32);
+ u32* color_buffer = (u32*)Memory::GetPointer(framebuffer_address);
+ for (int y = 0; y < framebuffer_height; ++y) {
+ for (int x = 0; x < framebuffer_width; ++x) {
+ u16 value = *(u16*)(((u8*)color_buffer) + x * 2 + y * framebuffer_width * 2);
+ u8 r = (value >> 11) & 0x1F;
+ u8 g = (value >> 5) & 0x3F;
+ u8 b = (value >> 1) & 0x1F;
+
+ decoded_image.setPixel(x, y, qRgba(r, g, b, 255));
+ }
+ }
+ pixmap = QPixmap::fromImage(decoded_image);
+ break;
+ }
+
+ case Format::RGBA4:
+ {
+ QImage decoded_image(framebuffer_width, framebuffer_height, QImage::Format_ARGB32);
+ u32* color_buffer = (u32*)Memory::GetPointer(framebuffer_address);
+ for (int y = 0; y < framebuffer_height; ++y) {
+ for (int x = 0; x < framebuffer_width; ++x) {
+ u16 value = *(u16*)(((u8*)color_buffer) + x * 2 + y * framebuffer_width * 2);
+ u8 r = (value >> 12) & 0xF;
+ u8 g = (value >> 8) & 0xF;
+ u8 b = (value >> 4) & 0xF;
+ u8 a = value & 0xF;
+
+ decoded_image.setPixel(x, y, qRgba(r, g, b, 255));
+ }
+ }
+ pixmap = QPixmap::fromImage(decoded_image);
+ break;
+ }
default:
qDebug() << "Unknown fb color format " << static_cast<int>(framebuffer_format);
break;
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index da78b85..6e26f24 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -103,23 +103,40 @@ inline void Write(u32 addr, const T data) {
source_color.a = srcptr[3]; // alpha
break;
}
-
+ case Regs::PixelFormat::RGB5A1:
+ {
+ u16 value = *(u16*)(source_pointer + x * 2 + y * config.input_width * 2);
+ source_color.r = (value >> 11) & 0x1F;
+ source_color.g = (value >> 6) & 0x1F;
+ source_color.b = (value >> 1) & 0x1F;
+ source_color.a = value & 1;
+ break;
+ }
+ case Regs::PixelFormat::RGBA4:
+ {
+ u16 value = *(u16*)(source_pointer + x * 2 + y * config.input_width * 2);
+ source_color.r = (value >> 12) & 0xF;
+ source_color.g = (value >> 8) & 0xF;
+ source_color.b = (value >> 4) & 0xF;
+ source_color.a = value & 0xF;
+ break;
+ }
default:
LOG_ERROR(HW_GPU, "Unknown source framebuffer format %x", config.input_format.Value());
break;
}
switch (config.output_format) {
- /*case Regs::PixelFormat::RGBA8:
+ case Regs::PixelFormat::RGBA8:
{
// TODO: Untested
- u8* dstptr = (u32*)(dest_pointer + x * 4 + y * config.output_width * 4);
+ u8* dstptr = (u8*)(dest_pointer + x * 4 + y * config.output_width * 4);
dstptr[0] = source_color.r;
dstptr[1] = source_color.g;
dstptr[2] = source_color.b;
dstptr[3] = source_color.a;
break;
- }*/
+ }
case Regs::PixelFormat::RGB8:
{
@@ -130,7 +147,18 @@ inline void Write(u32 addr, const T data) {
dstptr[2] = source_color.b; // red
break;
}
-
+ case Regs::PixelFormat::RGB5A1:
+ {
+ u16* value = (u16*)(dest_pointer + x * 2 + y * config.input_width * 2);
+ *value = (source_color.r << 11) | (source_color.g << 6) | (source_color.b << 1) | source_color.a;
+ break;
+ }
+ case Regs::PixelFormat::RGBA4:
+ {
+ u16* value = (u16*)(source_pointer + x * 2 + y * config.input_width * 2);
+ *value = (source_color.r << 12) | (source_color.g << 8) | (source_color.b << 4) | source_color.a;
+ break;
+ }
default:
LOG_ERROR(HW_GPU, "Unknown destination framebuffer format %x", config.output_format.Value());
break;
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index 5090c24..e932e11 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -227,13 +227,16 @@ struct Regs {
SourceAlpha = 2,
OneMinusSourceAlpha = 3,
+ Unknown1 = 5,
+
// Other values seem to be non-standard extensions
};
enum class AlphaModifier : u32 {
SourceAlpha = 0,
OneMinusSourceAlpha = 1,
-
+ Unknown0 = 2,
+ Unknown1 = 5,
// Other values seem to be non-standard extensions
};
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index 20a3a3c..1e44a34 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -286,11 +286,14 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
case ColorModifier::SourceAlpha:
return { values.a(), values.a(), values.a() };
-
+ case ColorModifier::OneMinusSourceColor:
+ return { 255 - values.r(), 255 - values.g(), 255 - values.b() };
+ case ColorModifier::Unknown1:
+ return values.rgb();
default:
LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor);
- _dbg_assert_(HW_GPU, 0);
- return {};
+ //_dbg_assert_(HW_GPU, 0);
+ return values.rgb();
}
};
@@ -301,11 +304,13 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
case AlphaModifier::OneMinusSourceAlpha:
return 255 - value;
-
+ case AlphaModifier::Unknown1:
+ case AlphaModifier::Unknown0:
+ return value;
default:
LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor);
- _dbg_assert_(HW_GPU, 0);
- return 0;
+ //_dbg_assert_(HW_GPU, 0);
+ return value;
}
};
@@ -350,6 +355,8 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
case Operation::Lerp:
return (input[0] * input[2] + input[1] * (255 - input[2])) / 255;
+ case Operation::Subtract:
+ return std::max(0, (s8)input[0] - (s8)input[1]);
default:
LOG_ERROR(HW_GPU, "Unknown alpha combiner operation %d\n", (int)op);
_dbg_assert_(HW_GPU, 0);
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index e2caeeb..94449af 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -98,8 +98,32 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig&
const u8* framebuffer_data = Memory::GetPointer(framebuffer_vaddr);
// TODO: Handle other pixel formats
- _dbg_assert_msg_(Render_OpenGL, framebuffer.color_format == GPU::Regs::PixelFormat::RGB8,
- "Unsupported 3DS pixel format.");
+ int glformat = 0;
+ int gltype = GL_BGR;
+ //_dbg_assert_msg_(Render_OpenGL, framebuffer.color_format == GPU::Regs::PixelFormat::RGB8,
+ // "Unsupported 3DS pixel format.");
+ switch (framebuffer.color_format) {
+ case GPU::Regs::PixelFormat::RGB8:
+ glformat = GL_UNSIGNED_BYTE;
+ gltype = GL_BGR;
+ break;
+ case GPU::Regs::PixelFormat::RGBA4:
+ glformat = GL_UNSIGNED_SHORT_4_4_4_4;
+ gltype = GL_BGRA;
+ break;
+ case GPU::Regs::PixelFormat::RGB5A1:
+ glformat = GL_UNSIGNED_SHORT_5_5_5_1;
+ gltype = GL_BGRA;
+ break;
+ case GPU::Regs::PixelFormat::RGB565:
+ glformat = GL_UNSIGNED_SHORT_5_6_5;
+ gltype = GL_BGR;
+ break;
+ case GPU::Regs::PixelFormat::RGBA8:
+ glformat = GL_UNSIGNED_INT_8_8_8_8;
+ gltype = GL_BGRA;
+ break;
+ }
size_t pixel_stride = framebuffer.stride / 3;
// OpenGL only supports specifying a stride in units of pixels, not bytes, unfortunately
@@ -117,7 +141,7 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig&
// TODO: Applications could theoretically crash Citra here by specifying too large
// framebuffer sizes. We should make sure that this cannot happen.
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer.width, framebuffer.height,
- GL_BGR, GL_UNSIGNED_BYTE, framebuffer_data);
+ gltype, glformat, framebuffer_data);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
@@ -211,6 +235,7 @@ void RendererOpenGL::DrawScreens() {
DrawSingleScreenRotated(textures[0], top_x, 0,
(float)VideoCore::kScreenTopWidth, (float)VideoCore::kScreenTopHeight);
+ glFlush();
DrawSingleScreenRotated(textures[1], bottom_x, (float)VideoCore::kScreenTopHeight,
(float)VideoCore::kScreenBottomWidth, (float)VideoCore::kScreenBottomHeight);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment