From e9710d4b25f46aada6c57c8ff603e31cb8e5e20f Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 31 Mar 2020 00:33:49 +0200 Subject: [PATCH] Ported the latest Matrox MGA fixes from PCem. Removed useless header. --- src/include/86box/cs8230.h | 1 - src/include/86box/vid_svga.h | 3 + src/video/vid_mga.c | 179 +++++++++++++++++++++++++++++------ src/video/vid_svga.c | 3 + 4 files changed, 157 insertions(+), 29 deletions(-) delete mode 100644 src/include/86box/cs8230.h diff --git a/src/include/86box/cs8230.h b/src/include/86box/cs8230.h deleted file mode 100644 index ed7dedc4b..000000000 --- a/src/include/86box/cs8230.h +++ /dev/null @@ -1 +0,0 @@ -void cs8230_init(void); diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 7adfff274..7c3cf291b 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -114,6 +114,9 @@ typedef struct svga_t vertical line interrupt*/ int (*line_compare)(struct svga_t *svga); + /*Called at the start of vertical sync*/ + void (*vsync_callback)(struct svga_t *svga); + /*If set then another device is driving the monitor output and the SVGA card should not attempt to display anything */ int override; diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 723546740..26fcba896 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -209,6 +209,17 @@ #define XREG_XZOOMCTRL 0x38 +#define XREG_XSENSETEST 0x3a + +#define XREG_XCRCREML 0x3c +#define XREG_XCRCREMH 0x3d +#define XREG_XCRCBITSEL 0x3e + +#define XREG_XCOLKEYMSKL 0x40 +#define XREG_XCOLKEYMSKH 0x41 +#define XREG_XCOLKEYL 0x42 +#define XREG_XCOLKEYH 0x43 + #define XREG_XPIXPLLCM 0x4c #define XREG_XPIXPLLCN 0x4d #define XREG_XPIXPLLCP 0x4e @@ -230,6 +241,11 @@ #define XPIXPLLSTAT_SYSLOCK (1 << 6) +#define XCURCTRL_CURMODE_MASK (3 << 0) +#define XCURCTRL_CURMODE_3COL (1 << 0) +#define XCURCTRL_CURMODE_XGA (2 << 0) +#define XCURCTRL_CURMODE_XWIN (3 << 0) + #define DWGCTRL_OPCODE_MASK (0xf << 0) #define DWGCTRL_OPCODE_LINE_OPEN (0x0 << 0) #define DWGCTRL_OPCODE_AUTOLINE_OPEN (0x1 << 0) @@ -304,6 +320,7 @@ #define DMA_MODE_VECTOR 2 #define STATUS_SOFTRAPEN (1 << 0) +#define STATUS_VSYNCPEN (1 << 4) #define STATUS_VLINEPEN (1 << 5) #define STATUS_DWGENGSTS (1 << 16) #define STATUS_ENDPRDMASTS (1 << 17) @@ -387,7 +404,10 @@ typedef struct mystique_t xmulctrl, xgenctrl, xmiscctrl, xpixclkctrl, xvrefctrl, ien, dmamod, - dmadatasiz, dirdatasiz; + dmadatasiz, dirdatasiz, + xcolkeymskl, xcolkeymskh, + xcolkeyl, xcolkeyh, + xcrcbitsel; uint8_t pci_regs[256], crtcext_regs[6], xreg_regs[256], dmamap[16]; @@ -641,17 +661,22 @@ mystique_out(uint16_t addr, uint8_t val, void *p) svga->crtcreg = val & 0x3f; return; case 0x3D5: - if (((svga->crtcreg & 31) < 7) && (svga->crtc[0x11] & 0x80)) + if (((svga->crtcreg & 0x3f) < 7) && (svga->crtc[0x11] & 0x80)) return; - if (((svga->crtcreg & 31) == 7) && (svga->crtc[0x11] & 0x80)) + if (((svga->crtcreg & 0x3f) == 7) && (svga->crtc[0x11] & 0x80)) val = (svga->crtc[7] & ~0x10) | (val & 0x10); old = svga->crtc[svga->crtcreg & 0x3f]; - svga->crtc[svga->crtcreg & 31] = val; + svga->crtc[svga->crtcreg & 0x3f] = val; if (old != val) { - if ((svga->crtcreg & 31) < 0xE || (svga->crtcreg & 31) > 0x10) { + if ((svga->crtcreg & 0x3f) < 0xE || (svga->crtcreg & 0x3f) > 0x10) { svga->fullchange = changeframecount; svga_recalctimings(svga); } + if (svga->crtcreg == 0x11) { + if (!(val & 0x10)) + mystique->status &= ~STATUS_VSYNCPEN; + mystique_update_irqs(mystique); + } } break; @@ -733,6 +758,17 @@ mystique_line_compare(svga_t *svga) return 0; } +static void +mystique_vsync_callback(svga_t *svga) +{ + mystique_t *mystique = (mystique_t *)svga->p; + + if (svga->crtc[0x11] & 0x10) { + mystique->status |= STATUS_VSYNCPEN; + mystique_update_irqs(mystique); + } +} + void mystique_recalctimings(svga_t *svga) @@ -906,10 +942,13 @@ void mystique_recalc_mapping(mystique_t *mystique) static void mystique_update_irqs(mystique_t *mystique) { + svga_t *svga = &mystique->svga; int irq = 0; if ((mystique->status & mystique->ien) & STATUS_SOFTRAPEN) irq = 1; + if ((mystique->status & STATUS_VSYNCPEN) && (svga->crtc[0x11] & 0x30) == 0x10) + irq = 1; if (irq) pci_set_irq(mystique->card, PCI_INTA); @@ -971,6 +1010,10 @@ mystique_read_xreg(mystique_t *mystique, int reg) ret = mystique->xgenctrl; break; + case XREG_XVREFCTRL: + ret = mystique->xvrefctrl; + break; + case XREG_XGENIOCTRL: ret = mystique->xgenioctrl; break; @@ -992,6 +1035,39 @@ mystique_read_xreg(mystique_t *mystique, int reg) ret = mystique->xzoomctrl; break; + case XREG_XSENSETEST: + ret = 0; + if (mystique->svga.vgapal[0].b < 0x80) + ret |= 1; + if (mystique->svga.vgapal[0].g < 0x80) + ret |= 2; + if (mystique->svga.vgapal[0].r < 0x80) + ret |= 4; + break; + + case XREG_XCRCREML: /*CRC not implemented*/ + ret = 0; + break; + case XREG_XCRCREMH: + ret = 0; + break; + case XREG_XCRCBITSEL: + ret = mystique->xcrcbitsel; + break; + + case XREG_XCOLKEYMSKL: + ret = mystique->xcolkeymskl; + break; + case XREG_XCOLKEYMSKH: + ret = mystique->xcolkeymskh; + break; + case XREG_XCOLKEYL: + ret = mystique->xcolkeyl; + break; + case XREG_XCOLKEYH: + ret = mystique->xcolkeyh; + break; + case XREG_XPIXCLKCTRL: ret = mystique->xpixclkctrl; break; @@ -1096,6 +1172,36 @@ mystique_write_xreg(mystique_t *mystique, int reg, uint8_t val) mystique->xzoomctrl = val & 3; break; + case XREG_XSENSETEST: + break; + + case XREG_XCRCREML: /*CRC not implemented*/ + break; + case XREG_XCRCREMH: + break; + case XREG_XCRCBITSEL: + mystique->xcrcbitsel = val & 0x1f; + break; + + case XREG_XCOLKEYMSKL: + mystique->xcolkeymskl = val; + break; + case XREG_XCOLKEYMSKH: + mystique->xcolkeymskh = val; + break; + case XREG_XCOLKEYL: + mystique->xcolkeyl = val; + break; + case XREG_XCOLKEYH: + mystique->xcolkeyh = val; + break; + + case XREG_XSYSPLLSTAT: + break; + + case XREG_XPIXPLLSTAT: + break; + case XREG_XPIXCLKCTRL: mystique->xpixclkctrl = val; break; @@ -1266,12 +1372,16 @@ mystique_ctrl_read_b(uint32_t addr, void *p) ret = mystique_read_xreg(mystique, mystique->xreg_idx); break; - case 0x1e50: case 0x1e51: case 0x1e52: case 0x1e53: + 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: case 0x3e08: break; + case 0x3c08: case 0x3c09: case 0x3c0b: + break; + + default: if ((addr & 0x3fff) >= 0x2c00 && (addr & 0x3fff) < 0x2c40) break; @@ -1990,9 +2100,8 @@ mystique_accel_iload_write_l(uint32_t addr, uint32_t val, void *p) break; case DMA_MODE_BLIT: - if (!mystique->busy) - fatal("mystique_iload_write_l: !busy\n"); - blit_iload_write(mystique, val, 32); + if (mystique->busy) + blit_iload_write(mystique, val, 32); break; /* default: @@ -2140,10 +2249,11 @@ run_dma(mystique_t *mystique) else reg_addr += 0x1c00; - if ((reg_addr & 0x300) == 0x100) + if ((reg_addr & 0x300) == 0x100 && reg_addr != REG_DMAPAD) mystique->blitter_submit_dma_refcount++; - mystique_accel_ctrl_write_l(reg_addr, val, mystique); + if (reg_addr != REG_DMAPAD) + mystique_accel_ctrl_write_l(reg_addr, val, mystique); } mystique->dma.pri_header >>= 8; @@ -2182,10 +2292,11 @@ run_dma(mystique_t *mystique) else reg_addr += 0x1c00; - if ((reg_addr & 0x300) == 0x100) + if ((reg_addr & 0x300) == 0x100 && reg_addr != REG_DMAPAD) mystique->blitter_submit_dma_refcount++; - mystique_accel_ctrl_write_l(reg_addr, val, mystique); + if (reg_addr != REG_DMAPAD) + mystique_accel_ctrl_write_l(reg_addr, val, mystique); mystique->dma.sec_header >>= 8; mystique->dma.sec_state = (mystique->dma.sec_state + 1) & 3; @@ -2204,10 +2315,8 @@ run_dma(mystique_t *mystique) uint32_t val = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK]; mystique->dma.secaddress += 4; - if (!mystique->busy) - fatal("mystique_iload_write_l: !busy\n"); - - blit_iload_write(mystique, val, 32); + if (mystique->busy) + blit_iload_write(mystique, val, 32); words_transferred++; if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { @@ -2608,6 +2717,7 @@ blit_iload_iload(mystique_t *mystique, uint32_t data, int size) const int transc = mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC; const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + uint32_t data_mask = 1; switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { case MACCESS_PWIDTH_8: @@ -2749,14 +2859,16 @@ blit_iload_iload(mystique_t *mystique, uint32_t data, int size) case DWGCTRL_BLTMOD_BMONOWF: data = (data >> 24) | ((data & 0x00ff0000) >> 8) | ((data & 0x0000ff00) << 8) | (data << 24); + data_mask = (1 << 31); + case DWGCTRL_BLTMOD_BMONOLEF: while (size) { 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 && - ((data & 0x80000000) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && + ((data & data_mask) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && trans[mystique->dwgreg.xdst & 3]) { uint32_t old_dst; - src = (data & 0x80000000) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + src = (data & data_mask) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { case MACCESS_PWIDTH_8: dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; @@ -2812,7 +2924,10 @@ blit_iload_iload(mystique_t *mystique, uint32_t data, int size) break; } else mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - data <<= 1; + if (data_mask == 1) + data >>= 1; + else + data <<= 1; size--; } break; @@ -4332,10 +4447,11 @@ blit_iload(mystique_t *mystique) switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { case DWGCTRL_ATYPE_RPL: case DWGCTRL_ATYPE_RSTR: - case DWGCTRL_ATYPE_BLK: + case DWGCTRL_ATYPE_BLK: /* pclog("ILOAD BLTMOD DWGCTRL = %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); */ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { case DWGCTRL_BLTMOD_BFCOL: + case DWGCTRL_BLTMOD_BMONOLEF: case DWGCTRL_BLTMOD_BMONOWF: case DWGCTRL_BLTMOD_BU24RGB: case DWGCTRL_BLTMOD_BU32RGB: @@ -4580,6 +4696,7 @@ mystique_start_blit(mystique_t *mystique) static void mystique_hwcursor_draw(svga_t *svga, int displine) { + mystique_t *mystique = (mystique_t *)svga->p; int x; uint64_t dat[2]; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; @@ -4590,15 +4707,19 @@ mystique_hwcursor_draw(svga_t *svga, int displine) 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; - for (x = 0; x < 64; x ++) { - if (!(dat[1] & (1ull << 63))) - buffer32->line[displine][offset + svga->x_add] = (dat[0] & (1ull << 63)) ? 0xffffff : 0; - else if (dat[0] & (1ull << 63)) + switch (mystique->xcurctrl & XCURCTRL_CURMODE_MASK) { + case XCURCTRL_CURMODE_XGA: + for (x = 0; x < 64; x ++) { + if (!(dat[1] & (1ull << 63))) + buffer32->line[displine][offset + svga->x_add] = (dat[0] & (1ull << 63)) ? mystique->cursor.col[1] : mystique->cursor.col[0]; + else if (dat[0] & (1ull << 63)) buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; - offset++; - dat[0] <<= 1; - dat[1] <<= 1; + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + break; } if (svga->interlace && !svga->hwcursor_oddeven) @@ -4885,6 +5006,8 @@ mystique_init(const device_t *info) mystique->status = STATUS_ENDPRDMASTS; + mystique->svga.vsync_callback = mystique_vsync_callback; + return mystique; } diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 5452827f5..f694f2377 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -813,6 +813,9 @@ svga_poll(void *p) svga->ma = (svga->ma << 2) + (skip << 2); svga->maback = (svga->maback << 2) + (skip << 2); svga->ca = (svga->ca << 2) + (skip << 2); + + if (svga->vsync_callback) + svga->vsync_callback(svga); } if (svga->vc == svga->vtotal) { svga->vc = 0;