diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h index fa62536181..ae9e192ef2 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -315,11 +315,14 @@ #define NV_PGRAPH_CSV0_C 0x00000FB8 # define NV_PGRAPH_CSV0_C_CHEOPS_PROGRAM_START 0x0000FF00 # define NV_PGRAPH_CSV0_C_SPECULAR_ENABLE (1 << 16) +# define NV_PGRAPH_CSV0_C_ALPHA_FROM_MATERIAL_SPECULAR (1 << 17) +# define NV_PGRAPH_CSV0_C_SEPARATE_SPECULAR (1 << 18) # define NV_PGRAPH_CSV0_C_SPECULAR (3 << 19) # define NV_PGRAPH_CSV0_C_DIFFUSE (3 << 21) # define NV_PGRAPH_CSV0_C_AMBIENT (3 << 23) # define NV_PGRAPH_CSV0_C_EMISSION (3 << 25) # define NV_PGRAPH_CSV0_C_NORMALIZATION_ENABLE (1 << 27) +# define NV_PGRAPH_CSV0_C_LOCALEYE (1 << 30) # define NV_PGRAPH_CSV0_C_LIGHTING (1 << 31) #define NV_PGRAPH_CSV1_B 0x00000FBC #define NV_PGRAPH_CSV1_A 0x00000FC0 @@ -882,6 +885,10 @@ # define NV097_SET_CONTROL0_STENCIL_WRITE_ENABLE (1 << 0) # define NV097_SET_CONTROL0_Z_FORMAT (1 << 12) # define NV097_SET_CONTROL0_Z_PERSPECTIVE_ENABLE (1 << 16) +# define NV097_SET_LIGHT_CONTROL 0x00000294 +# define NV097_SET_LIGHT_CONTROL_SEPARATE_SPECULAR 1 +# define NV097_SET_LIGHT_CONTROL_LOCALEYE (1 << 16) +# define NV097_SET_LIGHT_CONTROL_ALPHA_FROM_MATERIAL_SPECULAR (1 << 17) # define NV097_SET_COLOR_MATERIAL 0x00000298 # define NV097_SET_FOG_MODE 0x0000029C # define NV097_SET_FOG_MODE_V_LINEAR 0x2601 diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c index 445ce73066..b3c72bb2c2 100644 --- a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c +++ b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c @@ -384,13 +384,25 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz mstring_append(body, " oD1 = specular;\n"); } - if (!state->specular_enable) { - mstring_append(body, " oD1 = vec4(0.0, 0.0, 0.0, 1.0);\n"); - } - mstring_append(body, " oB0 = backDiffuse;\n"); mstring_append(body, " oB1 = backSpecular;\n"); + if (!state->specular_enable) { + mstring_append(body, " oD1 = vec4(0.0, 0.0, 0.0, 1.0);\n"); + mstring_append(body, " oB1 = vec4(0.0, 0.0, 0.0, 1.0);\n"); + } else { + if (!state->separate_specular) { + mstring_append(body, " oD1 = specular;\n"); + mstring_append(body, " oB1 = backSpecular;\n"); + } + if (state->ignore_specular_alpha) { + mstring_append(body, + " oD1.w = 1.0;\n" + " oB1.a = 1.0;\n" + ); + } + } + /* Fog */ if (state->fog_enable) { diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh.c b/hw/xbox/nv2a/pgraph/glsl/vsh.c index 5fff5cf410..25c846bbde 100644 --- a/hw/xbox/nv2a/pgraph/glsl/vsh.c +++ b/hw/xbox/nv2a/pgraph/glsl/vsh.c @@ -256,6 +256,13 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs) " vtxD1 = clamp(oD1, 0.0, 1.0);\n" " vtxB1 = clamp(oB1, 0.0, 1.0);\n" ); + + if (state->ignore_specular_alpha) { + mstring_append(body, + " vtxD1.w = 1.0;\n" + " vtxB1.w = 1.0;\n" + ); + } } else { mstring_append(body, " vtxD1 = vec4(0.0, 0.0, 0.0, 1.0);\n" diff --git a/hw/xbox/nv2a/pgraph/methods.h.inc b/hw/xbox/nv2a/pgraph/methods.h.inc index fd6184426e..894dff7709 100644 --- a/hw/xbox/nv2a/pgraph/methods.h.inc +++ b/hw/xbox/nv2a/pgraph/methods.h.inc @@ -27,6 +27,7 @@ DEF_METHOD(NV097, SET_COMBINER_SPECULAR_FOG_CW0) DEF_METHOD(NV097, SET_COMBINER_SPECULAR_FOG_CW1) DEF_METHOD_CASE_4(NV097, SET_TEXTURE_ADDRESS, 64) DEF_METHOD(NV097, SET_CONTROL0) +DEF_METHOD(NV097, SET_LIGHT_CONTROL) DEF_METHOD(NV097, SET_COLOR_MATERIAL) DEF_METHOD(NV097, SET_FOG_MODE) DEF_METHOD(NV097, SET_FOG_GEN_MODE) diff --git a/hw/xbox/nv2a/pgraph/pgraph.c b/hw/xbox/nv2a/pgraph/pgraph.c index f0cc6d8ace..aaee7bf783 100644 --- a/hw/xbox/nv2a/pgraph/pgraph.c +++ b/hw/xbox/nv2a/pgraph/pgraph.c @@ -1075,6 +1075,18 @@ DEF_METHOD(NV097, SET_CONTROL0) z_perspective); } +DEF_METHOD(NV097, SET_LIGHT_CONTROL) +{ + PG_SET_MASK(NV_PGRAPH_CSV0_C, NV_PGRAPH_CSV0_C_SEPARATE_SPECULAR, + (parameter & NV097_SET_LIGHT_CONTROL_SEPARATE_SPECULAR) != 0); + + PG_SET_MASK(NV_PGRAPH_CSV0_C, NV_PGRAPH_CSV0_C_LOCALEYE, + (parameter & NV097_SET_LIGHT_CONTROL_LOCALEYE) != 0); + + PG_SET_MASK(NV_PGRAPH_CSV0_C, NV_PGRAPH_CSV0_C_ALPHA_FROM_MATERIAL_SPECULAR, + (parameter & NV097_SET_LIGHT_CONTROL_ALPHA_FROM_MATERIAL_SPECULAR) != 0); +} + DEF_METHOD(NV097, SET_COLOR_MATERIAL) { PG_SET_MASK(NV_PGRAPH_CSV0_C, NV_PGRAPH_CSV0_C_EMISSION, diff --git a/hw/xbox/nv2a/pgraph/shaders.c b/hw/xbox/nv2a/pgraph/shaders.c index dce6d05bb3..ce80dc127a 100644 --- a/hw/xbox/nv2a/pgraph/shaders.c +++ b/hw/xbox/nv2a/pgraph/shaders.c @@ -92,6 +92,11 @@ ShaderState pgraph_get_shader_state(PGRAPHState *pg) pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_SPECULAR); } + state.separate_specular = GET_MASK( + pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_SEPARATE_SPECULAR); + state.ignore_specular_alpha = !GET_MASK( + pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_ALPHA_FROM_MATERIAL_SPECULAR); + /* vertex program stuff */ state.vertex_program = vertex_program, state.z_perspective = pgraph_reg_r(pg, NV_PGRAPH_CONTROL_0) & diff --git a/hw/xbox/nv2a/pgraph/shaders.h b/hw/xbox/nv2a/pgraph/shaders.h index 7ff93a6302..9496cbbea2 100644 --- a/hw/xbox/nv2a/pgraph/shaders.h +++ b/hw/xbox/nv2a/pgraph/shaders.h @@ -79,6 +79,9 @@ typedef struct ShaderState { enum MaterialColorSource diffuse_src; enum MaterialColorSource specular_src; + bool separate_specular; + bool ignore_specular_alpha; + bool lighting; enum VshLight light[NV2A_MAX_LIGHTS];