From c8f9b8cbd374026493720819fb44f00e7728609b Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 29 Dec 2021 09:48:56 +0500 Subject: [PATCH 1/6] Handle the internal name change for the S3 ViRGE/GX (formerly ViRGE/DX VBE 2.0) --- src/config.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 972fb82ab..01c13e85e 100644 --- a/src/config.c +++ b/src/config.c @@ -889,7 +889,10 @@ load_video(void) } free_p = 1; } - gfxcard = video_get_video_from_internal_name(p); + if (!strcmp(p, "virge375_vbe20_pci")) /* migrate renamed cards */ + gfxcard = video_get_video_from_internal_name("virge385_pci"); + else + gfxcard = video_get_video_from_internal_name(p); if (free_p) free(p); } From c4af6f4f9b617716e669620d2224150aa89e3efc Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 29 Dec 2021 09:49:38 +0500 Subject: [PATCH 2/6] Fix a typo in CH Flightstick Pro's internal name --- src/config.c | 4 +++- src/game/joystick_ch_flightstick_pro.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/config.c b/src/config.c index 01c13e85e..98842009b 100644 --- a/src/config.c +++ b/src/config.c @@ -918,7 +918,7 @@ load_input_devices(void) p = config_get_string(cat, "joystick_type", NULL); if (p != NULL) { - if (!strcmp(p, "standard_2button")) + if (!strcmp(p, "standard_2button")) /* migrate renamed types */ joystick_type = joystick_get_from_internal_name("2axis_2button"); else if (!strcmp(p, "standard_4button")) joystick_type = joystick_get_from_internal_name("2axis_4button"); @@ -926,6 +926,8 @@ load_input_devices(void) joystick_type = joystick_get_from_internal_name("2axis_6button"); else if (!strcmp(p, "standard_8button")) joystick_type = joystick_get_from_internal_name("2axis_8button"); + else if (!strcmp(p, "ch_flighstick_pro")) /* fix typo */ + joystick_type = joystick_get_from_internal_name("ch_flightstick_pro"); joystick_type = joystick_get_from_internal_name(p); if (!joystick_type) { diff --git a/src/game/joystick_ch_flightstick_pro.c b/src/game/joystick_ch_flightstick_pro.c index 14bdee7a5..b6cd8911f 100644 --- a/src/game/joystick_ch_flightstick_pro.c +++ b/src/game/joystick_ch_flightstick_pro.c @@ -116,7 +116,7 @@ static void ch_flightstick_pro_a0_over(void *p) const joystick_if_t joystick_ch_flightstick_pro = { "CH Flightstick Pro", - "ch_flighstick_pro", + "ch_flightstick_pro", ch_flightstick_pro_init, ch_flightstick_pro_close, ch_flightstick_pro_read, From b5539d5029b980d9af3f5420c4f85ce7b006af09 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 29 Dec 2021 09:51:42 +0500 Subject: [PATCH 3/6] Fix joystick type migration not working as intended Map legacy integer-based joystick type options directly --- src/config.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/src/config.c b/src/config.c index 98842009b..58cd07a56 100644 --- a/src/config.c +++ b/src/config.c @@ -928,21 +928,41 @@ load_input_devices(void) joystick_type = joystick_get_from_internal_name("2axis_8button"); else if (!strcmp(p, "ch_flighstick_pro")) /* fix typo */ joystick_type = joystick_get_from_internal_name("ch_flightstick_pro"); + else + joystick_type = joystick_get_from_internal_name(p); - joystick_type = joystick_get_from_internal_name(p); if (!joystick_type) { /* Try to read an integer for backwards compatibility with old configs */ - c = config_get_int(cat, "joystick_type", 8); - switch (c) { - case 0: case 1: case 2: case 3: /* 2-axis joysticks */ - joystick_type = c + 1; - break; - case 4: case 5: case 6: case 7: /* other joysticks */ - joystick_type = c + 3; - break; - default: /* "None" (8) or invalid value */ - joystick_type = 0; - break; + if (!strcmp(p, "0")) /* workaround for config_get_int returning 0 on non-integer data */ + joystick_type = joystick_get_from_internal_name("2axis_2button"); + else { + c = config_get_int(cat, "joystick_type", 8); + switch (c) { + case 1: + joystick_type = joystick_get_from_internal_name("2axis_4button"); + break; + case 2: + joystick_type = joystick_get_from_internal_name("2axis_6button"); + break; + case 3: + joystick_type = joystick_get_from_internal_name("2axis_8button"); + break; + case 4: + joystick_type = joystick_get_from_internal_name("4axis_4button"); + break; + case 5: + joystick_type = joystick_get_from_internal_name("ch_flightstick_pro"); + break; + case 6: + joystick_type = joystick_get_from_internal_name("sidewinder_pad"); + break; + case 7: + joystick_type = joystick_get_from_internal_name("thrustmaster_fcs"); + break; + default: + joystick_type = 0; + break; + } } } } else From e32a84528d8ec6aebf534837cf1af784bd826165 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 3 Feb 2022 05:47:56 -0500 Subject: [PATCH 4/6] Additional comments in sb_dsp.c --- src/sound/snd_sb_dsp.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 001d0e94f..f2797431b 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -533,6 +533,8 @@ sb_exec_command(sb_dsp_t *dsp) case 0x24: /* 8-bit single cycle DMA input */ sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); break; + case 0x28: /* Direct ADC, 8-bit (Burst) */ + break; case 0x2C: /* 8-bit autoinit DMA input */ if (dsp->sb_type >= SB15) sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); @@ -547,6 +549,10 @@ sb_exec_command(sb_dsp_t *dsp) dsp->midi_in_poll = 0; dsp->uart_irq = 1; break; + case 0x32: /* MIDI Read Timestamp Poll */ + break; + case 0x33: /* MIDI Read Timestamp Interrupt */ + break; case 0x34: /* MIDI In poll */ if (dsp->sb_type < SB2) break; @@ -594,6 +600,10 @@ sb_exec_command(sb_dsp_t *dsp) dsp->sb_8051_ram[0x14] = (dsp->sb_freq >> 8) & 0xff; } break; + case 0x45: /* Continue Auto-Initialize DMA, 8-bit */ + break; + case 0x47: /* Continue Auto-Initialize DMA, 16-bit */ + break; case 0x48: /* Set DSP block transfer size */ dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8); break; @@ -864,7 +874,7 @@ sb_exec_command(sb_dsp_t *dsp) if (dsp->sb_asp_mode & 4) dsp->sb_asp_ram_index = 0; sb_dsp_log("SB16 ASP set mode %02X\n", dsp->sb_asp_mode); - } + } /* else DSP Status (Obsolete) */ break; case 0x05: /* ASP set codec parameter */ if (dsp->sb_type >= SB16) From 33361dd37c46e4c89e457c56b250b68ba28d79bb Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 3 Feb 2022 06:13:55 -0500 Subject: [PATCH 5/6] Preliminary config stuff for selectable uart type --- src/config.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 972fb82ab..f5cb94ec4 100644 --- a/src/config.c +++ b/src/config.c @@ -2562,10 +2562,16 @@ save_ports(void) config_set_int(cat, temp, serial_enabled[c]); /* + sprintf(temp, "serial%d_type", c + 1); + if (!serial_enabled[c]) + config_delete_var(cat, temp); +// else +// config_set_string(cat, temp, (char *) serial_type[c]) + sprintf(temp, "serial%d_device", c + 1); if (com_ports[c].device == 0) config_delete_var(cat, temp); - else + else config_set_string(cat, temp, (char *) com_device_get_internal_name(com_ports[c].device)); */ From 012046bd89aec12a64e171365c3fc8aef3e54ef6 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 3 Feb 2022 20:08:46 +0100 Subject: [PATCH 6/6] Added the Matrox Millennium card to dev branch and its respective bitblt additions and ROM. --- src/include/86box/video.h | 3 +- src/video/vid_mga.c | 575 ++++++++++++++++++++++++++++---------- src/video/vid_table.c | 1 + 3 files changed, 425 insertions(+), 154 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 62d9e3153..ebd6d3933 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -318,7 +318,8 @@ extern const device_t im1024_device; extern const device_t pgc_device; #if defined(DEV_BRANCH) && defined(USE_MGA) -/* Matrox Mystique */ +/* Matrox MGA */ +extern const device_t millennium_device; extern const device_t mystique_device; extern const device_t mystique_220_device; #endif diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index cf5b90c63..fe93f0d98 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -34,6 +34,7 @@ #include <86box/vid_svga_render.h> +#define ROM_MILLENNIUM "roms/video/matrox/matrox2064wr2.BIN" #define ROM_MYSTIQUE "roms/video/matrox/MYSTIQUE.VBI" #define ROM_MYSTIQUE_220 "roms/video/matrox/Myst220_66-99mhz.vbi" @@ -136,6 +137,7 @@ #define REG_CRTCEXT_DATA 0x1fdf #define REG_CACHEFLUSH 0x1fff +/*Mystique only*/ #define REG_TMR0 0x2c00 #define REG_TMR1 0x2c04 #define REG_TMR2 0x2c08 @@ -154,6 +156,7 @@ #define REG_SECEND 0x2c44 #define REG_SOFTRAP 0x2c48 +/*Mystique only*/ #define REG_PALWTADD 0x3c00 #define REG_PALDATA 0x3c01 #define REG_PIXRDMSK 0x3c02 @@ -260,6 +263,7 @@ #define DWGCTRL_OPCODE_BITBLT (0x8 << 0) #define DWGCTRL_OPCODE_ILOAD (0x9 << 0) #define DWGCTRL_OPCODE_IDUMP (0xa << 0) +#define DWGCTRL_OPCODE_FBITBLT (0xc << 0) #define DWGCTRL_OPCODE_ILOAD_SCALE (0xd << 0) #define DWGCTRL_OPCODE_ILOAD_HIGHV (0xe << 0) #define DWGCTRL_OPCODE_ILOAD_FILTER (0xf << 0) /* Not implemented. */ @@ -369,6 +373,15 @@ #define DITHER_555 2 #define DITHER_NONE_555 3 +/*PCI configuration registers*/ +#define OPTION_INTERLEAVE (1 << 12) + +enum +{ + MGA_2064W, /*Millennium*/ + MGA_1064SG, /*Mystique*/ + MGA_1164SG, /*Mystique 220*/ +}; enum { @@ -397,6 +410,8 @@ typedef struct mystique_t svga_t svga; rom_t bios_rom; + + int type; mem_mapping_t lfb_mapping, ctrl_mapping, iload_mapping; @@ -612,9 +627,9 @@ static const uint8_t trans_masks[16][16] = static int8_t dither5[256][2][2]; static int8_t dither6[256][2][2]; +static video_timings_t timing_matrox_millennium = {VIDEO_PCI, 2, 2, 1, 10, 10, 10}; static video_timings_t timing_matrox_mystique = {VIDEO_PCI, 4, 4, 4, 10, 10, 10}; - static void mystique_start_blit(mystique_t *mystique); static void mystique_update_irqs(mystique_t *mystique); @@ -654,6 +669,12 @@ mystique_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3c8: mystique->xreg_idx = val; + case 0x3c6: case 0x3c7: case 0x3c9: + if (mystique->type == MGA_2064W) + { + tvp3026_ramdac_out(addr, 0, 0, val, svga->ramdac, svga); + return; + } break; case 0x3cf: @@ -740,11 +761,33 @@ mystique_in(uint16_t addr, void *p) addr ^= 0x60; switch (addr) { + case 0x3c1: + if (svga->attraddr >= 0x15) + temp = 0; + else + temp = svga->attrregs[svga->attraddr]; + break; + + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: + if (mystique->type == MGA_2064W) + temp = tvp3026_ramdac_in(addr, 0, 0, svga->ramdac, svga); + else + temp = svga_in(addr, svga); + break; + case 0x3D4: temp = svga->crtcreg; break; case 0x3D5: - temp = svga->crtc[svga->crtcreg & 0x3f]; + if ((svga->crtcreg >= 0x19 && svga->crtcreg <= 0x21) || + svga->crtcreg == 0x23 || svga->crtcreg == 0x25 || svga->crtcreg >= 0x27) + temp = 0; + else + temp = svga->crtc[svga->crtcreg & 0x3f]; + break; + + case 0x3de: + temp = mystique->crtcext_idx; break; case 0x3df: @@ -783,6 +826,23 @@ mystique_vsync_callback(svga_t *svga) } } +static float +mystique_getclock(int clock, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + if (clock == 0) return 25175000.0; + if (clock == 1) return 28322000.0; + + int m = mystique->xpixpll[2].m; + int n = mystique->xpixpll[2].n; + int pl = mystique->xpixpll[2].p; + + float fvco = 14318181.0 * (n + 1) / (m + 1); + float fo = fvco / (pl + 1); + + return fo; +} void mystique_recalctimings(svga_t *svga) @@ -790,16 +850,7 @@ mystique_recalctimings(svga_t *svga) mystique_t *mystique = (mystique_t *)svga->p; int clk_sel = (svga->miscout >> 2) & 3; - if (clk_sel & 2) { - int m = mystique->xpixpll[2].m; - int n = mystique->xpixpll[2].n; - int p = mystique->xpixpll[2].p; - - double fvco = 14318181.0 * (n + 1) / (m + 1); - double fo = fvco / (p + 1); - - svga->clock = (cpuclock * (float)(1ull << 32)) / fo; - } + svga->clock = (cpuclock * (float)(1ull << 32)) / svga->getclock(clk_sel & 2, svga->clock_gen); if (mystique->crtcext_regs[1] & CRTCX_R1_HTOTAL8) svga->htotal += 0x100; @@ -820,70 +871,87 @@ mystique_recalctimings(svga_t *svga) if (mystique->crtcext_regs[2] & CRTCX_R2_LINECOMP10) svga->split += 0x400; - svga->interlace = !!(mystique->crtcext_regs[0] & 0x80); + if (mystique->type == MGA_2064W) + tvp3026_recalctimings(svga->ramdac, svga); + else + svga->interlace = !!(mystique->crtcext_regs[0] & 0x80); if (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE) { - int row_offset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); - + svga->packed_chain4 = 1; svga->lowres = 0; - svga->char_width = 8; - svga->hdisp = (svga->crtc[1] + 1) * 8; - svga->hdisp_time = svga->hdisp; - if (svga->interlace) - svga->rowoffset = row_offset; - else - svga->rowoffset = row_offset * 2; - svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 17) | - (svga->crtc[0xc] << 9) | (svga->crtc[0xd] << 1); - - /*Mystique, unlike most SVGA cards, allows display start to take - effect mid-screen*/ - if (svga->ma_latch != mystique->ma_latch_old) { - if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2) + (svga->rowoffset << 1); - else - svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2); - mystique->ma_latch_old = svga->ma_latch; + svga->char_width = 8; + svga->hdisp = (svga->crtc[1] + 1) * 8; + svga->hdisp_time = svga->hdisp; + svga->rowoffset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); + svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | + (svga->crtc[0xc] << 8) | svga->crtc[0xd]; + if (mystique->pci_regs[0x41] & (OPTION_INTERLEAVE >> 8)) + { + svga->rowoffset <<= 1; + svga->ma_latch <<= 1; } + if (mystique->type >= MGA_1064SG) { + /*Mystique, unlike most SVGA cards, allows display start to take + effect mid-screen*/ + if (svga->ma_latch != mystique->ma_latch_old) { + if (svga->interlace && svga->oddeven) + svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2) + (svga->rowoffset << 1); + else + svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2); + mystique->ma_latch_old = svga->ma_latch; + } - switch (mystique->xmulctrl & XMULCTRL_DEPTH_MASK) { - case XMULCTRL_DEPTH_8: - case XMULCTRL_DEPTH_2G8V16: - svga->render = svga_render_8bpp_highres; - svga->bpp = 8; - break; - case XMULCTRL_DEPTH_15: - case XMULCTRL_DEPTH_G16V16: - svga->render = svga_render_15bpp_highres; - svga->bpp = 15; - break; - case XMULCTRL_DEPTH_16: - svga->render = svga_render_16bpp_highres; - svga->bpp = 16; - break; - case XMULCTRL_DEPTH_24: - svga->render = svga_render_24bpp_highres; - svga->bpp = 24; - break; - case XMULCTRL_DEPTH_32: - case XMULCTRL_DEPTH_32_OVERLAYED: - svga->render = svga_render_32bpp_highres; - svga->bpp = 32; - break; + switch (mystique->xmulctrl & XMULCTRL_DEPTH_MASK) { + case XMULCTRL_DEPTH_8: + case XMULCTRL_DEPTH_2G8V16: + svga->render = svga_render_8bpp_highres; + svga->bpp = 8; + break; + case XMULCTRL_DEPTH_15: + case XMULCTRL_DEPTH_G16V16: + svga->render = svga_render_15bpp_highres; + svga->bpp = 15; + break; + case XMULCTRL_DEPTH_16: + svga->render = svga_render_16bpp_highres; + svga->bpp = 16; + break; + case XMULCTRL_DEPTH_24: + svga->render = svga_render_24bpp_highres; + svga->bpp = 24; + break; + case XMULCTRL_DEPTH_32: + case XMULCTRL_DEPTH_32_OVERLAYED: + svga->render = svga_render_32bpp_highres; + svga->bpp = 32; + break; + } + } else { + switch (svga->bpp) + { + case 8: + svga->render = svga_render_8bpp_highres; + break; + case 15: + svga->render = svga_render_15bpp_highres; + break; + case 16: + svga->render = svga_render_16bpp_highres; + break; + case 24: + svga->render = svga_render_24bpp_highres; + break; + case 32: + svga->render = svga_render_32bpp_highres; + break; + } } - svga->line_compare = mystique_line_compare; - - mem_mapping_set_handler(&mystique->lfb_mapping, - mystique_readb_linear, mystique_readw_linear, mystique_readl_linear, - mystique_writeb_linear, mystique_writew_linear, mystique_writel_linear); } else { + svga->packed_chain4 = 0; svga->line_compare = NULL; - svga->bpp = 8; - - mem_mapping_set_handler(&mystique->lfb_mapping, - svga_read_linear, svga_readw_linear, svga_readl_linear, - svga_write_linear, svga_writew_linear, svga_writel_linear); + if (mystique->type >= MGA_1064SG) + svga->bpp = 8; } } @@ -1261,8 +1329,37 @@ mystique_ctrl_read_b(uint32_t addr, void *p) svga_t *svga = &mystique->svga; uint8_t ret = 0xff; int fifocount; + uint16_t addr_0x0f = 0; + uint16_t addr_0x03 = 0; + int rs2 = 0, rs3 = 0; - switch (addr & 0x3fff) { + if ((mystique->type == MGA_2064W) && (addr & 0x3e00) == 0x3c00) + { + /*RAMDAC*/ + addr_0x0f = addr & 0x0f; + + if ((addr_0x0f & 3) == 0) + addr_0x03 = 0x3c8; + else if ((addr_0x0f & 3) == 1) + addr_0x03 = 0x3c9; + else if ((addr_0x0f & 3) == 2) + addr_0x03 = 0x3c6; + else if ((addr_0x0f & 3) == 3) + addr_0x03 = 0x3c7; + + if ((addr_0x0f >= 0x04) && (addr_0x0f <= 0x07)) { + rs2 = 1; + rs3 = 0; + } else if ((addr_0x0f >= 0x08) && (addr_0x0f <= 0x0b)) { + rs2 = 0; + rs3 = 1; + } else if ((addr_0x0f >= 0x0c) && (addr_0x0f <= 0x0f)) { + rs2 = 1; + rs3 = 1; + } + + ret = tvp3026_ramdac_in(addr_0x03, rs2, rs3, svga->ramdac, svga); + } else switch (addr & 0x3fff) { case REG_FIFOSTATUS: fifocount = FIFO_SIZE - FIFO_ENTRIES; if (fifocount > 64) @@ -1315,6 +1412,7 @@ mystique_ctrl_read_b(uint32_t addr, void *p) ret = mystique->dirdatasiz; break; case REG_OPMODE+3: + ret = 0; break; case REG_PRIMADDRESS: case REG_PRIMADDRESS+1: case REG_PRIMADDRESS+2: case REG_PRIMADDRESS+3: @@ -1396,6 +1494,8 @@ mystique_ctrl_read_b(uint32_t addr, void *p) ret = mystique_read_xreg(mystique, mystique->xreg_idx); break; + case 0x1c40: case 0x1c41: case 0x1c42: case 0x1c43: + case 0x1d44: case 0x1d45: case 0x1d46: case 0x1d47: case 0x1e50: case 0x1e51: case 0x1e52: case 0x1e53: case REG_ICLEAR: case REG_ICLEAR+1: case REG_ICLEAR+2: case REG_ICLEAR+3: case 0x2c30: case 0x2c31: case 0x2c32: case 0x2c33: @@ -1624,6 +1724,7 @@ mystique_accel_ctrl_write_b(uint32_t addr, uint8_t val, void *p) WRITE8(addr, mystique->dwgreg.textrans, val); break; + case 0x1c18: case 0x1c19: case 0x1c1a: case 0x1c1b: case 0x1c28: case 0x1c29: case 0x1c2a: case 0x1c2b: case 0x1c2c: case 0x1c2d: case 0x1c2e: case 0x1c2f: case 0x1cc4: case 0x1cc5: case 0x1cc6: case 0x1cc7: @@ -1653,6 +1754,38 @@ mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *p) { mystique_t *mystique = (mystique_t *)p; svga_t *svga = &mystique->svga; + uint16_t addr_0x0f = 0; + uint16_t addr_0x03 = 0; + int rs2 = 0, rs3 = 0; + + if ((mystique->type == MGA_2064W) && (addr & 0x3e00) == 0x3c00) + { + /*RAMDAC*/ + addr_0x0f = addr & 0x0f; + + if ((addr & 3) == 0) + addr_0x03 = 0x3c8; + else if ((addr & 3) == 1) + addr_0x03 = 0x3c9; + else if ((addr & 3) == 2) + addr_0x03 = 0x3c6; + else if ((addr & 3) == 3) + addr_0x03 = 0x3c7; + + if ((addr_0x0f >= 0x04) && (addr_0x0f <= 0x07)) { + rs2 = 1; + rs3 = 0; + } else if ((addr_0x0f >= 0x08) && (addr_0x0f <= 0x0b)) { + rs2 = 0; + rs3 = 1; + } else if ((addr_0x0f >= 0x0c) && (addr_0x0f <= 0x0f)) { + rs2 = 1; + rs3 = 1; + } + + tvp3026_ramdac_out(addr_0x03, rs2, rs3, val, svga->ramdac, svga); + return; + } if ((addr & 0x3fff) < 0x1c00) { mystique_iload_write_b(addr, val, p); @@ -1839,6 +1972,40 @@ mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *p) switch (addr & 0x3ffc) { case REG_DWGCTL: mystique->dwgreg.dwgctrl = val; + + if (val & DWGCTRL_SOLID) { + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + mystique->dwgreg.pattern[y][x] = 1; + } + mystique->dwgreg.src[0] = 0xffffffff; + mystique->dwgreg.src[1] = 0xffffffff; + mystique->dwgreg.src[2] = 0xffffffff; + mystique->dwgreg.src[3] = 0xffffffff; + } + if (val & DWGCTRL_ARZERO) { + mystique->dwgreg.ar[0] = 0; + mystique->dwgreg.ar[1] = 0; + mystique->dwgreg.ar[2] = 0; + mystique->dwgreg.ar[4] = 0; + mystique->dwgreg.ar[5] = 0; + mystique->dwgreg.ar[6] = 0; + } + if (val & DWGCTRL_SGNZERO) { + mystique->dwgreg.sgn.sdydxl = 0; + mystique->dwgreg.sgn.scanleft = 0; + mystique->dwgreg.sgn.sdxl = 0; + mystique->dwgreg.sgn.sdy = 0; + mystique->dwgreg.sgn.sdxr = 0; + } + if (val & DWGCTRL_SHTZERO) { + mystique->dwgreg.funcnt = 0; + mystique->dwgreg.stylelen = 0; + mystique->dwgreg.xoff = 0; + mystique->dwgreg.yoff = 0; + } break; case REG_ZORG: @@ -2541,6 +2708,7 @@ blit_idump_idump(mystique_t *mystique) case DWGCTRL_ATYPE_RPL: switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { case DWGCTRL_BLTMOD_BU32RGB: + case DWGCTRL_BLTMOD_BFCOL: switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { case MACCESS_PWIDTH_8: while (count < 32) { @@ -2716,6 +2884,88 @@ blit_idump_read(mystique_t *mystique) return ret; } +static void +blit_fbitblt(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + uint32_t src_addr; + int y; + int x_dir = mystique->dwgreg.sgn.scanleft ? -1 : 1; + int16_t x_start = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxright : mystique->dwgreg.fxleft; + int16_t x_end = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxleft : mystique->dwgreg.fxright; + + src_addr = mystique->dwgreg.ar[3]; + + for (y = 0; y < mystique->dwgreg.length; y++) + { + int16_t x = x_start; + while (1) + { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) + { + uint32_t src, old_dst; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_8: + src = svga->vram[src_addr & mystique->vram_mask]; + + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = src; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w]; + + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = src; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + src = *(uint32_t *)&svga->vram[(src_addr * 3) & mystique->vram_mask]; + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (src & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + src = ((uint32_t *)svga->vram)[src_addr & mystique->vram_mask_l]; + + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = src; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("BITBLT RPL BFCOL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + + if (src_addr == mystique->dwgreg.ar[0]) + { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + break; + } + else + src_addr += x_dir; + + if (x != x_end) + x += x_dir; + else + break; + } + + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + + mystique->blitter_complete_refcount++; +} static void blit_iload_iload(mystique_t *mystique, uint32_t data, int size) @@ -2990,40 +3240,44 @@ blit_iload_iload(mystique_t *mystique, uint32_t data, int size) case DWGCTRL_BLTMOD_BU32RGB: size += mystique->dwgreg.iload_rem_count; - while (size >= 32) { - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_32: + data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count); + while (size >= 32) + { + int draw = (!transc || (data & bltcmsk) != bltckey) && trans[mystique->dwgreg.xdst & 3]; + + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) + { dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; dst = bitop(data, dst, mystique->dwgreg.dwgctrl_running); - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + } + + size = 0; + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) + { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) + { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + data64 = 0; + size = 0; break; - - default: - fatal("ILOAD RSTR/RPL BU32RGB pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); } - } - - size = 0; - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; } - mystique->dwgreg.iload_rem_count = size; + mystique->dwgreg.iload_rem_data = data64; break; case DWGCTRL_BLTMOD_BU32BGR: @@ -3157,10 +3411,14 @@ blit_iload_iload_scale(mystique_t *mystique, uint32_t data, int size) data >>= 16; size -= 16; } - - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) + { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); mystique->dwgreg.length_cur--; if (!mystique->dwgreg.length_cur) { @@ -3169,8 +3427,7 @@ blit_iload_iload_scale(mystique_t *mystique, uint32_t data, int size) break; } break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } } break; @@ -3190,10 +3447,14 @@ blit_iload_iload_scale(mystique_t *mystique, uint32_t data, int size) data64 >>= 32; size -= 32; } - - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) + { mystique->dwgreg.xdst = mystique->dwgreg.fxleft; mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); mystique->dwgreg.length_cur--; if (!mystique->dwgreg.length_cur) { @@ -3202,8 +3463,7 @@ blit_iload_iload_scale(mystique_t *mystique, uint32_t data, int size) break; } break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } } break; @@ -4608,40 +4868,6 @@ mystique_start_blit(mystique_t *mystique) mystique->dwgreg.dwgctrl_running = mystique->dwgreg.dwgctrl; mystique->maccess_running = mystique->maccess; - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SOLID) { - int x, y; - - for (y = 0; y < 8; y++) { - for (x = 0; x < 8; x++) - mystique->dwgreg.pattern[y][x] = 1; - } - mystique->dwgreg.src[0] = 0xffffffff; - mystique->dwgreg.src[1] = 0xffffffff; - mystique->dwgreg.src[2] = 0xffffffff; - mystique->dwgreg.src[3] = 0xffffffff; - } - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_ARZERO) { - mystique->dwgreg.ar[0] = 0; - mystique->dwgreg.ar[1] = 0; - mystique->dwgreg.ar[2] = 0; - mystique->dwgreg.ar[4] = 0; - mystique->dwgreg.ar[5] = 0; - mystique->dwgreg.ar[6] = 0; - } - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SGNZERO) { - mystique->dwgreg.sgn.sdydxl = 0; - mystique->dwgreg.sgn.scanleft = 0; - mystique->dwgreg.sgn.sdxl = 0; - mystique->dwgreg.sgn.sdy = 0; - mystique->dwgreg.sgn.sdxr = 0; - } - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SHTZERO) { - mystique->dwgreg.funcnt = 0; - mystique->dwgreg.stylelen = 0; - mystique->dwgreg.xoff = 0; - mystique->dwgreg.yoff = 0; - } - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) { case DWGCTRL_OPCODE_LINE_OPEN: blit_line(mystique, 0); @@ -4675,6 +4901,10 @@ mystique_start_blit(mystique_t *mystique) blit_bitblt(mystique); break; + case DWGCTRL_OPCODE_FBITBLT: + blit_fbitblt(mystique); + break; + case DWGCTRL_OPCODE_ILOAD: blit_iload(mystique); break; @@ -4751,7 +4981,7 @@ uint8_t mystique_pci_read(int func, int addr, void *p) case 0x00: ret = 0x2b; break; /*Matrox*/ case 0x01: ret = 0x10; break; - case 0x02: ret = 0x1a; break; /*MGA-1064SG*/ + case 0x02: ret = (mystique->type == MGA_2064W) ? 0x19 : 0x1a; break; /*MGA*/ case 0x03: ret = 0x05; break; case PCI_REG_COMMAND: @@ -4930,10 +5160,14 @@ mystique_init(const device_t *info) memset(mystique, 0, sizeof(mystique_t)); - if (info->local == 1) - romfn = ROM_MYSTIQUE_220; - else - romfn = ROM_MYSTIQUE; + mystique->type = info->local; + + if (mystique->type == MGA_2064W) + romfn = ROM_MILLENNIUM; + else if (mystique->type == MGA_1064SG) + romfn = ROM_MYSTIQUE; + else + romfn = ROM_MYSTIQUE_220; rom_init(&mystique->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); mem_mapping_disable(&mystique->bios_rom.mapping); @@ -4945,11 +5179,27 @@ mystique_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique); - svga_init(info, &mystique->svga, mystique, mystique->vram_size << 20, - mystique_recalctimings, - mystique_in, mystique_out, - mystique_hwcursor_draw, - NULL); + if (mystique->type == MGA_2064W) { + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_millennium); + svga_init(info, &mystique->svga, mystique, mystique->vram_size << 20, + mystique_recalctimings, + mystique_in, mystique_out, + NULL, + NULL); + mystique->svga.dac_hwcursor_draw = tvp3026_hwcursor_draw; + mystique->svga.ramdac = device_add(&tvp3026_ramdac_device); + mystique->svga.clock_gen = mystique->svga.ramdac; + mystique->svga.getclock = tvp3026_getclock; + } else { + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique); + svga_init(info, &mystique->svga, mystique, mystique->vram_size << 20, + mystique_recalctimings, + mystique_in, mystique_out, + mystique_hwcursor_draw, + NULL); + mystique->svga.clock_gen = mystique; + mystique->svga.getclock = mystique_getclock; + } io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); mem_mapping_add(&mystique->ctrl_mapping, 0, 0, @@ -4959,8 +5209,8 @@ mystique_init(const device_t *info) mem_mapping_disable(&mystique->ctrl_mapping); mem_mapping_add(&mystique->lfb_mapping, 0, 0, - svga_read_linear, svga_readw_linear, svga_readl_linear, - svga_write_linear, svga_writew_linear, svga_writel_linear, + mystique_readb_linear, mystique_readw_linear, mystique_readl_linear, + mystique_writeb_linear, mystique_writew_linear, mystique_writel_linear, NULL, 0, mystique); mem_mapping_disable(&mystique->lfb_mapping); @@ -5025,7 +5275,7 @@ mystique_init(const device_t *info) mystique->i2c_ddc = i2c_gpio_init("ddc_mga"); mystique->ddc = ddc_init(i2c_gpio_get_bus(mystique->i2c_ddc)); - return mystique; + return mystique; } @@ -5050,6 +5300,11 @@ mystique_close(void *p) free(mystique); } +static int +millennium_available(void) +{ + return rom_present(ROM_MILLENNIUM); +} static int mystique_available(void) @@ -5057,7 +5312,6 @@ mystique_available(void) return rom_present(ROM_MYSTIQUE); } - static int mystique_220_available(void) { @@ -5114,13 +5368,28 @@ static const device_config_t mystique_config[] = } }; +const device_t millennium_device = +{ + "Matrox Millennium", + "millennium", + DEVICE_PCI, + MGA_2064W, + mystique_init, + mystique_close, + NULL, + { millennium_available }, + mystique_speed_changed, + mystique_force_redraw, + mystique_config +}; + const device_t mystique_device = { "Matrox Mystique", "mystique", DEVICE_PCI, - 0, + MGA_1064SG, mystique_init, mystique_close, NULL, @@ -5136,7 +5405,7 @@ const device_t mystique_220_device = "Matrox Mystique 220", "mystique_220", DEVICE_PCI, - 1, + MGA_1164SG, mystique_init, mystique_close, NULL, diff --git a/src/video/vid_table.c b/src/video/vid_table.c index fcf5279c8..db09d7757 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -185,6 +185,7 @@ video_cards[] = { { &s3_diamond_stealth_4000_pci_device }, { &s3_trio3d2x_pci_device }, #if defined(DEV_BRANCH) && defined(USE_MGA) + { &millennium_device }, { &mystique_device }, { &mystique_220_device }, #endif