From 20d7bb00b237ff747fb4c48d890a95c0cbd70a2b Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 16 Sep 2021 23:49:16 +0200 Subject: [PATCH 1/2] S3 changes part 4. Fixed Chicago 73x (73f/g and 81)'s width/pitch in 15bpp mode using its built-in drivers at 800x600 using the 928. Vastly improved implementation of the Short Stroke Vectors. Removed threading for FIFO mode in the cards using the 964 chips and up. Implementation of the non-threaded FIFO for cards using the 964 chips and up. Should fix most remaining wallpaper issues with those chips. Improved recalctimings when 256+ mode Enhanced Mode is issued. Added the MiroCRYSTAL 8S VLB card (805, SDAC). --- src/include/86box/video.h | 1 + src/video/vid_s3.c | 1009 ++++++++++++++++++------------------- src/video/vid_table.c | 1 + 3 files changed, 488 insertions(+), 523 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 83c57e444..7aac2b633 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -330,6 +330,7 @@ extern const device_t s3_metheus_86c928_isa_device; extern const device_t s3_metheus_86c928_vlb_device; extern const device_t s3_spea_mirage_86c801_isa_device; extern const device_t s3_spea_mirage_86c805_vlb_device; +extern const device_t s3_mirocrystal_8s_805_vlb_device; extern const device_t s3_mirocrystal_10sd_805_vlb_device; extern const device_t s3_phoenix_86c801_isa_device; extern const device_t s3_phoenix_86c805_vlb_device; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 7ac691e8d..55dfa2300 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -43,6 +43,7 @@ #define ROM_METHEUS_86C928 "roms/video/s3/928.vbi" #define ROM_SPEA_MIRAGE_86C801 "roms/video/s3/V7MIRAGE.VBI" #define ROM_SPEA_MIRAGE_86C805 "roms/video/s3/86c805pspeavlbus.BIN" +#define ROM_MIROCRYSTAL8S_805 "roms/video/s3/S3_805VL_ATT20C491_miroCRYSTAL_8s_ver1.4.BIN" #define ROM_MIROCRYSTAL10SD_805 "roms/video/s3/MIROcrystal10SD_VLB.VBI" #define ROM_MIROCRYSTAL20SV_964_VLB "roms/video/s3/S3_964VL_BT485_27C256_miroCRYSTAL_20sv_ver1.2.bin" #define ROM_MIROCRYSTAL20SV_964_PCI "roms/video/s3/mirocrystal.VBI" @@ -97,7 +98,8 @@ enum S3_SPEA_MERCURY_P64V, S3_MIROCRYSTAL20SV_964, S3_MIROCRYSTAL20SD_864, - S3_PHOENIX_VISION968 + S3_PHOENIX_VISION968, + S3_MIROCRYSTAL8S_805 }; @@ -254,15 +256,19 @@ typedef struct s3_t int dat_count; int b2e8_pix, temp_cnt; uint8_t cur_x_bit12, cur_y_bit12; - int ssv_len1, ssv_len2; - uint8_t ssv_dir1, ssv_dir2; - uint8_t ssv_draw1, ssv_draw2; + int ssv_len; + uint8_t ssv_dir; + uint8_t ssv_draw; - /*S3 928 and 80x cards only*/ + /*For non-threaded FIFO*/ int setup_fifo_slot, setup_fifo_slot2; int draw_fifo_slot, draw_fifo_slot2; int port_slot1, port_slot2; int port_slot3, port_slot4; + + /*Vision964 and up only*/ + int ext_fifo_slot, ext_fifo_slot2; + int ext_port_slot1, ext_port_slot2; } accel; struct { @@ -383,21 +389,6 @@ static uint32_t s3_accel_in_l(uint16_t port, void *p); static uint8_t s3_pci_read(int func, int addr, void *p); static void s3_pci_write(int func, int addr, uint8_t val, void *p); -static __inline void -wake_fifo_thread(s3_t *s3) -{ - thread_set_event(s3->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ -} - -static void -s3_wait_fifo_idle(s3_t *s3) -{ - while (!FIFO_EMPTY) { - wake_fifo_thread(s3); - thread_wait_event(s3->fifo_not_full_event, 1); - } -} - static void s3_update_irqs(s3_t *s3) { @@ -412,6 +403,7 @@ s3_update_irqs(s3_t *s3) } void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3); +void s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv); static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); #define WRITE8(addr, var, val) switch ((addr) & 3) \ @@ -490,7 +482,6 @@ s3_enable_fifo(s3_t *s3) return 1; /* FIFO always enabled on these chips. */ return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); - //return 0; /*Disable FIFO on pre-964 cards due to glitches going around*/ } static void @@ -565,7 +556,7 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) break; } - if ((s3_enable_fifo(s3) && s3->chip >= S3_VISION964) || (s3_enable_fifo(s3) == 0)) { + if (s3_enable_fifo(s3) == 0) { s3->accel.draw_fifo_slot = 0; } } @@ -641,7 +632,7 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) break; } - if ((s3_enable_fifo(s3) && s3->chip >= S3_VISION964) || (s3_enable_fifo(s3) == 0)) { + if (s3_enable_fifo(s3) == 0) { s3->accel.draw_fifo_slot = 0; } } @@ -671,6 +662,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.poly_cy = s3->accel.cur_y; break; case 0x814a: case 0x82ea: + s3->accel.ext_port_slot1++; + s3->accel.ext_port_slot2++; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot++; + if (s3->accel.ext_fifo_slot > 5) + s3->accel.ext_fifo_slot = 1; s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xf00) | val; s3->accel.poly_cy2 = s3->accel.cur_y2; break; @@ -699,6 +696,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.poly_x = s3->accel.poly_cx >> 20; break; case 0x854a: case 0x86ea: + s3->accel.ext_port_slot1++; + s3->accel.ext_port_slot2++; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot++; + if (s3->accel.ext_fifo_slot > 5) + s3->accel.ext_fifo_slot = 1; s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xf00) | val; s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; break; @@ -724,6 +727,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.point_1_updated = 1; break; case 0x894a: case 0x8aea: + s3->accel.ext_port_slot1++; + s3->accel.ext_port_slot2++; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot++; + if (s3->accel.ext_fifo_slot > 5) + s3->accel.ext_fifo_slot = 1; s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0x3f00) | val; s3->accel.point_2_updated = 1; break; @@ -751,6 +760,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.point_1_updated = 1; break; case 0x8d4a: case 0x8eea: + s3->accel.ext_port_slot1++; + s3->accel.ext_port_slot2++; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot++; + if (s3->accel.ext_fifo_slot > 5) + s3->accel.ext_fifo_slot = 1; s3->accel.x2 = (s3->accel.x2 & 0xf00) | val; s3->accel.point_2_updated = 1; break; @@ -774,6 +789,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.err_term |= ~0x3fff; break; case 0x914a: case 0x92ea: + s3->accel.ext_port_slot1++; + s3->accel.ext_port_slot2++; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot++; + if (s3->accel.ext_fifo_slot > 5) + s3->accel.ext_fifo_slot = 1; s3->accel.err_term2 = (s3->accel.err_term2 & 0x3f00) | val; break; case 0x914b: case 0x92eb: @@ -797,6 +818,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.maj_axis_pcnt |= ~0x0fff; break; case 0x954a: case 0x96ea: + s3->accel.ext_port_slot1++; + s3->accel.ext_port_slot2++; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot++; + if (s3->accel.ext_fifo_slot > 5) + s3->accel.ext_fifo_slot = 1; s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xf00) | val; break; case 0x954b: case 0x96eb: @@ -834,10 +861,21 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val; break; case 0x9d49: case 0x9ee9: - s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); + s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); s3->accel.ssv_state = 1; - s3_accel_start(-1, 0, 0xffffffff, 0, s3); - s3->accel.multifunc[0xe] &= ~0x10; /*hack*/ + + s3->accel.cx = s3->accel.cur_x; + if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y; + if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; + + if (s3->accel.cmd & 0x1000) { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + } else { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + } break; case 0xa148: case 0xa2e8: @@ -1334,29 +1372,49 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; } - if ((s3_enable_fifo(s3) && s3->chip >= S3_VISION964) || (s3_enable_fifo(s3) == 0)) { - if (s3->accel.port_slot1 || s3->accel.port_slot2) { + if (s3_enable_fifo(s3) == 0) { + if (s3->accel.port_slot1 || s3->accel.port_slot2) s3->accel.draw_fifo_slot = 0; - } else if (s3->accel.port_slot3 || s3->accel.port_slot4) + if (s3->accel.port_slot3 || s3->accel.port_slot4) s3->accel.setup_fifo_slot = 0; + if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) + s3->accel.ext_fifo_slot = 0; } } static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) { - if (port == 0xb2e8) { - s3->accel.b2e8_pix = 1; + if (port != 0x9ee8 && port != 0x9d48) { + if (port == 0xb2e8) { + s3->accel.b2e8_pix = 1; + } else { + s3->accel.b2e8_pix = 0; + } + s3_accel_out_pixtrans_w(s3, val); } else { - s3->accel.b2e8_pix = 0; + s3->accel.short_stroke = val; + s3->accel.ssv_state = 1; + + s3->accel.cx = s3->accel.cur_x; + if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y; + if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; + + if (s3->accel.cmd & 0x1000) { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + } else { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + } } - s3_accel_out_pixtrans_w(s3, val); } static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) -{ +{ s3_accel_out_pixtrans_l(s3, val); } @@ -1390,9 +1448,9 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) case 0x8118: addr = 0x9ae8; break; /*ALT_CMD*/ case 0x811a: addr = 0x9aea; break; - - case 0x811c: addr = 0x9ee8; break; /*SHORT_STROKE*/ - + + case 0x811c: addr = 0x9ee8; break; + case 0x8120: case 0x8122: /*BKGD_COLOR*/ WRITE8(addr, s3->accel.bkgd_color, val); return; @@ -1526,7 +1584,6 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3->accel.draw_fifo_slot++; if (s3->accel.draw_fifo_slot > 8) s3->accel.draw_fifo_slot = 1; - if ((s3->accel.cmd & 0x600) == 0x200) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) @@ -1544,7 +1601,7 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) } else s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } - if ((s3_enable_fifo(s3) && s3->chip >= S3_VISION964) || (s3_enable_fifo(s3) == 0)) { + if (s3_enable_fifo(s3) == 0) { s3->accel.draw_fifo_slot = 0; } } @@ -1570,12 +1627,19 @@ s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) case 0xff20: s3_accel_write_fifo(s3, addr, val); break; + case 0x811c: + s3_accel_out_fifo_w(s3, 0x9ee8, val); + break; } } } else { if (addr & 0x8000) { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); + if (addr == 0x811c) + s3_accel_out_fifo_w(s3, 0x9ee8, val); + else { + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + } } else { s3_accel_out_pixtrans_w(s3, val); } @@ -1790,59 +1854,6 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) } } -static void -fifo_thread(void *param) -{ - s3_t *s3 = (s3_t *)param; - - while (s3->thread_run) - { - thread_set_event(s3->fifo_not_full_event); - thread_wait_event(s3->wake_fifo_thread, -1); - thread_reset_event(s3->wake_fifo_thread); - s3->blitter_busy = 1; - while (!FIFO_EMPTY) - { - uint64_t start_time = plat_timer_read(); - uint64_t end_time; - fifo_entry_t *fifo = &s3->fifo[s3->fifo_read_idx & FIFO_MASK]; - - switch (fifo->addr_type & FIFO_TYPE) - { - case FIFO_WRITE_BYTE: - s3_accel_write_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_WORD: - s3_accel_write_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_DWORD: - s3_accel_write_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_BYTE: - s3_accel_out_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_WORD: - s3_accel_out_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_DWORD: - s3_accel_out_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - } - - s3->fifo_read_idx++; - fifo->addr_type = FIFO_INVALID; - - if (FIFO_ENTRIES > 0xe000) - thread_set_event(s3->fifo_not_full_event); - - end_time = plat_timer_read(); - s3->blitter_time += end_time - start_time; - } - s3->blitter_busy = 0; - s3->subsys_stat |= INT_FIFO_EMP; - s3_update_irqs(s3); - } -} static void s3_vblank_start(svga_t *svga) @@ -1853,29 +1864,6 @@ s3_vblank_start(svga_t *svga) s3_update_irqs(s3); } -static void -s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type) -{ - fifo_entry_t *fifo = &s3->fifo[s3->fifo_write_idx & FIFO_MASK]; - - if (FIFO_FULL) - { - thread_reset_event(s3->fifo_not_full_event); - if (FIFO_FULL) - { - thread_wait_event(s3->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ - } - } - - fifo->val = val; - fifo->addr_type = (addr & FIFO_ADDR) | type; - - s3->fifo_write_idx++; - - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) - wake_fifo_thread(s3); -} - static uint32_t s3_hwcursor_convert_addr(svga_t *svga) @@ -1892,6 +1880,7 @@ s3_hwcursor_convert_addr(svga_t *svga) } + static void s3_hwcursor_draw(svga_t *svga, int displine) { @@ -1959,8 +1948,9 @@ s3_hwcursor_draw(svga_t *svga, int displine) for (x = 0; x < 64; x += 16) { - dat[0] = (svga->vram[real_addr & svga->vram_display_mask] << 8) | svga->vram[(real_addr + 1) & svga->vram_display_mask]; - dat[1] = (svga->vram[(real_addr + 2) & svga->vram_display_mask] << 8) | svga->vram[(real_addr + 3) & svga->vram_display_mask]; + dat[0] = (svga->vram[real_addr & s3->vram_mask] << 8) | svga->vram[(real_addr + 1) & s3->vram_mask]; + dat[1] = (svga->vram[(real_addr + 2) & s3->vram_mask] << 8) | svga->vram[(real_addr + 3) & s3->vram_mask]; + if (svga->crtc[0x55] & 0x10) { /*X11*/ for (xx = 0; xx < 16; xx++) { @@ -1975,13 +1965,13 @@ s3_hwcursor_draw(svga_t *svga, int displine) } } else { /*Windows*/ - for (xx = 0; xx < width; xx++) { - if (offset >= svga->hwcursor_latch.x) { + for (xx = 0; xx < width; xx++) { + if (offset >= svga->hwcursor_latch.x) { if (!(dat[0] & 0x8000)) buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; else if (dat[1] & 0x8000) buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; - } + } offset++; dat[0] <<= shift; @@ -2289,7 +2279,7 @@ s3_io_remove_alt(s3_t *s3) io_removehandler(0x9148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9d48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9d48, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_removehandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2323,7 +2313,7 @@ s3_io_remove(s3_t *s3) io_removehandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x96e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9ee8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_removehandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2381,7 +2371,7 @@ s3_io_set_alt(s3_t *s3) io_sethandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); else io_sethandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9d48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9d48, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_sethandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xa948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2440,7 +2430,7 @@ s3_io_set(s3_t *s3) io_sethandler(0x9ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); else io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9ee8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_sethandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2539,7 +2529,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968))) { rs3 = !!(svga->crtc[0x55] & 0x02); tvp3026_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805)) + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805)) att49x_ramdac_out(addr, rs2, val, svga->ramdac, svga); else if (s3->chip <= S3_86C924) sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); @@ -2567,20 +2557,21 @@ s3_out(uint16_t addr, uint8_t val, void *p) return; old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; + switch (svga->crtcreg) { case 0x31: s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4); break; case 0x32: - if (svga->crtc[0x31] & 0x30) - svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask; + if ((svga->crtc[0x31] & 0x30) && (svga->crtc[0x51] & 0x01) && (val & 0x40)) + svga->vram_display_mask = 0x3ffff; else svga->vram_display_mask = s3->vram_mask; break; case 0x40: - s3->enable_8514 = !!(svga->crtc[0x40] & 1); + s3->enable_8514 = (val & 0x01); break; case 0x50: @@ -2615,7 +2606,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) if (s3->chip >= S3_VISION964) s3->ma_ext = val & 0x1f; break; - + case 0x35: s3->bank = (s3->bank & 0x70) | (val & 0xf); if (svga->chain4) @@ -2624,18 +2615,17 @@ s3_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = s3->bank << 14; break; case 0x51: - if (s3->chip == S3_86C801 || s3->chip == S3_86C805) + if (s3->chip == S3_86C801 || s3->chip == S3_86C805) { s3->bank = (s3->bank & 0x6f) | ((val & 0x4) << 2); - else + s3->ma_ext = (s3->ma_ext & ~0x4) | ((val & 1) << 2); + } else { s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2); + s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); + } if (svga->chain4) svga->write_bank = svga->read_bank = s3->bank << 16; else svga->write_bank = svga->read_bank = s3->bank << 14; - if (s3->chip == S3_86C801 || s3->chip == S3_86C805) - s3->ma_ext = (s3->ma_ext & ~0x4) | ((val & 1) << 2); - else - s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); break; case 0x6a: @@ -2647,12 +2637,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = s3->bank << 14; } break; - - case 0x3a: - if (val & 0x10) - svga->gdcreg[5] |= 0x40; /*Horrible cheat*/ - break; - + case 0x45: if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) break; @@ -2665,9 +2650,10 @@ s3_out(uint16_t addr, uint8_t val, void *p) svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; if (svga->bpp == 32) svga->hwcursor.x >>= 1; svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; - svga->hwcursor.xoff = svga->crtc[0x4e] & 63; - svga->hwcursor.yoff = svga->crtc[0x4f] & 63; + svga->hwcursor.xoff = svga->crtc[0x4e] & 0x3f; + svga->hwcursor.yoff = svga->crtc[0x4f] & 0x3f; svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); + if ((s3->chip >= S3_TRIO32) && svga->bpp == 32) svga->hwcursor.x <<= 1; else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 15 || svga->bpp == 16)) @@ -2734,7 +2720,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) case 0x43: if (s3->chip < S3_VISION964) { s3_io_remove_alt(s3); - s3->translate = !!(svga->crtc[0x43] & 0x10); + s3->translate = !!(val & 0x10); s3_io_set_alt(s3); } break; @@ -2824,7 +2810,7 @@ s3_in(uint16_t addr, void *p) else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968))) { rs3 = !!(svga->crtc[0x55] & 0x02); return tvp3026_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805)) + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805)) return att49x_ramdac_in(addr, rs2, svga->ramdac, svga); else if (s3->chip <= S3_86C924) return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); @@ -2844,10 +2830,7 @@ s3_in(uint16_t addr, void *p) case 0x31: return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4); case 0x35: return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf); case 0x45: s3->hwc_col_stack_pos = 0; break; - case 0x51: - if (s3->chip == S3_86C801 || s3->chip == S3_86C805) - return (svga->crtc[0x51] & 0xfa) | ((s3->bank >> 2) & 0x4) | ((s3->ma_ext >> 2) & 1); - return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); + case 0x51: return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); case 0x5c: /* General Output Port Register */ temp = svga->crtc[svga->crtcreg] & 0xa0; if (((svga->miscout >> 2) & 3) == 3) @@ -2895,6 +2878,13 @@ static void s3_recalctimings(svga_t *svga) s3_t *s3 = (s3_t *)svga->p; int clk_sel = (svga->miscout >> 2) & 3; + if (!svga->scrblank && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (svga->crtc[0x3a] & 0x10) /*256+ color register*/ + svga->gdcreg[5] |= 0x40; + } + } + svga->ma_latch |= (s3->ma_ext << 16); if (s3->chip >= S3_86C928) { svga->hdisp = svga->hdisp_old; @@ -2940,7 +2930,21 @@ static void s3_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); - if (((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) || (svga->crtc[0x3a] & 0x10)) { + if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL20SD_864 || + s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_SPEA_MIRAGE_86C801 || + s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_MIROCRYSTAL8S_805) { + if (svga->bpp != 32) { + if (svga->crtc[0x31] & 2) /*This is needed if the pixel width gets set with delays*/ + s3->width = 2048; + } + } else if (s3->chip == S3_86C928) { + if (svga->bpp == 15) { + if (s3->width == 800) + s3->width = 1024; + } + } + + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { if (svga->crtc[0x31] & 0x08) /*This would typically force dword mode, but we are encountering accel bugs with it, so force byte mode instead*/ svga->force_byte_mode = 1; else @@ -2966,10 +2970,40 @@ static void s3_recalctimings(svga_t *svga) s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { if (svga->hdisp != 1408) svga->hdisp = s3->width; + if (s3->card_type == S3_MIROCRYSTAL20SD_864) { + if (s3->width == 2048) { + switch (svga->dispend) { + case 400: + case 480: + svga->hdisp = 640; + break; + + case 576: + svga->hdisp = 768; + break; + + case 600: + svga->hdisp = 800; + break; + + case 768: + svga->hdisp = 1024; + break; + + case 864: + svga->hdisp = 1152; + break; + + case 1024: + if (svga->vtotal == 1066) + svga->hdisp = 1280; + break; + } + } + } } - if (s3->card_type == S3_MIROCRYSTAL10SD_805) { - pclog("S3 CRTC51 = %02x, CRTC5D = %02x, CRTC5E = %02x, CRTC35 = %02x\n", svga->crtc[0x51], svga->crtc[0x5d], svga->crtc[0x5e], svga->crtc[0x35]); - if (svga->rowoffset == 256 && ((svga->crtc[0x51] & 0x30) == 0x00 && !(svga->crtc[0x43] & 0x04))) + if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL8S_805) { + if (svga->rowoffset == 256 && (((svga->crtc[0x51] & 0x30) == 0x00 && !(svga->crtc[0x43] & 0x04)))) svga->rowoffset >>= 1; } } @@ -3056,8 +3090,27 @@ static void s3_recalctimings(svga_t *svga) svga->hdisp *= 2; if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_PHOENIX_VISION968 || - s3->card_type == S3_SPEA_MERCURY_P64V) + s3->card_type == S3_SPEA_MERCURY_P64V) { svga->hdisp = s3->width; + if (s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964) { + if ((svga->crtc[0x31] & 2) && (svga->crtc[0x50] & 0xc1) != 0x00) { + switch (svga->dispend) { + case 400: + case 480: + svga->hdisp = 640; + break; + + case 576: + svga->hdisp = 768; + break; + + case 600: + svga->hdisp = 800; + break; + } + } + } + } break; } } else { @@ -3073,6 +3126,13 @@ static void s3_trio64v_recalctimings(svga_t *svga) s3_t *s3 = (s3_t *)svga->p; int clk_sel = (svga->miscout >> 2) & 3; + if (!svga->scrblank && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (svga->crtc[0x3a] & 0x10) /*256+ color register*/ + svga->gdcreg[5] |= 0x40; + } + } + svga->hdisp = svga->hdisp_old; if (svga->crtc[0x5d] & 0x01) svga->htotal |= 0x100; @@ -3310,19 +3370,12 @@ s3_accel_out(uint16_t port, uint8_t val, void *p) s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; - if (!s3->enable_8514) - return; - if (port >= 0x8000) { - if (s3_enable_fifo(s3)) { - if (s3->chip <= S3_86C805) - s3_accel_out_fifo(s3, port, val); - else - s3_queue(s3, port, val, FIFO_OUT_BYTE); - } else { - s3_accel_out_fifo(s3, port, val); - } + if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + return; + + s3_accel_out_fifo(s3, port, val); } else { @@ -3362,16 +3415,10 @@ s3_accel_out_w(uint16_t port, uint16_t val, void *p) { s3_t *s3 = (s3_t *)p; - if (!s3->enable_8514) - return; + if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + return; - if (s3_enable_fifo(s3)) { - if (s3->chip <= S3_86C805) - s3_accel_out_fifo_w(s3, port, val); - else - s3_queue(s3, port, val, FIFO_OUT_WORD); - } else - s3_accel_out_fifo_w(s3, port, val); + s3_accel_out_fifo_w(s3, port, val); } static void @@ -3379,16 +3426,10 @@ s3_accel_out_l(uint16_t port, uint32_t val, void *p) { s3_t *s3 = (s3_t *)p; - if (!s3->enable_8514) - return; + if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + return; - if (s3_enable_fifo(s3)) { - if (s3->chip <= S3_86C805) - s3_accel_out_fifo_l(s3, port, val); - else - s3_queue(s3, port, val, FIFO_OUT_DWORD); - } else - s3_accel_out_fifo_l(s3, port, val); + s3_accel_out_fifo_l(s3, port, val); } static uint8_t @@ -3398,7 +3439,7 @@ s3_accel_in(uint16_t port, void *p) svga_t *svga = &s3->svga; int temp; - if (!s3->enable_8514) + if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) return 0xff; switch (port) { @@ -3408,62 +3449,49 @@ s3_accel_in(uint16_t port, void *p) return s3->subsys_cntl; case 0x8148: case 0x82e8: - s3_wait_fifo_idle(s3); - return s3->accel.cur_y & 0xff; case 0x8149: case 0x82e9: - s3_wait_fifo_idle(s3); - return s3->accel.cur_y >> 8; + return s3->accel.cur_y >> 8; case 0x8548: case 0x86e8: - s3_wait_fifo_idle(s3); return s3->accel.cur_x & 0xff; case 0x8549: case 0x86e9: - s3_wait_fifo_idle(s3); - return s3->accel.cur_x >> 8; + return s3->accel.cur_x >> 8; case 0x8948: case 0x8ae8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.desty_axstp & 0xff; } break; case 0x8949: case 0x8ae9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.desty_axstp >> 8; } break; case 0x8d48: case 0x8ee8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.destx_distp & 0xff; } break; case 0x8d49: case 0x8ee9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.destx_distp >> 8; } break; case 0x9148: case 0x92e8: - s3_wait_fifo_idle(s3); return s3->accel.err_term & 0xff; case 0x9149: case 0x92e9: - s3_wait_fifo_idle(s3); return s3->accel.err_term >> 8; case 0x9548: case 0x96e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.maj_axis_pcnt & 0xff; } break; case 0x9549: case 0x96e9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.maj_axis_pcnt >> 8; } break; @@ -3471,120 +3499,134 @@ s3_accel_in(uint16_t port, void *p) case 0x8118: case 0x9948: case 0x9ae8: temp = 0; /* FIFO empty */ - if (!s3->blitter_busy && s3->chip >= S3_VISION964) - wake_fifo_thread(s3); - if (FIFO_FULL && (s3->chip >= S3_VISION964)) - temp = 0xff; /*FIFO full*/ - else if (s3->chip <= S3_86C805) { - if (s3_enable_fifo(s3)) { - if (s3->accel.port_slot3) { - if (s3->accel.setup_fifo_slot) { - switch (s3->accel.setup_fifo_slot) { - case 1: - temp = 1; - break; - case 2: - temp = 3; - break; - case 3: - temp = 7; - break; - case 4: - temp = 0x0f; - break; - case 5: - temp = 0x1f; - break; - case 6: - temp = 0x3f; - break; - case 7: - temp = 0x7f; - break; - case 8: - temp = 0xff; - break; - } + if (s3_enable_fifo(s3)) { + if (s3->accel.port_slot3) { + if (s3->accel.setup_fifo_slot) { + switch (s3->accel.setup_fifo_slot) { + case 1: + temp = 1; + break; + case 2: + temp = 3; + break; + case 3: + temp = 7; + break; + case 4: + temp = 0x0f; + break; + case 5: + temp = 0x1f; + break; + case 6: + temp = 0x3f; + break; + case 7: + temp = 0x7f; + break; + case 8: + temp = 0xff; /*FIFO full*/ + break; } - - s3->accel.setup_fifo_slot2 = s3->accel.setup_fifo_slot; - s3->accel.setup_fifo_slot = 0; - s3->accel.port_slot3 = 0; - } else if (s3->accel.port_slot1) { - if (s3->accel.draw_fifo_slot) { - switch (s3->accel.draw_fifo_slot) { - case 1: - temp = 1; - break; - case 2: - temp = 3; - break; - case 3: - temp = 7; - break; - case 4: - temp = 0x0f; - break; - case 5: - temp = 0x1f; - break; - case 6: - temp = 0x3f; - break; - case 7: - temp = 0x7f; - break; - case 8: - temp = 0xff; - break; - } - } - - s3->accel.draw_fifo_slot2 = s3->accel.draw_fifo_slot; - s3->accel.draw_fifo_slot = 0; - s3->accel.port_slot1 = 0; } + + s3->accel.setup_fifo_slot2 = s3->accel.setup_fifo_slot; + s3->accel.setup_fifo_slot = 0; + s3->accel.port_slot3 = 0; + } else if (s3->accel.port_slot1) { + if (s3->accel.draw_fifo_slot) { + switch (s3->accel.draw_fifo_slot) { + case 1: + temp = 1; + break; + case 2: + temp = 3; + break; + case 3: + temp = 7; + break; + case 4: + temp = 0x0f; + break; + case 5: + temp = 0x1f; + break; + case 6: + temp = 0x3f; + break; + case 7: + temp = 0x7f; + break; + case 8: + temp = 0xff; /*FIFO full*/ + break; + } + } + + s3->accel.draw_fifo_slot2 = s3->accel.draw_fifo_slot; + s3->accel.draw_fifo_slot = 0; + s3->accel.port_slot1 = 0; } } return temp; case 0x8119: case 0x9949: case 0x9ae9: - if (!s3->blitter_busy && s3->chip >= S3_VISION964) - wake_fifo_thread(s3); temp = 0; if (s3_enable_fifo(s3)) { - if (s3->chip >= S3_VISION964) { - if (!FIFO_EMPTY || s3->force_busy) { - temp |= 0x02; /*Hardware busy*/ - } else { - temp |= 0x04; /*FIFO empty*/ - } - s3->force_busy = 0; - if (FIFO_FULL) - temp |= 0xf8; /*FIFO full*/ + if (s3->force_busy) { + temp |= 0x02; /*Hardware busy*/ + s3->subsys_stat |= INT_GE_BSY; } else { - if (s3->force_busy) { - temp |= 0x02; /*Hardware busy*/ - } else { - if (s3->accel.port_slot2) { - s3->accel.port_slot2 = 0; - if (!s3->accel.draw_fifo_slot2) - temp |= 0x04; /*FIFO empty*/ - if (s3->accel.draw_fifo_slot2) - s3->accel.draw_fifo_slot2 = 0; - } else if (s3->accel.port_slot4) { - s3->accel.port_slot4 = 0; - if (!s3->accel.setup_fifo_slot2) - temp |= 0x04; /*FIFO empty*/ - if (s3->accel.setup_fifo_slot2) - s3->accel.setup_fifo_slot2 = 0; + if (s3->accel.port_slot2) { + s3->accel.port_slot2 = 0; + if (!s3->accel.draw_fifo_slot2) { + temp |= 0x04; /*FIFO empty*/ + s3->subsys_stat |= INT_FIFO_EMP; } + if (s3->accel.draw_fifo_slot2) + s3->accel.draw_fifo_slot2 = 0; + } else if (s3->accel.port_slot4) { + s3->accel.port_slot4 = 0; + if (!s3->accel.setup_fifo_slot2) { + temp |= 0x04; /*FIFO empty*/ + s3->subsys_stat |= INT_FIFO_EMP; + } + if (s3->accel.setup_fifo_slot2) + s3->accel.setup_fifo_slot2 = 0; } + } - s3->force_busy = 0; - if (s3->data_available) { - temp |= 0x01; /*Read Data available*/ - s3->data_available = 0; + s3->force_busy = 0; + if (s3->data_available) { + temp |= 0x01; /*Read Data available*/ + s3->data_available = 0; + } + + if (s3->chip >= S3_VISION964) { + if (s3->accel.ext_port_slot1) { + if (s3->accel.ext_fifo_slot) { + switch (s3->accel.ext_fifo_slot) { + case 1: + temp |= 0x08; + break; + case 2: + temp |= 0x18; + break; + case 3: + temp |= 0x38; + break; + case 4: + temp |= 0x78; + break; + case 5: + temp |= 0xf8; /*FIFO full*/ + break; + } + } + + s3->accel.ext_fifo_slot2 = s3->accel.ext_fifo_slot; + s3->accel.ext_fifo_slot = 0; + s3->accel.ext_port_slot1 = 0; } } } else { @@ -3601,126 +3643,101 @@ s3_accel_in(uint16_t port, void *p) case 0x9d48: case 0x9ee8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.short_stroke & 0xff; } break; case 0x9d49: case 0x9ee9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.short_stroke >> 8; } break; case 0xa148: case 0xa2e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.bkgd_color & 0xff; } break; case 0xa149: case 0xa2e9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.bkgd_color >> 8; } break; case 0xa14a: case 0xa2ea: - s3_wait_fifo_idle(s3); return s3->accel.bkgd_color >> 16; case 0xa14b: case 0xa2eb: - s3_wait_fifo_idle(s3); return s3->accel.bkgd_color >> 24; case 0xa548: case 0xa6e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.frgd_color & 0xff; } break; case 0xa549: case 0xa6e9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.frgd_color >> 8; } break; case 0xa54a: case 0xa6ea: - s3_wait_fifo_idle(s3); return s3->accel.frgd_color >> 16; case 0xa54b: case 0xa6eb: - s3_wait_fifo_idle(s3); return s3->accel.frgd_color >> 24; case 0xa948: case 0xaae8: - if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); + if (s3->chip >= S3_86C928) { return s3->accel.wrt_mask & 0xff; } break; case 0xa949: case 0xaae9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.wrt_mask >> 8; } break; case 0xa94a: case 0xaaea: - s3_wait_fifo_idle(s3); return s3->accel.wrt_mask >> 16; case 0xa94b: case 0xaaeb: - s3_wait_fifo_idle(s3); return s3->accel.wrt_mask >> 24; case 0xad48: case 0xaee8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.rd_mask & 0xff; } break; case 0xad49: case 0xaee9: - s3_wait_fifo_idle(s3); return s3->accel.rd_mask >> 8; case 0xad4a: case 0xaeea: - s3_wait_fifo_idle(s3); return s3->accel.rd_mask >> 16; case 0xad4b: case 0xaeeb: - s3_wait_fifo_idle(s3); return s3->accel.rd_mask >> 24; case 0xb148: case 0xb2e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.color_cmp & 0xff; } break; case 0xb149: case 0xb2e9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.color_cmp >> 8; } break; case 0xb14a: case 0xb2ea: - s3_wait_fifo_idle(s3); return s3->accel.color_cmp >> 16; case 0xb14b: case 0xb2eb: - s3_wait_fifo_idle(s3); return s3->accel.color_cmp >> 24; case 0xb548: case 0xb6e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.bkgd_mix; } break; case 0xb948: case 0xbae8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.frgd_mix; } break; case 0xbd48: case 0xbee8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); temp = s3->accel.multifunc[0xf] & 0xf; switch (temp) { @@ -3741,7 +3758,6 @@ s3_accel_in(uint16_t port, void *p) break; case 0xbd49: case 0xbee9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); temp = s3->accel.multifunc[0xf] & 0xf; s3->accel.multifunc[0xf]++; switch (temp) @@ -3763,59 +3779,45 @@ s3_accel_in(uint16_t port, void *p) break; case 0xd148: case 0xd2e8: - s3_wait_fifo_idle(s3); return s3->accel.ropmix & 0xff; case 0xd149: case 0xd2e9: - s3_wait_fifo_idle(s3); return s3->accel.ropmix >> 8; case 0xe548: case 0xe6e8: - s3_wait_fifo_idle(s3); return s3->accel.pat_bg_color & 0xff; case 0xe549: case 0xe6e9: - s3_wait_fifo_idle(s3); return s3->accel.pat_bg_color >> 8; case 0xe54a: case 0xe6ea: - s3_wait_fifo_idle(s3); return s3->accel.pat_bg_color >> 16; case 0xe54b: case 0xe6eb: - s3_wait_fifo_idle(s3); return s3->accel.pat_bg_color >> 24; case 0xe948: case 0xeae8: - s3_wait_fifo_idle(s3); return s3->accel.pat_y & 0xff; case 0xe949: case 0xeae9: - s3_wait_fifo_idle(s3); return s3->accel.pat_y >> 8; case 0xe94a: case 0xeaea: - s3_wait_fifo_idle(s3); return s3->accel.pat_x & 0xff; case 0xe94b: case 0xeaeb: - s3_wait_fifo_idle(s3); return s3->accel.pat_x >> 8; case 0xed48: case 0xeee8: - s3_wait_fifo_idle(s3); return s3->accel.pat_fg_color & 0xff; case 0xed49: case 0xeee9: - s3_wait_fifo_idle(s3); return s3->accel.pat_fg_color >> 8; case 0xed4a: case 0xeeea: - s3_wait_fifo_idle(s3); return s3->accel.pat_fg_color >> 16; case 0xed4b: case 0xeeeb: - s3_wait_fifo_idle(s3); return s3->accel.pat_fg_color >> 24; case 0xe148: case 0xe2e8: @@ -3835,9 +3837,9 @@ s3_accel_in(uint16_t port, void *p) if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); } else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -3869,12 +3871,23 @@ s3_accel_in(uint16_t port, void *p) break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); + else + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + } else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + } else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); else s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } break; } } @@ -3938,44 +3951,52 @@ s3_accel_in_w(uint16_t port, void *p) uint16_t temp = 0x0000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514) + if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) return 0xffff; + + if (port != 0x9ee8 && port != 0x9d48) { + if (s3_cpu_dest(s3)) { + READ_PIXTRANS_WORD - if (s3_cpu_dest(s3)) { - READ_PIXTRANS_WORD - - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; - - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(8, 1, temp | (temp << 16), 0, s3); - else + s3->accel.port_slot1++; + s3->accel.port_slot2++; + if (s3->accel.port_slot1 || s3->accel.port_slot2) + s3->accel.draw_fifo_slot++; + if (s3->accel.draw_fifo_slot > 8) + s3->accel.draw_fifo_slot = 1; + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = (temp >> 8) | (temp << 8); + s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + } else s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); - } else - s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(16, 1, temp | (temp << 16), 0, s3); - else + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = (temp >> 8) | (temp << 8); + s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + } else s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); - } else - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); - break; - } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; + break; + } + + if (s3_enable_fifo(s3) == 0) { + s3->accel.draw_fifo_slot = 0; + } } + } else { + temp = s3->accel.short_stroke; } + return temp; } @@ -3987,7 +4008,7 @@ s3_accel_in_l(uint16_t port, void *p) uint32_t temp = 0x00000000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514) + if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) return 0xffffffff; if (s3_cpu_dest(s3)) { @@ -4004,6 +4025,8 @@ s3_accel_in_l(uint16_t port, void *p) case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = ((temp & 0xff00ff00) >> 8) | ((temp & 0x00ff00ff) << 8); s3_accel_start(8, 1, temp, 0, s3); s3_accel_start(8, 1, temp >> 16, 0, s3); } else { @@ -4018,6 +4041,8 @@ s3_accel_in_l(uint16_t port, void *p) case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = ((temp & 0xff00ff00) >> 8) | ((temp & 0x00ff00ff) << 8); s3_accel_start(16, 1, temp, 0, s3); s3_accel_start(16, 1, temp >> 16, 0, s3); } else { @@ -4046,20 +4071,13 @@ s3_accel_write(uint32_t addr, uint8_t val, void *p) s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; - if (!s3->enable_8514) + if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) { - if (s3->chip <= S3_86C805) { + if (svga->crtc[0x53] & 0x08) + s3_accel_write_fifo(s3, addr & 0x1ffff, val); + else s3_accel_write_fifo(s3, addr & 0xffff, val); - } else { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_BYTE); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); - } - } else - s3_accel_write_fifo(s3, addr & 0xffff, val); } static void @@ -4068,20 +4086,13 @@ s3_accel_write_w(uint32_t addr, uint16_t val, void *p) s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; - if (!s3->enable_8514) + if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) { - if (s3->chip <= S3_86C805) { + if (svga->crtc[0x53] & 0x08) + s3_accel_write_fifo_w(s3, addr & 0x1ffff, val); + else s3_accel_write_fifo_w(s3, addr & 0xffff, val); - } else { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_WORD); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); - } - } else - s3_accel_write_fifo_w(s3, addr & 0xffff, val); } static void @@ -4090,20 +4101,13 @@ s3_accel_write_l(uint32_t addr, uint32_t val, void *p) s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; - if (!s3->enable_8514) + if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) { - if (s3->chip <= S3_86C805) { + if (svga->crtc[0x53] & 0x08) + s3_accel_write_fifo_l(s3, addr & 0x1ffff, val); + else s3_accel_write_fifo_l(s3, addr & 0xffff, val); - } else { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_DWORD); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); - } - } else - s3_accel_write_fifo_l(s3, addr & 0xffff, val); } static uint8_t @@ -4113,9 +4117,8 @@ s3_accel_read(uint32_t addr, void *p) svga_t *svga = &s3->svga; uint8_t temp = 0x00; - if (!s3->enable_8514) { - return 0xff; - } + if (!s3->enable_8514) + return 0xff; if (svga->crtc[0x53] & 0x08) { if ((addr >= 0x08000) && (addr <= 0x0803f)) @@ -4193,11 +4196,14 @@ s3_accel_read_w(uint32_t addr, void *p) uint16_t temp = 0x0000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514) + if (!s3->enable_8514) return 0xffff; if (svga->crtc[0x53] & 0x08) { switch (addr & 0x1fffe) { + case 0x811c: + return s3->accel.short_stroke; + default: return s3_accel_read(addr, p) | s3_accel_read(addr + 1, p) << 8; @@ -4205,8 +4211,12 @@ s3_accel_read_w(uint32_t addr, void *p) return 0xffff; } else { if (addr & 0x8000) { - temp = s3_accel_read((addr & 0xfffe), p); - temp |= s3_accel_read((addr & 0xfffe) + 1, p) << 8; + if (addr == 0x811c) + temp = s3->accel.short_stroke; + else { + temp = s3_accel_read((addr & 0xfffe), p); + temp |= s3_accel_read((addr & 0xfffe) + 1, p) << 8; + } } else if (s3_cpu_dest(s3)) { READ_PIXTRANS_WORD @@ -4256,7 +4266,7 @@ s3_accel_read_l(uint32_t addr, void *p) uint32_t temp = 0x00000000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514) + if (!s3->enable_8514) return 0xffffffff; if (svga->crtc[0x53] & 0x08) { @@ -5148,6 +5158,22 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) } } +void +s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv) +{ + if (!cpu_input) { + s3->accel.ssv_len = ssv & 0x0f; + s3->accel.ssv_dir = ssv & 0xe0; + s3->accel.ssv_draw = ssv & 0x10; + + if (s3_cpu_src(s3)) { + return; /*Wait for data from CPU*/ + } + } + + s3_accel_start(count, cpu_input, mix_dat, cpu_dat, s3); +} + void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3) { @@ -5243,46 +5269,18 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ - switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ if (s3->accel.ssv_state == 0) break; - - if (!cpu_input) { - s3->accel.cx = s3->accel.cur_x; - if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y; - if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; - - if (s3->accel.cmd & 0x1000) { - s3->accel.ssv_len1 = (s3->accel.short_stroke >> 8) & 0x0f; - s3->accel.ssv_dir1 = (s3->accel.short_stroke >> 8) & 0xe0; - s3->accel.ssv_draw1 = (s3->accel.short_stroke >> 8) & 0x10; - s3->accel.ssv_len2 = s3->accel.short_stroke & 0x0f; - s3->accel.ssv_dir2 = s3->accel.short_stroke & 0xe0; - s3->accel.ssv_draw2 = s3->accel.short_stroke & 0x10; - } else { - s3->accel.ssv_len2 = (s3->accel.short_stroke >> 8) & 0x0f; - s3->accel.ssv_dir2 = (s3->accel.short_stroke >> 8) & 0xe0; - s3->accel.ssv_draw2 = (s3->accel.short_stroke >> 8) & 0x10; - s3->accel.ssv_len1 = s3->accel.short_stroke & 0x0f; - s3->accel.ssv_dir1 = s3->accel.short_stroke & 0xe0; - s3->accel.ssv_draw1 = s3->accel.short_stroke & 0x10; - } - - if (s3_cpu_src(s3)) { - return; /*Wait for data from CPU*/ - } - } - + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; if (s3->accel.cmd & 8) /*Radial*/ - { - while (count-- && s3->accel.ssv_len1 >= 0) + { + while (count-- && s3->accel.ssv_len >= 0) { if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) @@ -5303,7 +5301,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ MIX - if (s3->accel.ssv_draw1) { + if (s3->accel.ssv_draw) { WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); } } @@ -5313,10 +5311,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat |= 1; if (s3->bpp == 0) cpu_dat >>= 8; else cpu_dat >>= 16; - if (!s3->accel.ssv_len1) + if (!s3->accel.ssv_len) break; - switch (s3->accel.ssv_dir1 & 0xe0) + switch (s3->accel.ssv_dir & 0xe0) { case 0x00: s3->accel.cx++; break; case 0x20: s3->accel.cx++; s3->accel.cy--; break; @@ -5327,56 +5325,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0xc0: s3->accel.cy++; break; case 0xe0: s3->accel.cx++; s3->accel.cy++; break; } - s3->accel.ssv_len1--; + + s3->accel.ssv_len--; } - - while (count-- && s3->accel.ssv_len2 >= 0) - { - if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && - (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) - { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; break; - } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - - MIX - - if (s3->accel.ssv_draw2) { - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - } - } - } - - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; - if (!s3->accel.ssv_len2) - break; - - switch (s3->accel.ssv_dir2 & 0xe0) - { - case 0x00: s3->accel.cx++; break; - case 0x20: s3->accel.cx++; s3->accel.cy--; break; - case 0x40: s3->accel.cy--; break; - case 0x60: s3->accel.cx--; s3->accel.cy--; break; - case 0x80: s3->accel.cx--; break; - case 0xa0: s3->accel.cx--; s3->accel.cy++; break; - case 0xc0: s3->accel.cy++; break; - case 0xe0: s3->accel.cx++; s3->accel.cy++; break; - } - s3->accel.ssv_len2--; - } s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; } @@ -6616,6 +6568,11 @@ static void *s3_init(const device_t *info) chip = S3_86C805; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); break; + case S3_MIROCRYSTAL8S_805: + bios_fn = ROM_MIROCRYSTAL8S_805; + chip = S3_86C805; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + break; case S3_MIROCRYSTAL10SD_805: bios_fn = ROM_MIROCRYSTAL10SD_805; chip = S3_86C805; @@ -6795,11 +6752,7 @@ static void *s3_init(const device_t *info) memset(s3, 0, sizeof(s3_t)); - if (info->local == S3_SPEA_MIRAGE_86C801 || - info->local == S3_SPEA_MIRAGE_86C805) - vram = 1; - else - vram = device_get_config_int("memory"); + vram = device_get_config_int("memory"); if (vram) vram_size = vram << 20; @@ -6963,6 +6916,7 @@ static void *s3_init(const device_t *info) svga->getclock = ics2494_getclock; break; + case S3_MIROCRYSTAL8S_805: case S3_MIROCRYSTAL10SD_805: svga->decode_mask = (2 << 20) - 1; stepping = 0xa0; /*86C801/86C805*/ @@ -6979,7 +6933,7 @@ static void *s3_init(const device_t *info) case S3_SPEA_MIRAGE_86C801: case S3_SPEA_MIRAGE_86C805: - svga->decode_mask = (1 << 20) - 1; + svga->decode_mask = (2 << 20) - 1; stepping = 0xa0; /*86C801/86C805*/ s3->id = stepping; s3->id_ext = stepping; @@ -7177,11 +7131,6 @@ static void *s3_init(const device_t *info) svga->packed_chain4 = 1; - s3->wake_fifo_thread = thread_create_event(); - s3->fifo_not_full_event = thread_create_event(); - s3->thread_run = 1; - s3->fifo_thread = thread_create(fifo_thread, s3); - return s3; } @@ -7215,6 +7164,11 @@ static int s3_phoenix_86c80x_available(void) return rom_present(ROM_PHOENIX_86C80X); } +static int s3_mirocrystal_8s_805_available(void) +{ + return rom_present(ROM_MIROCRYSTAL8S_805); +} + static int s3_mirocrystal_10sd_805_available(void) { return rom_present(ROM_MIROCRYSTAL10SD_805); @@ -7331,12 +7285,6 @@ static void s3_close(void *p) svga_close(&s3->svga); - s3->thread_run = 0; - thread_set_event(s3->wake_fifo_thread); - thread_wait(s3->fifo_thread, -1); - thread_destroy_event(s3->wake_fifo_thread); - thread_destroy_event(s3->fifo_not_full_event); - ddc_close(s3->ddc); i2c_gpio_close(s3->i2c); @@ -7529,7 +7477,7 @@ const device_t s3_spea_mirage_86c801_isa_device = { s3_spea_mirage_86c801_available }, s3_speed_changed, s3_force_redraw, - NULL + s3_9fx_config }; const device_t s3_spea_mirage_86c805_vlb_device = @@ -7543,9 +7491,24 @@ const device_t s3_spea_mirage_86c805_vlb_device = { s3_spea_mirage_86c805_available }, s3_speed_changed, s3_force_redraw, - NULL + s3_9fx_config }; +const device_t s3_mirocrystal_8s_805_vlb_device = +{ + "S3 86c805 VLB (MiroCRYSTAL 8S)", + DEVICE_VLB, + S3_MIROCRYSTAL8S_805, + s3_init, + s3_close, + NULL, + { s3_mirocrystal_8s_805_available }, + s3_speed_changed, + s3_force_redraw, + s3_9fx_config +}; + + const device_t s3_mirocrystal_10sd_805_vlb_device = { "S3 86c805 VLB (MiroCRYSTAL 10SD)", diff --git a/src/video/vid_table.c b/src/video/vid_table.c index a34e77b48..aa40e3079 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -185,6 +185,7 @@ video_cards[] = { { "stealth3d_2000_vlb", &s3_virge_vlb_device }, { "stealth3d_3000_vlb", &s3_virge_988_vlb_device }, { "metheus928_vlb", &s3_metheus_86c928_vlb_device }, + { "mirocrystal8s_vlb", &s3_mirocrystal_8s_805_vlb_device }, { "mirocrystal10sd_vlb", &s3_mirocrystal_10sd_805_vlb_device }, { "px_86c805_vlb", &s3_phoenix_86c805_vlb_device }, { "px_s3_v7_805_vlb", &s3_spea_mirage_86c805_vlb_device }, From c4038f48f3e24ee0b4d17a2bf3e726f80c2e7f6e Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 18 Sep 2021 00:36:54 +0200 Subject: [PATCH 2/2] S3 changes part 5: Rewritten non-threaded FIFO to be sure that it won't hang any OS (especially OS/2) and won't cause any more glitches on Windows 3.1 86x/96x drivers. Fixed the decode mask of the Vision868 (8MB instead of 4MB). Fixed 16bpp cursor using the MiroCRYSTAL 10SD specific drivers for OS/2 (including seamless Win-OS/2) --- src/video/vid_s3.c | 620 ++++++++++++++++----------------------------- 1 file changed, 225 insertions(+), 395 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 55dfa2300..d5d507c14 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -261,14 +261,10 @@ typedef struct s3_t uint8_t ssv_draw; /*For non-threaded FIFO*/ - int setup_fifo_slot, setup_fifo_slot2; - int draw_fifo_slot, draw_fifo_slot2; - int port_slot1, port_slot2; - int port_slot3, port_slot4; - - /*Vision964 and up only*/ - int ext_fifo_slot, ext_fifo_slot2; - int ext_port_slot1, ext_port_slot2; + int setup_fifo_slot; + int draw_fifo_slot; + int setup_fifo, setup_fifo2; + int draw_fifo, draw_fifo2; } accel; struct { @@ -488,14 +484,8 @@ static void s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) { svga_t *svga = &s3->svga; - + if (s3->accel.cmd & 0x100) { - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -555,10 +545,6 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) } break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } @@ -566,12 +552,6 @@ static void s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) { if (s3->accel.cmd & 0x100) { - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -631,10 +611,6 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) } break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } @@ -645,12 +621,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) switch (port) { case 0x8148: case 0x82e8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.cur_y_bitres = (s3->accel.cur_y_bitres & 0xff00) | val; s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; s3->accel.poly_cy = s3->accel.cur_y; @@ -662,12 +633,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.poly_cy = s3->accel.cur_y; break; case 0x814a: case 0x82ea: - s3->accel.ext_port_slot1++; - s3->accel.ext_port_slot2++; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot++; - if (s3->accel.ext_fifo_slot > 5) - s3->accel.ext_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xf00) | val; s3->accel.poly_cy2 = s3->accel.cur_y2; break; @@ -677,12 +643,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x8548: case 0x86e8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.cur_x_bitres = (s3->accel.cur_x_bitres & 0xff00) | val; s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val; s3->accel.poly_cx = s3->accel.cur_x << 20; @@ -696,12 +657,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.poly_x = s3->accel.poly_cx >> 20; break; case 0x854a: case 0x86ea: - s3->accel.ext_port_slot1++; - s3->accel.ext_port_slot2++; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot++; - if (s3->accel.ext_fifo_slot > 5) - s3->accel.ext_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xf00) | val; s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; break; @@ -711,12 +667,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x8948: case 0x8ae8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val; s3->accel.point_1_updated = 1; break; @@ -727,12 +678,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.point_1_updated = 1; break; case 0x894a: case 0x8aea: - s3->accel.ext_port_slot1++; - s3->accel.ext_port_slot2++; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot++; - if (s3->accel.ext_fifo_slot > 5) - s3->accel.ext_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0x3f00) | val; s3->accel.point_2_updated = 1; break; @@ -744,12 +690,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x8d48: case 0x8ee8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val; s3->accel.point_1_updated = 1; break; @@ -760,12 +701,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.point_1_updated = 1; break; case 0x8d4a: case 0x8eea: - s3->accel.ext_port_slot1++; - s3->accel.ext_port_slot2++; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot++; - if (s3->accel.ext_fifo_slot > 5) - s3->accel.ext_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.x2 = (s3->accel.x2 & 0xf00) | val; s3->accel.point_2_updated = 1; break; @@ -775,12 +711,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9148: case 0x92e8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.err_term = (s3->accel.err_term & 0x3f00) | val; break; case 0x9149: case 0x92e9: @@ -789,12 +720,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.err_term |= ~0x3fff; break; case 0x914a: case 0x92ea: - s3->accel.ext_port_slot1++; - s3->accel.ext_port_slot2++; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot++; - if (s3->accel.ext_fifo_slot > 5) - s3->accel.ext_fifo_slot = 1; s3->accel.err_term2 = (s3->accel.err_term2 & 0x3f00) | val; break; case 0x914b: case 0x92eb: @@ -804,12 +729,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9548: case 0x96e8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xf00) | val; break; case 0x9459: case 0x96e9: @@ -818,12 +738,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.maj_axis_pcnt |= ~0x0fff; break; case 0x954a: case 0x96ea: - s3->accel.ext_port_slot1++; - s3->accel.ext_port_slot2++; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot++; - if (s3->accel.ext_fifo_slot > 5) - s3->accel.ext_fifo_slot = 1; s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xf00) | val; break; case 0x954b: case 0x96eb: @@ -833,12 +747,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9948: case 0x9ae8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; s3->accel.cmd = (s3->accel.cmd & 0xff00) | val; s3->data_available = 0; s3->accel.b2e8_pix = 0; @@ -879,12 +788,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa148: case 0xa2e8: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); else @@ -921,12 +825,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa548: case 0xa6e8: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); else @@ -963,12 +862,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa948: case 0xaae8: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); else @@ -1005,12 +899,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xad48: case 0xaee8: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); else @@ -1047,12 +936,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xb148: case 0xb2e8: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); else @@ -1089,22 +972,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xb548: case 0xb6e8: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; s3->accel.bkgd_mix = val; break; case 0xb948: case 0xbae8: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; s3->accel.frgd_mix = val; break; @@ -1116,31 +989,23 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; switch (s3->accel.multifunc_cntl >> 12) { case 0: - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; + s3->accel.draw_fifo_slot++; break; case 0xa: - s3->accel.port_slot3++; - s3->accel.port_slot4++; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot++; - if (s3->accel.setup_fifo_slot > 8) - s3->accel.setup_fifo_slot = 1; + s3->accel.setup_fifo_slot++; break; } break; case 0xd148: case 0xd2e8: + s3->accel.setup_fifo_slot++; s3->accel.ropmix = (s3->accel.ropmix & 0xff00) | val; break; case 0xd149: case 0xd2e9: s3->accel.ropmix = (s3->accel.ropmix & 0x00ff) | (val << 8); break; case 0xe548: case 0xe6e8: + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); else @@ -1176,18 +1041,21 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) } break; case 0xe948: case 0xeae8: + s3->accel.draw_fifo_slot++; s3->accel.pat_y = (s3->accel.pat_y & 0xf00) | val; break; case 0xe949: case 0xeae9: s3->accel.pat_y = (s3->accel.pat_y & 0xff) | ((val & 0x1f) << 8); break; case 0xe94a: case 0xeaea: + s3->accel.draw_fifo_slot++; s3->accel.pat_x = (s3->accel.pat_x & 0xf00) | val; break; case 0xe94b: case 0xeaeb: s3->accel.pat_x = (s3->accel.pat_x & 0xff) | ((val & 0x1f) << 8); break; case 0xed48: case 0xeee8: + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); else @@ -1229,12 +1097,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; s3->accel.pix_trans[0] = val; if (s3->accel.cmd & 0x100) { - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; if (!(s3->accel.cmd & 0x600)) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) @@ -1294,7 +1156,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) } break; case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); @@ -1356,7 +1218,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); break; case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); @@ -1373,12 +1235,8 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) } if (s3_enable_fifo(s3) == 0) { - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot = 0; - if (s3->accel.port_slot3 || s3->accel.port_slot4) - s3->accel.setup_fifo_slot = 0; - if (s3->accel.ext_port_slot1 || s3->accel.ext_port_slot2) - s3->accel.ext_fifo_slot = 0; + s3->accel.setup_fifo_slot = 0; + s3->accel.draw_fifo_slot = 0; } } @@ -1578,12 +1436,6 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3_accel_out_fifo(s3, addr & 0xffff, val); } else { if (s3->accel.cmd & 0x100) { - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; if ((s3->accel.cmd & 0x600) == 0x200) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) @@ -1601,9 +1453,6 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) } else s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } } @@ -1899,9 +1748,11 @@ s3_hwcursor_draw(svga_t *svga, int displine) fg = video_15to32[s3->hwc_fg_col & 0xffff]; bg = video_15to32[s3->hwc_bg_col & 0xffff]; if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { - if (!(svga->crtc[0x45] & 0x04)) { - shift = 2; - width = 8; + if (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805) { + if (!(svga->crtc[0x45] & 0x04)) { + shift = 2; + width = 8; + } } } break; @@ -1910,9 +1761,15 @@ s3_hwcursor_draw(svga_t *svga, int displine) fg = video_16to32[s3->hwc_fg_col & 0xffff]; bg = video_16to32[s3->hwc_bg_col & 0xffff]; if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { - if (!(svga->crtc[0x45] & 0x04)) { - shift = 2; - width = 8; + if (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805) { + if (!(svga->crtc[0x45] & 0x04)) { + shift = 2; + width = 8; + } + } else if (s3->card_type == S3_MIROCRYSTAL10SD_805) { + if (!(svga->crtc[0x45] & 0x04)) { + offset <<= 1; + } } } break; @@ -1965,17 +1822,17 @@ s3_hwcursor_draw(svga_t *svga, int displine) } } else { /*Windows*/ - for (xx = 0; xx < width; xx++) { + for (xx = 0; xx < width; xx++) { if (offset >= svga->hwcursor_latch.x) { if (!(dat[0] & 0x8000)) buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; else if (dat[1] & 0x8000) buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; } - - offset++; - dat[0] <<= shift; - dat[1] <<= shift; + + offset++; + dat[0] <<= shift; + dat[1] <<= shift; } } svga->hwcursor_latch.addr += 4; @@ -2465,7 +2322,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) addr ^= 0x60; switch (addr) - { + { case 0x3c2: if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { if (((val >> 2) & 3) != 3) @@ -2648,17 +2505,19 @@ s3_out(uint16_t addr, uint8_t val, void *p) if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) break; svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; - if (svga->bpp == 32) svga->hwcursor.x >>= 1; + if (svga->bpp == 32 && s3->chip != S3_VISION868) svga->hwcursor.x >>= 1; svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; svga->hwcursor.xoff = svga->crtc[0x4e] & 0x3f; svga->hwcursor.yoff = svga->crtc[0x4f] & 0x3f; svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); - - if ((s3->chip >= S3_TRIO32) && svga->bpp == 32) + if ((s3->chip >= S3_TRIO32) && (s3->chip != S3_VISION868) && svga->bpp == 32) svga->hwcursor.x <<= 1; - else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 15 || svga->bpp == 16)) - svga->hwcursor.x >>= 1; - else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 24)) + else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 15 || svga->bpp == 16)) { + if ((s3->card_type == S3_MIROCRYSTAL10SD_805) && !(svga->crtc[0x45] & 0x04) && svga->bpp == 16) + svga->hwcursor.x >>= 2; + else + svga->hwcursor.x >>= 1; + } else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 24)) svga->hwcursor.x /= 3; break; @@ -2943,13 +2802,18 @@ static void s3_recalctimings(svga_t *svga) s3->width = 1024; } } + + if (s3->chip != S3_TRIO64 && s3->chip != S3_TRIO32) { + if (svga->crtc[0x31] & 0x08) {/*This would typically force dword mode, but we are encountering accel bugs with it, so force byte mode instead*/ + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) + svga->force_byte_mode = 0; + else + svga->force_byte_mode = 1; + } else + svga->force_byte_mode = 0; + } if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - if (svga->crtc[0x31] & 0x08) /*This would typically force dword mode, but we are encountering accel bugs with it, so force byte mode instead*/ - svga->force_byte_mode = 1; - else - svga->force_byte_mode = 0; - switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -3372,7 +3236,7 @@ s3_accel_out(uint16_t port, uint8_t val, void *p) if (port >= 0x8000) { - if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + if (!s3->enable_8514) return; s3_accel_out_fifo(s3, port, val); @@ -3415,7 +3279,7 @@ s3_accel_out_w(uint16_t port, uint16_t val, void *p) { s3_t *s3 = (s3_t *)p; - if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + if (!s3->enable_8514) return; s3_accel_out_fifo_w(s3, port, val); @@ -3426,7 +3290,7 @@ s3_accel_out_l(uint16_t port, uint32_t val, void *p) { s3_t *s3 = (s3_t *)p; - if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + if (!s3->enable_8514) return; s3_accel_out_fifo_l(s3, port, val); @@ -3439,7 +3303,7 @@ s3_accel_in(uint16_t port, void *p) svga_t *svga = &s3->svga; int temp; - if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + if (!s3->enable_8514) return 0xff; switch (port) { @@ -3500,72 +3364,12 @@ s3_accel_in(uint16_t port, void *p) case 0x9948: case 0x9ae8: temp = 0; /* FIFO empty */ if (s3_enable_fifo(s3)) { - if (s3->accel.port_slot3) { - if (s3->accel.setup_fifo_slot) { - switch (s3->accel.setup_fifo_slot) { - case 1: - temp = 1; - break; - case 2: - temp = 3; - break; - case 3: - temp = 7; - break; - case 4: - temp = 0x0f; - break; - case 5: - temp = 0x1f; - break; - case 6: - temp = 0x3f; - break; - case 7: - temp = 0x7f; - break; - case 8: - temp = 0xff; /*FIFO full*/ - break; - } - } - - s3->accel.setup_fifo_slot2 = s3->accel.setup_fifo_slot; - s3->accel.setup_fifo_slot = 0; - s3->accel.port_slot3 = 0; - } else if (s3->accel.port_slot1) { - if (s3->accel.draw_fifo_slot) { - switch (s3->accel.draw_fifo_slot) { - case 1: - temp = 1; - break; - case 2: - temp = 3; - break; - case 3: - temp = 7; - break; - case 4: - temp = 0x0f; - break; - case 5: - temp = 0x1f; - break; - case 6: - temp = 0x3f; - break; - case 7: - temp = 0x7f; - break; - case 8: - temp = 0xff; /*FIFO full*/ - break; - } - } - - s3->accel.draw_fifo_slot2 = s3->accel.draw_fifo_slot; - s3->accel.draw_fifo_slot = 0; - s3->accel.port_slot1 = 0; + if (s3->accel.setup_fifo_slot) { + temp = s3->accel.setup_fifo; + s3->accel.setup_fifo = 0; + } else if (s3->accel.draw_fifo_slot) { + temp = s3->accel.draw_fifo; + s3->accel.draw_fifo = 0; } } return temp; @@ -3573,68 +3377,41 @@ s3_accel_in(uint16_t port, void *p) case 0x9949: case 0x9ae9: temp = 0; if (s3_enable_fifo(s3)) { - if (s3->force_busy) { + if ((s3->accel.setup_fifo_slot && s3->accel.draw_fifo_slot) || s3->force_busy) { temp |= 0x02; /*Hardware busy*/ - s3->subsys_stat |= INT_GE_BSY; } else { - if (s3->accel.port_slot2) { - s3->accel.port_slot2 = 0; - if (!s3->accel.draw_fifo_slot2) { - temp |= 0x04; /*FIFO empty*/ - s3->subsys_stat |= INT_FIFO_EMP; - } - if (s3->accel.draw_fifo_slot2) - s3->accel.draw_fifo_slot2 = 0; - } else if (s3->accel.port_slot4) { - s3->accel.port_slot4 = 0; - if (!s3->accel.setup_fifo_slot2) { - temp |= 0x04; /*FIFO empty*/ - s3->subsys_stat |= INT_FIFO_EMP; - } - if (s3->accel.setup_fifo_slot2) - s3->accel.setup_fifo_slot2 = 0; - } + temp |= 0x04; /*FIFO empty*/ + s3->subsys_stat |= INT_FIFO_EMP; + s3_update_irqs(s3); } s3->force_busy = 0; + + if (s3->chip >= S3_VISION964) { + if (s3->accel.setup_fifo_slot > 8) { + temp |= s3->accel.setup_fifo2; + s3->accel.setup_fifo2 = 0; + } else if (s3->accel.draw_fifo_slot > 8) { + temp |= s3->accel.draw_fifo2; + s3->accel.draw_fifo2 = 0; + } + } + + if (s3->accel.setup_fifo_slot) + s3->accel.setup_fifo_slot--; + if (s3->accel.draw_fifo_slot) + s3->accel.draw_fifo_slot--; + if (s3->data_available) { temp |= 0x01; /*Read Data available*/ s3->data_available = 0; } - - if (s3->chip >= S3_VISION964) { - if (s3->accel.ext_port_slot1) { - if (s3->accel.ext_fifo_slot) { - switch (s3->accel.ext_fifo_slot) { - case 1: - temp |= 0x08; - break; - case 2: - temp |= 0x18; - break; - case 3: - temp |= 0x38; - break; - case 4: - temp |= 0x78; - break; - case 5: - temp |= 0xf8; /*FIFO full*/ - break; - } - } - - s3->accel.ext_fifo_slot2 = s3->accel.ext_fifo_slot; - s3->accel.ext_fifo_slot = 0; - s3->accel.ext_port_slot1 = 0; - } - } } else { if (s3->force_busy) { temp |= 0x02; /*Hardware busy*/ } s3->force_busy = 0; - if (s3->data_available && (s3->chip <= S3_86C805)) { + if (s3->data_available) { temp |= 0x01; /*Read Data available*/ s3->data_available = 0; } @@ -3825,12 +3602,6 @@ s3_accel_in(uint16_t port, void *p) break; READ_PIXTRANS_BYTE_IO(0) if (s3->accel.cmd & 0x100) { - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -3936,10 +3707,6 @@ s3_accel_in(uint16_t port, void *p) return temp; } - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } - return 0xff; } @@ -3951,19 +3718,13 @@ s3_accel_in_w(uint16_t port, void *p) uint16_t temp = 0x0000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + if (!s3->enable_8514) return 0xffff; if (port != 0x9ee8 && port != 0x9d48) { if (s3_cpu_dest(s3)) { READ_PIXTRANS_WORD - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -3988,10 +3749,6 @@ s3_accel_in_w(uint16_t port, void *p) s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } else { temp = s3->accel.short_stroke; @@ -4008,19 +3765,12 @@ s3_accel_in_l(uint16_t port, void *p) uint32_t temp = 0x00000000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514 || !(s3->accel.advfunc_cntl & 1)) + if (!s3->enable_8514) return 0xffffffff; if (s3_cpu_dest(s3)) { READ_PIXTRANS_LONG - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; - switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -4055,10 +3805,6 @@ s3_accel_in_l(uint16_t port, void *p) } break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } return temp; @@ -4151,13 +3897,6 @@ s3_accel_read(uint32_t addr, void *p) } else if (s3_cpu_dest(s3)) { READ_PIXTRANS_BYTE_MM - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; - switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -4178,10 +3917,6 @@ s3_accel_read(uint32_t addr, void *p) s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } @@ -4220,13 +3955,6 @@ s3_accel_read_w(uint32_t addr, void *p) } else if (s3_cpu_dest(s3)) { READ_PIXTRANS_WORD - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; - switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -4247,10 +3975,6 @@ s3_accel_read_w(uint32_t addr, void *p) s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } @@ -4389,13 +4113,6 @@ s3_accel_read_l(uint32_t addr, void *p) } else if (s3_cpu_dest(s3)) { READ_PIXTRANS_LONG - s3->accel.port_slot1++; - s3->accel.port_slot2++; - if (s3->accel.port_slot1 || s3->accel.port_slot2) - s3->accel.draw_fifo_slot++; - if (s3->accel.draw_fifo_slot > 8) - s3->accel.draw_fifo_slot = 1; - switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -4426,10 +4143,6 @@ s3_accel_read_l(uint32_t addr, void *p) } break; } - - if (s3_enable_fifo(s3) == 0) { - s3->accel.draw_fifo_slot = 0; - } } } @@ -5158,6 +4871,104 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) } } +static void +s3_fifo_slots(s3_t *s3) +{ + switch (s3->accel.setup_fifo_slot) { + case 1: + s3->accel.setup_fifo |= 1; + break; + case 2: + s3->accel.setup_fifo |= 3; + break; + case 3: + s3->accel.setup_fifo |= 7; + break; + case 4: + s3->accel.setup_fifo |= 0x0f; + break; + case 5: + s3->accel.setup_fifo |= 0x1f; + break; + case 6: + s3->accel.setup_fifo |= 0x3f; + break; + case 7: + s3->accel.setup_fifo |= 0x7f; + break; + case 8: + s3->accel.setup_fifo |= 0xff; /* FIFO full */ + break; + case 9: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0x08; + break; + case 10: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0x18; + break; + case 11: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0x38; + break; + case 12: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0x78; + break; + case 13: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0xf8; /* FIFO full */ + break; + } + + switch (s3->accel.draw_fifo_slot) { + case 1: + s3->accel.draw_fifo |= 1; + break; + case 2: + s3->accel.draw_fifo |= 3; + break; + case 3: + s3->accel.draw_fifo |= 7; + break; + case 4: + s3->accel.draw_fifo |= 0x0f; + break; + case 5: + s3->accel.draw_fifo |= 0x1f; + break; + case 6: + s3->accel.draw_fifo |= 0x3f; + break; + case 7: + s3->accel.draw_fifo |= 0x7f; + break; + case 8: + s3->accel.draw_fifo |= 0xff; /* FIFO full */ + break; + case 9: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0x08; + break; + case 10: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0x18; + break; + case 11: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0x38; + break; + case 12: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0x78; + break; + case 13: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0xf8; /* FIFO full */ + break; + } +} + void s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv) { @@ -5166,6 +4977,8 @@ s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_d s3->accel.ssv_dir = ssv & 0xe0; s3->accel.ssv_draw = ssv & 0x10; + s3_fifo_slots(s3); + if (s3_cpu_src(s3)) { return; /*Wait for data from CPU*/ } @@ -5265,7 +5078,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0x400: mix_mask = 0x80000000; break; case 0x600: mix_mask = (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? 0x80 : 0x80000000; break; } - + /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ @@ -5343,11 +5156,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.sy = s3->accel.maj_axis_pcnt; + s3_fifo_slots(s3); + if (s3_cpu_src(s3)) { return; /*Wait for data from CPU*/ } } - + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; @@ -5524,6 +5339,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.dest = dstbase + s3->accel.cy * s3->width; + s3_fifo_slots(s3); + if (s3_cpu_src(s3)) { s3->data_available = 0; return; /*Wait for data from CPU*/ @@ -5646,6 +5463,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ polygon_setup(s3); + s3_fifo_slots(s3); + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ end_y1 = s3->accel.desty_axstp; @@ -5758,6 +5577,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; + + s3_fifo_slots(s3); } if ((s3->accel.cmd & 0x100) && !cpu_input) { @@ -5933,6 +5754,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy = s3->accel.dy & 7; s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width); + + s3_fifo_slots(s3); } if ((s3->accel.cmd & 0x100) && !cpu_input) { @@ -6055,6 +5878,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy = s3->accel.cur_y; if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; + + s3_fifo_slots(s3); } if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ @@ -6147,6 +5972,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ polygon_setup(s3); + s3_fifo_slots(s3); + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ end_y1 = s3->accel.desty_axstp; @@ -6156,6 +5983,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) { int y = s3->accel.poly_cy; @@ -6256,7 +6084,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.dest = dstbase + (s3->accel.dy * s3->width); s3->accel.src = srcbase + (s3->accel.cy * s3->width); - s3->accel.pattern = (s3->accel.py * s3->width); + s3->accel.pattern = (s3->accel.py * s3->width); + + s3_fifo_slots(s3); } if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ @@ -7041,7 +6871,7 @@ static void *s3_init(const device_t *info) break; case S3_PHOENIX_VISION868: - svga->decode_mask = (4 << 20) - 1; + svga->decode_mask = (8 << 20) - 1; s3->id = 0xe1; /*Vision868*/ s3->id_ext = 0x90; s3->id_ext_pci = 0x80;