|
|
|
@@ -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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|