From bde65cb5ce5936465854d50fd79587e4ff34a748 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 18 Jan 2020 04:33:57 +0100 Subject: [PATCH] More Matrox clean-ups, fixed the interlaced modes (1920x resolutions now work), and added the Matrox Mystique 220. --- src/video/vid_mga.c | 693 ++++++++++++++++++++---------------------- src/video/vid_mga.h | 5 +- src/video/vid_table.c | 3 +- 3 files changed, 341 insertions(+), 360 deletions(-) diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 340c15560..5df1a693b 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -8,7 +8,7 @@ * * Matrox MGA graphics card emulation. * - * Version: @(#)vid_mga.c 1.0.0 2020/01/16 + * Version: @(#)vid_mga.c 1.0.1 2020/01/18 * * Author: Sarah Walker, * Copyright 2008-2020 Sarah Walker. @@ -31,12 +31,16 @@ #include "vid_svga.h" #include "vid_svga_render.h" + +#define ROM_MYSTIQUE L"roms/video/matrox/MYSTIQUE.VBI" +#define ROM_MYSTIQUE_220 L"roms/video/matrox/Myst220_66-99mhz.vbi" + #define FIFO_SIZE 65536 #define FIFO_MASK (FIFO_SIZE - 1) #define FIFO_ENTRY_SIZE (1 << 31) #define FIFO_THRESHOLD 0xe000 -#define WAKE_DELAY (100 * TIMER_USEC) /*100us*/ +#define WAKE_DELAY (100 * TIMER_USEC) /* 100us */ #define FIFO_ENTRIES (mystique->fifo_write_idx - mystique->fifo_read_idx) #define FIFO_FULL ((mystique->fifo_write_idx - mystique->fifo_read_idx) >= (FIFO_SIZE-1)) @@ -45,311 +49,6 @@ #define FIFO_TYPE 0xff000000 #define FIFO_ADDR 0x00ffffff -enum -{ - FIFO_INVALID = (0x00 << 24), - FIFO_WRITE_CTRL_BYTE = (0x01 << 24), - FIFO_WRITE_CTRL_LONG = (0x02 << 24), - FIFO_WRITE_ILOAD_LONG = (0x03 << 24) -}; - -typedef struct -{ - uint32_t addr_type; - uint32_t val; -} fifo_entry_t; - -typedef struct mystique_t -{ - svga_t svga; - - rom_t bios_rom; - - mem_mapping_t lfb_mapping; - mem_mapping_t ctrl_mapping; - mem_mapping_t iload_mapping; - - uint8_t pci_regs[256]; - uint8_t int_line; - int card; - - int vram_size; - uint32_t vram_mask, vram_mask_w, vram_mask_l; - - uint32_t lfb_base, ctrl_base, iload_base; - - uint8_t crtcext_regs[6]; - int crtcext_idx; - - uint8_t xreg_regs[256]; - int xreg_idx; - - uint32_t ma_latch_old; - - uint32_t maccess, mctlwtst; - uint32_t maccess_running; - - uint32_t status; - - uint8_t xcurctrl; - - uint8_t xsyspllm, xsysplln, xsyspllp; - struct - { - int m, n, p, s; - } xpixpll[3]; - - uint8_t xgenioctrl; - uint8_t xgeniodata; - uint8_t xmulctrl; - uint8_t xgenctrl; - uint8_t xmiscctrl; - uint8_t xpixclkctrl; - uint8_t xvrefctrl; - int xzoomctrl; - - uint8_t ien; - - struct - { - uint8_t funcnt, stylelen; - int xoff, yoff; - - uint16_t cxleft, cxright; - int16_t fxleft, fxright; - uint16_t length; - - uint32_t dwgctrl; - uint32_t dwgctrl_running; - uint32_t bcol, fcol; - uint32_t pitch; - uint32_t plnwt; - uint32_t ybot; - uint32_t ydstorg; - uint32_t ytop; - int selline; - - uint32_t src[4]; - uint32_t ar[7]; - uint32_t dr[16]; - - int pattern[8][8]; - - struct - { - int sdydxl; - int scanleft; - int sdxl; - int sdy; - int sdxr; - } sgn; - - uint32_t tmr[9]; - uint32_t texorg, texwidth, texheight; - uint32_t texctl, textrans; - uint32_t zorg; - - int ydst; - uint32_t ydst_lin; - - int length_cur; - int16_t xdst; - uint32_t src_addr; - uint32_t z_base; - - int iload_rem_count; - uint32_t iload_rem_data; - int idump_end_of_line; - - int words; - - int ta_key, ta_mask; - - int lastpix_r, lastpix_g, lastpix_b; - - int highv_line; - uint32_t highv_data; - - int beta; - - int dither; - - uint8_t dmamod; - } dwgreg; - - struct - { - uint8_t r, g, b; - } lut[256]; - - struct - { - uint16_t pos_x, pos_y; - uint16_t addr; - uint32_t col[3]; - } cursor; - - uint8_t dmamod, dmadatasiz, dirdatasiz; - struct - { - uint32_t primaddress, primend; - uint32_t secaddress, secend; - - int pri_pos, sec_pos, iload_pos; - uint32_t pri_header, sec_header, iload_header; - - int pri_state, sec_state, iload_state; - - int state; - - mutex_t *lock; - } dma; - - uint8_t dmamap[16]; - - volatile int busy; - volatile int blitter_submit_refcount; - volatile int blitter_submit_dma_refcount; - volatile int blitter_complete_refcount; - - volatile int endprdmasts_pending; - volatile int softrap_pending; - uint32_t softrap_pending_val; - - pc_timer_t softrap_pending_timer; - - uint64_t blitter_time; - uint64_t status_time; - - int pixel_count, trap_count; - - fifo_entry_t fifo[FIFO_SIZE]; - volatile int fifo_read_idx, fifo_write_idx; - - thread_t *fifo_thread; - event_t *wake_fifo_thread; - event_t *fifo_not_full_event; - - pc_timer_t wake_timer; -} mystique_t; - -static void mystique_start_blit(mystique_t *mystique); -static void mystique_update_irqs(mystique_t *mystique); - -static void wake_fifo_thread(mystique_t *mystique); -static void wait_fifo_idle(mystique_t *mystique); -static void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type); - -static const uint8_t trans_masks[16][16] = -{ - { - 1, 1, 1, 1, - 1, 1, 1, 1, - 1, 1, 1, 1, - 1, 1, 1, 1 - }, - { - 1, 0, 1, 0, - 0, 1, 0, 1, - 1, 0, 1, 0, - 0, 1, 0, 1 - }, - { - 0, 1, 0, 1, - 1, 0, 1, 0, - 0, 1, 0, 1, - 1, 0, 1, 0 - }, - { - 1, 0, 1, 0, - 0, 0, 0, 0, - 1, 0, 1, 0, - 0, 0, 0, 0 - }, - { - 0, 1, 0, 1, - 0, 0, 0, 0, - 0, 1, 0, 1, - 0, 0, 0, 0 - }, - { - 0, 0, 0, 0, - 1, 0, 1, 0, - 0, 0, 0, 0, - 1, 0, 1, 0 - }, - { - 0, 0, 0, 0, - 0, 1, 0, 1, - 0, 0, 0, 0, - 0, 1, 0, 1 - }, - { - 1, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 0 - }, - { - 0, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 1 - }, - { - 0, 0, 0, 1, - 0, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0 - }, - { - 0, 0, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 0, - 1, 0, 0, 0 - }, - { - 0, 0, 0, 0, - 1, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 1, 0 - }, - { - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 1, - 0, 0, 0, 0 - }, - { - 0, 0, 0, 0, - 0, 0, 0, 1, - 0, 0, 0, 0, - 0, 1, 0, 0 - }, - { - 0, 0, 1, 0, - 0, 0, 0, 0, - 1, 0, 0, 0, - 0, 0, 0, 0 - }, - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - } -}; - -static int8_t dither5[256][2][2]; -static int8_t dither6[256][2][2]; - -enum -{ - DMA_STATE_IDLE = 0, - DMA_STATE_PRI, - DMA_STATE_SEC -}; - #define DMA_POLL_TIME_US 100 /*100us*/ #define DMA_MAX_WORDS 256 /*256 quad words per 100us poll*/ @@ -645,18 +344,262 @@ enum #define DITHER_555 2 #define DITHER_NONE_555 3 -static void mystique_recalc_mapping(mystique_t *mystique); -static int mystique_line_compare(svga_t *svga); -static uint8_t mystique_iload_read_b(uint32_t addr, void *p); -static uint32_t mystique_iload_read_l(uint32_t addr, void *p); -static void mystique_iload_write_b(uint32_t addr, uint8_t val, void *p); -static void mystique_iload_write_l(uint32_t addr, uint32_t val, void *p); +enum +{ + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_CTRL_BYTE = (0x01 << 24), + FIFO_WRITE_CTRL_LONG = (0x02 << 24), + FIFO_WRITE_ILOAD_LONG = (0x03 << 24) +}; -static uint32_t blit_idump_read(mystique_t *mystique); -static void blit_iload_write(mystique_t *mystique, uint32_t data, int size); +enum +{ + DMA_STATE_IDLE = 0, + DMA_STATE_PRI, + DMA_STATE_SEC +}; -static video_timings_t timing_matrox_mystique = {VIDEO_BUS, 4, 4, 4, 10, 10, 10}; + +typedef struct +{ + uint32_t addr_type; + uint32_t val; +} fifo_entry_t; + +typedef struct mystique_t +{ + svga_t svga; + + rom_t bios_rom; + + mem_mapping_t lfb_mapping, ctrl_mapping, + iload_mapping; + + uint8_t int_line, xcurctrl, + xsyspllm, xsysplln, xsyspllp, + xgenioctrl, xgeniodata, + xmulctrl, xgenctrl, + xmiscctrl, xpixclkctrl, + xvrefctrl, ien, dmamod, + dmadatasiz, dirdatasiz; + + uint8_t pci_regs[256], crtcext_regs[6], + xreg_regs[256], dmamap[16]; + + int card, vram_size, crtcext_idx, xreg_idx, + xzoomctrl, + pixel_count, trap_count; + + volatile int busy, blitter_submit_refcount, + blitter_submit_dma_refcount, blitter_complete_refcount, + endprdmasts_pending, softrap_pending, + fifo_read_idx, fifo_write_idx; + + uint32_t vram_mask, vram_mask_w, vram_mask_l, + lfb_base, ctrl_base, iload_base, + ma_latch_old, maccess, mctlwtst, maccess_running, + status, softrap_pending_val; + + uint64_t blitter_time, status_time; + + pc_timer_t softrap_pending_timer, wake_timer; + + fifo_entry_t fifo[FIFO_SIZE]; + + thread_t *fifo_thread; + + event_t *wake_fifo_thread, *fifo_not_full_event; + + struct + { + int m, n, p, s; + } xpixpll[3]; + + struct + { + uint8_t funcnt, stylelen, + dmamod; + + int16_t fxleft, fxright, + xdst; + + uint16_t cxleft, cxright, + length; + + int xoff, yoff, selline, ydst, + length_cur, iload_rem_count, idump_end_of_line, words, + ta_key, ta_mask, lastpix_r, lastpix_g, + lastpix_b, highv_line, beta, dither; + + int pattern[8][8]; + + uint32_t dwgctrl, dwgctrl_running, bcol, fcol, + pitch, plnwt, ybot, ydstorg, + ytop, texorg, texwidth, texheight, + texctl, textrans, zorg, ydst_lin, + src_addr, z_base, iload_rem_data, highv_data; + + uint32_t src[4], ar[7], + dr[16], tmr[9]; + + struct + { + int sdydxl, scanleft, sdxl, sdy, + sdxr; + } sgn; + } dwgreg; + + struct + { + uint8_t r, g, b; + } lut[256]; + + struct + { + uint16_t pos_x, pos_y, + addr; + uint32_t col[3]; + } cursor; + + struct + { + int pri_pos, sec_pos, iload_pos, + pri_state, sec_state, iload_state, state; + + uint32_t primaddress, primend, secaddress, secend, + pri_header, sec_header, + iload_header; + + mutex_t *lock; + } dma; +} mystique_t; + + +static const uint8_t trans_masks[16][16] = +{ + { + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1 + }, + { + 1, 0, 1, 0, + 0, 1, 0, 1, + 1, 0, 1, 0, + 0, 1, 0, 1 + }, + { + 0, 1, 0, 1, + 1, 0, 1, 0, + 0, 1, 0, 1, + 1, 0, 1, 0 + }, + { + 1, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 1, 0, + 0, 0, 0, 0 + }, + { + 0, 1, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 1, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 1, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 1, 0 + }, + { + 0, 0, 0, 0, + 0, 1, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 1 + }, + { + 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 + }, + { + 0, 0, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 1, 0 + }, + { + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 0 + }, + { + 0, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + } +}; + + +static int8_t dither5[256][2][2]; +static int8_t dither6[256][2][2]; + +static video_timings_t timing_matrox_mystique = {VIDEO_BUS, 4, 4, 4, 10, 10, 10}; + + +static void mystique_start_blit(mystique_t *mystique); +static void mystique_update_irqs(mystique_t *mystique); + +static void wake_fifo_thread(mystique_t *mystique); +static void wait_fifo_idle(mystique_t *mystique); +static void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type); + +static void mystique_recalc_mapping(mystique_t *mystique); +static int mystique_line_compare(svga_t *svga); + +static uint8_t mystique_iload_read_b(uint32_t addr, void *p); +static uint32_t mystique_iload_read_l(uint32_t addr, void *p); +static void mystique_iload_write_b(uint32_t addr, uint8_t val, void *p); +static void mystique_iload_write_l(uint32_t addr, uint32_t val, void *p); + +static uint32_t blit_idump_read(mystique_t *mystique); +static void blit_iload_write(mystique_t *mystique, uint32_t data, int size); void @@ -815,18 +758,26 @@ 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->crtcext_regs[3] & CRTCX_R3_MGAMODE) { int row_offset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); svga->lowres = 0; - svga->rowoffset = row_offset * 2; + 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) { - svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2); + 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; } @@ -4351,6 +4302,9 @@ mystique_hwcursor_draw(svga_t *svga, int displine) uint64_t dat[2]; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; + dat[0] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr]); dat[1] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr + 8]); svga->hwcursor_latch.addr += 16; @@ -4364,6 +4318,9 @@ mystique_hwcursor_draw(svga_t *svga, int displine) dat[0] <<= 1; dat[1] <<= 1; } + + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; } @@ -4510,10 +4467,16 @@ mystique_init(const device_t *info) { int c; mystique_t *mystique = malloc(sizeof(mystique_t)); + wchar_t *romfn; memset(mystique, 0, sizeof(mystique_t)); - rom_init(&mystique->bios_rom, L"roms/video/matrox/MYSTIQUE.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (info->local == 1) + romfn = ROM_MYSTIQUE_220; + else + romfn = ROM_MYSTIQUE; + + rom_init(&mystique->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); mystique->vram_size = device_get_config_int("memory"); mystique->vram_mask = (mystique->vram_size << 20) - 1; @@ -4549,7 +4512,7 @@ mystique_init(const device_t *info) mystique->pci_regs[0x2f] = mystique->bios_rom.rom[0x7ff8]; mystique->svga.miscout = 1; - mystique->pci_regs[0x41] = 0x01; /*vgaboot=1*/ + mystique->pci_regs[0x41] = 0x01; /* vgaboot = 1 */ for (c = 0; c < 256; c++) { dither5[c][0][0] = c >> 3; @@ -4634,45 +4597,61 @@ mystique_force_redraw(void *p) static const device_config_t mystique_config[] = { - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "8 MB", - .value = 8 - }, - { - .description = "" - } - }, - .default_int = 4 - }, - { - .type = -1 - } + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "8 MB", + .value = 8 + }, + { + .description = "" + } + }, + .default_int = 8 + }, + { + .type = -1 + } }; + const device_t mystique_device = { - "Matrox Mystique", - DEVICE_PCI, - 0, - mystique_init, - mystique_close, - NULL, - mystique_available, - mystique_speed_changed, - mystique_force_redraw, - mystique_config + "Matrox Mystique", + DEVICE_PCI, + 0, + mystique_init, + mystique_close, + NULL, + mystique_available, + mystique_speed_changed, + mystique_force_redraw, + mystique_config +}; + + +const device_t mystique_220_device = +{ + "Matrox Mystique 220", + DEVICE_PCI, + 1, + mystique_init, + mystique_close, + NULL, + mystique_available, + mystique_speed_changed, + mystique_force_redraw, + mystique_config }; diff --git a/src/video/vid_mga.h b/src/video/vid_mga.h index 50c72d3ae..5291c81e4 100644 --- a/src/video/vid_mga.h +++ b/src/video/vid_mga.h @@ -8,10 +8,11 @@ * * Matrox MGA graphics card emulation. * - * Version: @(#)vid_mga.h 1.0.0 2020/01/16 + * Version: @(#)vid_mga.h 1.0.1 2020/01/18 * * Author: Sarah Walker, * Copyright 2008-2020 Sarah Walker. */ -extern const device_t mystique_device; \ No newline at end of file +extern const device_t mystique_device; +extern const device_t mystique_220_device; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 4db6190ba..b72a71e08 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -8,7 +8,7 @@ * * Define all known video cards. * - * Version: @(#)vid_table.c 1.0.45 2020/01/17 + * Version: @(#)vid_table.c 1.0.46 2020/01/18 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -150,6 +150,7 @@ video_cards[] = { { "[PCI] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_pci", &s3_diamond_stealth64_pci_device }, { "[PCI] Diamond Stealth 64 VRAM (S3 Vision964)", "stealth64v_pci", &s3_diamond_stealth64_964_pci_device }, { "[PCI] Matrox Mystique", "mystique", &mystique_device }, + { "[PCI] Matrox Mystique 220", "mystique_220", &mystique_220_device }, { "[PCI] Number Nine 9FX (S3 Trio64)", "n9_9fx_pci", &s3_9fx_pci_device }, { "[PCI] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_pci", &s3_bahamas64_pci_device }, { "[PCI] Phoenix S3 Vision864", "px_vision864_pci", &s3_phoenix_vision864_pci_device },