PCem
changeset 85:3b1a61addfa4
ViRGE: Preliminary stream processor emulation - enough to fix double buffering in DirectX.
Implemented transparent blit mode with colour sources.
Implemented old style MMIO.
| author | TomW |
|---|---|
| date | Thu Mar 20 16:33:31 2014 +0000 |
| parents | b53e148867e5 |
| children | 42ac4acbb4c5 |
| files | src/vid_s3_virge.c |
| diffstat | 1 files changed, 274 insertions(+), 99 deletions(-) [+] |
line diff
1.1 --- a/src/vid_s3_virge.c Thu Mar 20 14:03:55 2014 +0000 1.2 +++ b/src/vid_s3_virge.c Thu Mar 20 16:33:31 2014 +0000 1.3 @@ -70,6 +70,33 @@ 1.4 uint32_t pattern_16[8*8]; 1.5 uint32_t pattern_32[8*8]; 1.6 } s3d; 1.7 + 1.8 + struct 1.9 + { 1.10 + uint32_t pri_ctrl; 1.11 + uint32_t chroma_ctrl; 1.12 + uint32_t sec_ctrl; 1.13 + uint32_t chroma_upper_bound; 1.14 + uint32_t sec_filter; 1.15 + uint32_t blend_ctrl; 1.16 + uint32_t pri_fb0, pri_fb1; 1.17 + uint32_t pri_stride; 1.18 + uint32_t buffer_ctrl; 1.19 + uint32_t sec_fb0, sec_fb1; 1.20 + uint32_t sec_stride; 1.21 + uint32_t overlay_ctrl; 1.22 + uint32_t k1_vert_scale; 1.23 + uint32_t k2_vert_scale; 1.24 + uint32_t dda_vert_accumulator; 1.25 + uint32_t fifo_ctrl; 1.26 + uint32_t pri_start; 1.27 + uint32_t pri_size; 1.28 + uint32_t sec_start; 1.29 + uint32_t sec_size; 1.30 + 1.31 + int pri_x, pri_y, pri_w, pri_h; 1.32 + int sec_x, sec_y, sec_w, sec_h; 1.33 + } streams; 1.34 } virge_t; 1.35 1.36 static void s3_virge_updatemapping(virge_t *virge); 1.37 @@ -83,13 +110,6 @@ 1.38 static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p); 1.39 static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p); 1.40 1.41 -static uint8_t s3_virge_new_mmio_read(uint32_t addr, void *p); 1.42 -static uint16_t s3_virge_new_mmio_read_w(uint32_t addr, void *p); 1.43 -static uint32_t s3_virge_new_mmio_read_l(uint32_t addr, void *p); 1.44 -static void s3_virge_new_mmio_write(uint32_t addr, uint8_t val, void *p); 1.45 -static void s3_virge_new_mmio_write_w(uint32_t addr, uint16_t val, void *p); 1.46 -static void s3_virge_new_mmio_write_l(uint32_t addr, uint32_t val, void *p); 1.47 - 1.48 enum 1.49 { 1.50 CMD_SET_AE = 1, 1.51 @@ -159,7 +179,7 @@ 1.52 svga->crtcreg = val & 0x7f; 1.53 return; 1.54 case 0x3d5: 1.55 - //pclog("Write CRTC R%02X %02X\n", svga->crtcreg, val); 1.56 +// pclog("Write CRTC R%02X %02X\n", svga->crtcreg, val); 1.57 if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) 1.58 return; 1.59 if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) 1.60 @@ -218,7 +238,6 @@ 1.61 case 0x46: case 0x47: case 0x48: case 0x49: 1.62 case 0x4c: case 0x4d: case 0x4e: case 0x4f: 1.63 svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; 1.64 - if (svga->bpp == 32) svga->hwcursor.x >>= 1; 1.65 svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; 1.66 svga->hwcursor.xoff = svga->crtc[0x4e] & 63; 1.67 svga->hwcursor.yoff = svga->crtc[0x4f] & 63; 1.68 @@ -235,8 +254,8 @@ 1.69 { 1.70 case 3: svga->bpp = 15; break; 1.71 case 5: svga->bpp = 16; break; 1.72 -// case 7: svga->bpp = 24; break; 1.73 - case 13: svga->bpp = 24; break; 1.74 + case 7: svga->bpp = 24; break; 1.75 + case 13: svga->bpp = 32; break; 1.76 default: svga->bpp = 8; break; 1.77 } 1.78 break; 1.79 @@ -301,61 +320,86 @@ 1.80 static void s3_virge_recalctimings(svga_t *svga) 1.81 { 1.82 virge_t *virge = (virge_t *)svga->p; 1.83 -// pclog("recalctimings\n"); 1.84 - svga->ma_latch |= (virge->ma_ext << 16); 1.85 -// pclog("SVGA_MA %08X\n", svga_ma); 1.86 -// if (gdcreg[5] & 0x40) svga_lowres = !(crtc[0x3a] & 0x10); 1.87 - if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) 1.88 - { 1.89 - switch (svga->bpp) 1.90 - { 1.91 - case 8: 1.92 - svga->render = svga_render_8bpp_highres; 1.93 - break; 1.94 - case 15: 1.95 - svga->render = svga_render_15bpp_highres; 1.96 - break; 1.97 - case 16: 1.98 - svga->render = svga_render_16bpp_highres; 1.99 - break; 1.100 - case 24: 1.101 - svga->render = svga_render_24bpp_highres; 1.102 - break; 1.103 - case 32: 1.104 - svga->render = svga_render_32bpp_highres; 1.105 - break; 1.106 - } 1.107 - } 1.108 - 1.109 + 1.110 if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100; 1.111 if (svga->crtc[0x5d] & 0x02) svga->hdisp += 0x100; 1.112 if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400; 1.113 if (svga->crtc[0x5e] & 0x02) svga->dispend += 0x400; 1.114 if (svga->crtc[0x5e] & 0x10) svga->vsyncstart += 0x400; 1.115 if (svga->crtc[0x5e] & 0x40) svga->split += 0x400; 1.116 - if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4; 1.117 - else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; 1.118 - if (!svga->rowoffset) svga->rowoffset = 256; 1.119 svga->interlace = svga->crtc[0x42] & 0x20; 1.120 -// pclog("svga->rowoffset = %i bpp=%i\n", svga->rowoffset, svga->bpp); 1.121 - if (svga->bpp == 15 || svga->bpp == 16) 1.122 + 1.123 + if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ 1.124 { 1.125 - svga->htotal >>= 1; 1.126 - svga->hdisp >>= 1; 1.127 + svga->ma_latch |= (virge->ma_ext << 16); 1.128 + 1.129 + if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4; 1.130 + else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; 1.131 + if (!svga->rowoffset) svga->rowoffset = 256; 1.132 + 1.133 + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) 1.134 + { 1.135 + switch (svga->bpp) 1.136 + { 1.137 + case 8: 1.138 + svga->render = svga_render_8bpp_highres; 1.139 + break; 1.140 + case 15: 1.141 + svga->render = svga_render_15bpp_highres; 1.142 + break; 1.143 + case 16: 1.144 + svga->render = svga_render_16bpp_highres; 1.145 + break; 1.146 + case 24: 1.147 + svga->render = svga_render_24bpp_highres; 1.148 + break; 1.149 + case 32: 1.150 + svga->render = svga_render_32bpp_highres; 1.151 + break; 1.152 + } 1.153 + } 1.154 + 1.155 +// pclog("svga->rowoffset = %i bpp=%i\n", svga->rowoffset, svga->bpp); 1.156 + if (svga->bpp == 15 || svga->bpp == 16) 1.157 + { 1.158 + svga->htotal >>= 1; 1.159 + svga->hdisp >>= 1; 1.160 + } 1.161 + if (svga->bpp == 24) 1.162 + { 1.163 + svga->rowoffset = (svga->rowoffset * 3) / 4; /*Hack*/ 1.164 + } 1.165 } 1.166 - if (svga->bpp == 24) 1.167 + else /*Streams mode*/ 1.168 { 1.169 - svga->rowoffset = (svga->rowoffset * 3) / 4; /*Hack*/ 1.170 + if (virge->streams.buffer_ctrl & 1) 1.171 + svga->ma_latch = virge->streams.pri_fb1 >> 2; 1.172 + else 1.173 + svga->ma_latch = virge->streams.pri_fb0 >> 2; 1.174 + 1.175 + svga->rowoffset = virge->streams.pri_stride >> 3; 1.176 + 1.177 + switch ((virge->streams.pri_ctrl >> 24) & 0x7) 1.178 + { 1.179 + case 0: /*RGB-8 (CLUT)*/ 1.180 + svga->render = svga_render_8bpp_highres; 1.181 + break; 1.182 + case 3: /*KRGB-16 (1.5.5.5)*/ 1.183 + svga->render = svga_render_15bpp_highres; 1.184 + break; 1.185 + case 5: /*RGB-16 (5.6.5)*/ 1.186 + svga->render = svga_render_16bpp_highres; 1.187 + break; 1.188 + case 6: /*RGB-24 (8.8.8)*/ 1.189 + svga->render = svga_render_24bpp_highres; 1.190 + break; 1.191 + case 7: /*XRGB-32 (X.8.8.8)*/ 1.192 + svga->render = svga_render_32bpp_highres; 1.193 + break; 1.194 + } 1.195 } 1.196 1.197 -/* if (svga->bpp == 32) 1.198 - { 1.199 - svga->htotal <<= 2; 1.200 - svga->hdisp <<= 2; 1.201 - }*/ 1.202 - //svga_clock = cpuclock / sdac_getclock((svga_miscout >> 2) & 3); 1.203 -// pclog("SVGA_CLOCK = %f %02X %f\n", svga_clock, svga_miscout, cpuclock); 1.204 - //if (bpp > 8) svga_clock /= 2; 1.205 + 1.206 } 1.207 1.208 static void s3_virge_updatemapping(virge_t *virge) 1.209 @@ -433,7 +477,7 @@ 1.210 if (svga->crtc[0x53] & 0x20) 1.211 mem_mapping_set_addr(&virge->mmio_mapping, 0xb8000, 0x8000); 1.212 else 1.213 - mem_mapping_set_addr(&virge->mmio_mapping, 0xa8000, 0x8000); 1.214 + mem_mapping_set_addr(&virge->mmio_mapping, 0xa0000, 0x10000); 1.215 } 1.216 else 1.217 mem_mapping_disable(&virge->mmio_mapping); 1.218 @@ -448,34 +492,6 @@ 1.219 1.220 static uint8_t s3_virge_mmio_read(uint32_t addr, void *p) 1.221 { 1.222 -// pclog("MMIO readb %08X\n", addr); 1.223 - return 0xff; 1.224 -} 1.225 -static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p) 1.226 -{ 1.227 -// pclog("MMIO readw %08X\n", addr); 1.228 - return 0xffff; 1.229 -} 1.230 -static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p) 1.231 -{ 1.232 -// pclog("MMIO readl %08X\n", addr); 1.233 - return 0xffffffff; 1.234 -} 1.235 -static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p) 1.236 -{ 1.237 -// pclog("MMIO writeb %08X %02X\n", addr, val); 1.238 -} 1.239 -static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p) 1.240 -{ 1.241 -// pclog("MMIO writew %08X %04X\n", addr, val); 1.242 -} 1.243 -static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) 1.244 -{ 1.245 -// pclog("MMIO writel %08X %08X\n", addr, val); 1.246 -} 1.247 - 1.248 -static uint8_t s3_virge_new_mmio_read(uint32_t addr, void *p) 1.249 -{ 1.250 // pclog("New MMIO readb %08X\n", addr); 1.251 switch (addr & 0xffff) 1.252 { 1.253 @@ -495,23 +511,90 @@ 1.254 } 1.255 return 0xff; 1.256 } 1.257 -static uint16_t s3_virge_new_mmio_read_w(uint32_t addr, void *p) 1.258 +static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p) 1.259 { 1.260 // pclog("New MMIO readw %08X\n", addr); 1.261 switch (addr & 0xfffe) 1.262 { 1.263 default: 1.264 - return s3_virge_new_mmio_read(addr, p) | (s3_virge_new_mmio_read(addr + 1, p) << 8); 1.265 + return s3_virge_mmio_read(addr, p) | (s3_virge_mmio_read(addr + 1, p) << 8); 1.266 } 1.267 return 0xffff; 1.268 } 1.269 -static uint32_t s3_virge_new_mmio_read_l(uint32_t addr, void *p) 1.270 +static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p) 1.271 { 1.272 virge_t *virge = (virge_t *)p; 1.273 uint32_t ret = 0xffffffff; 1.274 // pclog("New MMIO readl %08X\n", addr); 1.275 switch (addr & 0xfffc) 1.276 { 1.277 + case 0x8180: 1.278 + ret = virge->streams.pri_ctrl; 1.279 + break; 1.280 + case 0x8184: 1.281 + ret = virge->streams.chroma_ctrl; 1.282 + break; 1.283 + case 0x8190: 1.284 + ret = virge->streams.sec_ctrl; 1.285 + break; 1.286 + case 0x8194: 1.287 + ret = virge->streams.chroma_upper_bound; 1.288 + break; 1.289 + case 0x8198: 1.290 + ret = virge->streams.sec_filter; 1.291 + break; 1.292 + case 0x81a0: 1.293 + ret = virge->streams.blend_ctrl; 1.294 + break; 1.295 + case 0x81c0: 1.296 + ret = virge->streams.pri_fb0; 1.297 + break; 1.298 + case 0x81c4: 1.299 + ret = virge->streams.pri_fb1; 1.300 + break; 1.301 + case 0x81c8: 1.302 + ret = virge->streams.pri_stride; 1.303 + break; 1.304 + case 0x81cc: 1.305 + ret = virge->streams.buffer_ctrl; 1.306 + break; 1.307 + case 0x81d0: 1.308 + ret = virge->streams.sec_fb0; 1.309 + break; 1.310 + case 0x81d4: 1.311 + ret = virge->streams.sec_fb1; 1.312 + break; 1.313 + case 0x81d8: 1.314 + ret = virge->streams.sec_stride; 1.315 + break; 1.316 + case 0x81dc: 1.317 + ret = virge->streams.overlay_ctrl; 1.318 + break; 1.319 + case 0x81e0: 1.320 + ret = virge->streams.k1_vert_scale; 1.321 + break; 1.322 + case 0x81e4: 1.323 + ret = virge->streams.k2_vert_scale; 1.324 + break; 1.325 + case 0x81e8: 1.326 + ret = virge->streams.dda_vert_accumulator; 1.327 + break; 1.328 + case 0x81ec: 1.329 + ret = virge->streams.fifo_ctrl; 1.330 + break; 1.331 + case 0x81f0: 1.332 + ret = virge->streams.pri_start; 1.333 + break; 1.334 + case 0x81f4: 1.335 + ret = virge->streams.pri_size; 1.336 + break; 1.337 + case 0x81f8: 1.338 + ret = virge->streams.sec_start; 1.339 + break; 1.340 + case 0x81fc: 1.341 + ret = virge->streams.sec_size; 1.342 + break; 1.343 + 1.344 case 0x8504: 1.345 ret = (0x1f << 8) | (1 << 13); 1.346 break; 1.347 @@ -562,11 +645,11 @@ 1.348 break; 1.349 1.350 default: 1.351 - return s3_virge_new_mmio_read_w(addr, p) | (s3_virge_new_mmio_read_w(addr + 2, p) << 16); 1.352 + return s3_virge_mmio_read_w(addr, p) | (s3_virge_mmio_read_w(addr + 2, p) << 16); 1.353 } 1.354 return ret; 1.355 } 1.356 -static void s3_virge_new_mmio_write(uint32_t addr, uint8_t val, void *p) 1.357 +static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p) 1.358 { 1.359 virge_t *virge = (virge_t *)p; 1.360 svga_t *svga = &virge->svga; 1.361 @@ -595,7 +678,7 @@ 1.362 1.363 1.364 } 1.365 -static void s3_virge_new_mmio_write_w(uint32_t addr, uint16_t val, void *p) 1.366 +static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p) 1.367 { 1.368 virge_t *virge = (virge_t *)p; 1.369 // pclog("New MMIO writew %08X %04X\n", addr, val); 1.370 @@ -609,15 +692,15 @@ 1.371 else switch (addr & 0xfffe) 1.372 { 1.373 case 0x83d4: 1.374 - s3_virge_new_mmio_write(addr, val, p); 1.375 - s3_virge_new_mmio_write(addr + 1, val >> 8, p); 1.376 + s3_virge_mmio_write(addr, val, p); 1.377 + s3_virge_mmio_write(addr + 1, val >> 8, p); 1.378 break; 1.379 } 1.380 } 1.381 -static void s3_virge_new_mmio_write_l(uint32_t addr, uint32_t val, void *p) 1.382 +static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) 1.383 { 1.384 virge_t *virge = (virge_t *)p; 1.385 - 1.386 + svga_t *svga = &virge->svga; 1.387 // if ((addr & 0xfffc) >= 0x8000) 1.388 // pclog("New MMIO writel %08X %08X\n", addr, val); 1.389 1.390 @@ -630,6 +713,94 @@ 1.391 } 1.392 else switch (addr & 0xfffc) 1.393 { 1.394 + case 0x8180: 1.395 + virge->streams.pri_ctrl = val; 1.396 + s3_virge_recalctimings(svga); 1.397 + svga->fullchange = changeframecount; 1.398 + break; 1.399 + case 0x8184: 1.400 + virge->streams.chroma_ctrl = val; 1.401 + break; 1.402 + case 0x8190: 1.403 + virge->streams.sec_ctrl = val; 1.404 + break; 1.405 + case 0x8194: 1.406 + virge->streams.chroma_upper_bound = val; 1.407 + break; 1.408 + case 0x8198: 1.409 + virge->streams.sec_filter = val; 1.410 + break; 1.411 + case 0x81a0: 1.412 + virge->streams.blend_ctrl = val; 1.413 + break; 1.414 + case 0x81c0: 1.415 + virge->streams.pri_fb0 = val & 0x3fffff; 1.416 + s3_virge_recalctimings(svga); 1.417 + svga->fullchange = changeframecount; 1.418 + break; 1.419 + case 0x81c4: 1.420 + virge->streams.pri_fb1 = val & 0x3fffff; 1.421 + s3_virge_recalctimings(svga); 1.422 + svga->fullchange = changeframecount; 1.423 + break; 1.424 + case 0x81c8: 1.425 + virge->streams.pri_stride = val & 0xfff; 1.426 + s3_virge_recalctimings(svga); 1.427 + svga->fullchange = changeframecount; 1.428 + break; 1.429 + case 0x81cc: 1.430 + virge->streams.buffer_ctrl = val; 1.431 + s3_virge_recalctimings(svga); 1.432 + break; 1.433 + case 0x81d0: 1.434 + virge->streams.sec_fb0 = val; 1.435 + break; 1.436 + case 0x81d4: 1.437 + virge->streams.sec_fb1 = val; 1.438 + break; 1.439 + case 0x81d8: 1.440 + virge->streams.sec_stride = val; 1.441 + break; 1.442 + case 0x81dc: 1.443 + virge->streams.overlay_ctrl = val; 1.444 + break; 1.445 + case 0x81e0: 1.446 + virge->streams.k1_vert_scale = val; 1.447 + break; 1.448 + case 0x81e4: 1.449 + virge->streams.k2_vert_scale = val; 1.450 + break; 1.451 + case 0x81e8: 1.452 + virge->streams.dda_vert_accumulator = val; 1.453 + break; 1.454 + case 0x81ec: 1.455 + virge->streams.fifo_ctrl = val; 1.456 + break; 1.457 + case 0x81f0: 1.458 + virge->streams.pri_start = val; 1.459 + virge->streams.pri_x = (val >> 16) & 0x7ff; 1.460 + virge->streams.pri_y = val & 0x7ff; 1.461 + s3_virge_recalctimings(svga); 1.462 + svga->fullchange = changeframecount; 1.463 + break; 1.464 + case 0x81f4: 1.465 + virge->streams.pri_size = val; 1.466 + virge->streams.pri_w = (val >> 16) & 0x7ff; 1.467 + virge->streams.pri_h = val & 0x7ff; 1.468 + s3_virge_recalctimings(svga); 1.469 + svga->fullchange = changeframecount; 1.470 + break; 1.471 + case 0x81f8: 1.472 + virge->streams.sec_start = val; 1.473 + virge->streams.sec_x = (val >> 16) & 0x7ff; 1.474 + virge->streams.sec_y = val & 0x7ff; 1.475 + break; 1.476 + case 0x81fc: 1.477 + virge->streams.sec_size = val; 1.478 + virge->streams.sec_w = (val >> 16) & 0x7ff; 1.479 + virge->streams.sec_h = val & 0x7ff; 1.480 + break; 1.481 + 1.482 case 0xa000: case 0xa004: case 0xa008: case 0xa00c: 1.483 case 0xa010: case 0xa014: case 0xa018: case 0xa01c: 1.484 case 0xa020: case 0xa024: case 0xa028: case 0xa02c: 1.485 @@ -931,6 +1102,8 @@ 1.486 case 0: 1.487 case CMD_SET_MS: 1.488 READ(src_addr, source); 1.489 + if ((virge->s3d.cmd_set & CMD_SET_TP) && source == virge->s3d.src_fg_clr) 1.490 + update = 0; 1.491 break; 1.492 case CMD_SET_IDS: 1.493 if (virge->s3d.data_left_count) 1.494 @@ -960,6 +1133,8 @@ 1.495 count = 0; 1.496 } 1.497 } 1.498 + if ((virge->s3d.cmd_set & CMD_SET_TP) && source == virge->s3d.src_fg_clr) 1.499 + update = 0; 1.500 break; 1.501 case CMD_SET_IDS | CMD_SET_MS: 1.502 source = (cpu_dat & (1 << 31)) ? virge->s3d.src_fg_clr : virge->s3d.src_bg_clr; 1.503 @@ -1287,12 +1462,12 @@ 1.504 NULL, 1.505 0, 1.506 virge); 1.507 - mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_new_mmio_read, 1.508 - s3_virge_new_mmio_read_w, 1.509 - s3_virge_new_mmio_read_l, 1.510 - s3_virge_new_mmio_write, 1.511 - s3_virge_new_mmio_write_w, 1.512 - s3_virge_new_mmio_write_l, 1.513 + mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read, 1.514 + s3_virge_mmio_read_w, 1.515 + s3_virge_mmio_read_l, 1.516 + s3_virge_mmio_write, 1.517 + s3_virge_mmio_write_w, 1.518 + s3_virge_mmio_write_l, 1.519 NULL, 1.520 0, 1.521 virge);
