Merge pull request #6559 from Cacodemon345/voodoo-alpha-planes

Implement Voodoo alpha planes and alpha mask support
This commit is contained in:
Miran Grča
2025-12-14 18:41:57 +01:00
committed by GitHub
3 changed files with 50 additions and 7 deletions

View File

@@ -656,6 +656,7 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params,
int block_pos = 0;
int z_skip_pos = 0;
int a_skip_pos = 0;
int amask_skip_pos = 0;
int chroma_skip_pos = 0;
int depth_jump_pos = 0;
int depth_jump_pos2 = 0;
@@ -1732,6 +1733,15 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params,
addbyte(0xdb);
break;
}
if (params->fbzMode & FBZ_ALPHA_MASK) {
addbyte(0xf7); /*TEST EBX, 1*/
addbyte(0xc3);
addlong(1);
addbyte(0x0f); /* JZ amask_skip_pos */
addbyte(0x84);
amask_skip_pos = block_pos;
addlong(0);
}
/*ECX = a_local*/
switch (cca_localselect) {
case CCA_LOCALSELECT_ITER_A:
@@ -2986,6 +2996,8 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params,
*(uint32_t *) &code_block[a_skip_pos] = (block_pos - a_skip_pos) - 4;
if (chroma_skip_pos)
*(uint32_t *) &code_block[chroma_skip_pos] = (block_pos - chroma_skip_pos) - 4;
if (amask_skip_pos)
*(uint32_t *) &code_block[amask_skip_pos] = (block_pos - amask_skip_pos) - 4;
addbyte(0x4c); /*MOV RSI, R15*/
addbyte(0x89);
@@ -3225,6 +3237,12 @@ voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *stat
voodoo_x86_data_t *voodoo_x86_data = voodoo->codegen_data;
voodoo_x86_data_t *data;
if (params->fbzMode & FBZ_ALPHA_ENABLE) {
// Lands of Lore III relies on the alpha buffer functionality to create its transparent textures.
// Fallback to interpreter.
return NULL;
}
for (uint8_t c = 0; c < 8; c++) {
data = &voodoo_x86_data[odd_even + c * 4]; //&voodoo_x86_data[odd_even][b];

View File

@@ -366,11 +366,14 @@ enum {
FBZ_DEPTH_WMASK = (1 << 10),
FBZ_DITHER_2x2 = (1 << 11),
FBZ_ALPHA_MASK = (1 << 13),
FBZ_DRAW_FRONT = 0x0000,
FBZ_DRAW_BACK = 0x4000,
FBZ_DRAW_MASK = 0xc000,
FBZ_DEPTH_BIAS = (1 << 16),
FBZ_ALPHA_ENABLE = (1 << 18),
FBZ_DITHER_SUB = (1 << 19),
FBZ_DEPTH_SOURCE = (1 << 20),
@@ -655,6 +658,8 @@ enum {
#define src_afunc ((params->alphaMode >> 8) & 0xf)
#define dest_afunc ((params->alphaMode >> 12) & 0xf)
#define src_aafunc ((params->alphaMode >> 16) & 0xf)
#define dest_aafunc ((params->alphaMode >> 20) & 0xf)
#define alpha_func ((params->alphaMode >> 1) & 7)
#define a_ref (params->alphaMode >> 24)
#define depth_op ((params->fbzMode >> 5) & 7)

View File

@@ -932,7 +932,7 @@ voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *
state->x = x;
state->x2 = x2;
#ifndef NO_CODEGEN
if (voodoo->use_recompiler) {
if (voodoo->use_recompiler && voodoo_draw) {
voodoo_draw(state, params, x, real_y);
} else
#endif
@@ -1017,6 +1017,13 @@ voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *
dest_b |= (dest_b >> 5);
dest_a = 0xff;
if (params->fbzMode & FBZ_ALPHA_ENABLE) {
if (voodoo->params.aux_tiled)
dest_a = aux_mem[x_tiled];
else
dest_a = aux_mem[x];
}
if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) {
if ((params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL || !voodoo->dual_tmus) {
/*TMU0 only sampling local colour or only one TMU, only sample TMU0*/
@@ -1032,11 +1039,6 @@ voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *
} else {
voodoo_tmu_fetch_and_blend(voodoo, params, state, x);
}
if ((params->fbzMode & FBZ_CHROMAKEY) && state->tex_r[0] == params->chromaKey_r && state->tex_g[0] == params->chromaKey_g && state->tex_b[0] == params->chromaKey_b) {
voodoo->fbiChromaFail++;
goto skip_pixel;
}
}
if (voodoo->trexInit1[0] & (1 << 18)) {
@@ -1088,6 +1090,11 @@ voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *
break;
}
if ((params->fbzMode & FBZ_CHROMAKEY) && cother_r == params->chromaKey_r && cother_g == params->chromaKey_g && cother_b == params->chromaKey_b) {
voodoo->fbiChromaFail++;
goto skip_pixel;
}
switch (cca_localselect) {
case CCA_LOCALSELECT_ITER_A:
alocal = CLAMP(state->ia >> 12);
@@ -1123,6 +1130,10 @@ voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *
break;
}
if ((params->fbzMode & FBZ_ALPHA_MASK) && !(aother & 1)) {
goto skip_pixel;
}
if (cc_zero_other) {
src_r = 0;
src_g = 0;
@@ -1283,6 +1294,9 @@ voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *
dest_b = dithersub_rb2x2[dest_b][real_y & 1][x & 1];
}
ALPHA_BLEND(src_r, src_g, src_b, src_a);
// TODO: Implement proper alpha blending support here for alpha values.
src_a = (((dest_aafunc == 4) ? dest_a * 256 : 0) + ((src_aafunc == 4) ? src_a * 256 : 0)) >> 8;
}
if (update) {
@@ -1308,7 +1322,13 @@ voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *
else
fb_mem[x] = src_b | (src_g << 5) | (src_r << 11);
}
if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) {
if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_ALPHA_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_ALPHA_ENABLE)) {
if (voodoo->params.aux_tiled)
aux_mem[x_tiled] = src_a;
else
aux_mem[x] = src_a;
}
else if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) {
if (voodoo->params.aux_tiled)
aux_mem[x_tiled] = new_depth;
else