Added support for multiple texture base addresses on Voodoo. Fixes bad textures in Powerslide.
This commit is contained in:
parent
0e028ca64c
commit
c14bacd783
1 changed files with 116 additions and 35 deletions
151
src/vid_voodoo.c
151
src/vid_voodoo.c
|
|
@ -169,6 +169,7 @@ typedef struct voodoo_params_t
|
|||
uint32_t texBaseAddr[2], texBaseAddr1[2], texBaseAddr2[2], texBaseAddr38[2];
|
||||
|
||||
uint32_t tex_base[2][LOD_MAX+2];
|
||||
uint32_t tex_end[2][LOD_MAX+2];
|
||||
int tex_width[2];
|
||||
int tex_w_mask[2][LOD_MAX+2];
|
||||
int tex_w_nmask[2][LOD_MAX+2];
|
||||
|
|
@ -200,7 +201,7 @@ typedef struct texture_t
|
|||
volatile int refcount, refcount_r[2];
|
||||
int is16;
|
||||
uint32_t palette_checksum;
|
||||
uint32_t addr_start, addr_end;
|
||||
uint32_t addr_start[4], addr_end[4];
|
||||
uint32_t *data;
|
||||
} texture_t;
|
||||
|
||||
|
|
@ -994,11 +995,12 @@ enum
|
|||
|
||||
enum
|
||||
{
|
||||
LOD_ODD = (1 << 18),
|
||||
LOD_SPLIT = (1 << 19),
|
||||
LOD_S_IS_WIDER = (1 << 20),
|
||||
LOD_TMIRROR_S = (1 << 28),
|
||||
LOD_TMIRROR_T = (1 << 29)
|
||||
LOD_ODD = (1 << 18),
|
||||
LOD_SPLIT = (1 << 19),
|
||||
LOD_S_IS_WIDER = (1 << 20),
|
||||
LOD_TMULTIBASEADDR = (1 << 24),
|
||||
LOD_TMIRROR_S = (1 << 28),
|
||||
LOD_TMIRROR_T = (1 << 29)
|
||||
};
|
||||
enum
|
||||
{
|
||||
|
|
@ -1157,6 +1159,7 @@ static void voodoo_recalc_tex(voodoo_t *voodoo, int tmu)
|
|||
int shift = 8;
|
||||
int lod;
|
||||
uint32_t base = voodoo->params.texBaseAddr[tmu];
|
||||
uint32_t offset = 0;
|
||||
int tex_lod = 0;
|
||||
|
||||
if (voodoo->params.tLOD[tmu] & LOD_S_IS_WIDER)
|
||||
|
|
@ -1173,6 +1176,8 @@ static void voodoo_recalc_tex(voodoo_t *voodoo, int tmu)
|
|||
height >>= 1;
|
||||
shift--;
|
||||
tex_lod++;
|
||||
if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)
|
||||
base = voodoo->params.texBaseAddr1[tmu];
|
||||
}
|
||||
|
||||
for (lod = 0; lod <= LOD_MAX+1; lod++)
|
||||
|
|
@ -1183,7 +1188,11 @@ static void voodoo_recalc_tex(voodoo_t *voodoo, int tmu)
|
|||
height = 1;
|
||||
if (shift < 0)
|
||||
shift = 0;
|
||||
voodoo->params.tex_base[tmu][lod] = base;
|
||||
voodoo->params.tex_base[tmu][lod] = base + offset;
|
||||
if (voodoo->params.tformat[tmu] & 8)
|
||||
voodoo->params.tex_end[tmu][lod] = base + offset + (width * height * 2);
|
||||
else
|
||||
voodoo->params.tex_end[tmu][lod] = base + offset + (width * height);
|
||||
voodoo->params.tex_w_mask[tmu][lod] = width - 1;
|
||||
voodoo->params.tex_w_nmask[tmu][lod] = ~(width - 1);
|
||||
voodoo->params.tex_h_mask[tmu][lod] = height - 1;
|
||||
|
|
@ -1195,9 +1204,9 @@ static void voodoo_recalc_tex(voodoo_t *voodoo, int tmu)
|
|||
if (!(voodoo->params.tLOD[tmu] & LOD_ODD) || lod != 0)
|
||||
{
|
||||
if (voodoo->params.tformat[tmu] & 8)
|
||||
base += width * height * 2;
|
||||
offset += width * height * 2;
|
||||
else
|
||||
base += width * height;
|
||||
offset += width * height;
|
||||
|
||||
if (voodoo->params.tLOD[tmu] & LOD_SPLIT)
|
||||
{
|
||||
|
|
@ -1213,6 +1222,25 @@ static void voodoo_recalc_tex(voodoo_t *voodoo, int tmu)
|
|||
shift--;
|
||||
tex_lod++;
|
||||
}
|
||||
|
||||
if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)
|
||||
{
|
||||
switch (tex_lod)
|
||||
{
|
||||
case 0:
|
||||
base = voodoo->params.texBaseAddr[tmu];
|
||||
break;
|
||||
case 1:
|
||||
base = voodoo->params.texBaseAddr1[tmu];
|
||||
break;
|
||||
case 2:
|
||||
base = voodoo->params.texBaseAddr2[tmu];
|
||||
break;
|
||||
default:
|
||||
base = voodoo->params.texBaseAddr38[tmu];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1224,7 +1252,7 @@ static void voodoo_recalc_tex(voodoo_t *voodoo, int tmu)
|
|||
|
||||
static void use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu)
|
||||
{
|
||||
int c;
|
||||
int c, d;
|
||||
int lod;
|
||||
int lod_min, lod_max;
|
||||
uint32_t addr = 0, addr_end;
|
||||
|
|
@ -1251,10 +1279,15 @@ static void use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu)
|
|||
else
|
||||
palette_checksum = 0;
|
||||
|
||||
if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR))
|
||||
addr = params->texBaseAddr1[tmu];
|
||||
else
|
||||
addr = params->texBaseAddr[tmu];
|
||||
|
||||
/*Try to find texture in cache*/
|
||||
for (c = 0; c < TEX_CACHE_MAX; c++)
|
||||
{
|
||||
if (voodoo->texture_cache[tmu][c].base == params->texBaseAddr[tmu] &&
|
||||
if (voodoo->texture_cache[tmu][c].base == addr &&
|
||||
voodoo->texture_cache[tmu][c].tLOD == (params->tLOD[tmu] & 0xf00fff) &&
|
||||
voodoo->texture_cache[tmu][c].palette_checksum == palette_checksum)
|
||||
{
|
||||
|
|
@ -1283,12 +1316,16 @@ static void use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu)
|
|||
|
||||
c = voodoo->texture_last_removed;
|
||||
|
||||
voodoo->texture_cache[tmu][c].base = params->texBaseAddr[tmu];
|
||||
|
||||
if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR))
|
||||
voodoo->texture_cache[tmu][c].base = params->texBaseAddr1[tmu];
|
||||
else
|
||||
voodoo->texture_cache[tmu][c].base = params->texBaseAddr[tmu];
|
||||
voodoo->texture_cache[tmu][c].tLOD = params->tLOD[tmu] & 0xf00fff;
|
||||
|
||||
lod_min = (params->tLOD[tmu] >> 2) & 15;
|
||||
lod_max = (params->tLOD[tmu] >> 8) & 15;
|
||||
// pclog(" add new texture to %i tformat=%i %08x LOD=%i-%i\n", c, voodoo->params.tformat[tmu], params->texBaseAddr[tmu], lod_min, lod_max);
|
||||
// pclog(" add new texture to %i tformat=%i %08x LOD=%i-%i tmu=%i\n", c, voodoo->params.tformat[tmu], params->texBaseAddr[tmu], lod_min, lod_max, tmu);
|
||||
|
||||
for (lod = lod_min; lod <= lod_max; lod++)
|
||||
{
|
||||
|
|
@ -1520,13 +1557,51 @@ static void use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu)
|
|||
voodoo->texture_cache[tmu][c].palette_checksum = palette_checksum;
|
||||
else
|
||||
voodoo->texture_cache[tmu][c].palette_checksum = 0;
|
||||
|
||||
addr = voodoo->params.tex_base[tmu][lod_min];
|
||||
addr_end = voodoo->params.tex_base[tmu][lod_max+1];
|
||||
voodoo->texture_cache[tmu][c].addr_start = addr;
|
||||
voodoo->texture_cache[tmu][c].addr_end = addr_end;
|
||||
for (; addr <= addr_end; addr += (1 << TEX_DIRTY_SHIFT))
|
||||
voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1;
|
||||
|
||||
if (lod_min == 0)
|
||||
{
|
||||
voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->params.tex_base[tmu][0];
|
||||
voodoo->texture_cache[tmu][c].addr_end[0] = voodoo->params.tex_end[tmu][0];
|
||||
}
|
||||
else
|
||||
voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->texture_cache[tmu][c].addr_end[0] = 0;
|
||||
|
||||
if (lod_min <= 1 && lod_max >= 1)
|
||||
{
|
||||
voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->params.tex_base[tmu][1];
|
||||
voodoo->texture_cache[tmu][c].addr_end[1] = voodoo->params.tex_end[tmu][1];
|
||||
}
|
||||
else
|
||||
voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->texture_cache[tmu][c].addr_end[1] = 0;
|
||||
|
||||
if (lod_min <= 2 && lod_max >= 2)
|
||||
{
|
||||
voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->params.tex_base[tmu][2];
|
||||
voodoo->texture_cache[tmu][c].addr_end[2] = voodoo->params.tex_end[tmu][2];
|
||||
}
|
||||
else
|
||||
voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->texture_cache[tmu][c].addr_end[2] = 0;
|
||||
|
||||
if (lod_max >= 3)
|
||||
{
|
||||
voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->params.tex_base[tmu][(lod_min > 3) ? lod_min : 3];
|
||||
voodoo->texture_cache[tmu][c].addr_end[3] = voodoo->params.tex_end[tmu][(lod_max < 8) ? lod_max : 8];
|
||||
}
|
||||
else
|
||||
voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->texture_cache[tmu][c].addr_end[3] = 0;
|
||||
|
||||
|
||||
for (d = 0; d < 4; d++)
|
||||
{
|
||||
addr = voodoo->texture_cache[tmu][c].addr_start[d];
|
||||
addr_end = voodoo->texture_cache[tmu][c].addr_end[d];
|
||||
|
||||
if (addr_end != 0)
|
||||
{
|
||||
for (; addr <= addr_end; addr += (1 << TEX_DIRTY_SHIFT))
|
||||
voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
params->tex_entry[tmu] = c;
|
||||
voodoo->texture_cache[tmu][c].refcount++;
|
||||
|
|
@ -1543,23 +1618,31 @@ static void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu)
|
|||
{
|
||||
if (voodoo->texture_cache[tmu][c].base != -1)
|
||||
{
|
||||
int addr_start = voodoo->texture_cache[tmu][c].addr_start;
|
||||
int addr_end = voodoo->texture_cache[tmu][c].addr_end;
|
||||
|
||||
if (dirty_addr >= (addr_start & voodoo->texture_mask & ~0x3ff) && dirty_addr < (((addr_end & voodoo->texture_mask) + 0x3ff) & ~0x3ff))
|
||||
int d;
|
||||
|
||||
for (d = 0; d < 4; d++)
|
||||
{
|
||||
int addr_start = voodoo->texture_cache[tmu][c].addr_start[d];
|
||||
int addr_end = voodoo->texture_cache[tmu][c].addr_end[d];
|
||||
|
||||
if (addr_end != 0)
|
||||
{
|
||||
if (dirty_addr >= (addr_start & voodoo->texture_mask & ~0x3ff) && dirty_addr < (((addr_end & voodoo->texture_mask) + 0x3ff) & ~0x3ff))
|
||||
{
|
||||
// pclog(" Evict texture %i %08x\n", c, voodoo->texture_cache[tmu][c].base);
|
||||
|
||||
if (voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[0] ||
|
||||
(voodoo->render_threads == 2 && voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[1]))
|
||||
wait_for_idle = 1;
|
||||
if (voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[0] ||
|
||||
(voodoo->render_threads == 2 && voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[1]))
|
||||
wait_for_idle = 1;
|
||||
|
||||
voodoo->texture_cache[tmu][c].base = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; addr_start <= addr_end; addr_start += (1 << TEX_DIRTY_SHIFT))
|
||||
voodoo->texture_present[tmu][(addr_start & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1;
|
||||
voodoo->texture_cache[tmu][c].base = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; addr_start <= addr_end; addr_start += (1 << TEX_DIRTY_SHIFT))
|
||||
voodoo->texture_present[tmu][(addr_start & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2664,7 +2747,6 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood
|
|||
state->xend += state->dx2;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_CODEGEN
|
||||
if (voodoo->use_recompiler)
|
||||
voodoo_draw = voodoo_get_block(voodoo, params, state, odd_even);
|
||||
|
|
@ -2825,7 +2907,6 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood
|
|||
state->texel_count = 0;
|
||||
state->x = x;
|
||||
state->x2 = x2;
|
||||
|
||||
#ifndef NO_CODEGEN
|
||||
if (voodoo->use_recompiler)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue