diff --git a/src/dual/include/dual/nds/video_unit/gpu/gpu.hpp b/src/dual/include/dual/nds/video_unit/gpu/gpu.hpp index b52be8c..d48983f 100644 --- a/src/dual/include/dual/nds/video_unit/gpu/gpu.hpp +++ b/src/dual/include/dual/nds/video_unit/gpu/gpu.hpp @@ -68,14 +68,20 @@ namespace dual::nds { m_cmd_processor.Write_GXSTAT(value, mask); } + void Write_ALPHA_TEST_REF(u32 value, u32 mask) { + const u32 write_mask = 0x1Fu & mask; + + m_io.alpha_test_ref = (value & write_mask) | (m_io.alpha_test_ref & ~write_mask); + } + void Write_CLEAR_COLOR(u32 value, u32 mask) { const u32 write_mask = 0x3F1FFFFFu & mask; m_io.clear_color.word = (value & write_mask) | (m_io.clear_color.word & ~write_mask); } - void Write_CLEAR_DEPTH(u16 value, u16 mask) { - const u16 write_mask = 0x7FFFu & mask; + void Write_CLEAR_DEPTH(u32 value, u32 mask) { + const u32 write_mask = 0x7FFFu & mask; m_io.clear_depth = (value & write_mask) | (m_io.clear_depth & ~write_mask); } diff --git a/src/dual/include/dual/nds/video_unit/gpu/registers.hpp b/src/dual/include/dual/nds/video_unit/gpu/registers.hpp index cb86556..20fb8ab 100644 --- a/src/dual/include/dual/nds/video_unit/gpu/registers.hpp +++ b/src/dual/include/dual/nds/video_unit/gpu/registers.hpp @@ -59,8 +59,9 @@ namespace dual::nds::gpu { struct IO { DISP3DCNT disp3dcnt; GXSTAT gxstat; + u32 alpha_test_ref{}; CLEAR_COLOR clear_color; - u16 clear_depth{}; + u32 clear_depth{}; }; } // namespace dual::nds::gpu diff --git a/src/dual/src/nds/arm9/io.cpp b/src/dual/src/nds/arm9/io.cpp index 7b09086..9b107c2 100644 --- a/src/dual/src/nds/arm9/io.cpp +++ b/src/dual/src/nds/arm9/io.cpp @@ -377,8 +377,9 @@ namespace dual::nds::arm9 { case REG(0x04000304): hw.video_unit.Write_POWCNT((u16)value, (u16)mask); break; // GPU3D + case REG(0x04000340): if(gpu.GetRenderEnginePowerOn()) gpu.Write_ALPHA_TEST_REF(value, mask); break; case REG(0x04000350): if(gpu.GetRenderEnginePowerOn()) gpu.Write_CLEAR_COLOR(value, mask); break; - case REG(0x04000354): if(gpu.GetRenderEnginePowerOn()) gpu.Write_CLEAR_DEPTH((u16)value, (u16)mask); break; + case REG(0x04000354): if(gpu.GetRenderEnginePowerOn()) gpu.Write_CLEAR_DEPTH(value, mask); break; case REG(0x04000400): // GXFIFO (mirrored from 04000400 to 0400043C) case REG(0x04000404): case REG(0x04000408): diff --git a/src/dual/src/nds/video_unit/gpu/renderer/software/rasterizer.cpp b/src/dual/src/nds/video_unit/gpu/renderer/software/rasterizer.cpp index 46ca952..9786083 100644 --- a/src/dual/src/nds/video_unit/gpu/renderer/software/rasterizer.cpp +++ b/src/dual/src/nds/video_unit/gpu/renderer/software/rasterizer.cpp @@ -212,6 +212,12 @@ namespace dual::nds::gpu { const int x_min = line.x[0]; const int x_max = line.x[1]; + int alpha_test_threshold = 0u; + + if(m_io.disp3dcnt.enable_alpha_test) { + alpha_test_threshold = m_io.alpha_test_ref << 1 | m_io.alpha_test_ref >> 4; + } + for(int x = x0; x <= x1; x++) { line_interp.Setup(line.w_16[0], line.w_16[1], x, x_min, x_max); @@ -237,7 +243,9 @@ namespace dual::nds::gpu { if(m_io.disp3dcnt.enable_texture_mapping && polygon.texture_params.format != TextureParams::Format::Disabled) { const Color4 texel = SampleTexture(polygon.texture_params, polygon.palette_base, uv); - // @todo: alpha test + if(texel.A().Raw() <= alpha_test_threshold) { + continue; + } switch((Polygon::Mode)polygon.attributes.polygon_mode) { case Polygon::Mode::Modulation: {