Get GL_LEGACY working again (poorly)

This commit is contained in:
MysterD 2023-05-03 13:13:33 -07:00
parent 0bb7adfd2d
commit ab2cbb2dbc
6 changed files with 285 additions and 332 deletions

View file

@ -534,17 +534,17 @@ struct PcDebug gPcDebug = {
.tags = { .tags = {
0x0000000000000000, 0x0000000000000000,
0x000000000000FFFF, 0x000000000000FFFF,
0x440C28A5CC404F11, 0x2D1D50FB02617949,
0x2783114DDB90E597, 0x8AEB7180FAE739EB,
0x0EF4AF18EEC1303A, 0x0CDB1A233CC71057,
0x5E6A9446709E7CFF, 0x53D5D9880C8B278E,
0x914FA1C52D410003, 0xE8E307BE5802542E,
0xE9A402C28144FD8B, 0x8A3ACC4FDB4FFE45,
0x83B8B87B1E6A0B78, 0x09046C2BA3C5000D,
0xEE7B0ED661ABA0ED, 0xF027964ADE989C29,
0x076CF19655C70007, 0x076CF19655C70007,
0x9325E55A037D6511, 0x440C28A5CC404F11,
0x77ACD7B422D978A6, 0xE9A402C28144FD8B,
0x9A2269E87B26BE68, 0x9A2269E87B26BE68,
}, },
.id = DEFAULT_ID, .id = DEFAULT_ID,

View file

@ -4,45 +4,43 @@
#include "gfx_pc.h" #include "gfx_pc.h"
static u8 sAllowCCPrint = 1; static u8 sAllowCCPrint = 1;
void gfx_cc_get_features(uint32_t shader_id, struct CCFeatures *cc_features) {
// DO NOT COMMIT: TODO - need to fix this void gfx_cc_get_features(struct ColorCombiner* cc, struct CCFeatures* ccf) {
for (int32_t i = 0; i < 4; i++) { // DO NOT COMMIT: TODO - need to convert dx and regular gl
cc_features->c[0][i] = (shader_id >> (i * 3)) & 7;
cc_features->c[1][i] = (shader_id >> (12 + i * 3)) & 7; // reset ccf
memset(ccf, 0, sizeof(struct CCFeatures));
int cmd_length = cc->cm.use_2cycle ? 16 : 8;
for (int i = 0; i < cmd_length; i++) {
u8 c = cc->shader_commands[i];
if (c >= SHADER_INPUT_1 && c <= SHADER_INPUT_8) {
if (c > ccf->num_inputs) { ccf->num_inputs = c; }
}
ccf->used_textures[0] = ccf->used_textures[0] || c == SHADER_TEXEL0 || c == SHADER_TEXEL0A;
ccf->used_textures[1] = ccf->used_textures[1] || c == SHADER_TEXEL1 || c == SHADER_TEXEL1A;
} }
cc_features->opt_alpha = (shader_id & SHADER_OPT_ALPHA) != 0; // figure out optimizations
cc_features->opt_fog = (shader_id & SHADER_OPT_FOG) != 0; for (int i = 0; i < 16 / 4; i++) {
cc_features->opt_texture_edge = (shader_id & SHADER_OPT_TEXTURE_EDGE) != 0; u8* c = &cc->shader_commands[i * 4];
cc_features->opt_noise = (shader_id & SHADER_OPT_NOISE) != 0; ccf->do_single[i] = (c[2] == 0);
ccf->do_multiply[i] = (c[1] == 0 && c[3] == 0);
ccf->do_mix[i] = (c[1] == c[3]);
}
cc_features->used_textures[0] = false; ccf->color_alpha_same[0] = 1;
cc_features->used_textures[1] = false; ccf->color_alpha_same[1] = 1;
cc_features->num_inputs = 0;
for (int32_t i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
for (int32_t j = 0; j < 4; j++) { u8* cmd = &cc->shader_commands[i * 8];
if (cc_features->c[i][j] >= SHADER_INPUT_1 && cc_features->c[i][j] <= SHADER_INPUT_8) { for (int j = 0; j < 4; j++) {
if (cc_features->c[i][j] > cc_features->num_inputs) { if (cmd[j] != cmd[j + 4]) {
cc_features->num_inputs = cc_features->c[i][j]; ccf->color_alpha_same[i] = 0;
} break;
}
if (cc_features->c[i][j] == SHADER_TEXEL0 || cc_features->c[i][j] == SHADER_TEXEL0A) {
cc_features->used_textures[0] = true;
}
if (cc_features->c[i][j] == SHADER_TEXEL1 || cc_features->c[i][j] == SHADER_TEXEL1A) {
cc_features->used_textures[1] = true;
} }
} }
} }
cc_features->do_single[0] = cc_features->c[0][2] == 0;
cc_features->do_single[1] = cc_features->c[1][2] == 0;
cc_features->do_multiply[0] = cc_features->c[0][1] == 0 && cc_features->c[0][3] == 0;
cc_features->do_multiply[1] = cc_features->c[1][1] == 0 && cc_features->c[1][3] == 0;
cc_features->do_mix[0] = cc_features->c[0][1] == cc_features->c[0][3];
cc_features->do_mix[1] = cc_features->c[1][1] == cc_features->c[1][3];
cc_features->color_alpha_same = (shader_id & 0xfff) == ((shader_id >> 12) & 0xfff);
} }
void gfx_cc_print(struct ColorCombiner *cc) { void gfx_cc_print(struct ColorCombiner *cc) {
@ -103,6 +101,197 @@ void gfx_cc_precomp(void) {
gfx_pc_precomp_shader(0x04060401, 0x05000000, 0x04060402, 0x05000b0b, 0x00000001); // 1d970841b086b2e6 gfx_pc_precomp_shader(0x04060401, 0x05000000, 0x04060402, 0x05000b0b, 0x00000001); // 1d970841b086b2e6
gfx_pc_precomp_shader(0x01000000, 0x04000000, 0x02000000, 0x04000b0b, 0x00000001); // 410000008f86b2e6 gfx_pc_precomp_shader(0x01000000, 0x04000000, 0x02000000, 0x04000b0b, 0x00000001); // 410000008f86b2e6
sAllowCCPrint = 1; sAllowCCPrint = 1;
} }
static uint8_t color_comb_component_a(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
case G_CCMUX_1: return CC_1;
//case G_CCMUX_NOISE: return CC_NOISE;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
default: return CC_0;
}
}
static uint8_t color_comb_component_b(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
//case G_CCMUX_CENTER: return CC_CENTER; // is this correct for "Chrome Key Center"?
//case G_CCMUX_K4: return CC_K4;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
default: return CC_0;
}
}
static uint8_t color_comb_component_c(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
//case G_CCMUX_CENTER: return CC_CENTER; // is this correct for "Chrome Key Center"?
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_LOD_FRACTION: return CC_LOD;
//case G_CCMUX_PRIM_LOD_FRAC: return CC_PRIM_LOD_FRACTION;
//case G_CCMUX_K5: return CC_K5;
case G_CCMUX_0: return CC_0;
default: return CC_0;
}
}
static uint8_t color_comb_component_d(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
default: return CC_0;
}
}
uint32_t color_comb_rgb(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint8_t cycle) {
return color_comb_component_a(a, cycle)
| (color_comb_component_b(b, cycle) << 8)
| (color_comb_component_c(c, cycle) << 16)
| (color_comb_component_d(d, cycle) << 24);
}
static uint8_t color_comb_component_a_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static uint8_t color_comb_component_b_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static uint8_t color_comb_component_c_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_LOD_FRACTION: return CC_LOD;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
//case G_CCMUX_PRIM_LOD_FRAC: return CC_PRIM_LOD_FRACTION;
case G_CCMUX_0: return CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static uint8_t color_comb_component_d_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
uint32_t color_comb_alpha(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint8_t cycle) {
return color_comb_component_a_alpha(a, cycle)
| (color_comb_component_b_alpha(b, cycle) << 8)
| (color_comb_component_c_alpha(c, cycle) << 16)
| (color_comb_component_d_alpha(d, cycle) << 24);
}

View file

@ -48,17 +48,12 @@ enum {
#define SHADER_OPT_NOISE (1 << 27) #define SHADER_OPT_NOISE (1 << 27)
struct CCFeatures { struct CCFeatures {
uint8_t c[2][4];
bool opt_alpha;
bool opt_fog;
bool opt_texture_edge;
bool opt_noise;
bool used_textures[2]; bool used_textures[2];
int num_inputs; int num_inputs;
bool do_single[2]; bool do_single[4];
bool do_multiply[2]; bool do_multiply[4];
bool do_mix[2]; bool do_mix[4];
bool color_alpha_same; bool color_alpha_same[2];
}; };
#pragma pack(1) #pragma pack(1)
@ -107,9 +102,11 @@ struct ColorCombiner {
extern "C" { extern "C" {
#endif #endif
void gfx_cc_get_features(uint32_t shader_id, struct CCFeatures *cc_features); void gfx_cc_get_features(struct ColorCombiner* cc, struct CCFeatures *cc_features);
void gfx_cc_print(struct ColorCombiner *cc); void gfx_cc_print(struct ColorCombiner *cc);
void gfx_cc_precomp(void); void gfx_cc_precomp(void);
uint32_t color_comb_rgb(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint8_t cycle);
uint32_t color_comb_alpha(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint8_t cycle);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -237,6 +237,9 @@ static void append_formula(char *buf, size_t *len, uint8_t* cmd, bool do_single,
} }
static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorCombiner* cc) { static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorCombiner* cc) {
struct CCFeatures ccf = { 0 };
gfx_cc_get_features(cc, &ccf);
bool opt_alpha = cc->cm.use_alpha; bool opt_alpha = cc->cm.use_alpha;
bool opt_fog = cc->cm.use_fog; bool opt_fog = cc->cm.use_fog;
bool opt_texture_edge = cc->cm.texture_edge; bool opt_texture_edge = cc->cm.texture_edge;
@ -249,40 +252,6 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
bool opt_noise = cc->cm.use_noise; bool opt_noise = cc->cm.use_noise;
#endif #endif
bool used_textures[2] = { 0 };
int num_inputs = 0;
int cmd_length = opt_2cycle ? 16 : 8;
for (int i = 0; i < cmd_length; i++) {
u8 c = cc->shader_commands[i];
if (c >= SHADER_INPUT_1 && c <= SHADER_INPUT_8) {
if (c > num_inputs) { num_inputs = c; }
}
used_textures[0] = used_textures[0] || c == SHADER_TEXEL0 || c == SHADER_TEXEL0A;
used_textures[1] = used_textures[1] || c == SHADER_TEXEL1 || c == SHADER_TEXEL1A;
}
// figure out optimizations
bool do_single[4] = { 0 };
bool do_multiply[4] = { 0 };
bool do_mix[4] = { 0 };
for (int i = 0; i < 16 / 4; i++) {
u8* c = &cc->shader_commands[i * 4];
do_single[i] = (c[2] == 0);
do_multiply[i] = (c[1] == 0 && c[3] == 0);
do_mix[i] = (c[1] == c[3]);
}
bool color_alpha_same[2] = { 1, 1 };
for (int i = 0; i < 2; i++) {
u8* cmd = &cc->shader_commands[i * 8];
for (int j = 0; j < 4; j++) {
if (cmd[j] != cmd[j + 4]) {
color_alpha_same[i] = 0;
break;
}
}
}
char vs_buf[1024]; char vs_buf[1024];
char fs_buf[2048]; char fs_buf[2048];
size_t vs_len = 0; size_t vs_len = 0;
@ -296,7 +265,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
append_line(vs_buf, &vs_len, "#version 120"); append_line(vs_buf, &vs_len, "#version 120");
#endif #endif
append_line(vs_buf, &vs_len, "attribute vec4 aVtxPos;"); append_line(vs_buf, &vs_len, "attribute vec4 aVtxPos;");
if (used_textures[0] || used_textures[1]) { if (ccf.used_textures[0] || ccf.used_textures[1]) {
append_line(vs_buf, &vs_len, "attribute vec2 aTexCoord;"); append_line(vs_buf, &vs_len, "attribute vec2 aTexCoord;");
append_line(vs_buf, &vs_len, "varying vec2 vTexCoord;"); append_line(vs_buf, &vs_len, "varying vec2 vTexCoord;");
num_floats += 2; num_floats += 2;
@ -311,13 +280,13 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
append_line(vs_buf, &vs_len, "varying vec2 vLightMap;"); append_line(vs_buf, &vs_len, "varying vec2 vLightMap;");
num_floats += 2; num_floats += 2;
} }
for (int i = 0; i < num_inputs; i++) { for (int i = 0; i < ccf.num_inputs; i++) {
vs_len += sprintf(vs_buf + vs_len, "attribute vec%d aInput%d;\n", opt_alpha ? 4 : 3, i + 1); vs_len += sprintf(vs_buf + vs_len, "attribute vec%d aInput%d;\n", opt_alpha ? 4 : 3, i + 1);
vs_len += sprintf(vs_buf + vs_len, "varying vec%d vInput%d;\n", opt_alpha ? 4 : 3, i + 1); vs_len += sprintf(vs_buf + vs_len, "varying vec%d vInput%d;\n", opt_alpha ? 4 : 3, i + 1);
num_floats += opt_alpha ? 4 : 3; num_floats += opt_alpha ? 4 : 3;
} }
append_line(vs_buf, &vs_len, "void main() {"); append_line(vs_buf, &vs_len, "void main() {");
if (used_textures[0] || used_textures[1]) { if (ccf.used_textures[0] || ccf.used_textures[1]) {
append_line(vs_buf, &vs_len, "vTexCoord = aTexCoord;"); append_line(vs_buf, &vs_len, "vTexCoord = aTexCoord;");
} }
if (opt_fog) { if (opt_fog) {
@ -326,7 +295,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
if (opt_light_map) { if (opt_light_map) {
append_line(vs_buf, &vs_len, "vLightMap = aLightMap;"); append_line(vs_buf, &vs_len, "vLightMap = aLightMap;");
} }
for (int i = 0; i < num_inputs; i++) { for (int i = 0; i < ccf.num_inputs; i++) {
vs_len += sprintf(vs_buf + vs_len, "vInput%d = aInput%d;\n", i + 1, i + 1); vs_len += sprintf(vs_buf + vs_len, "vInput%d = aInput%d;\n", i + 1, i + 1);
} }
append_line(vs_buf, &vs_len, "gl_Position = aVtxPos;"); append_line(vs_buf, &vs_len, "gl_Position = aVtxPos;");
@ -340,7 +309,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
append_line(fs_buf, &fs_len, "#version 120"); append_line(fs_buf, &fs_len, "#version 120");
#endif #endif
if (used_textures[0] || used_textures[1]) { if (ccf.used_textures[0] || ccf.used_textures[1]) {
append_line(fs_buf, &fs_len, "varying vec2 vTexCoord;"); append_line(fs_buf, &fs_len, "varying vec2 vTexCoord;");
} }
if (opt_fog) { if (opt_fog) {
@ -349,15 +318,15 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
if (opt_light_map) { if (opt_light_map) {
append_line(fs_buf, &fs_len, "varying vec2 vLightMap;"); append_line(fs_buf, &fs_len, "varying vec2 vLightMap;");
} }
for (int i = 0; i < num_inputs; i++) { for (int i = 0; i < ccf.num_inputs; i++) {
fs_len += sprintf(fs_buf + fs_len, "varying vec%d vInput%d;\n", opt_alpha ? 4 : 3, i + 1); fs_len += sprintf(fs_buf + fs_len, "varying vec%d vInput%d;\n", opt_alpha ? 4 : 3, i + 1);
} }
if (used_textures[0]) { if (ccf.used_textures[0]) {
append_line(fs_buf, &fs_len, "uniform sampler2D uTex0;"); append_line(fs_buf, &fs_len, "uniform sampler2D uTex0;");
append_line(fs_buf, &fs_len, "uniform vec2 uTex0Size;"); append_line(fs_buf, &fs_len, "uniform vec2 uTex0Size;");
append_line(fs_buf, &fs_len, "uniform bool uTex0Filter;"); append_line(fs_buf, &fs_len, "uniform bool uTex0Filter;");
} }
if (used_textures[1]) { if (ccf.used_textures[1]) {
append_line(fs_buf, &fs_len, "uniform sampler2D uTex1;"); append_line(fs_buf, &fs_len, "uniform sampler2D uTex1;");
append_line(fs_buf, &fs_len, "uniform vec2 uTex1Size;"); append_line(fs_buf, &fs_len, "uniform vec2 uTex1Size;");
append_line(fs_buf, &fs_len, "uniform bool uTex1Filter;"); append_line(fs_buf, &fs_len, "uniform bool uTex1Filter;");
@ -367,7 +336,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
// Original author: ArthurCarvalho // Original author: ArthurCarvalho
// Slightly modified GLSL implementation by twinaphex, mupen64plus-libretro project. // Slightly modified GLSL implementation by twinaphex, mupen64plus-libretro project.
if (used_textures[0] || used_textures[1]) { if (ccf.used_textures[0] || ccf.used_textures[1]) {
if (configFiltering == 2) { if (configFiltering == 2) {
append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture2D(tex, texCoord - (off)/texSize)"); append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture2D(tex, texCoord - (off)/texSize)");
append_line(fs_buf, &fs_len, "vec4 filter3point(in sampler2D tex, in vec2 texCoord, in vec2 texSize) {"); append_line(fs_buf, &fs_len, "vec4 filter3point(in sampler2D tex, in vec2 texCoord, in vec2 texSize) {");
@ -402,10 +371,10 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
append_line(fs_buf, &fs_len, "void main() {"); append_line(fs_buf, &fs_len, "void main() {");
if (used_textures[0]) { if (ccf.used_textures[0]) {
append_line(fs_buf, &fs_len, "vec4 texVal0 = sampleTex(uTex0, vTexCoord, uTex0Size, uTex0Filter);"); append_line(fs_buf, &fs_len, "vec4 texVal0 = sampleTex(uTex0, vTexCoord, uTex0Size, uTex0Filter);");
} }
if (used_textures[1]) { if (ccf.used_textures[1]) {
if (cc->cm.light_map) { if (cc->cm.light_map) {
append_line(fs_buf, &fs_len, "vec4 texVal1 = sampleTex(uTex1, vLightMap, uTex1Size, uTex1Filter);"); append_line(fs_buf, &fs_len, "vec4 texVal1 = sampleTex(uTex1, vLightMap, uTex1Size, uTex1Filter);");
} else { } else {
@ -416,14 +385,14 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
append_str(fs_buf, &fs_len, (opt_alpha) ? "vec4 texel = " : "vec3 texel = "); append_str(fs_buf, &fs_len, (opt_alpha) ? "vec4 texel = " : "vec3 texel = ");
for (int i = 0; i < (opt_2cycle + 1); i++) { for (int i = 0; i < (opt_2cycle + 1); i++) {
u8* cmd = &cc->shader_commands[i * 8]; u8* cmd = &cc->shader_commands[i * 8];
if (!color_alpha_same[i] && opt_alpha) { if (!ccf.color_alpha_same[i] && opt_alpha) {
append_str(fs_buf, &fs_len, "vec4("); append_str(fs_buf, &fs_len, "vec4(");
append_formula(fs_buf, &fs_len, cmd, do_single[i*2+0], do_multiply[i*2+0], do_mix[i*2+0], false, false, true); append_formula(fs_buf, &fs_len, cmd, ccf.do_single[i*2+0], ccf.do_multiply[i*2+0], ccf.do_mix[i*2+0], false, false, true);
append_str(fs_buf, &fs_len, ", "); append_str(fs_buf, &fs_len, ", ");
append_formula(fs_buf, &fs_len, cmd, do_single[i*2+1], do_multiply[i*2+1], do_mix[i*2+1], true, true, true); append_formula(fs_buf, &fs_len, cmd, ccf.do_single[i*2+1], ccf.do_multiply[i*2+1], ccf.do_mix[i*2+1], true, true, true);
append_str(fs_buf, &fs_len, ")"); append_str(fs_buf, &fs_len, ")");
} else { } else {
append_formula(fs_buf, &fs_len, cmd, do_single[i*2+0], do_multiply[i*2+0], do_mix[i*2+0], opt_alpha, false, opt_alpha); append_formula(fs_buf, &fs_len, cmd, ccf.do_single[i*2+0], ccf.do_multiply[i*2+0], ccf.do_mix[i*2+0], opt_alpha, false, opt_alpha);
} }
append_line(fs_buf, &fs_len, ";"); append_line(fs_buf, &fs_len, ";");
@ -509,7 +478,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
prg->attrib_sizes[cnt] = 4; prg->attrib_sizes[cnt] = 4;
++cnt; ++cnt;
if (used_textures[0] || used_textures[1]) { if (ccf.used_textures[0] || ccf.used_textures[1]) {
prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, "aTexCoord"); prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, "aTexCoord");
prg->attrib_sizes[cnt] = 2; prg->attrib_sizes[cnt] = 2;
++cnt; ++cnt;
@ -527,7 +496,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
++cnt; ++cnt;
} }
for (int i = 0; i < num_inputs; i++) { for (int i = 0; i < ccf.num_inputs; i++) {
char name[16]; char name[16];
sprintf(name, "aInput%d", i + 1); sprintf(name, "aInput%d", i + 1);
prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, name); prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, name);
@ -537,21 +506,21 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
prg->hash = cc->hash; prg->hash = cc->hash;
prg->opengl_program_id = shader_program; prg->opengl_program_id = shader_program;
prg->num_inputs = num_inputs; prg->num_inputs = ccf.num_inputs;
prg->used_textures[0] = used_textures[0]; prg->used_textures[0] = ccf.used_textures[0];
prg->used_textures[1] = used_textures[1]; prg->used_textures[1] = ccf.used_textures[1];
prg->num_floats = num_floats; prg->num_floats = num_floats;
prg->num_attribs = cnt; prg->num_attribs = cnt;
gfx_opengl_load_shader(prg); gfx_opengl_load_shader(prg);
if (used_textures[0]) { if (ccf.used_textures[0]) {
GLint sampler_location = glGetUniformLocation(shader_program, "uTex0"); GLint sampler_location = glGetUniformLocation(shader_program, "uTex0");
prg->uniform_locations[0] = glGetUniformLocation(shader_program, "uTex0Size"); prg->uniform_locations[0] = glGetUniformLocation(shader_program, "uTex0Size");
prg->uniform_locations[1] = glGetUniformLocation(shader_program, "uTex0Filter"); prg->uniform_locations[1] = glGetUniformLocation(shader_program, "uTex0Filter");
glUniform1i(sampler_location, 0); glUniform1i(sampler_location, 0);
} }
if (used_textures[1]) { if (ccf.used_textures[1]) {
GLint sampler_location = glGetUniformLocation(shader_program, "uTex1"); GLint sampler_location = glGetUniformLocation(shader_program, "uTex1");
prg->uniform_locations[2] = glGetUniformLocation(shader_program, "uTex1Size"); prg->uniform_locations[2] = glGetUniformLocation(shader_program, "uTex1Size");
prg->uniform_locations[3] = glGetUniformLocation(shader_program, "uTex1Filter"); prg->uniform_locations[3] = glGetUniformLocation(shader_program, "uTex1Filter");

View file

@ -49,8 +49,9 @@ enum MixType {
struct ShaderProgram { struct ShaderProgram {
bool enabled; bool enabled;
uint32_t shader_id; uint64_t hash;
struct CCFeatures cc; struct ColorCombiner cc;
struct CCFeatures ccf;
enum MixType mix; enum MixType mix;
bool texture_used[2]; bool texture_used[2];
int texture_ord[2]; int texture_ord[2];
@ -140,25 +141,12 @@ static inline GLenum texenv_set_texture(UNUSED struct ShaderProgram *prg) {
} }
static inline GLenum texenv_set_texture_color(struct ShaderProgram *prg) { static inline GLenum texenv_set_texture_color(struct ShaderProgram *prg) {
GLenum mode;
// HACK: lord forgive me for this, but this is easier // HACK: lord forgive me for this, but this is easier
if (prg->cc.cm.rgb1 == color_comb_rgb(G_CCMUX_TEXEL0, G_CCMUX_SHADE, G_CCMUX_TEXEL0_ALPHA, G_CCMUX_SHADE, 0)) {
switch (prg->shader_id) { return GL_DECAL;
case 0x0000038D: // mario's eyes } else {
case 0x01045A00: // peach letter return GL_MODULATE;
case 0x01200A00: // intro copyright fade in
mode = GL_DECAL;
break;
case 0x00000551: // goddard
mode = GL_BLEND;
break;
default:
mode = GL_MODULATE;
break;
} }
return mode;
} }
static inline GLenum texenv_set_texture_texture(UNUSED struct ShaderProgram *prg) { static inline GLenum texenv_set_texture_texture(UNUSED struct ShaderProgram *prg) {
@ -183,7 +171,7 @@ static void gfx_opengl_apply_shader(struct ShaderProgram *prg) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
} }
if (prg->shader_id & SHADER_OPT_FOG) { if (prg->cc.cm.use_fog) {
// blend it on top of normal tris later // blend it on top of normal tris later
cur_fog_ofs = ofs; cur_fog_ofs = ofs;
ofs += 4; ofs += 4;
@ -195,10 +183,10 @@ static void gfx_opengl_apply_shader(struct ShaderProgram *prg) {
// HACK: if there's a texture and two colors, one of them is likely for speculars or some shit (see mario head) // HACK: if there's a texture and two colors, one of them is likely for speculars or some shit (see mario head)
// if there's two colors but no texture, the real color is likely the second one // if there's two colors but no texture, the real color is likely the second one
// HACKHACK: alpha is 0 in the transition shader (0x01A00045), maybe figure out the flags instead // HACKHACK: alpha is 0 in the transition shader (0x01A00045), maybe figure out the flags instead
const int vlen = (prg->cc.opt_alpha && prg->shader_id != 0x01A00045) ? 4 : 3; const int vlen = (prg->cc.cm.use_alpha /*&& prg->shader_id != 0x01A00045*/) ? 4 : 3;
const int hack = vlen * (prg->num_inputs > 1); const int hack = vlen * (prg->num_inputs > 1);
if (prg->texture_used[1] && prg->cc.do_mix[0]) { if (prg->texture_used[1] && prg->ccf.do_mix[0]) {
// HACK: when two textures are mixed by vertex color, store the color // HACK: when two textures are mixed by vertex color, store the color
// it will be used later when rendering two texture passes // it will be used later when rendering two texture passes
c_mix[0] = *(ofs + hack + 0); c_mix[0] = *(ofs + hack + 0);
@ -224,7 +212,7 @@ static void gfx_opengl_apply_shader(struct ShaderProgram *prg) {
// we only need to do this once // we only need to do this once
prg->enabled = true; prg->enabled = true;
if (prg->shader_id & SHADER_OPT_TEXTURE_EDGE) { if (prg->cc.cm.texture_edge) {
// (horrible) alpha discard // (horrible) alpha discard
glEnable(GL_ALPHA_TEST); glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.666f); glAlphaFunc(GL_GREATER, 0.666f);
@ -258,14 +246,15 @@ static void gfx_opengl_load_shader(struct ShaderProgram *new_prg) {
cur_shader->enabled = false; cur_shader->enabled = false;
} }
static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shader_id) { static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorCombiner* cc) {
struct CCFeatures ccf;
gfx_cc_get_features(shader_id, &ccf);
struct ShaderProgram *prg = &shader_program_pool[shader_program_pool_size++]; struct ShaderProgram *prg = &shader_program_pool[shader_program_pool_size++];
prg->shader_id = shader_id; struct CCFeatures ccf = { 0 };
prg->cc = ccf; gfx_cc_get_features(cc, &ccf);
prg->hash = cc->hash;
prg->cc = *cc;
prg->ccf = ccf;
prg->num_inputs = ccf.num_inputs; prg->num_inputs = ccf.num_inputs;
prg->texture_used[0] = ccf.used_textures[0]; prg->texture_used[0] = ccf.used_textures[0];
prg->texture_used[1] = ccf.used_textures[1]; prg->texture_used[1] = ccf.used_textures[1];
@ -296,9 +285,9 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shad
return prg; return prg;
} }
static struct ShaderProgram *gfx_opengl_lookup_shader(uint32_t shader_id) { static struct ShaderProgram *gfx_opengl_lookup_shader(struct ColorCombiner* cc) {
for (size_t i = 0; i < shader_program_pool_size; i++) for (size_t i = 0; i < shader_program_pool_size; i++)
if (shader_program_pool[i].shader_id == shader_id) if (shader_program_pool[i].hash == cc->hash)
return &shader_program_pool[i]; return &shader_program_pool[i];
return NULL; return NULL;
} }

View file

@ -1407,197 +1407,6 @@ static void gfx_dp_load_tile(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t
rdp.texture_tile.lrt = lrt; rdp.texture_tile.lrt = lrt;
} }
static uint8_t color_comb_component_a(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
case G_CCMUX_1: return CC_1;
//case G_CCMUX_NOISE: return CC_NOISE;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
default: return CC_0;
}
}
static uint8_t color_comb_component_b(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
//case G_CCMUX_CENTER: return CC_CENTER; // is this correct for "Chrome Key Center"?
//case G_CCMUX_K4: return CC_K4;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
default: return CC_0;
}
}
static uint8_t color_comb_component_c(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
//case G_CCMUX_CENTER: return CC_CENTER; // is this correct for "Chrome Key Center"?
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_LOD_FRACTION: return CC_LOD;
//case G_CCMUX_PRIM_LOD_FRAC: return CC_PRIM_LOD_FRACTION;
//case G_CCMUX_K5: return CC_K5;
case G_CCMUX_0: return CC_0;
default: return CC_0;
}
}
static uint8_t color_comb_component_d(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
default: return CC_0;
}
}
static inline uint32_t color_comb_rgb(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint8_t cycle) {
return color_comb_component_a(a, cycle)
| (color_comb_component_b(b, cycle) << 8)
| (color_comb_component_c(c, cycle) << 16)
| (color_comb_component_d(d, cycle) << 24);
}
static uint8_t color_comb_component_a_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static uint8_t color_comb_component_b_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static uint8_t color_comb_component_c_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_LOD_FRACTION: return CC_LOD;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
//case G_CCMUX_PRIM_LOD_FRAC: return CC_PRIM_LOD_FRACTION;
case G_CCMUX_0: return CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static uint8_t color_comb_component_d_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static inline uint32_t color_comb_alpha(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint8_t cycle) {
return color_comb_component_a_alpha(a, cycle)
| (color_comb_component_b_alpha(b, cycle) << 8)
| (color_comb_component_c_alpha(c, cycle) << 16)
| (color_comb_component_d_alpha(d, cycle) << 24);
}
static void gfx_dp_set_combine_mode(uint32_t rgb1, uint32_t alpha1, uint32_t rgb2, uint32_t alpha2) { static void gfx_dp_set_combine_mode(uint32_t rgb1, uint32_t alpha1, uint32_t rgb2, uint32_t alpha2) {
//printf(">>> combine: %08x %08x %08x %08x\n", rgb1, alpha1, rgb2, alpha2); //printf(">>> combine: %08x %08x %08x %08x\n", rgb1, alpha1, rgb2, alpha2);
memset(&rdp.combine_mode, 0, sizeof(struct CombineMode)); memset(&rdp.combine_mode, 0, sizeof(struct CombineMode));