diff --git a/src/include/86box/vid_voodoo_texture.h b/src/include/86box/vid_voodoo_texture.h index d5ab603ab..2e0af97a3 100644 --- a/src/include/86box/vid_voodoo_texture.h +++ b/src/include/86box/vid_voodoo_texture.h @@ -33,7 +33,8 @@ static const uint32_t texture_offset[LOD_MAX + 3] = { 256 * 256 + 128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2 + 1 * 1 + 1 }; -void voodoo_recalc_tex(voodoo_t *voodoo, int tmu); +void voodoo_recalc_tex12(voodoo_t *voodoo, int tmu); +void voodoo_recalc_tex3(voodoo_t *voodoo, int tmu); void voodoo_use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu); void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p); void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu); diff --git a/src/video/vid_voodoo_reg.c b/src/video/vid_voodoo_reg.c index 9eb2dc3f8..1b8e13022 100644 --- a/src/video/vid_voodoo_reg.c +++ b/src/video/vid_voodoo_reg.c @@ -73,6 +73,7 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) { voodoo_t *voodoo = (voodoo_t *) p; + void (*voodoo_recalc_tex)(voodoo_t *voodoo, int tmu) = NULL; union { uint32_t i; float f; @@ -82,6 +83,11 @@ voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) if (!chip) chip = 0xf; + if (voodoo->type == VOODOO_3) + voodoo_recalc_tex = voodoo_recalc_tex3; + else + voodoo_recalc_tex = voodoo_recalc_tex12; + tempif.i = val; // voodoo_reg_log("voodoo_reg_write_l: addr=%08x val=%08x(%f) chip=%x\n", addr, val, tempif.f, chip); addr &= 0x3fc; diff --git a/src/video/vid_voodoo_texture.c b/src/video/vid_voodoo_texture.c index 12ec56d0b..9d1149c65 100644 --- a/src/video/vid_voodoo_texture.c +++ b/src/video/vid_voodoo_texture.c @@ -59,7 +59,94 @@ voodoo_texture_log(const char *fmt, ...) #endif void -voodoo_recalc_tex(voodoo_t *voodoo, int tmu) +voodoo_recalc_tex12(voodoo_t *voodoo, int tmu) +{ + int aspect = (voodoo->params.tLOD[tmu] >> 21) & 3; + int width = 256, height = 256; + 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) + height >>= aspect; + else { + width >>= aspect; + shift -= aspect; + } + + if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD)) { + width >>= 1; + 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++) { + if (!width) + width = 1; + if (!height) + height = 1; + if (shift < 0) + shift = 0; + 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; + voodoo->params.tex_shift[tmu][lod] = shift; + voodoo->params.tex_lod[tmu][lod] = tex_lod; + + if (!(voodoo->params.tLOD[tmu] & LOD_SPLIT) || ((lod & 1) && (voodoo->params.tLOD[tmu] & LOD_ODD)) || (!(lod & 1) && !(voodoo->params.tLOD[tmu] & LOD_ODD))) { + if (!(voodoo->params.tLOD[tmu] & LOD_ODD) || lod != 0) { + if (voodoo->params.tformat[tmu] & 8) + offset += width * height * 2; + else + offset += width * height; + + if (voodoo->params.tLOD[tmu] & LOD_SPLIT) { + width >>= 2; + height >>= 2; + shift -= 2; + tex_lod += 2; + } else { + width >>= 1; + height >>= 1; + 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; + } + } + } + } + } + + voodoo->params.tex_width[tmu] = width; +} + +void +voodoo_recalc_tex3(voodoo_t *voodoo, int tmu) { int aspect = (voodoo->params.tLOD[tmu] >> 21) & 3; int width = 256, height = 256;