Change VIA FM and other behavior to match real hardware, and add "real fake OPL" mode
This commit is contained in:
@@ -75,7 +75,7 @@ typedef struct
|
|||||||
ide_regs[256],
|
ide_regs[256],
|
||||||
usb_regs[2][256],
|
usb_regs[2][256],
|
||||||
power_regs[256],
|
power_regs[256],
|
||||||
ac97_regs[2][256], fmnmi_regs[4], fm_regs[4];
|
ac97_regs[2][256], fmnmi_regs[4];
|
||||||
sff8038i_t *bm[2];
|
sff8038i_t *bm[2];
|
||||||
nvr_t *nvr;
|
nvr_t *nvr;
|
||||||
int nvr_enabled, slot;
|
int nvr_enabled, slot;
|
||||||
@@ -475,30 +475,10 @@ static uint8_t
|
|||||||
pipc_midigame_read(uint16_t addr, void *priv)
|
pipc_midigame_read(uint16_t addr, void *priv)
|
||||||
{
|
{
|
||||||
pipc_t *dev = (pipc_t *) priv;
|
pipc_t *dev = (pipc_t *) priv;
|
||||||
uint8_t ret = 0xff;
|
|
||||||
|
|
||||||
addr &= 0x03;
|
/* This BAR apparently doesn't work at all on a real 686B. It doesn't react to writes,
|
||||||
switch (addr) {
|
and reads always return 0x80 or 0xff depending on AC97 audio register 0x42 bit 7. */
|
||||||
case 0x02: case 0x03:
|
return (dev->ac97_regs[0][0x42] & 0x80) ? 0x80 : 0xff;
|
||||||
ret = pipc_read(5, 0x48 + addr, dev);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
pipc_midigame_write(uint16_t addr, uint8_t val, void *priv)
|
|
||||||
{
|
|
||||||
pipc_t *dev = (pipc_t *) priv;
|
|
||||||
|
|
||||||
addr &= 0x03;
|
|
||||||
switch (addr) {
|
|
||||||
case 0x02: case 0x03:
|
|
||||||
pipc_write(5, 0x48 + addr, val, dev);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -509,12 +489,12 @@ pipc_midigame_handlers(pipc_t *dev, uint8_t modem)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (dev->midigame_base)
|
if (dev->midigame_base)
|
||||||
io_removehandler(dev->midigame_base, 4, pipc_midigame_read, NULL, NULL, pipc_midigame_write, NULL, NULL, dev);
|
io_removehandler(dev->midigame_base, 4, pipc_midigame_read, NULL, NULL, NULL, NULL, NULL, dev);
|
||||||
|
|
||||||
dev->midigame_base = (dev->ac97_regs[0][0x19] << 8) | (dev->ac97_regs[0][0x18] & 0xfc);
|
dev->midigame_base = (dev->ac97_regs[0][0x19] << 8) | (dev->ac97_regs[0][0x18] & 0xfc);
|
||||||
|
|
||||||
if (dev->midigame_base && (dev->ac97_regs[0][0x04] & PCI_COMMAND_IO))
|
if (dev->midigame_base && (dev->ac97_regs[0][0x04] & PCI_COMMAND_IO))
|
||||||
io_sethandler(dev->midigame_base, 4, pipc_midigame_read, NULL, NULL, pipc_midigame_write, NULL, NULL, dev);
|
io_sethandler(dev->midigame_base, 4, pipc_midigame_read, NULL, NULL, NULL, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -539,31 +519,29 @@ pipc_fmnmi_read(uint16_t addr, void *priv)
|
|||||||
|
|
||||||
pipc_log("PIPC: fmnmi_read(%02X) = %02X\n", addr & 0x03, ret);
|
pipc_log("PIPC: fmnmi_read(%02X) = %02X\n", addr & 0x03, ret);
|
||||||
|
|
||||||
|
#ifdef VIA_PIPC_FM_EMULATION
|
||||||
|
/* Clear NMI/SMI if enabled. */
|
||||||
|
if (dev->ac97_regs[0][0x48] & 0x01) {
|
||||||
if (dev->ac97_regs[0][0x48] & 0x04)
|
if (dev->ac97_regs[0][0x48] & 0x04)
|
||||||
smi_line = 0;
|
smi_line = 0;
|
||||||
else
|
else
|
||||||
nmi = 0;
|
nmi = 0;
|
||||||
|
}
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
pipc_fmnmi_write(uint16_t addr, uint8_t val, void *priv)
|
|
||||||
{
|
|
||||||
#ifdef ENABLE_PIPC_LOG
|
|
||||||
pipc_t *dev = (pipc_t *) priv;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pipc_log("PIPC: fmnmi_write(%02X, %02X)\n", addr & 0x03, val);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
pipc_fm_read(uint16_t addr, void *priv)
|
pipc_fm_read(uint16_t addr, void *priv)
|
||||||
{
|
{
|
||||||
|
#ifdef VIA_PIPC_FM_EMULATION
|
||||||
|
uint8_t ret = 0x00;
|
||||||
|
#else
|
||||||
pipc_t *dev = (pipc_t *) priv;
|
pipc_t *dev = (pipc_t *) priv;
|
||||||
uint8_t ret = opl3_read(addr, &dev->sb->opl);
|
uint8_t ret = opl3_read(addr, &dev->sb->opl);
|
||||||
|
#endif
|
||||||
|
|
||||||
pipc_log("PIPC: fm_read(%02X) = %02X\n", addr & 0x03, ret);
|
pipc_log("PIPC: fm_read(%02X) = %02X\n", addr & 0x03, ret);
|
||||||
|
|
||||||
@@ -578,17 +556,26 @@ pipc_fm_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
|
|
||||||
pipc_log("PIPC: fm_write(%02X, %02X)\n", addr & 0x03, val);
|
pipc_log("PIPC: fm_write(%02X, %02X)\n", addr & 0x03, val);
|
||||||
|
|
||||||
opl3_write(addr, val, &dev->sb->opl);
|
#ifdef VIA_PIPC_FM_EMULATION
|
||||||
dev->fm_regs[addr & 0x03] = val;
|
/* Real 686B only updates the bank ID register when writing to the
|
||||||
|
index port, and only fires NMI/SMI when writing to the data port. */
|
||||||
|
if (!(addr & 0x01)) {
|
||||||
dev->fmnmi_regs[0x00] = (addr & 0x02) ? 0x02 : 0x01;
|
dev->fmnmi_regs[0x00] = (addr & 0x02) ? 0x02 : 0x01;
|
||||||
dev->fmnmi_regs[0x01] = dev->fm_regs[addr & 0x02];
|
dev->fmnmi_regs[0x01] = val;
|
||||||
dev->fmnmi_regs[0x02] = dev->fm_regs[(addr & 0x02) | 0x01];
|
} else {
|
||||||
|
dev->fmnmi_regs[0x02] = val;
|
||||||
|
|
||||||
|
/* Fire NMI/SMI if enabled. */
|
||||||
|
if (dev->ac97_regs[0][0x48] & 0x01) {
|
||||||
if (dev->ac97_regs[0][0x48] & 0x04)
|
if (dev->ac97_regs[0][0x48] & 0x04)
|
||||||
smi_line = 1;
|
smi_line = 1;
|
||||||
else
|
else
|
||||||
nmi = 1;
|
nmi = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
opl3_write(addr, val, &dev->sb->opl);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -599,7 +586,7 @@ pipc_fmnmi_handlers(pipc_t *dev, uint8_t modem)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (dev->fmnmi_base)
|
if (dev->fmnmi_base)
|
||||||
io_removehandler(dev->fmnmi_base, 4, pipc_fmnmi_read, NULL, NULL, pipc_fmnmi_write, NULL, NULL, dev);
|
io_removehandler(dev->fmnmi_base, 4, pipc_fmnmi_read, NULL, NULL, NULL, NULL, NULL, dev);
|
||||||
|
|
||||||
if (dev->fm_enabled)
|
if (dev->fm_enabled)
|
||||||
io_removehandler(0x388, 4, pipc_fm_read, NULL, NULL, pipc_fm_write, NULL, NULL, dev);
|
io_removehandler(0x388, 4, pipc_fm_read, NULL, NULL, pipc_fm_write, NULL, NULL, dev);
|
||||||
@@ -608,7 +595,7 @@ pipc_fmnmi_handlers(pipc_t *dev, uint8_t modem)
|
|||||||
dev->fm_enabled = !!(dev->ac97_regs[0][0x42] & 0x04);
|
dev->fm_enabled = !!(dev->ac97_regs[0][0x42] & 0x04);
|
||||||
|
|
||||||
if (dev->fmnmi_base && (dev->ac97_regs[0][0x04] & PCI_COMMAND_IO))
|
if (dev->fmnmi_base && (dev->ac97_regs[0][0x04] & PCI_COMMAND_IO))
|
||||||
io_sethandler(dev->fmnmi_base, 4, pipc_fmnmi_read, NULL, NULL, pipc_fmnmi_write, NULL, NULL, dev);
|
io_sethandler(dev->fmnmi_base, 4, pipc_fmnmi_read, NULL, NULL, NULL, NULL, NULL, dev);
|
||||||
|
|
||||||
if (dev->fm_enabled)
|
if (dev->fm_enabled)
|
||||||
io_sethandler(0x388, 4, pipc_fm_read, NULL, NULL, pipc_fm_write, NULL, NULL, dev);
|
io_sethandler(0x388, 4, pipc_fm_read, NULL, NULL, pipc_fm_write, NULL, NULL, dev);
|
||||||
@@ -1230,7 +1217,7 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
|
|||||||
|
|
||||||
case 0x42: case 0x4a: case 0x4b:
|
case 0x42: case 0x4a: case 0x4b:
|
||||||
dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val;
|
dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val;
|
||||||
gameport_remap(dev->gameport, (dev->ac97_regs[0][0x42] & 0x08) ? ((dev->ac97_regs[0][0x4b] << 8) | dev->ac97_regs[0][0x4a]) : 0);
|
gameport_remap(dev->gameport, (dev->ac97_regs[0][0x42] & 0x08) ? ((dev->ac97_regs[0][0x4b] << 8) | (dev->ac97_regs[0][0x4a] & 0xf8)) : 0);
|
||||||
if (addr == 0x42)
|
if (addr == 0x42)
|
||||||
pipc_fmnmi_handlers(dev, func);
|
pipc_fmnmi_handlers(dev, func);
|
||||||
break;
|
break;
|
||||||
@@ -1243,24 +1230,10 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
|
|||||||
dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val & 0xf0;
|
dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val & 0xf0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x45:
|
case 0x45: case 0x48:
|
||||||
dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val & 0x0f;
|
dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val & 0x0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x48:
|
|
||||||
dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val & 0x0f;
|
|
||||||
/*if (!(val & 0x01)) {
|
|
||||||
if (val & 0x04)
|
|
||||||
smi_line = 0;
|
|
||||||
else
|
|
||||||
nmi = 0;
|
|
||||||
}*/
|
|
||||||
if (val & 0x04)
|
|
||||||
smi_line = !!(val & 0x01);
|
|
||||||
else
|
|
||||||
nmi = !!(val & 0x01);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dev->ac97_regs[func][addr] = val;
|
dev->ac97_regs[func][addr] = val;
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user