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  };