PCem
changeset 114:9834054948fc
ViRGE S3D improvements :
- 24 bpp mode implemented
- Improved subpixel correction - fixes polygon gaps in some games
- Implemented dithering
- Z Update bit now has an effect - fixes Tomb Raider 2
- Improved mipmapping
| author | TomW |
|---|---|
| date | Sun Jul 06 12:45:35 2014 +0100 |
| parents | f749363ad763 |
| children | bd2ab065dd81 |
| files | src/vid_s3_virge.c |
| diffstat | 1 files changed, 91 insertions(+), 41 deletions(-) [+] |
line diff
1.1 --- a/src/vid_s3_virge.c Mon Jun 30 21:31:28 2014 +0100 1.2 +++ b/src/vid_s3_virge.c Sun Jul 06 12:45:35 2014 +0100 1.3 @@ -15,6 +15,14 @@ 1.4 static uint64_t status_time = 0; 1.5 static int reg_writes = 0; 1.6 1.7 +static int dither[4][4] = 1.8 +{ 1.9 + 0, 4, 1, 5, 1.10 + 6, 2, 7, 3, 1.11 + 1, 5, 0, 4, 1.12 + 7, 3, 6, 2, 1.13 +}; 1.14 + 1.15 typedef struct virge_t 1.16 { 1.17 mem_mapping_t linear_mapping; 1.18 @@ -39,6 +47,7 @@ 1.19 int is_375; 1.20 1.21 int bilinear_enabled; 1.22 + int dithering_enabled; 1.23 int memory_size; 1.24 1.25 int pixel_count, tri_count; 1.26 @@ -179,6 +188,8 @@ 1.27 CMD_SET_ITA_WORD = (1 << 10), 1.28 CMD_SET_ITA_DWORD = (2 << 10), 1.29 1.30 + CMD_SET_ZUP = (1 << 23), 1.31 + 1.32 CMD_SET_ZB_MODE = (3 << 24), 1.33 1.34 CMD_SET_XP = (1 << 25), 1.35 @@ -802,7 +813,7 @@ 1.36 virge_t *virge = (virge_t *)p; 1.37 svga_t *svga = &virge->svga; 1.38 reg_writes++; 1.39 -// if ((addr & 0xfffc) >= 0x8000 && (addr & 0xfffc) < 0x8400) 1.40 +// if ((addr & 0xfffc) >= 0xb400 && (addr & 0xfffc) < 0xb800) 1.41 // pclog("New MMIO writel %08X %08X %04x(%08x):%08x\n", addr, val, CS, cs, pc); 1.42 1.43 if ((addr & 0xfffc) < 0x8000) 1.44 @@ -1580,15 +1591,25 @@ 1.45 } 1.46 } 1.47 1.48 -#define RGB15_TO_24(val, r, g, b) b = (val & 0x1f) << 3; \ 1.49 - g = (val & 0x3e0) >> 2; \ 1.50 - r = (val & 0x7c00) >> 7 1.51 +#define RGB15_TO_24(val, r, g, b) b = ((val & 0x001f) << 3) | ((val & 0x001f) >> 2); \ 1.52 + g = ((val & 0x03e0) >> 2) | ((val & 0x03e0) >> 7); \ 1.53 + r = ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); 1.54 1.55 #define RGB24_TO_24(val, r, g, b) b = val & 0xff; \ 1.56 g = (val & 0xff00) >> 8; \ 1.57 r = (val & 0xff0000) >> 16 1.58 1.59 -#define RGB15(r, g, b) ((((b) >> 3) & 0x1f) | ((((g) >> 3) & 0x1f) << 5) | ((((r) >> 3) & 0x1f) << 10)) 1.60 +#define RGB15(r, g, b, dest) \ 1.61 + if (virge->dithering_enabled) \ 1.62 + { \ 1.63 + int add = dither[_y & 3][_x & 3]; \ 1.64 + int _r = (r > 248) ? 248 : r+add; \ 1.65 + int _g = (g > 248) ? 248 : g+add; \ 1.66 + int _b = (b > 248) ? 248 : b+add; \ 1.67 + dest = ((_b >> 3) & 0x1f) | (((_g >> 3) & 0x1f) << 5) | (((_r >> 3) & 0x1f) << 10); \ 1.68 + } \ 1.69 + else \ 1.70 + dest = ((b >> 3) & 0x1f) | (((g >> 3) & 0x1f) << 5) | (((r >> 3) & 0x1f) << 10) 1.71 1.72 #define RGB24(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) 1.73 1.74 @@ -1774,7 +1795,9 @@ 1.75 { 1.76 s3d_texture_state_t texture_state; 1.77 1.78 - texture_state.level = MAX(MIN(9 - ((state->d >> 27) & 0xf), state->max_d), 0); 1.79 + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); 1.80 + if (texture_state.level < 0) 1.81 + texture_state.level = 0; 1.82 texture_state.texture_shift = 18 + (9 - texture_state.level); 1.83 texture_state.u = state->u + state->tbu; 1.84 texture_state.v = state->v + state->tbv; 1.85 @@ -1790,7 +1813,9 @@ 1.86 int du, dv; 1.87 int d[4]; 1.88 1.89 - texture_state.level = MAX(MIN(9 - ((state->d >> 27) & 0xf), state->max_d), 0); 1.90 + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); 1.91 + if (texture_state.level < 0) 1.92 + texture_state.level = 0; 1.93 texture_state.texture_shift = 18 + (9 - texture_state.level); 1.94 tex_offset = 1 << texture_state.texture_shift; 1.95 1.96 @@ -1960,7 +1985,9 @@ 1.97 if (state->w) 1.98 w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); 1.99 1.100 - texture_state.level = MAX(MIN(9 - ((state->d >> 27) & 0xf), state->max_d), 0); 1.101 + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); 1.102 + if (texture_state.level < 0) 1.103 + texture_state.level = 0; 1.104 texture_state.texture_shift = 18 + (9 - texture_state.level); 1.105 texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; 1.106 texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; 1.107 @@ -1983,7 +2010,9 @@ 1.108 u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; 1.109 v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; 1.110 1.111 - texture_state.level = MAX(MIN(9 - ((state->d >> 27) & 0xf), state->max_d), 0); 1.112 + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); 1.113 + if (texture_state.level < 0) 1.114 + texture_state.level = 0; 1.115 texture_state.texture_shift = 18 + (9 - texture_state.level); 1.116 tex_offset = 1 << texture_state.texture_shift; 1.117 1.118 @@ -2024,7 +2053,9 @@ 1.119 if (state->w) 1.120 w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); 1.121 1.122 - texture_state.level = MAX(MIN(9 - ((state->d >> 27) & 0xf), state->max_d), 0); 1.123 + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); 1.124 + if (texture_state.level < 0) 1.125 + texture_state.level = 0; 1.126 texture_state.texture_shift = 18 + (9 - texture_state.level); 1.127 texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; 1.128 texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; 1.129 @@ -2047,7 +2078,9 @@ 1.130 u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; 1.131 v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; 1.132 1.133 - texture_state.level = MAX(MIN(9 - ((state->d >> 27) & 0xf), state->max_d), 0); 1.134 + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); 1.135 + if (texture_state.level < 0) 1.136 + texture_state.level = 0; 1.137 texture_state.texture_shift = 18 + (9 - texture_state.level); 1.138 tex_offset = 1 << texture_state.texture_shift; 1.139 1.140 @@ -2185,7 +2218,7 @@ 1.141 1.142 int y_count = yc; 1.143 1.144 - int bpp = 1; 1.145 + int bpp = (virge->s3d.cmd_set >> 2) & 7; 1.146 1.147 uint32_t dest_offset, z_offset; 1.148 1.149 @@ -2223,24 +2256,33 @@ 1.150 1.151 for (; y_count > 0; y_count--) 1.152 { 1.153 - int x = state->x1 >> 20; 1.154 - int xe = state->x2 >> 20; 1.155 + int x = (state->x1 + ((1 << 20) - 1)) >> 20; 1.156 + int xe = (state->x2 + ((1 << 20) - 1)) >> 20; 1.157 uint32_t z = state->base_z; 1.158 + if (x_dir < 0) 1.159 + { 1.160 + x--; 1.161 + xe--; 1.162 + } 1.163 + 1.164 if (x != xe && (x_dir > 0 && x < xe) || (x_dir < 0 && x > xe)) 1.165 { 1.166 uint32_t dest_addr, z_addr; 1.167 - int dx = (x_dir > 0) ? 8 - ((state->x1 >> 16) & 0xf) : ((state->x1 >> 16) & 0xf) - 8; 1.168 - int x_offset = x_dir << bpp; 1.169 - 1.170 - state->r = state->base_r + ((virge->s3d.TdRdX * dx) >> 4); 1.171 - state->g = state->base_g + ((virge->s3d.TdGdX * dx) >> 4); 1.172 - state->b = state->base_b + ((virge->s3d.TdBdX * dx) >> 4); 1.173 - state->a = state->base_a + ((virge->s3d.TdAdX * dx) >> 4); 1.174 - state->u = state->base_u + ((virge->s3d.TdUdX * dx) >> 4); 1.175 - state->v = state->base_v + ((virge->s3d.TdVdX * dx) >> 4); 1.176 - state->w = state->base_w + ((virge->s3d.TdWdX * dx) >> 4); 1.177 - state->d = state->base_d + ((virge->s3d.TdDdX * dx) >> 4); 1.178 - z += ((virge->s3d.TdZdX * dx) >> 4); 1.179 + int dx = (x_dir > 0) ? ((31 - ((state->x1-1) >> 15)) & 0x1f) : (((state->x1-1) >> 15) & 0x1f); 1.180 + int x_offset = x_dir * (bpp + 1); 1.181 + int xz_offset = x_dir << 1; 1.182 + if (x_dir > 0) 1.183 + dx += 1; 1.184 + state->r = state->base_r + ((virge->s3d.TdRdX * dx) >> 5); 1.185 + state->g = state->base_g + ((virge->s3d.TdGdX * dx) >> 5); 1.186 + state->b = state->base_b + ((virge->s3d.TdBdX * dx) >> 5); 1.187 + state->a = state->base_a + ((virge->s3d.TdAdX * dx) >> 5); 1.188 + state->u = state->base_u + ((virge->s3d.TdUdX * dx) >> 5); 1.189 + state->v = state->base_v + ((virge->s3d.TdVdX * dx) >> 5); 1.190 + state->w = state->base_w + ((virge->s3d.TdWdX * dx) >> 5); 1.191 + state->d = state->base_d + ((virge->s3d.TdDdX * dx) >> 5); 1.192 + z += ((virge->s3d.TdZdX * dx) >> 5); 1.193 + 1.194 // pclog("Draw Y=%i X=%i to XE=%i %i %08x %08x %08x %08x %08x %08x %08x %08x %i %08x\n", state->y, x, xe, dx, state->x1, state->x2, dx1, virge->s3d.TdWdX, state->u, state->v, virge->s3d.TdUdX, virge->s3d.TdUdY, dx, (virge->s3d.TdUdX * dx) >> 4); 1.195 1.196 if (virge->s3d.cmd_set & CMD_SET_HC) 1.197 @@ -2299,10 +2341,10 @@ 1.198 1.199 virge->svga.changedvram[(dest_offset & 0x3fffff) >> 12] = changeframecount; 1.200 1.201 - dest_addr = dest_offset + (x << bpp); 1.202 - z_addr = z_offset + (x << bpp); 1.203 + dest_addr = dest_offset + (x * (bpp + 1)); 1.204 + z_addr = z_offset + (x << 1); 1.205 1.206 - for (; x != ((xe + x_dir) & 0xfff); x = (x + x_dir) & 0xfff) 1.207 + for (; x != xe; x = (x + x_dir) & 0xfff) 1.208 { 1.209 int update = 1; 1.210 int16_t src_z; 1.211 @@ -2351,16 +2393,18 @@ 1.212 /*Not implemented yet*/ 1.213 break; 1.214 case 1: /*16 bpp*/ 1.215 - dest_col = RGB15(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b); 1.216 + RGB15(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, dest_col); 1.217 *(uint16_t *)&vram[dest_addr] = dest_col; 1.218 break; 1.219 case 2: /*24 bpp*/ 1.220 dest_col = RGB24(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b); 1.221 - *(uint32_t *)&vram[dest_addr] = dest_col; 1.222 + *(uint8_t *)&vram[dest_addr] = dest_col & 0xff; 1.223 + *(uint8_t *)&vram[dest_addr + 1] = (dest_col >> 8) & 0xff; 1.224 + *(uint8_t *)&vram[dest_addr + 2] = (dest_col >> 16) & 0xff; 1.225 break; 1.226 } 1.227 1.228 - if (use_z) 1.229 + if (use_z && (virge->s3d.cmd_set & CMD_SET_ZUP)) 1.230 Z_WRITE(z_addr, src_z); 1.231 } 1.232 1.233 @@ -2374,7 +2418,7 @@ 1.234 state->d += virge->s3d.TdDdX; 1.235 state->w += virge->s3d.TdWdX; 1.236 dest_addr += x_offset; 1.237 - z_addr += x_offset; 1.238 + z_addr += xz_offset; 1.239 virge->pixel_count++; 1.240 } 1.241 } 1.242 @@ -2979,8 +3023,8 @@ 1.243 memset(virge, 0, sizeof(virge_t)); 1.244 1.245 virge->bilinear_enabled = device_get_config_int("bilinear"); 1.246 + virge->dithering_enabled = device_get_config_int("dithering"); 1.247 virge->memory_size = device_get_config_int("memory"); 1.248 - pclog("bilinear_enabled=%i memory_size=%i\n", virge->bilinear_enabled, virge->memory_size); 1.249 1.250 svga_init(&virge->svga, virge, virge->memory_size << 20, 1.251 s3_virge_recalctimings, 1.252 @@ -3064,8 +3108,8 @@ 1.253 memset(virge, 0, sizeof(virge_t)); 1.254 1.255 virge->bilinear_enabled = device_get_config_int("bilinear"); 1.256 + virge->dithering_enabled = device_get_config_int("dithering"); 1.257 virge->memory_size = device_get_config_int("memory"); 1.258 - pclog("bilinear_enabled=%i memory_size=%i\n", virge->bilinear_enabled, virge->memory_size); 1.259 1.260 svga_init(&virge->svga, virge, virge->memory_size << 20, 1.261 s3_virge_recalctimings, 1.262 @@ -3208,12 +3252,6 @@ 1.263 static device_config_t s3_virge_config[] = 1.264 { 1.265 { 1.266 - .name = "bilinear", 1.267 - .description = "Bilinear filtering", 1.268 - .type = CONFIG_BINARY, 1.269 - .default_int = 1 1.270 - }, 1.271 - { 1.272 .name = "memory", 1.273 .description = "Memory size", 1.274 .type = CONFIG_SELECTION, 1.275 @@ -3234,6 +3272,18 @@ 1.276 .default_int = 4 1.277 }, 1.278 { 1.279 + .name = "bilinear", 1.280 + .description = "Bilinear filtering", 1.281 + .type = CONFIG_BINARY, 1.282 + .default_int = 1 1.283 + }, 1.284 + { 1.285 + .name = "dithering", 1.286 + .description = "Dithering", 1.287 + .type = CONFIG_BINARY, 1.288 + .default_int = 1 1.289 + }, 1.290 + { 1.291 .type = -1 1.292 } 1.293 };
