diff --git a/src/include/86box/video.h b/src/include/86box/video.h
index 8b9ddab84..59fead3b9 100644
--- a/src/include/86box/video.h
+++ b/src/include/86box/video.h
@@ -344,6 +344,8 @@ extern const device_t s3_phoenix_trio64_onboard_pci_device;
extern const device_t s3_phoenix_trio64_pci_device;
extern const device_t s3_phoenix_trio64vplus_pci_device;
extern const device_t s3_phoenix_trio64vplus_onboard_pci_device;
+extern const device_t s3_mirocrystal_20sv_964_vlb_device;
+extern const device_t s3_mirocrystal_20sv_964_pci_device;
extern const device_t s3_phoenix_vision864_pci_device;
extern const device_t s3_phoenix_vision864_vlb_device;
extern const device_t s3_phoenix_vision868_pci_device;
@@ -406,6 +408,7 @@ extern const device_t voodoo_3_2000_agp_device;
extern const device_t voodoo_3_2000_agp_onboard_8m_device;
extern const device_t voodoo_3_3000_device;
extern const device_t voodoo_3_3000_agp_device;
+extern const device_t velocity_100_agp_device;
/* Wyse 700 */
extern const device_t wy700_device;
diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c
index e34324657..a24978750 100644
--- a/src/sound/snd_audiopci.c
+++ b/src/sound/snd_audiopci.c
@@ -1,3 +1,23 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Ensoniq AudioPCI (ES1371) emulation.
+ *
+ *
+ *
+ * Authors: Sarah Walker,
+ * RichardG,
+ * Miran Grca,
+ *
+ * Copyright 2008-2021 Sarah Walker.
+ * Copyright 2021 RichardG.
+ * Copyright 2021 Miran Grca.
+ */
#include
#include
#include
@@ -23,69 +43,70 @@
#define ES1371_NCoef 91
+
static float low_fir_es1371_coef[ES1371_NCoef];
+
typedef struct {
- uint8_t pci_command, pci_serr;
+ uint8_t pci_command, pci_serr;
- uint32_t base_addr;
+ uint32_t base_addr;
- uint8_t int_line;
+ uint8_t int_line;
- uint16_t pmcsr;
+ uint16_t pmcsr;
- uint32_t int_ctrl;
- uint32_t int_status;
+ uint32_t int_ctrl, int_status,
+ legacy_ctrl;
- uint32_t legacy_ctrl;
+ int mem_page;
- int mem_page;
+ uint32_t si_cr;
- uint32_t si_cr;
+ uint32_t sr_cir;
+ uint16_t sr_ram[128];
- uint32_t sr_cir;
- uint16_t sr_ram[128];
+ uint8_t uart_ctrl, uart_status,
+ uart_res;
+ uint32_t uart_fifo;
- uint8_t uart_ctrl;
- uint8_t uart_status;
-
- ac97_codec_t *codec;
- uint32_t codec_ctrl;
+ ac97_codec_t * codec;
+ uint32_t codec_ctrl;
struct {
- uint32_t addr, addr_latch;
- uint16_t count, size;
+ uint32_t addr, addr_latch;
+ uint16_t count, size;
- uint16_t samp_ct;
- int curr_samp_ct;
+ uint16_t samp_ct;
+ int curr_samp_ct;
- pc_timer_t timer;
- uint64_t latch;
+ pc_timer_t timer;
+ uint64_t latch;
- uint32_t vf, ac;
+ uint32_t vf, ac;
- int16_t buffer_l[64], buffer_r[64];
- int buffer_pos, buffer_pos_end;
+ int16_t buffer_l[64], buffer_r[64];
+ int buffer_pos, buffer_pos_end;
- int filtered_l[32], filtered_r[32];
- int f_pos;
+ int filtered_l[32], filtered_r[32];
+ int f_pos;
- int16_t out_l, out_r;
+ int16_t out_l, out_r;
- int32_t vol_l, vol_r;
+ int32_t vol_l, vol_r;
} dac[2], adc;
- int64_t dac_latch, dac_time;
+ int64_t dac_latch, dac_time;
- int master_vol_l, master_vol_r;
- int cd_vol_l, cd_vol_r;
+ int master_vol_l, master_vol_r,
+ cd_vol_l, cd_vol_r;
- int card;
+ int card;
- int pos;
- int16_t buffer[SOUNDBUFLEN * 2];
+ int pos;
+ int16_t buffer[SOUNDBUFLEN * 2];
- int type;
+ int type;
} es1371_t;
@@ -145,8 +166,10 @@ typedef struct {
#define FORMAT_MONO_16 2
#define FORMAT_STEREO_16 3
-static void es1371_fetch(es1371_t *es1371, int dac_nr);
-static void update_legacy(es1371_t *es1371, uint32_t old_legacy_ctrl);
+
+static void es1371_fetch(es1371_t *dev, int dac_nr);
+static void update_legacy(es1371_t *dev, uint32_t old_legacy_ctrl);
+
#ifdef ENABLE_AUDIOPCI_LOG
int audiopci_do_log = ENABLE_AUDIOPCI_LOG;
@@ -168,1234 +191,1707 @@ audiopci_log(const char *fmt, ...)
#endif
-static void es1371_update_irqs(es1371_t *es1371)
+static void
+es1371_update_irqs(es1371_t *dev)
{
- int irq = 0;
-
- if ((es1371->int_status & INT_STATUS_DAC1) && (es1371->si_cr & SI_P1_INTR_EN))
- irq = 1;
- if ((es1371->int_status & INT_STATUS_DAC2) && (es1371->si_cr & SI_P2_INTR_EN)) {
- irq = 1;
- }
- /*MIDI input is unsupported for now*/
- if ((es1371->int_status & INT_STATUS_UART) && (es1371->uart_status & UART_STATUS_TXINT)) {
- irq = 1;
- }
+ int irq = 0;
- if (irq)
- es1371->int_status |= INT_STATUS_INTR;
- else
- es1371->int_status &= ~INT_STATUS_INTR;
+ if ((dev->int_status & INT_STATUS_DAC1) && (dev->si_cr & SI_P1_INTR_EN))
+ irq = 1;
+ if ((dev->int_status & INT_STATUS_DAC2) && (dev->si_cr & SI_P2_INTR_EN))
+ irq = 1;
- if (es1371->legacy_ctrl & LEGACY_FORCE_IRQ)
- irq = 1;
-
- if (irq)
- {
- pci_set_irq(es1371->card, PCI_INTA);
-// audiopci_log("Raise IRQ\n");
- }
- else
- {
- pci_clear_irq(es1371->card, PCI_INTA);
-// audiopci_log("Drop IRQ\n");
- }
+ /* MIDI input is unsupported for now */
+ if ((dev->int_status & INT_STATUS_UART) && (dev->uart_status & UART_STATUS_TXINT))
+ irq = 1;
+
+ if (irq)
+ dev->int_status |= INT_STATUS_INTR;
+ else
+ dev->int_status &= ~INT_STATUS_INTR;
+
+ if (dev->legacy_ctrl & LEGACY_FORCE_IRQ)
+ irq = 1;
+
+ if (irq)
+ pci_set_irq(dev->card, PCI_INTA);
+ else
+ pci_clear_irq(dev->card, PCI_INTA);
}
-static uint8_t es1371_inb(uint16_t port, void *p)
+
+static void
+es1371_reset(void *p)
{
- es1371_t *es1371 = (es1371_t *)p;
- uint8_t ret = 0;
-
- switch (port & 0x3f)
- {
- case 0x00:
- ret = es1371->int_ctrl & 0xff;
+ es1371_t *dev = (es1371_t *) p;
+
+ nmi = 0;
+
+ /* Interrupt/Chip Select Control Register, Address 00H
+ Addressable as byte, word, longword */
+ dev->int_ctrl = 0xfc0f0000;
+
+ /* Interrupt/Chip Select Control Register, Address 00H
+ Addressable as longword only */
+ dev->int_status = 0x7ffffec0;
+
+ /* UART Status Register, Address 09H
+ Addressable as byte only */
+ dev->uart_status = 0x00;
+
+ /* UART Control Register, Address 09H
+ Addressable as byte only */
+ dev->uart_ctrl = 0x00;
+
+ /* UART Reserved Register, Address 0AH
+ Addressable as byte only */
+ dev->uart_res = 0x00;
+
+ /* Memory Page Register, Address 0CH
+ Addressable as byte, word, longword */
+ dev->mem_page = 0x00;
+
+ /* Sample Rate Concerter Interface Register, Address 10H
+ Addressable as longword only */
+ dev->sr_cir = 0x00000000;
+
+ /* CODEC Write Register, Address 14H
+ Addressable as longword only */
+ dev->codec_ctrl = 0x00000000;
+
+ /* Legacy Control/Status Register, Address 18H
+ Addressable as byte, word, longword */
+ dev->legacy_ctrl = 0x0000f800;
+
+ /* Serial Interface Control Register, Address 20H
+ Addressable as byte, word, longword */
+ dev->si_cr = 0xff800000;
+
+ /* DAC1 Channel Sample Count Register, Address 24H
+ Addressable as word, longword */
+ dev->dac[0].samp_ct = 0x00000000;
+ dev->dac[0].curr_samp_ct = 0x00000000;
+
+ /* DAC2 Channel Sample Count Register, Address 28H
+ Addressable as word, longword */
+ dev->dac[1].samp_ct = 0x00000000;
+ dev->dac[1].curr_samp_ct = 0x00000000;
+
+ /* ADC Channel Sample Count Register, Address 2CH
+ Addressable as word, longword */
+ dev->adc.samp_ct = 0x00000000;
+ dev->adc.curr_samp_ct = 0x00000000;
+
+ /* DAC1 Frame Register 1, Address 30H, Memory Page 1100b
+ Addressable as longword only */
+ dev->dac[0].addr_latch = 0x00000000;
+
+ /* DAC1 Frame Register 2, Address 34H, Memory Page 1100b
+ Addressable as longword only */
+ dev->dac[0].size = 0x00000000;
+ dev->dac[0].count = 0x00000000;
+
+ /* DAC2 Frame Register 1, Address 38H, Memory Page 1100b
+ Addressable as longword only */
+ dev->dac[1].addr_latch = 0x00000000;
+
+ /* DAC2 Frame Register 2, Address 3CH, Memory Page 1100b
+ Addressable as longword only */
+ dev->dac[1].size = 0x00000000;
+ dev->dac[1].count = 0x00000000;
+
+ /* ADC Frame Register 1, Address 30H, Memory Page 1101b
+ Addressable as longword only */
+ dev->adc.addr_latch = 0x00000000;
+
+ /* ADC Frame Register 2, Address 34H, Memory Page 1101b
+ Addressable as longword only */
+ dev->adc.size = 0x00000000;
+ dev->adc.count = 0x00000000;
+
+ /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
+ Addressable as longword only */
+ dev->uart_fifo = 0xfffffe00;
+}
+
+
+static uint32_t
+es1371_read_frame_reg(es1371_t *dev, int frame, int page)
+{
+ uint32_t ret = 0xffffffff;
+
+ switch (frame) {
+ case 0x30:
+ switch (page) {
+ /* DAC1 Frame Register 1, Address 30H, Memory Page 1100b
+ Addressable as longword only */
+ case 0xc:
+ ret = dev->dac[0].addr_latch;
+ break;
+ /* ADC Frame Register 1, Address 30H, Memory Page 1101b
+ Addressable as longword only */
+ case 0xd:
+ ret = dev->adc.addr_latch;
+ break;
+ /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
+ Addressable as longword only */
+ case 0xe: case 0xf:
+ ret = dev->uart_fifo;
+ break;
+ }
break;
- case 0x01:
- ret = (es1371->int_ctrl >> 8) & 0xff;
+ case 0x34:
+ switch (page) {
+ /* DAC1 Frame Register 2, Address 34H, Memory Page 1100b
+ Addressable as longword only */
+ case 0xc:
+ ret = dev->dac[0].size | (dev->dac[0].count << 16);
+ break;
+ /* ADC Frame Register 2, Address 34H, Memory Page 1101b
+ Addressable as longword only */
+ case 0xd:
+ ret = dev->adc.size | (dev->adc.count << 16);
+ break;
+ /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
+ Addressable as longword only */
+ case 0xe: case 0xf:
+ ret = dev->uart_fifo;
+ break;
+ }
break;
- case 0x02:
- ret = (es1371->int_ctrl >> 16) & 0xff;
+ case 0x38:
+ switch (page) {
+ /* DAC2 Frame Register 1, Address 38H, Memory Page 1100b
+ Addressable as longword only */
+ case 0xc:
+ ret = dev->dac[1].addr_latch;
+ break;
+ /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
+ Addressable as longword only */
+ case 0xe: case 0xf:
+ ret = dev->uart_fifo;
+ break;
+ }
break;
- case 0x03:
- ret = (es1371->int_ctrl >> 24) & 0xff;
+ case 0x3c:
+ switch (page) {
+ /* DAC2 Frame Register 2, Address 3CH, Memory Page 1100b
+ Addressable as longword only */
+ case 0xc:
+ ret = dev->dac[1].size | (dev->dac[1].count << 16);
+ break;
+ /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
+ Addressable as longword only */
+ case 0xe: case 0xf:
+ ret = dev->uart_fifo;
+ break;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+
+static void
+es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val)
+{
+ switch (frame) {
+ case 0x30:
+ switch (page) {
+ /* DAC1 Frame Register 1, Address 30H, Memory Page 1100b
+ Addressable as longword only */
+ case 0xc:
+ dev->dac[0].addr_latch = val;
+ break;
+ /* ADC Frame Register 1, Address 30H, Memory Page 1101b
+ Addressable as longword only */
+ case 0xd:
+ dev->adc.addr_latch = val;
+ break;
+ /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
+ Addressable as longword only */
+ case 0xe: case 0xf:
+ dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
+ break;
+ }
+ break;
+ case 0x34:
+ switch (page) {
+ /* DAC1 Frame Register 2, Address 34H, Memory Page 1100b
+ Addressable as longword only */
+ case 0xc:
+ dev->dac[0].size = val & 0xffff;
+ dev->dac[0].count = val >> 16;
+ break;
+ /* ADC Frame Register 2, Address 34H, Memory Page 1101b
+ Addressable as longword only */
+ case 0xd:
+ dev->adc.size = val & 0xffff;
+ dev->adc.count = val >> 16;
+ break;
+ /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
+ Addressable as longword only */
+ case 0xe: case 0xf:
+ dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
+ break;
+ }
+ break;
+ case 0x38:
+ switch (page) {
+ /* DAC2 Frame Register 1, Address 38H, Memory Page 1100b
+ Addressable as longword only */
+ case 0xc:
+ dev->dac[1].addr_latch = val;
+ break;
+ /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
+ Addressable as longword only */
+ case 0xe: case 0xf:
+ dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
+ break;
+ }
+ break;
+ case 0x3c:
+ switch (page) {
+ /* DAC2 Frame Register 2, Address 3CH, Memory Page 1100b
+ Addressable as longword only */
+ case 0xc:
+ dev->dac[1].size = val & 0xffff;
+ dev->dac[1].count = val >> 16;
+ break;
+ /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
+ Addressable as longword only */
+ case 0xe: case 0xf:
+ dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
+ break;
+ }
+ break;
+ }
+}
+
+
+static uint8_t
+es1371_inb(uint16_t port, void *p)
+{
+ es1371_t *dev = (es1371_t *) p;
+ uint8_t ret = 0xff;
+
+ switch (port & 0x3f) {
+ /* Interrupt/Chip Select Control Register, Address 00H
+ Addressable as byte, word, longword */
+ case 0x00:
+ ret = dev->int_ctrl & 0xff;
+ break;
+ case 0x01:
+ ret = (dev->int_ctrl >> 8) & 0xff;
+ break;
+ case 0x02:
+ ret = (dev->int_ctrl >> 16) & 0x0f;
+ break;
+ case 0x03:
+ ret = ((dev->int_ctrl >> 24) & 0x03) | 0xfc;
break;
- case 0x04:
- ret = es1371->int_status & 0xff;
+ /* Interrupt/Chip Select Status Register, Address 04H
+ Addressable as longword only, but PCem implemens byte access, which
+ must be for a reason */
+ case 0x04:
+ ret = dev->int_status & 0xff;
break;
- case 0x05:
- ret = (es1371->int_status >> 8) & 0xff;
+ case 0x05:
+ ret = (dev->int_status >> 8) & 0xff;
break;
- case 0x06:
- ret = (es1371->int_status >> 16) & 0xff;
+ case 0x06:
+ ret = (dev->int_status >> 16) & 0x0f;
break;
- case 0x07:
- ret = (es1371->int_status >> 24) & 0xff;
+ case 0x07:
+ ret = ((dev->int_status >> 24) & 0x03) | 0xfc;
+ break;
+
+ /* UART Data Register, Address 08H
+ Addressable as byte only */
+ case 0x08:
+ ret = 0x00;
+ break;
+
+ /* UART Status Register, Address 09H
+ Addressable as byte only */
+ case 0x09:
+ ret = dev->uart_status & 0x87;
+ audiopci_log("ES1371 UART Status = %02x\n", dev->uart_status);
+ break;
+
+ /* UART Reserved Register, Address 0AH
+ Addressable as byte only */
+ case 0x0a:
+ ret = dev->uart_res & 0x01;
+ break;
+
+ /* Memory Page Register, Address 0CH
+ Addressable as byte, word, longword */
+ case 0x0c:
+ ret = dev->mem_page;
+ break;
+ case 0x0d ... 0x0e:
+ ret = 0x00;
break;
- case 0x09:
- ret = es1371->uart_status & 0xc7;
- audiopci_log("ES1371 UART Status = %02x\n", es1371->uart_status);
+ /* Legacy Control/Status Register, Address 18H
+ Addressable as byte, word, longword */
+ case 0x18:
+ ret = dev->legacy_ctrl & 0xfd;
break;
-
- case 0x0c:
- ret = es1371->mem_page;
+ case 0x19:
+ ret = ((dev->legacy_ctrl >> 8) & 0x07) | 0xf8;
break;
-
- case 0x1a:
- ret = es1371->legacy_ctrl >> 16;
+ case 0x1a:
+ ret = dev->legacy_ctrl >> 16;
break;
- case 0x1b:
- ret = es1371->legacy_ctrl >> 24;
+ case 0x1b:
+ ret = dev->legacy_ctrl >> 24;
break;
-
- case 0x20:
- ret = es1371->si_cr & 0xff;
+
+ /* Serial Interface Control Register, Address 20H
+ Addressable as byte, word, longword */
+ case 0x20:
+ ret = dev->si_cr & 0xff;
break;
- case 0x21:
- ret = es1371->si_cr >> 8;
+ case 0x21:
+ ret = dev->si_cr >> 8;
break;
- case 0x22:
- ret = (es1371->si_cr >> 16) | 0x80;
+ case 0x22:
+ ret = (dev->si_cr >> 16) | 0x80;
break;
- case 0x23:
+ case 0x23:
ret = 0xff;
break;
- default:
+ default:
audiopci_log("Bad es1371_inb: port=%04x\n", port);
- }
+ }
- audiopci_log("es1371_inb: port=%04x ret=%02x\n", port, ret);
-// output = 3;
- return ret;
-}
-static uint16_t es1371_inw(uint16_t port, void *p)
-{
- es1371_t *es1371 = (es1371_t *)p;
- uint16_t ret = 0;
-
- switch (port & 0x3e)
- {
- case 0x00:
- ret = es1371->int_ctrl & 0xffff;
- break;
- case 0x02:
- ret = (es1371->int_ctrl >> 16) & 0xffff;
- break;
-
- case 0x18:
- ret = es1371->legacy_ctrl & 0xffff;
-// audiopci_log("Read legacy ctrl %04x\n", ret);
- break;
-
- case 0x26:
- ret = es1371->dac[0].curr_samp_ct;
- break;
-
- case 0x2a:
- ret = es1371->dac[1].curr_samp_ct;
- break;
-
- case 0x36:
- switch (es1371->mem_page)
- {
- case 0xc:
- ret = es1371->dac[0].count;
- break;
-
- default:
- audiopci_log("Bad es1371_inw: mem_page=%x port=%04x\n", es1371->mem_page, port);
- }
- break;
-
- case 0x3e:
- switch (es1371->mem_page)
- {
- case 0xc:
- ret = es1371->dac[1].count;
- break;
-
- default:
- audiopci_log("Bad es1371_inw: mem_page=%x port=%04x\n", es1371->mem_page, port);
- }
- break;
-
- default:
- ret = es1371_inb(port, p);
- ret |= es1371_inb(port + 1, p) << 8;
- }
-
-// audiopci_log("es1371_inw: port=%04x ret=%04x %04x:%08x\n", port, ret, CS,cpu_state.pc);
- return ret;
-}
-static uint32_t es1371_inl(uint16_t port, void *p)
-{
- es1371_t *es1371 = (es1371_t *)p;
- uint32_t ret = 0;
-
- switch (port & 0x3c)
- {
- case 0x00:
- ret = es1371->int_ctrl;
- break;
- case 0x04:
- ret = es1371->int_status;
- break;
-
- case 0x10:
- ret = es1371->sr_cir & ~0xffff;
- ret |= es1371->sr_ram[es1371->sr_cir >> 25];
- break;
-
- case 0x14:
- ret = es1371->codec_ctrl | CODEC_READY;
- break;
-
- case 0x30:
- switch (es1371->mem_page) {
- case 0xe: case 0xf:
- audiopci_log("ES1371 0x30 read UART FIFO: val = %02x\n", ret & 0xff);
- break;
- }
- break;
-
- case 0x34:
- switch (es1371->mem_page) {
- case 0xc:
- ret = es1371->dac[0].size | (es1371->dac[0].count << 16);
- break;
-
- case 0xd:
- ret = es1371->adc.size | (es1371->adc.count << 16);
- break;
-
- case 0xe: case 0xf:
- audiopci_log("ES1371 0x34 read UART FIFO: val = %02x\n", ret & 0xff);
- break;
-
- default:
- audiopci_log("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port);
- }
- break;
-
- case 0x38:
- switch (es1371->mem_page) {
- case 0xe: case 0xf:
- audiopci_log("ES1371 0x38 read UART FIFO: val = %02x\n", ret & 0xff);
- break;
- }
- break;
-
- case 0x3c:
- switch (es1371->mem_page) {
- case 0xc:
- ret = es1371->dac[1].size | (es1371->dac[1].count << 16);
- break;
-
- case 0xe: case 0xf:
- audiopci_log("ES1371 0x3c read UART FIFO: val = %02x\n", ret & 0xff);
- break;
-
- default:
- audiopci_log("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port);
- }
- break;
-
- default:
- ret = es1371_inw(port, p);
- ret |= es1371_inw(port + 2, p) << 16;
- }
-
- audiopci_log("es1371_inl: port=%04x ret=%08x\n", port, ret);
- return ret;
+ audiopci_log("es1371_inb: port=%04x ret=%02x\n", port, ret);
+ return ret;
}
-static void es1371_outb(uint16_t port, uint8_t val, void *p)
-{
- es1371_t *es1371 = (es1371_t *)p;
- uint32_t old_legacy_ctrl;
- audiopci_log("es1371_outb: port=%04x val=%02x\n", port, val);
- switch (port & 0x3f)
- {
- case 0x00:
- if (!(es1371->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN))
- {
- es1371->dac[0].addr = es1371->dac[0].addr_latch;
- es1371->dac[0].buffer_pos = 0;
- es1371->dac[0].buffer_pos_end = 0;
- es1371_fetch(es1371, 0);
- }
- if (!(es1371->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN))
- {
- es1371->dac[1].addr = es1371->dac[1].addr_latch;
- es1371->dac[1].buffer_pos = 0;
- es1371->dac[1].buffer_pos_end = 0;
- es1371_fetch(es1371, 1);
- }
- es1371->int_ctrl = (es1371->int_ctrl & 0xffffff00) | val;
+static uint16_t
+es1371_inw(uint16_t port, void *p)
+{
+ es1371_t *dev = (es1371_t *) p;
+ uint16_t ret = 0xffff;
+
+ switch (port & 0x3e) {
+ /* Interrupt/Chip Select Control Register, Address 00H
+ Addressable as byte, word, longword */
+ case 0x00:
+ ret = dev->int_ctrl & 0xffff;
break;
- case 0x01:
- es1371->int_ctrl = (es1371->int_ctrl & 0xffff00ff) | (val << 8);
+ case 0x02:
+ ret = ((dev->int_ctrl >> 16) & 0x030f) | 0xfc00;
break;
- case 0x02:
- es1371->int_ctrl = (es1371->int_ctrl & 0xff00ffff) | (val << 16);
+
+ /* Memory Page Register, Address 0CH
+ Addressable as byte, word, longword */
+ case 0x0c:
+ ret = dev->mem_page;
break;
- case 0x03:
- es1371->int_ctrl = (es1371->int_ctrl & 0x00ffffff) | (val << 24);
+ case 0x0e:
+ ret = 0x0000;
+ break;
+
+ /* Legacy Control/Status Register, Address 18H
+ Addressable as byte, word, longword */
+ case 0x18:
+ ret = (dev->legacy_ctrl & 0x07fd) | 0xf800;
+ break;
+ case 0x1a:
+ ret = dev->legacy_ctrl >> 16;
+ break;
+
+ /* Serial Interface Control Register, Address 20H
+ Addressable as byte, word, longword */
+ case 0x20:
+ ret = dev->si_cr & 0xffff;
+ break;
+ case 0x22:
+ ret = (dev->si_cr >> 16) | 0xff80;
+ break;
+
+ /* DAC1 Channel Sample Count Register, Address 24H
+ Addressable as word, longword */
+ case 0x24:
+ ret = dev->dac[0].samp_ct;
+ break;
+ case 0x26:
+ ret = dev->dac[0].curr_samp_ct;
+ break;
+
+ /* DAC2 Channel Sample Count Register, Address 28H
+ Addressable as word, longword */
+ case 0x28:
+ ret = dev->dac[1].samp_ct;
+ break;
+ case 0x2a:
+ ret = dev->dac[1].curr_samp_ct;
+ break;
+
+ /* ADC Channel Sample Count Register, Address 2CH
+ Addressable as word, longword */
+ case 0x2c:
+ ret = dev->adc.samp_ct;
+ break;
+ case 0x2e:
+ ret = dev->adc.curr_samp_ct;
+ break;
+
+ case 0x30: case 0x34: case 0x38: case 0x3c:
+ ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page) & 0xffff;
+ break;
+ case 0x32: case 0x36: case 0x3a: case 0x3e:
+ ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page) >> 16;
+ break;
+ }
+
+ return ret;
+}
+
+
+static uint32_t
+es1371_inl(uint16_t port, void *p)
+{
+ es1371_t *dev = (es1371_t *) p;
+ uint32_t ret = 0xffffffff;
+
+ switch (port & 0x3c) {
+ /* Interrupt/Chip Select Control Register, Address 00H
+ Addressable as byte, word, longword */
+ case 0x00:
+ ret = (dev->int_ctrl & 0x030fffff) | 0xfc000000;
+ break;
+
+ /* Interrupt/Chip Select Status Register, Address 04H
+ Addressable as longword only */
+ case 0x04:
+ ret = dev->int_status;
+ break;
+
+ /* Memory Page Register, Address 0CH
+ Addressable as byte, word, longword */
+ case 0x0c:
+ ret = dev->mem_page;
+ break;
+
+ /* Sample Rate Concerter Interface Register, Address 10H
+ Addressable as longword only */
+ case 0x10:
+ ret = dev->sr_cir & ~0xffff;
+ ret |= dev->sr_ram[dev->sr_cir >> 25];
break;
- case 0x08:
+ /* CODEC Read Register, Address 14H
+ Addressable as longword only */
+ case 0x14:
+ ret = dev->codec_ctrl | CODEC_READY;
+ break;
+
+ /* Legacy Control/Status Register, Address 18H
+ Addressable as byte, word, longword */
+ case 0x18:
+ ret = (dev->legacy_ctrl & 0xffff07fd) | 0x0000f800;
+ break;
+
+ /* Serial Interface Control Register, Address 20H
+ Addressable as byte, word, longword */
+ case 0x20:
+ ret = dev->si_cr | 0xff800000;
+ break;
+
+ /* DAC1 Channel Sample Count Register, Address 24H
+ Addressable as word, longword */
+ case 0x24:
+ ret = dev->dac[0].samp_ct | (((uint32_t) dev->dac[0].curr_samp_ct) << 16);
+ break;
+
+ /* DAC2 Channel Sample Count Register, Address 28H
+ Addressable as word, longword */
+ case 0x28:
+ ret = dev->dac[1].samp_ct | (((uint32_t) dev->dac[1].curr_samp_ct) << 16);
+ break;
+
+ /* ADC Channel Sample Count Register, Address 2CH
+ Addressable as word, longword */
+ case 0x2c:
+ ret = dev->adc.samp_ct | (((uint32_t) dev->adc.curr_samp_ct) << 16);
+ break;
+
+ case 0x30: case 0x34: case 0x38: case 0x3c:
+ ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page);
+ break;
+ }
+
+ audiopci_log("es1371_inl: port=%04x ret=%08x\n", port, ret);
+ return ret;
+}
+
+
+static void
+es1371_outb(uint16_t port, uint8_t val, void *p)
+{
+ es1371_t *dev = (es1371_t *)p;
+ uint32_t old_legacy_ctrl;
+
+ audiopci_log("es1371_outb: port=%04x val=%02x\n", port, val);
+
+ switch (port & 0x3f) {
+ /* Interrupt/Chip Select Control Register, Address 00H
+ Addressable as byte, word, longword */
+ case 0x00:
+ if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) {
+ dev->dac[0].addr = dev->dac[0].addr_latch;
+ dev->dac[0].buffer_pos = 0;
+ dev->dac[0].buffer_pos_end = 0;
+ es1371_fetch(dev, 0);
+ }
+ if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) {
+ dev->dac[1].addr = dev->dac[1].addr_latch;
+ dev->dac[1].buffer_pos = 0;
+ dev->dac[1].buffer_pos_end = 0;
+ es1371_fetch(dev, 1);
+ }
+ dev->int_ctrl = (dev->int_ctrl & 0xffffff00) | val;
+ break;
+ case 0x01:
+ dev->int_ctrl = (dev->int_ctrl & 0xffff00ff) | (val << 8);
+ break;
+ case 0x02:
+ dev->int_ctrl = (dev->int_ctrl & 0xff00ffff) | (val << 16);
+ break;
+ case 0x03:
+ dev->int_ctrl = (dev->int_ctrl & 0x00ffffff) | (val << 24);
+ break;
+
+ /* UART Data Register, Address 08H
+ Addressable as byte only */
+ case 0x08:
midi_raw_out_byte(val);
break;
-
- case 0x09:
- es1371->uart_ctrl = val & 0xe3;
- audiopci_log("ES1371 UART Cntrl = %02x\n", es1371->uart_ctrl);
- break;
-
- case 0x0c:
- es1371->mem_page = val & 0xf;
+
+ /* UART Control Register, Address 09H
+ Addressable as byte only */
+ case 0x09:
+ dev->uart_ctrl = val & 0xe3;
+ audiopci_log("ES1371 UART Cntrl = %02x\n", dev->uart_ctrl);
break;
- case 0x18:
- es1371->legacy_ctrl |= LEGACY_INT;
- nmi = 0;
+ /* UART Reserved Register, Address 0AH
+ Addressable as byte only */
+ case 0x0a:
+ dev->uart_res = val & 0x01;
break;
- case 0x1a:
- old_legacy_ctrl = es1371->legacy_ctrl;
- es1371->legacy_ctrl = (es1371->legacy_ctrl & 0xff00ffff) | (val << 16);
- update_legacy(es1371, old_legacy_ctrl);
+
+ /* Memory Page Register, Address 0CH
+ Addressable as byte, word, longword */
+ case 0x0c:
+ dev->mem_page = val & 0xf;
break;
- case 0x1b:
- old_legacy_ctrl = es1371->legacy_ctrl;
- es1371->legacy_ctrl = (es1371->legacy_ctrl & 0x00ffffff) | (val << 24);
- es1371_update_irqs(es1371);
-// output = 3;
- update_legacy(es1371, old_legacy_ctrl);
+ case 0x0d ... 0x0f:
break;
-
- case 0x20:
- es1371->si_cr = (es1371->si_cr & 0xffff00) | val;
+
+ /* Legacy Control/Status Register, Address 18H
+ Addressable as byte, word, longword */
+ case 0x18:
+ dev->legacy_ctrl |= LEGACY_INT;
+ // nmi = 0;
break;
- case 0x21:
- es1371->si_cr = (es1371->si_cr & 0xff00ff) | (val << 8);
- if (!(es1371->si_cr & SI_P1_INTR_EN))
- es1371->int_status &= ~INT_STATUS_DAC1;
- if (!(es1371->si_cr & SI_P2_INTR_EN))
- es1371->int_status &= ~INT_STATUS_DAC2;
- es1371_update_irqs(es1371);
+ case 0x1a:
+ old_legacy_ctrl = dev->legacy_ctrl;
+ dev->legacy_ctrl = (dev->legacy_ctrl & 0xff00ffff) | (val << 16);
+ update_legacy(dev, old_legacy_ctrl);
break;
- case 0x22:
- es1371->si_cr = (es1371->si_cr & 0x00ffff) | (val << 16);
+ case 0x1b:
+ old_legacy_ctrl = dev->legacy_ctrl;
+ dev->legacy_ctrl = (dev->legacy_ctrl & 0x00ffffff) | (val << 24);
+ es1371_update_irqs(dev);
+ update_legacy(dev, old_legacy_ctrl);
break;
-
- default:
+
+ /* Serial Interface Control Register, Address 20H
+ Addressable as byte, word, longword */
+ case 0x20:
+ dev->si_cr = (dev->si_cr & 0xffffff00) | val;
+ break;
+ case 0x21:
+ dev->si_cr = (dev->si_cr & 0xffff00ff) | (val << 8);
+ if (!(dev->si_cr & SI_P1_INTR_EN))
+ dev->int_status &= ~INT_STATUS_DAC1;
+ if (!(dev->si_cr & SI_P2_INTR_EN))
+ dev->int_status &= ~INT_STATUS_DAC2;
+ es1371_update_irqs(dev);
+ break;
+ case 0x22:
+ dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x7f) << 16);
+ break;
+
+ default:
audiopci_log("Bad es1371_outb: port=%04x val=%02x\n", port, val);
- }
+ }
}
-static void es1371_outw(uint16_t port, uint16_t val, void *p)
+
+
+static void
+es1371_outw(uint16_t port, uint16_t val, void *p)
{
- es1371_t *es1371 = (es1371_t *)p;
+ es1371_t *dev = (es1371_t *)p;
+ uint32_t old_legacy_ctrl;
-// audiopci_log("es1371_outw: port=%04x val=%04x\n", port, val);
- switch (port & 0x3f)
- {
- case 0x0c:
- es1371->mem_page = val & 0xf;
+ switch (port & 0x3f) {
+ /* Interrupt/Chip Select Control Register, Address 00H
+ Addressable as byte, word, longword */
+ case 0x00:
+ if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) {
+ dev->dac[0].addr = dev->dac[0].addr_latch;
+ dev->dac[0].buffer_pos = 0;
+ dev->dac[0].buffer_pos_end = 0;
+ es1371_fetch(dev, 0);
+ }
+ if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) {
+ dev->dac[1].addr = dev->dac[1].addr_latch;
+ dev->dac[1].buffer_pos = 0;
+ dev->dac[1].buffer_pos_end = 0;
+ es1371_fetch(dev, 1);
+ }
+ dev->int_ctrl = (dev->int_ctrl & 0xffff0000) | val;
+ break;
+ case 0x02:
+ dev->int_ctrl = (dev->int_ctrl & 0x0000ffff) | (val << 16);
break;
- case 0x24:
- es1371->dac[0].samp_ct = val;
+ /* Memory Page Register, Address 0CH
+ Addressable as byte, word, longword */
+ case 0x0c:
+ dev->mem_page = val & 0xf;
+ break;
+ case 0x0e:
break;
- case 0x28:
- es1371->dac[1].samp_ct = val;
+ /* Legacy Control/Status Register, Address 18H
+ Addressable as byte, word, longword */
+ case 0x18:
+ dev->legacy_ctrl |= LEGACY_INT;
+ // nmi = 0;
break;
-
- default:
- es1371_outb(port, val & 0xff, p);
- es1371_outb(port + 1, (val >> 8) & 0xff, p);
- }
+ case 0x1a:
+ old_legacy_ctrl = dev->legacy_ctrl;
+ dev->legacy_ctrl = (dev->legacy_ctrl & 0x0000ffff) | (val << 16);
+ es1371_update_irqs(dev);
+ update_legacy(dev, old_legacy_ctrl);
+ break;
+
+ /* Serial Interface Control Register, Address 20H
+ Addressable as byte, word, longword */
+ case 0x20:
+ dev->si_cr = (dev->si_cr & 0xffff0000) | val;
+ if (!(dev->si_cr & SI_P1_INTR_EN))
+ dev->int_status &= ~INT_STATUS_DAC1;
+ if (!(dev->si_cr & SI_P2_INTR_EN))
+ dev->int_status &= ~INT_STATUS_DAC2;
+ es1371_update_irqs(dev);
+ break;
+ case 0x22:
+ dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x007f) << 16);
+ break;
+
+ /* DAC1 Channel Sample Count Register, Address 24H
+ Addressable as word, longword */
+ case 0x24:
+ dev->dac[0].samp_ct = val;
+ break;
+
+ /* DAC2 Channel Sample Count Register, Address 28H
+ Addressable as word, longword */
+ case 0x28:
+ dev->dac[1].samp_ct = val;
+ break;
+
+ /* ADC Channel Sample Count Register, Address 2CH
+ Addressable as word, longword */
+ case 0x2c:
+ dev->adc.samp_ct = val;
+ break;
+ }
}
-static void es1371_outl(uint16_t port, uint32_t val, void *p)
+
+
+static void
+es1371_outl(uint16_t port, uint32_t val, void *p)
{
- es1371_t *es1371 = (es1371_t *)p;
+ es1371_t *dev = (es1371_t *)p;
+ uint32_t old_legacy_ctrl;
- audiopci_log("es1371_outl: port=%04x val=%08x\n", port, val);
- switch (port & 0x3f)
- {
- case 0x04:
- break;
-
- case 0x0c:
- es1371->mem_page = val & 0xf;
+ audiopci_log("es1371_outl: port=%04x val=%08x\n", port, val);
+
+ switch (port & 0x3f) {
+ /* Interrupt/Chip Select Control Register, Address 00H
+ Addressable as byte, word, longword */
+ case 0x00:
+ if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) {
+ dev->dac[0].addr = dev->dac[0].addr_latch;
+ dev->dac[0].buffer_pos = 0;
+ dev->dac[0].buffer_pos_end = 0;
+ es1371_fetch(dev, 0);
+ }
+ if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) {
+ dev->dac[1].addr = dev->dac[1].addr_latch;
+ dev->dac[1].buffer_pos = 0;
+ dev->dac[1].buffer_pos_end = 0;
+ es1371_fetch(dev, 1);
+ }
+ dev->int_ctrl = val;
break;
- case 0x10:
- es1371->sr_cir = val;
- if (es1371->sr_cir & SRC_RAM_WE)
- {
-// audiopci_log("Write SR RAM %02x %04x\n", es1371->sr_cir >> 25, val & 0xffff);
- es1371->sr_ram[es1371->sr_cir >> 25] = val & 0xffff;
- switch (es1371->sr_cir >> 25)
- {
+ /* Interrupt/Chip Select Status Register, Address 04H
+ Addressable as longword only */
+ case 0x04:
+ break;
+
+ /* Memory Page Register, Address 0CH
+ Addressable as byte, word, longword */
+ case 0x0c:
+ dev->mem_page = val & 0xf;
+ break;
+
+ /* Sample Rate Concerter Interface Register, Address 10H
+ Addressable as longword only */
+ case 0x10:
+ dev->sr_cir = val;
+ if (dev->sr_cir & SRC_RAM_WE) {
+ dev->sr_ram[dev->sr_cir >> 25] = val & 0xffff;
+ switch (dev->sr_cir >> 25) {
case 0x71:
- es1371->dac[0].vf = (es1371->dac[0].vf & ~0x1f8000) | ((val & 0xfc00) << 5);
- es1371->dac[0].ac = (es1371->dac[0].ac & ~0x7f8000) | ((val & 0x00ff) << 15);
- es1371->dac[0].f_pos = 0;
- break;
+ dev->dac[0].vf = (dev->dac[0].vf & ~0x1f8000) | ((val & 0xfc00) << 5);
+ dev->dac[0].ac = (dev->dac[0].ac & ~0x7f8000) | ((val & 0x00ff) << 15);
+ dev->dac[0].f_pos = 0;
+ break;
case 0x72:
- es1371->dac[0].ac = (es1371->dac[0].ac & ~0x7fff) | (val & 0x7fff);
- break;
+ dev->dac[0].ac = (dev->dac[0].ac & ~0x7fff) | (val & 0x7fff);
+ break;
case 0x73:
- es1371->dac[0].vf = (es1371->dac[0].vf & ~0x7fff) | (val & 0x7fff);
- break;
+ dev->dac[0].vf = (dev->dac[0].vf & ~0x7fff) | (val & 0x7fff);
+ break;
case 0x75:
- es1371->dac[1].vf = (es1371->dac[1].vf & ~0x1f8000) | ((val & 0xfc00) << 5);
- es1371->dac[1].ac = (es1371->dac[1].ac & ~0x7f8000) | ((val & 0x00ff) << 15);
- es1371->dac[1].f_pos = 0;
- break;
+ dev->dac[1].vf = (dev->dac[1].vf & ~0x1f8000) | ((val & 0xfc00) << 5);
+ dev->dac[1].ac = (dev->dac[1].ac & ~0x7f8000) | ((val & 0x00ff) << 15);
+ dev->dac[1].f_pos = 0;
+ break;
case 0x76:
- es1371->dac[1].ac = (es1371->dac[1].ac & ~0x7fff) | (val & 0x7fff);
- break;
+ dev->dac[1].ac = (dev->dac[1].ac & ~0x7fff) | (val & 0x7fff);
+ break;
case 0x77:
- es1371->dac[1].vf = (es1371->dac[1].vf & ~0x7fff) | (val & 0x7fff);
- break;
-
+ dev->dac[1].vf = (dev->dac[1].vf & ~0x7fff) | (val & 0x7fff);
+ break;
+
case 0x7c:
- es1371->dac[0].vol_l = (int32_t)(int16_t)(val & 0xffff);
- break;
+ dev->dac[0].vol_l = (int32_t)(int16_t)(val & 0xffff);
+ break;
case 0x7d:
- es1371->dac[0].vol_r = (int32_t)(int16_t)(val & 0xffff);
- break;
+ dev->dac[0].vol_r = (int32_t)(int16_t)(val & 0xffff);
+ break;
case 0x7e:
- es1371->dac[1].vol_l = (int32_t)(int16_t)(val & 0xffff);
- break;
+ dev->dac[1].vol_l = (int32_t)(int16_t)(val & 0xffff);
+ break;
case 0x7f:
- es1371->dac[1].vol_r = (int32_t)(int16_t)(val & 0xffff);
- break;
+ dev->dac[1].vol_r = (int32_t)(int16_t)(val & 0xffff);
+ break;
}
}
break;
- case 0x14:
+ /* CODEC Write Register, Address 14H
+ Addressable as longword only */
+ case 0x14:
if (val & CODEC_READ) {
- es1371->codec_ctrl &= 0x00ff0000;
+ dev->codec_ctrl &= 0x00ff0000;
val = (val >> 16) & 0x7e;
- es1371->codec_ctrl |= ac97_codec_read(es1371->codec, val);
- es1371->codec_ctrl |= ac97_codec_read(es1371->codec, val | 1) << 8;
+ dev->codec_ctrl |= ac97_codec_read(dev->codec, val);
+ dev->codec_ctrl |= ac97_codec_read(dev->codec, val | 1) << 8;
} else {
- es1371->codec_ctrl = val & 0x00ffffff;
- ac97_codec_write(es1371->codec, (val >> 16) & 0x7e, val & 0xff);
- ac97_codec_write(es1371->codec, ((val >> 16) & 0x7e) | 1, val >> 8);
+ dev->codec_ctrl = val & 0x00ffffff;
+ ac97_codec_write(dev->codec, (val >> 16) & 0x7e, val & 0xff);
+ ac97_codec_write(dev->codec, ((val >> 16) & 0x7e) | 1, val >> 8);
- ac97_codec_getattn(es1371->codec, 0x02, &es1371->master_vol_l, &es1371->master_vol_r);
- ac97_codec_getattn(es1371->codec, 0x12, &es1371->cd_vol_l, &es1371->cd_vol_r);
- }
- break;
-
- case 0x24:
- es1371->dac[0].samp_ct = val & 0xffff;
- break;
-
- case 0x28:
- es1371->dac[1].samp_ct = val & 0xffff;
- break;
-
- case 0x30:
- switch (es1371->mem_page)
- {
- case 0x0: case 0x1: case 0x2: case 0x3:
- case 0x4: case 0x5: case 0x6: case 0x7:
- case 0x8: case 0x9: case 0xa: case 0xb:
- break;
-
- case 0xc:
- es1371->dac[0].addr_latch = val;
-// audiopci_log("DAC1 addr %08x\n", val);
- break;
-
- case 0xe: case 0xf:
- audiopci_log("ES1371 0x30 write UART FIFO: val = %02x\n", val & 0xff);
- break;
-
- default:
- audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val);
- }
- break;
- case 0x34:
- switch (es1371->mem_page)
- {
- case 0x0: case 0x1: case 0x2: case 0x3:
- case 0x4: case 0x5: case 0x6: case 0x7:
- case 0x8: case 0x9: case 0xa: case 0xb:
- break;
-
- case 0xc:
- es1371->dac[0].size = val & 0xffff;
- es1371->dac[0].count = val >> 16;
- break;
-
- case 0xd:
- es1371->adc.size = val & 0xffff;
- es1371->adc.count = val >> 16;
- break;
-
- case 0xe: case 0xf:
- audiopci_log("ES1371 0x34 write UART FIFO: val = %02x\n", val & 0xff);
- break;
-
- default:
- audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val);
- }
- break;
- case 0x38:
- switch (es1371->mem_page)
- {
- case 0x0: case 0x1: case 0x2: case 0x3:
- case 0x4: case 0x5: case 0x6: case 0x7:
- case 0x8: case 0x9: case 0xa: case 0xb:
- break;
-
- case 0xc:
- es1371->dac[1].addr_latch = val;
- break;
-
- case 0xd:
- break;
-
- case 0xe: case 0xf:
- audiopci_log("ES1371 0x38 write UART FIFO: val = %02x\n", val & 0xff);
- break;
-
- default:
- audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val);
- }
- break;
- case 0x3c:
- switch (es1371->mem_page)
- {
- case 0x0: case 0x1: case 0x2: case 0x3:
- case 0x4: case 0x5: case 0x6: case 0x7:
- case 0x8: case 0x9: case 0xa: case 0xb:
- break;
-
- case 0xc:
- es1371->dac[1].size = val & 0xffff;
- es1371->dac[1].count = val >> 16;
- break;
-
- case 0xe: case 0xf:
- audiopci_log("ES1371 0x3c write UART FIFO: val = %02x\n", val & 0xff);
- break;
-
- default:
- audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val);
+ ac97_codec_getattn(dev->codec, 0x02, &dev->master_vol_l, &dev->master_vol_r);
+ ac97_codec_getattn(dev->codec, 0x12, &dev->cd_vol_l, &dev->cd_vol_r);
}
break;
- default:
- es1371_outw(port, val & 0xffff, p);
- es1371_outw(port + 2, (val >> 16) & 0xffff, p);
+ /* Legacy Control/Status Register, Address 18H
+ Addressable as byte, word, longword */
+ case 0x18:
+ old_legacy_ctrl = dev->legacy_ctrl;
+ dev->legacy_ctrl = (dev->legacy_ctrl & 0x0000ffff) | (val & 0xffff0000);
+ dev->legacy_ctrl |= LEGACY_INT;
+ // nmi = 0;
+ es1371_update_irqs(dev);
+ update_legacy(dev, old_legacy_ctrl);
+ break;
+
+ /* Serial Interface Control Register, Address 20H
+ Addressable as byte, word, longword */
+ case 0x20:
+ dev->si_cr = (val & 0x007fffff) | 0xff800000;
+ if (!(dev->si_cr & SI_P1_INTR_EN))
+ dev->int_status &= ~INT_STATUS_DAC1;
+ if (!(dev->si_cr & SI_P2_INTR_EN))
+ dev->int_status &= ~INT_STATUS_DAC2;
+ es1371_update_irqs(dev);
+ break;
+
+ /* DAC1 Channel Sample Count Register, Address 24H
+ Addressable as word, longword */
+ case 0x24:
+ dev->dac[0].samp_ct = val & 0xffff;
+ break;
+
+ /* DAC2 Channel Sample Count Register, Address 28H
+ Addressable as word, longword */
+ case 0x28:
+ dev->dac[1].samp_ct = val & 0xffff;
+ break;
+
+ /* ADC Channel Sample Count Register, Address 2CH
+ Addressable as word, longword */
+ case 0x2c:
+ dev->adc.samp_ct = val & 0xffff;
+ break;
+
+ case 0x30: case 0x34: case 0x38: case 0x3c:
+ es1371_write_frame_reg(dev, port & 0x3c, dev->mem_page, val);
+ break;
+ }
+}
+
+
+static void
+capture_event(es1371_t *dev, int type, int rw, uint16_t port)
+{
+ dev->legacy_ctrl &= ~(LEGACY_EVENT_MASK | LEGACY_EVENT_ADDR_MASK);
+ dev->legacy_ctrl |= type;
+ if (rw)
+ dev->legacy_ctrl |= LEGACY_EVENT_TYPE_RW;
+ else
+ dev->legacy_ctrl &= ~LEGACY_EVENT_TYPE_RW;
+ dev->legacy_ctrl |= ((port << LEGACY_EVENT_ADDR_SHIFT) & LEGACY_EVENT_ADDR_MASK);
+ dev->legacy_ctrl &= ~LEGACY_INT;
+ nmi = 1;
+}
+
+
+static void
+capture_write_sscape(uint16_t port, uint8_t val, void *p)
+{
+ capture_event(p, LEGACY_EVENT_SSCAPE, 1, port);
+}
+
+
+static void
+capture_write_codec(uint16_t port, uint8_t val, void *p)
+{
+ capture_event(p, LEGACY_EVENT_CODEC, 1, port);
+}
+
+
+static void
+capture_write_sb(uint16_t port, uint8_t val, void *p)
+{
+ capture_event(p, LEGACY_EVENT_SB, 1, port);
+}
+
+
+static void
+capture_write_adlib(uint16_t port, uint8_t val, void *p)
+{
+ capture_event(p, LEGACY_EVENT_ADLIB, 1, port);
+}
+
+
+static void
+capture_write_master_pic(uint16_t port, uint8_t val, void *p)
+{
+ capture_event(p, LEGACY_EVENT_MASTER_PIC, 1, port);
+}
+
+
+static void
+capture_write_master_dma(uint16_t port, uint8_t val, void *p)
+{
+ capture_event(p, LEGACY_EVENT_MASTER_DMA, 1, port);
+}
+
+
+static void
+capture_write_slave_pic(uint16_t port, uint8_t val, void *p)
+{
+ capture_event(p, LEGACY_EVENT_SLAVE_PIC, 1, port);
+}
+
+
+static void
+capture_write_slave_dma(uint16_t port, uint8_t val, void *p)
+{
+ capture_event(p, LEGACY_EVENT_SLAVE_DMA, 1, port);
+}
+
+
+static uint8_t
+capture_read_sscape(uint16_t port, void *p)
+{
+ capture_event(p, LEGACY_EVENT_SSCAPE, 0, port);
+ return 0xff;
+}
+
+
+static uint8_t
+capture_read_codec(uint16_t port, void *p)
+{
+ capture_event(p, LEGACY_EVENT_CODEC, 0, port);
+ return 0xff;
+}
+
+
+static uint8_t
+capture_read_sb(uint16_t port, void *p)
+{
+ capture_event(p, LEGACY_EVENT_SB, 0, port);
+ return 0xff;
+}
+
+
+static uint8_t
+capture_read_adlib(uint16_t port, void *p)
+{
+ capture_event(p, LEGACY_EVENT_ADLIB, 0, port);
+ return 0xff;
+}
+
+
+static uint8_t
+capture_read_master_pic(uint16_t port, void *p)
+{
+ capture_event(p, LEGACY_EVENT_MASTER_PIC, 0, port);
+ return 0xff;
+}
+
+
+static uint8_t
+capture_read_master_dma(uint16_t port, void *p)
+{
+ capture_event(p, LEGACY_EVENT_MASTER_DMA, 0, port);
+ return 0xff;
+}
+
+
+static uint8_t
+capture_read_slave_pic(uint16_t port, void *p)
+{
+ capture_event(p, LEGACY_EVENT_SLAVE_PIC, 0, port);
+ return 0xff;
+}
+
+
+static uint8_t
+capture_read_slave_dma(uint16_t port, void *p)
+{
+ capture_event(p, LEGACY_EVENT_SLAVE_DMA, 0, port);
+ return 0xff;
+}
+
+
+static void
+update_legacy(es1371_t *dev, uint32_t old_legacy_ctrl)
+{
+ if (old_legacy_ctrl & LEGACY_CAPTURE_SSCAPE) {
+ switch ((old_legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3) {
+ case 0:
+ io_removehandler(0x0320, 0x0008,
+ capture_read_sscape, NULL, NULL,
+ capture_write_sscape, NULL, NULL, dev);
+ break;
+ case 1:
+ io_removehandler(0x0330, 0x0008,
+ capture_read_sscape, NULL, NULL,
+ capture_write_sscape, NULL, NULL, dev);
+ break;
+ case 2:
+ io_removehandler(0x0340, 0x0008,
+ capture_read_sscape, NULL ,NULL,
+ capture_write_sscape, NULL, NULL, dev);
+ break;
+ case 3:
+ io_removehandler(0x0350, 0x0008,
+ capture_read_sscape, NULL, NULL,
+ capture_write_sscape, NULL, NULL, dev);
+ break;
}
-}
+ }
-static void capture_event(es1371_t *es1371, int type, int rw, uint16_t port)
-{
- es1371->legacy_ctrl &= ~(LEGACY_EVENT_MASK | LEGACY_EVENT_ADDR_MASK);
- es1371->legacy_ctrl |= type;
- if (rw)
- es1371->legacy_ctrl |= LEGACY_EVENT_TYPE_RW;
- else
- es1371->legacy_ctrl &= ~LEGACY_EVENT_TYPE_RW;
- es1371->legacy_ctrl |= ((port << LEGACY_EVENT_ADDR_SHIFT) & LEGACY_EVENT_ADDR_MASK);
- es1371->legacy_ctrl &= ~LEGACY_INT;
- nmi = 1;
-// audiopci_log("Event! %s %04x\n", rw ? "write" : "read", port);
-}
-
-static void capture_write_sscape(uint16_t port, uint8_t val, void *p)
-{
- capture_event(p, LEGACY_EVENT_SSCAPE, 1, port);
-}
-static void capture_write_codec(uint16_t port, uint8_t val, void *p)
-{
- capture_event(p, LEGACY_EVENT_CODEC, 1, port);
-}
-static void capture_write_sb(uint16_t port, uint8_t val, void *p)
-{
- capture_event(p, LEGACY_EVENT_SB, 1, port);
-}
-static void capture_write_adlib(uint16_t port, uint8_t val, void *p)
-{
- capture_event(p, LEGACY_EVENT_ADLIB, 1, port);
-}
-static void capture_write_master_pic(uint16_t port, uint8_t val, void *p)
-{
- capture_event(p, LEGACY_EVENT_MASTER_PIC, 1, port);
-}
-static void capture_write_master_dma(uint16_t port, uint8_t val, void *p)
-{
- capture_event(p, LEGACY_EVENT_MASTER_DMA, 1, port);
-}
-static void capture_write_slave_pic(uint16_t port, uint8_t val, void *p)
-{
- capture_event(p, LEGACY_EVENT_SLAVE_PIC, 1, port);
-}
-static void capture_write_slave_dma(uint16_t port, uint8_t val, void *p)
-{
- capture_event(p, LEGACY_EVENT_SLAVE_DMA, 1, port);
-}
-
-static uint8_t capture_read_sscape(uint16_t port, void *p)
-{
- capture_event(p, LEGACY_EVENT_SSCAPE, 0, port);
- return 0xff;
-}
-static uint8_t capture_read_codec(uint16_t port, void *p)
-{
- capture_event(p, LEGACY_EVENT_CODEC, 0, port);
- return 0xff;
-}
-static uint8_t capture_read_sb(uint16_t port, void *p)
-{
- capture_event(p, LEGACY_EVENT_SB, 0, port);
- return 0xff;
-}
-static uint8_t capture_read_adlib(uint16_t port, void *p)
-{
- capture_event(p, LEGACY_EVENT_ADLIB, 0, port);
- return 0xff;
-}
-static uint8_t capture_read_master_pic(uint16_t port, void *p)
-{
- capture_event(p, LEGACY_EVENT_MASTER_PIC, 0, port);
- return 0xff;
-}
-static uint8_t capture_read_master_dma(uint16_t port, void *p)
-{
- capture_event(p, LEGACY_EVENT_MASTER_DMA, 0, port);
- return 0xff;
-}
-static uint8_t capture_read_slave_pic(uint16_t port, void *p)
-{
- capture_event(p, LEGACY_EVENT_SLAVE_PIC, 0, port);
- return 0xff;
-}
-static uint8_t capture_read_slave_dma(uint16_t port, void *p)
-{
- capture_event(p, LEGACY_EVENT_SLAVE_DMA, 0, port);
- return 0xff;
-}
-
-static void update_legacy(es1371_t *es1371, uint32_t old_legacy_ctrl)
-{
- if (old_legacy_ctrl & LEGACY_CAPTURE_SSCAPE)
- {
- switch ((old_legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3)
- {
- case 0: io_removehandler(0x0320, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
- case 1: io_removehandler(0x0330, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
- case 2: io_removehandler(0x0340, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
- case 3: io_removehandler(0x0350, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
- }
- }
- if (old_legacy_ctrl & LEGACY_CAPTURE_CODEC)
- {
- switch ((old_legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3)
- {
- case 0: io_removehandler(0x5300, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break;
- case 2: io_removehandler(0xe800, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break;
- case 3: io_removehandler(0xf400, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break;
- }
- }
- if (old_legacy_ctrl & LEGACY_CAPTURE_SB)
- {
- if (!(old_legacy_ctrl & LEGACY_SB_ADDR))
- io_removehandler(0x0220, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371);
- else
- io_removehandler(0x0240, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371);
- }
- if (old_legacy_ctrl & LEGACY_CAPTURE_ADLIB)
- io_removehandler(0x0388, 0x0004, capture_read_adlib,NULL,NULL, capture_write_adlib,NULL,NULL, es1371);
- if (old_legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC)
- io_removehandler(0x0020, 0x0002, capture_read_master_pic,NULL,NULL, capture_write_master_pic,NULL,NULL, es1371);
- if (old_legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA)
- io_removehandler(0x0000, 0x0010, capture_read_master_dma,NULL,NULL, capture_write_master_dma,NULL,NULL, es1371);
- if (old_legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC)
- io_removehandler(0x00a0, 0x0002, capture_read_slave_pic,NULL,NULL, capture_write_slave_pic,NULL,NULL, es1371);
- if (old_legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA)
- io_removehandler(0x00c0, 0x0020, capture_read_slave_dma,NULL,NULL, capture_write_slave_dma,NULL,NULL, es1371);
-
- if (es1371->legacy_ctrl & LEGACY_CAPTURE_SSCAPE)
- {
- switch ((es1371->legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3)
- {
- case 0: io_sethandler(0x0320, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
- case 1: io_sethandler(0x0330, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
- case 2: io_sethandler(0x0340, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
- case 3: io_sethandler(0x0350, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
- }
- }
- if (es1371->legacy_ctrl & LEGACY_CAPTURE_CODEC)
- {
- switch ((es1371->legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3)
- {
- case 0: io_sethandler(0x5300, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break;
- case 2: io_sethandler(0xe800, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break;
- case 3: io_sethandler(0xf400, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break;
- }
- }
- if (es1371->legacy_ctrl & LEGACY_CAPTURE_SB)
- {
- if (!(es1371->legacy_ctrl & LEGACY_SB_ADDR))
- io_sethandler(0x0220, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371);
- else
- io_sethandler(0x0240, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371);
- }
- if (es1371->legacy_ctrl & LEGACY_CAPTURE_ADLIB)
- io_sethandler(0x0388, 0x0004, capture_read_adlib,NULL,NULL, capture_write_adlib,NULL,NULL, es1371);
- if (es1371->legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC)
- io_sethandler(0x0020, 0x0002, capture_read_master_pic,NULL,NULL, capture_write_master_pic,NULL,NULL, es1371);
- if (es1371->legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA)
- io_sethandler(0x0000, 0x0010, capture_read_master_dma,NULL,NULL, capture_write_master_dma,NULL,NULL, es1371);
- if (es1371->legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC)
- io_sethandler(0x00a0, 0x0002, capture_read_slave_pic,NULL,NULL, capture_write_slave_pic,NULL,NULL, es1371);
- if (es1371->legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA)
- io_sethandler(0x00c0, 0x0020, capture_read_slave_dma,NULL,NULL, capture_write_slave_dma,NULL,NULL, es1371);
-}
-
-
-static uint8_t es1371_pci_read(int func, int addr, void *p)
-{
- es1371_t *es1371 = (es1371_t *)p;
-
- if (func)
- return 0;
-
- //audiopci_log("ES1371 PCI read %08X PC=%08x\n", addr, cpu_state.pc);
-
- if (addr > 0x3f)
- return 0x00;
-
- switch (addr)
- {
- case 0x00: return 0x74; /*Ensoniq*/
- case 0x01: return 0x12;
-
- case 0x02: return 0x71; /* ES1371 */
- case 0x03: return 0x13;
-
- case 0x04: return es1371->pci_command;
- case 0x05: return es1371->pci_serr;
-
- case 0x06: return 0x10; /* Supports ACPI */
- case 0x07: return 0x00;
-
- case 0x08: return 0x02; /* Revision ID */
- case 0x09: return 0x00; /* Multimedia audio device */
- case 0x0a: return 0x01;
- case 0x0b: return 0x04;
-
- case 0x10: return 0x01 | (es1371->base_addr & 0xc0); /* memBaseAddr */
- case 0x11: return es1371->base_addr >> 8;
- case 0x12: return es1371->base_addr >> 16;
- case 0x13: return es1371->base_addr >> 24;
-
- case 0x2c: return 0x74; /* Subsystem vendor ID */
- case 0x2d: return 0x12;
- case 0x2e: return 0x71;
- case 0x2f: return 0x13;
-
- case 0x34: return 0xdc; /*Capabilites pointer*/
-
- case 0x3c: return es1371->int_line;
- case 0x3d: return 0x01; /*INTA*/
-
- case 0x3e: return 0xc; /*Minimum grant*/
- case 0x3f: return 0x80; /*Maximum latency*/
-
- case 0xdc: return 0x01; /*Capabilities identifier*/
- case 0xdd: return 0x00; /*Next item pointer*/
- case 0xde: return 0x31; /*Power management capabilities*/
- case 0xdf: return 0x6c;
-
- case 0xe0: return es1371->pmcsr & 0xff;
- case 0xe1: return es1371->pmcsr >> 8;
+ if (old_legacy_ctrl & LEGACY_CAPTURE_CODEC) {
+ switch ((old_legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3) {
+ case 0:
+ io_removehandler(0x5300, 0x0080,
+ capture_read_codec, NULL, NULL,
+ capture_write_codec, NULL, NULL, dev);
+ break;
+ case 2:
+ io_removehandler(0xe800, 0x0080,
+ capture_read_codec, NULL, NULL,
+ capture_write_codec,NULL,NULL, dev);
+ break;
+ case 3:
+ io_removehandler(0xf400, 0x0080,
+ capture_read_codec, NULL, NULL,
+ capture_write_codec, NULL, NULL, dev);
+ break;
}
- return 0;
-}
+ }
-static void es1371_pci_write(int func, int addr, uint8_t val, void *p)
-{
- es1371_t *es1371 = (es1371_t *)p;
-
- if (func)
- return;
-
-// audiopci_log("ES1371 PCI write %04X %02X PC=%08x\n", addr, val, cpu_state.pc);
-
- switch (addr)
- {
- case 0x04:
- if (es1371->pci_command & PCI_COMMAND_IO)
- io_removehandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371);
- es1371->pci_command = val & 0x05;
- if (es1371->pci_command & PCI_COMMAND_IO)
- io_sethandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371);
- break;
- case 0x05:
- es1371->pci_serr = val & 1;
- break;
-
- case 0x10:
- if (es1371->pci_command & PCI_COMMAND_IO)
- io_removehandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371);
- es1371->base_addr = (es1371->base_addr & 0xffffff00) | (val & 0xc0);
- if (es1371->pci_command & PCI_COMMAND_IO)
- io_sethandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371);
- break;
- case 0x11:
- if (es1371->pci_command & PCI_COMMAND_IO)
- io_removehandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371);
- es1371->base_addr = (es1371->base_addr & 0xffff00c0) | (val << 8);
- if (es1371->pci_command & PCI_COMMAND_IO)
- io_sethandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371);
- break;
- case 0x12:
- es1371->base_addr = (es1371->base_addr & 0xff00ffc0) | (val << 16);
- break;
- case 0x13:
- es1371->base_addr = (es1371->base_addr & 0x00ffffc0) | (val << 24);
- break;
-
- case 0x3c:
- es1371->int_line = val;
- break;
-
- case 0xe0:
- es1371->pmcsr = (es1371->pmcsr & 0xff00) | (val & 0x03);
- break;
- case 0xe1:
- es1371->pmcsr = (es1371->pmcsr & 0x00ff) | ((val & 0x01) << 8);
- break;
+ if (old_legacy_ctrl & LEGACY_CAPTURE_SB) {
+ if (!(old_legacy_ctrl & LEGACY_SB_ADDR)) {
+ io_removehandler(0x0220, 0x0010,
+ capture_read_sb, NULL, NULL,
+ capture_write_sb, NULL, NULL, dev);
+ } else {
+ io_removehandler(0x0240, 0x0010,
+ capture_read_sb, NULL, NULL,
+ capture_write_sb, NULL, NULL, dev);
}
-// audiopci_log("es1371->base_addr %08x\n", es1371->base_addr);
+ }
+
+ if (old_legacy_ctrl & LEGACY_CAPTURE_ADLIB) {
+ io_removehandler(0x0388, 0x0004,
+ capture_read_adlib, NULL, NULL,
+ capture_write_adlib, NULL, NULL, dev);
+ }
+
+ if (old_legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC) {
+ io_removehandler(0x0020, 0x0002,
+ capture_read_master_pic, NULL, NULL,
+ capture_write_master_pic,NULL,NULL, dev);
+ }
+
+ if (old_legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA) {
+ io_removehandler(0x0000, 0x0010,
+ capture_read_master_dma, NULL, NULL,
+ capture_write_master_dma, NULL, NULL, dev);
+ }
+
+ if (old_legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC) {
+ io_removehandler(0x00a0, 0x0002,
+ capture_read_slave_pic, NULL, NULL,
+ capture_write_slave_pic, NULL, NULL, dev);
+ }
+
+ if (old_legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA) {
+ io_removehandler(0x00c0, 0x0020,
+ capture_read_slave_dma, NULL, NULL,
+ capture_write_slave_dma, NULL, NULL, dev);
+ }
+
+ if (dev->legacy_ctrl & LEGACY_CAPTURE_SSCAPE) {
+ switch ((dev->legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3) {
+ case 0:
+ io_sethandler(0x0320, 0x0008,
+ capture_read_sscape, NULL, NULL,
+ capture_write_sscape, NULL, NULL, dev);
+ break;
+ case 1:
+ io_sethandler(0x0330, 0x0008,
+ capture_read_sscape, NULL, NULL,
+ capture_write_sscape, NULL, NULL, dev);
+ break;
+ case 2:
+ io_sethandler(0x0340, 0x0008,
+ capture_read_sscape, NULL, NULL,
+ capture_write_sscape, NULL, NULL, dev);
+ break;
+ case 3:
+ io_sethandler(0x0350, 0x0008,
+ capture_read_sscape, NULL, NULL,
+ capture_write_sscape, NULL, NULL, dev);
+ break;
+ }
+ }
+
+ if (dev->legacy_ctrl & LEGACY_CAPTURE_CODEC) {
+ switch ((dev->legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3) {
+ case 0:
+ io_sethandler(0x5300, 0x0080,
+ capture_read_codec, NULL, NULL,
+ capture_write_codec, NULL, NULL, dev);
+ break;
+ case 2:
+ io_sethandler(0xe800, 0x0080,
+ capture_read_codec, NULL, NULL,
+ capture_write_codec, NULL, NULL, dev);
+ break;
+ case 3:
+ io_sethandler(0xf400, 0x0080,
+ capture_read_codec, NULL, NULL,
+ capture_write_codec, NULL, NULL, dev);
+ break;
+ }
+ }
+
+ if (dev->legacy_ctrl & LEGACY_CAPTURE_SB) {
+ if (!(dev->legacy_ctrl & LEGACY_SB_ADDR)) {
+ io_sethandler(0x0220, 0x0010,
+ capture_read_sb, NULL, NULL,
+ capture_write_sb, NULL, NULL, dev);
+ } else {
+ io_sethandler(0x0240, 0x0010,
+ capture_read_sb, NULL, NULL,
+ capture_write_sb, NULL, NULL, dev);
+ }
+ }
+
+ if (dev->legacy_ctrl & LEGACY_CAPTURE_ADLIB) {
+ io_sethandler(0x0388, 0x0004,
+ capture_read_adlib, NULL, NULL,
+ capture_write_adlib, NULL, NULL, dev);
+ }
+
+ if (dev->legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC) {
+ io_sethandler(0x0020, 0x0002,
+ capture_read_master_pic, NULL, NULL,
+ capture_write_master_pic, NULL, NULL, dev);
+ }
+
+ if (dev->legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA) {
+ io_sethandler(0x0000, 0x0010,
+ capture_read_master_dma, NULL, NULL,
+ capture_write_master_dma, NULL, NULL, dev);
+ }
+
+ if (dev->legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC) {
+ io_sethandler(0x00a0, 0x0002,
+ capture_read_slave_pic, NULL, NULL,
+ capture_write_slave_pic, NULL, NULL, dev);
+ }
+
+ if (dev->legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA) {
+ io_sethandler(0x00c0, 0x0020,
+ capture_read_slave_dma, NULL, NULL,
+ capture_write_slave_dma, NULL, NULL, dev);
+ }
}
-static void es1371_fetch(es1371_t *es1371, int dac_nr)
-{
- int format = dac_nr ? ((es1371->si_cr >> 2) & 3) : (es1371->si_cr & 3);
- int pos = es1371->dac[dac_nr].buffer_pos & 63;
- int c;
-//audiopci_log("Fetch format=%i %08x %08x %08x %08x %08x\n", format, es1371->dac[dac_nr].count, es1371->dac[dac_nr].size, es1371->dac[dac_nr].curr_samp_ct,es1371->dac[dac_nr].samp_ct, es1371->dac[dac_nr].addr);
- switch (format)
- {
- case FORMAT_MONO_8:
- for (c = 0; c < 32; c += 4)
- {
- es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr) ^ 0x80) << 8;
- es1371->dac[dac_nr].buffer_l[(pos+c+1) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+1) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr+1) ^ 0x80) << 8;
- es1371->dac[dac_nr].buffer_l[(pos+c+2) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+2) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr+2) ^ 0x80) << 8;
- es1371->dac[dac_nr].buffer_l[(pos+c+3) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+3) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr+3) ^ 0x80) << 8;
- es1371->dac[dac_nr].addr += 4;
-
- es1371->dac[dac_nr].buffer_pos_end += 4;
- es1371->dac[dac_nr].count++;
- if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size)
- {
- es1371->dac[dac_nr].count = 0;
- es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch;
+static uint8_t
+es1371_pci_read(int func, int addr, void *p)
+{
+ es1371_t *dev = (es1371_t *)p;
+
+ if (func > 0)
+ return 0xff;
+
+ if (addr > 0x3f)
+ return 0x00;
+
+ switch (addr) {
+ case 0x00: return 0x74; /* Ensoniq */
+ case 0x01: return 0x12;
+
+ case 0x02: return 0x71; /* ES1371 */
+ case 0x03: return 0x13;
+
+ case 0x04: return dev->pci_command;
+ case 0x05: return dev->pci_serr;
+
+ case 0x06: return 0x10; /* Supports ACPI */
+ case 0x07: return 0x00;
+
+ case 0x08: return 0x02; /* Revision ID */
+ case 0x09: return 0x00; /* Multimedia audio device */
+ case 0x0a: return 0x01;
+ case 0x0b: return 0x04;
+
+ case 0x10: return 0x01 | (dev->base_addr & 0xc0); /* memBaseAddr */
+ case 0x11: return dev->base_addr >> 8;
+ case 0x12: return dev->base_addr >> 16;
+ case 0x13: return dev->base_addr >> 24;
+
+ case 0x2c: return 0x74; /* Subsystem vendor ID */
+ case 0x2d: return 0x12;
+ case 0x2e: return 0x71;
+ case 0x2f: return 0x13;
+
+ case 0x34: return 0xdc; /* Capabilites pointer */
+
+ case 0x3c: return dev->int_line;
+ case 0x3d: return 0x01; /* INTA */
+
+ case 0x3e: return 0xc; /* Minimum grant */
+ case 0x3f: return 0x80; /* Maximum latency */
+
+ case 0xdc: return 0x01; /* Capabilities identifier */
+ case 0xdd: return 0x00; /* Next item pointer */
+ case 0xde: return 0x31; /* Power management capabilities */
+ case 0xdf: return 0x6c;
+
+ case 0xe0: return dev->pmcsr & 0xff;
+ case 0xe1: return dev->pmcsr >> 8;
+ }
+
+ return 0x00;
+}
+
+
+static void
+es1371_io_set(es1371_t *dev, int set)
+{
+ if (dev->pci_command & PCI_COMMAND_IO) {
+ io_handler(set, dev->base_addr, 0x0040,
+ es1371_inb, es1371_inw, es1371_inl,
+ es1371_outb, es1371_outw, es1371_outl, dev);
+ }
+}
+
+
+static void
+es1371_pci_write(int func, int addr, uint8_t val, void *p)
+{
+ es1371_t *dev = (es1371_t *)p;
+
+ if (func)
+ return;
+
+ switch (addr) {
+ case 0x04:
+ es1371_io_set(dev, 0);
+ dev->pci_command = val & 0x05;
+ es1371_io_set(dev, 1);
+ break;
+ case 0x05:
+ dev->pci_serr = val & 1;
+ break;
+
+ case 0x10:
+ es1371_io_set(dev, 0);
+ dev->base_addr = (dev->base_addr & 0xffffff00) | (val & 0xc0);
+ es1371_io_set(dev, 1);
+ break;
+ case 0x11:
+ es1371_io_set(dev, 0);
+ dev->base_addr = (dev->base_addr & 0xffff00c0) | (val << 8);
+ es1371_io_set(dev, 1);
+ break;
+ case 0x12:
+ dev->base_addr = (dev->base_addr & 0xff00ffc0) | (val << 16);
+ break;
+ case 0x13:
+ dev->base_addr = (dev->base_addr & 0x00ffffc0) | (val << 24);
+ break;
+
+ case 0x3c:
+ dev->int_line = val;
+ break;
+
+ case 0xe0:
+ dev->pmcsr = (dev->pmcsr & 0xff00) | (val & 0x03);
+ break;
+ case 0xe1:
+ dev->pmcsr = (dev->pmcsr & 0x00ff) | ((val & 0x01) << 8);
+ break;
+ }
+}
+
+
+static void
+es1371_fetch(es1371_t *dev, int dac_nr)
+{
+ int format = dac_nr ? ((dev->si_cr >> 2) & 3) : (dev->si_cr & 3);
+ int pos = dev->dac[dac_nr].buffer_pos & 63;
+ int c;
+
+ switch (format) {
+ case FORMAT_MONO_8:
+ for (c = 0; c < 32; c += 4) {
+ dev->dac[dac_nr].buffer_l[(pos+c) & 63] = dev->dac[dac_nr].buffer_r[(pos+c) & 63] =
+ (mem_readb_phys(dev->dac[dac_nr].addr) ^ 0x80) << 8;
+ dev->dac[dac_nr].buffer_l[(pos+c+1) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+1) & 63] =
+ (mem_readb_phys(dev->dac[dac_nr].addr+1) ^ 0x80) << 8;
+ dev->dac[dac_nr].buffer_l[(pos+c+2) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+2) & 63] =
+ (mem_readb_phys(dev->dac[dac_nr].addr+2) ^ 0x80) << 8;
+ dev->dac[dac_nr].buffer_l[(pos+c+3) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+3) & 63] =
+ (mem_readb_phys(dev->dac[dac_nr].addr+3) ^ 0x80) << 8;
+ dev->dac[dac_nr].addr += 4;
+
+ dev->dac[dac_nr].buffer_pos_end += 4;
+ dev->dac[dac_nr].count++;
+
+ if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) {
+ dev->dac[dac_nr].count = 0;
+ dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch;
break;
}
}
break;
- case FORMAT_STEREO_8:
- for (c = 0; c < 16; c += 2)
- {
- es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr) ^ 0x80) << 8;
- es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr + 1) ^ 0x80) << 8;
- es1371->dac[dac_nr].buffer_l[(pos+c+1) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr + 2) ^ 0x80) << 8;
- es1371->dac[dac_nr].buffer_r[(pos+c+1) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr + 3) ^ 0x80) << 8;
- es1371->dac[dac_nr].addr += 4;
-
- es1371->dac[dac_nr].buffer_pos_end += 2;
- es1371->dac[dac_nr].count++;
- if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size)
- {
- es1371->dac[dac_nr].count = 0;
- es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch;
+
+ case FORMAT_STEREO_8:
+ for (c = 0; c < 16; c += 2) {
+ dev->dac[dac_nr].buffer_l[(pos+c) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr) ^ 0x80) << 8;
+ dev->dac[dac_nr].buffer_r[(pos+c) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 1) ^ 0x80) << 8;
+ dev->dac[dac_nr].buffer_l[(pos+c+1) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 2) ^ 0x80) << 8;
+ dev->dac[dac_nr].buffer_r[(pos+c+1) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 3) ^ 0x80) << 8;
+ dev->dac[dac_nr].addr += 4;
+
+ dev->dac[dac_nr].buffer_pos_end += 2;
+ dev->dac[dac_nr].count++;
+
+ if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) {
+ dev->dac[dac_nr].count = 0;
+ dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch;
break;
}
}
break;
- case FORMAT_MONO_16:
- for (c = 0; c < 16; c += 2)
- {
- es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr);
- es1371->dac[dac_nr].buffer_l[(pos+c+1) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+1) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr + 2);
- es1371->dac[dac_nr].addr += 4;
- es1371->dac[dac_nr].buffer_pos_end += 2;
- es1371->dac[dac_nr].count++;
- if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size)
- {
- es1371->dac[dac_nr].count = 0;
- es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch;
+ case FORMAT_MONO_16:
+ for (c = 0; c < 16; c += 2) {
+ dev->dac[dac_nr].buffer_l[(pos+c) & 63] = dev->dac[dac_nr].buffer_r[(pos+c) & 63] =
+ mem_readw_phys(dev->dac[dac_nr].addr);
+ dev->dac[dac_nr].buffer_l[(pos+c+1) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+1) & 63] =
+ mem_readw_phys(dev->dac[dac_nr].addr + 2);
+ dev->dac[dac_nr].addr += 4;
+
+ dev->dac[dac_nr].buffer_pos_end += 2;
+ dev->dac[dac_nr].count++;
+
+ if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) {
+ dev->dac[dac_nr].count = 0;
+ dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch;
break;
}
}
break;
- case FORMAT_STEREO_16:
- for (c = 0; c < 4; c++)
- {
- es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr);
- es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr + 2);
-// audiopci_log("Fetch %02x %08x %04x %04x\n", (pos+c) & 63, es1371->dac[dac_nr].addr, es1371->dac[dac_nr].buffer_l[(pos+c) & 63], es1371->dac[dac_nr].buffer_r[(pos+c) & 63]);
- es1371->dac[dac_nr].addr += 4;
-
- es1371->dac[dac_nr].buffer_pos_end++;
- es1371->dac[dac_nr].count++;
- if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size)
- {
- es1371->dac[dac_nr].count = 0;
- es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch;
+
+ case FORMAT_STEREO_16:
+ for (c = 0; c < 4; c++) {
+ dev->dac[dac_nr].buffer_l[(pos+c) & 63] = mem_readw_phys(dev->dac[dac_nr].addr);
+ dev->dac[dac_nr].buffer_r[(pos+c) & 63] = mem_readw_phys(dev->dac[dac_nr].addr + 2);
+ dev->dac[dac_nr].addr += 4;
+
+ dev->dac[dac_nr].buffer_pos_end++;
+ dev->dac[dac_nr].count++;
+
+ if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) {
+ dev->dac[dac_nr].count = 0;
+ dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch;
break;
}
}
break;
- }
+ }
}
-static inline float low_fir_es1371(int dac_nr, int i, float NewSample)
+
+static inline float
+low_fir_es1371(int dac_nr, int i, float NewSample)
{
- static float x[2][2][128]; //input samples
- static int x_pos[2] = {0, 0};
- float out = 0.0;
- int read_pos;
- int n_coef;
- int pos = x_pos[dac_nr];
+ static float x[2][2][128]; //input samples
+ static int x_pos[2] = {0, 0};
+ float out = 0.0;
+ int read_pos, n_coef;
+ int pos = x_pos[dac_nr];
- x[dac_nr][i][pos] = NewSample;
+ x[dac_nr][i][pos] = NewSample;
- /*Since only 1/16th of input samples are non-zero, only filter those that
- are valid.*/
- read_pos = (pos + 15) & (127 & ~15);
- n_coef = (16 - pos) & 15;
+ /* Since only 1/16th of input samples are non-zero, only filter those that
+ are valid.*/
+ read_pos = (pos + 15) & (127 & ~15);
+ n_coef = (16 - pos) & 15;
- while (n_coef < ES1371_NCoef)
- {
- out += low_fir_es1371_coef[n_coef] * x[dac_nr][i][read_pos];
- read_pos = (read_pos + 16) & (127 & ~15);
- n_coef += 16;
+ while (n_coef < ES1371_NCoef) {
+ out += low_fir_es1371_coef[n_coef] * x[dac_nr][i][read_pos];
+ read_pos = (read_pos + 16) & (127 & ~15);
+ n_coef += 16;
+ }
+
+ if (i == 1) {
+ x_pos[dac_nr] = (x_pos[dac_nr] + 1) & 127;
+ if (x_pos[dac_nr] > 127)
+ x_pos[dac_nr] = 0;
+ }
+
+ return out;
+}
+
+
+static void
+es1371_next_sample_filtered(es1371_t *dev, int dac_nr, int out_idx)
+{
+ int out_l, out_r;
+ int c;
+
+ if ((dev->dac[dac_nr].buffer_pos - dev->dac[dac_nr].buffer_pos_end) >= 0)
+ es1371_fetch(dev, dac_nr);
+
+ out_l = dev->dac[dac_nr].buffer_l[dev->dac[dac_nr].buffer_pos & 63];
+ out_r = dev->dac[dac_nr].buffer_r[dev->dac[dac_nr].buffer_pos & 63];
+
+ dev->dac[dac_nr].filtered_l[out_idx] = (int)low_fir_es1371(dac_nr, 0, (float)out_l);
+ dev->dac[dac_nr].filtered_r[out_idx] = (int)low_fir_es1371(dac_nr, 1, (float)out_r);
+
+ for (c = 1; c < 16; c++) {
+ dev->dac[dac_nr].filtered_l[out_idx+c] = (int)low_fir_es1371(dac_nr, 0, 0);
+ dev->dac[dac_nr].filtered_r[out_idx+c] = (int)low_fir_es1371(dac_nr, 1, 0);
+ }
+
+ dev->dac[dac_nr].buffer_pos++;
+}
+
+
+static void
+es1371_update(es1371_t *dev)
+{
+ int32_t l, r;
+
+ l = (dev->dac[0].out_l * dev->dac[0].vol_l) >> 12;
+ l += ((dev->dac[1].out_l * dev->dac[1].vol_l) >> 12);
+ r = (dev->dac[0].out_r * dev->dac[0].vol_r) >> 12;
+ r += ((dev->dac[1].out_r * dev->dac[1].vol_r) >> 12);
+
+ l >>= 1;
+ r >>= 1;
+
+ l = (l * dev->master_vol_l) >> 15;
+ r = (r * dev->master_vol_r) >> 15;
+
+ if (l < -32768)
+ l = -32768;
+ else if (l > 32767)
+ l = 32767;
+ if (r < -32768)
+ r = -32768;
+ else if (r > 32767)
+ r = 32767;
+
+ for (; dev->pos < sound_pos_global; dev->pos++) {
+ dev->buffer[dev->pos*2] = l;
+ dev->buffer[dev->pos*2 + 1] = r;
+ }
+}
+
+
+static void
+es1371_poll(void *p)
+{
+ es1371_t *dev = (es1371_t *)p;
+ int frac, idx, samp1_l, samp1_r, samp2_l, samp2_r;
+
+ timer_advance_u64(&dev->dac[1].timer, dev->dac[1].latch);
+
+ es1371_update(dev);
+
+ if (dev->int_ctrl & INT_UART_EN) {
+ audiopci_log("UART INT Enabled\n");
+ if (dev->uart_ctrl & UART_CTRL_RXINTEN) {
+ /* We currently don't implement MIDI Input.
+ But if anything sets MIDI Input and Output together we'd have to take account
+ of the MIDI Output case, and disable IRQ's and RX bits when MIDI Input is
+ enabled as well but not in the MIDI Output portion */
+ if (dev->uart_ctrl & UART_CTRL_TXINTEN)
+ dev->int_status |= INT_STATUS_UART;
+ else
+ dev->int_status &= ~INT_STATUS_UART;
+ } else if (!(dev->uart_ctrl & UART_CTRL_RXINTEN) && ((dev->uart_ctrl & UART_CTRL_TXINTEN))) {
+ /* Or enable the UART IRQ and the respective TX bits only when the MIDI Output is
+ enabled */
+ dev->int_status |= INT_STATUS_UART;
}
- if (i == 1)
- {
- x_pos[dac_nr] = (x_pos[dac_nr] + 1) & 127;
- if (x_pos[dac_nr] > 127)
- x_pos[dac_nr] = 0;
- }
+ if (dev->uart_ctrl & UART_CTRL_RXINTEN) {
+ if (dev->uart_ctrl & UART_CTRL_TXINTEN)
+ dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
+ else
+ dev->uart_status &= ~(UART_STATUS_TXINT | UART_STATUS_TXRDY);
+ } else
+ dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
- return out;
-}
+ es1371_update_irqs(dev);
+ }
-static void es1371_next_sample_filtered(es1371_t *es1371, int dac_nr, int out_idx)
-{
- int out_l, out_r;
- int c;
-
- if ((es1371->dac[dac_nr].buffer_pos - es1371->dac[dac_nr].buffer_pos_end) >= 0)
- {
- es1371_fetch(es1371, dac_nr);
- }
+ if (dev->int_ctrl & INT_DAC1_EN) {
+ frac = dev->dac[0].ac & 0x7fff;
+ idx = dev->dac[0].ac >> 15;
+ samp1_l = dev->dac[0].filtered_l[idx];
+ samp1_r = dev->dac[0].filtered_r[idx];
+ samp2_l = dev->dac[0].filtered_l[(idx + 1) & 31];
+ samp2_r = dev->dac[0].filtered_r[(idx + 1) & 31];
- out_l = es1371->dac[dac_nr].buffer_l[es1371->dac[dac_nr].buffer_pos & 63];
- out_r = es1371->dac[dac_nr].buffer_r[es1371->dac[dac_nr].buffer_pos & 63];
-
- es1371->dac[dac_nr].filtered_l[out_idx] = (int)low_fir_es1371(dac_nr, 0, (float)out_l);
- es1371->dac[dac_nr].filtered_r[out_idx] = (int)low_fir_es1371(dac_nr, 1, (float)out_r);
- for (c = 1; c < 16; c++)
- {
- es1371->dac[dac_nr].filtered_l[out_idx+c] = (int)low_fir_es1371(dac_nr, 0, 0);
- es1371->dac[dac_nr].filtered_r[out_idx+c] = (int)low_fir_es1371(dac_nr, 1, 0);
- }
-
-// audiopci_log("Use %02x %04x %04x\n", es1371->dac[dac_nr].buffer_pos & 63, es1371->dac[dac_nr].out_l, es1371->dac[dac_nr].out_r);
-
- es1371->dac[dac_nr].buffer_pos++;
-// audiopci_log("Next sample %08x %08x %08x\n", es1371->dac[dac_nr].buffer_pos, es1371->dac[dac_nr].buffer_pos_end, es1371->dac[dac_nr].curr_samp_ct);
-}
+ dev->dac[0].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15;
+ dev->dac[0].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15;
+ dev->dac[0].ac += dev->dac[0].vf;
+ dev->dac[0].ac &= ((32 << 15) - 1);
+ if ((dev->dac[0].ac >> (15+4)) != dev->dac[0].f_pos) {
+ es1371_next_sample_filtered(dev, 0, dev->dac[0].f_pos ? 16 : 0);
+ dev->dac[0].f_pos = (dev->dac[0].f_pos + 1) & 1;
-//static FILE *es1371_f;//,*es1371_f2;
-
-static void es1371_update(es1371_t *es1371)
-{
- int32_t l, r;
-
- l = (es1371->dac[0].out_l * es1371->dac[0].vol_l) >> 12;
- l += ((es1371->dac[1].out_l * es1371->dac[1].vol_l) >> 12);
- r = (es1371->dac[0].out_r * es1371->dac[0].vol_r) >> 12;
- r += ((es1371->dac[1].out_r * es1371->dac[1].vol_r) >> 12);
-
- l >>= 1;
- r >>= 1;
-
- l = (l * es1371->master_vol_l) >> 15;
- r = (r * es1371->master_vol_r) >> 15;
-
- if (l < -32768)
- l = -32768;
- else if (l > 32767)
- l = 32767;
- if (r < -32768)
- r = -32768;
- else if (r > 32767)
- r = 32767;
-
- for (; es1371->pos < sound_pos_global; es1371->pos++)
- {
- es1371->buffer[es1371->pos*2] = l;
- es1371->buffer[es1371->pos*2 + 1] = r;
- }
-}
-
-static void es1371_poll(void *p)
-{
- es1371_t *es1371 = (es1371_t *)p;
-
- timer_advance_u64(&es1371->dac[1].timer, es1371->dac[1].latch);
-
- es1371_update(es1371);
-
- if (es1371->int_ctrl & INT_UART_EN) {
- audiopci_log("UART INT Enabled\n");
- if (es1371->uart_ctrl & UART_CTRL_RXINTEN) { /*We currently don't implement MIDI Input.*/
- /*But if anything sets MIDI Input and Output together we'd have to take account
- of the MIDI Output case, and disable IRQ's and RX bits when MIDI Input is enabled as well but not in the MIDI Output portion*/
- if (es1371->uart_ctrl & UART_CTRL_TXINTEN)
- es1371->int_status |= INT_STATUS_UART;
- else
- es1371->int_status &= ~INT_STATUS_UART;
- } else if (!(es1371->uart_ctrl & UART_CTRL_RXINTEN) && ((es1371->uart_ctrl & UART_CTRL_TXINTEN))) { /*Or enable the UART IRQ and the respective TX bits only when the MIDI Output is enabled*/
- es1371->int_status |= INT_STATUS_UART;
- }
-
- if (es1371->uart_ctrl & UART_CTRL_RXINTEN) {
- if (es1371->uart_ctrl & UART_CTRL_TXINTEN)
- es1371->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
- else
- es1371->uart_status &= ~(UART_STATUS_TXINT | UART_STATUS_TXRDY);
- } else
- es1371->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
-
- es1371_update_irqs(es1371);
- }
-
- if (es1371->int_ctrl & INT_DAC1_EN) {
- int frac = es1371->dac[0].ac & 0x7fff;
- int idx = es1371->dac[0].ac >> 15;
- int samp1_l = es1371->dac[0].filtered_l[idx];
- int samp1_r = es1371->dac[0].filtered_r[idx];
- int samp2_l = es1371->dac[0].filtered_l[(idx + 1) & 31];
- int samp2_r = es1371->dac[0].filtered_r[(idx + 1) & 31];
-
- es1371->dac[0].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15;
- es1371->dac[0].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15;
- es1371->dac[0].ac += es1371->dac[0].vf;
- es1371->dac[0].ac &= ((32 << 15) - 1);
- if ((es1371->dac[0].ac >> (15+4)) != es1371->dac[0].f_pos)
- {
- es1371_next_sample_filtered(es1371, 0, es1371->dac[0].f_pos ? 16 : 0);
- es1371->dac[0].f_pos = (es1371->dac[0].f_pos + 1) & 1;
-
- es1371->dac[0].curr_samp_ct--;
- if (es1371->dac[0].curr_samp_ct < 0)
- {
- es1371->int_status |= INT_STATUS_DAC1;
- es1371_update_irqs(es1371);
- es1371->dac[0].curr_samp_ct = es1371->dac[0].samp_ct;
- }
+ dev->dac[0].curr_samp_ct--;
+ if (dev->dac[0].curr_samp_ct < 0) {
+ dev->int_status |= INT_STATUS_DAC1;
+ es1371_update_irqs(dev);
+ dev->dac[0].curr_samp_ct = dev->dac[0].samp_ct;
}
}
+ }
- if (es1371->int_ctrl & INT_DAC2_EN)
- {
- int frac = es1371->dac[1].ac & 0x7fff;
- int idx = es1371->dac[1].ac >> 15;
- int samp1_l = es1371->dac[1].filtered_l[idx];
- int samp1_r = es1371->dac[1].filtered_r[idx];
- int samp2_l = es1371->dac[1].filtered_l[(idx + 1) & 31];
- int samp2_r = es1371->dac[1].filtered_r[(idx + 1) & 31];
-
- es1371->dac[1].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15;
- es1371->dac[1].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15;
- es1371->dac[1].ac += es1371->dac[1].vf;
- es1371->dac[1].ac &= ((32 << 15) - 1);
- if ((es1371->dac[1].ac >> (15+4)) != es1371->dac[1].f_pos)
- {
- es1371_next_sample_filtered(es1371, 1, es1371->dac[1].f_pos ? 16 : 0);
- es1371->dac[1].f_pos = (es1371->dac[1].f_pos + 1) & 1;
+ if (dev->int_ctrl & INT_DAC2_EN) {
+ frac = dev->dac[1].ac & 0x7fff;
+ idx = dev->dac[1].ac >> 15;
+ samp1_l = dev->dac[1].filtered_l[idx];
+ samp1_r = dev->dac[1].filtered_r[idx];
+ samp2_l = dev->dac[1].filtered_l[(idx + 1) & 31];
+ samp2_r = dev->dac[1].filtered_r[(idx + 1) & 31];
- es1371->dac[1].curr_samp_ct--;
- if (es1371->dac[1].curr_samp_ct < 0)
- {
- es1371->int_status |= INT_STATUS_DAC2;
- es1371_update_irqs(es1371);
- es1371->dac[1].curr_samp_ct = es1371->dac[1].samp_ct;
- }
+ dev->dac[1].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15;
+ dev->dac[1].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15;
+ dev->dac[1].ac += dev->dac[1].vf;
+ dev->dac[1].ac &= ((32 << 15) - 1);
+ if ((dev->dac[1].ac >> (15+4)) != dev->dac[1].f_pos) {
+ es1371_next_sample_filtered(dev, 1, dev->dac[1].f_pos ? 16 : 0);
+ dev->dac[1].f_pos = (dev->dac[1].f_pos + 1) & 1;
+
+ dev->dac[1].curr_samp_ct--;
+ if (dev->dac[1].curr_samp_ct < 0) {
+ dev->int_status |= INT_STATUS_DAC2;
+ es1371_update_irqs(dev);
+ dev->dac[1].curr_samp_ct = dev->dac[1].samp_ct;
}
}
+ }
}
-static void es1371_get_buffer(int32_t *buffer, int len, void *p)
+
+static void
+es1371_get_buffer(int32_t *buffer, int len, void *p)
{
- es1371_t *es1371 = (es1371_t *)p;
- int c;
+ es1371_t *dev = (es1371_t *)p;
+ int c;
- es1371_update(es1371);
+ es1371_update(dev);
- for (c = 0; c < len * 2; c++)
- buffer[c] += (es1371->buffer[c] / 2);
-
- es1371->pos = 0;
+ for (c = 0; c < len * 2; c++)
+ buffer[c] += (dev->buffer[c] / 2);
+
+ dev->pos = 0;
}
-static void es1371_filter_cd_audio(int channel, double *buffer, void *p)
+
+static void
+es1371_filter_cd_audio(int channel, double *buffer, void *p)
{
- es1371_t *es1371 = (es1371_t *)p;
- int32_t c;
- int cd = channel ? es1371->cd_vol_r : es1371->cd_vol_l;
- int master = channel ? es1371->master_vol_r : es1371->master_vol_l;
+ es1371_t *dev = (es1371_t *)p;
+ int32_t c;
+ int cd = channel ? dev->cd_vol_r : dev->cd_vol_l;
+ int master = channel ? dev->master_vol_r : dev->master_vol_l;
- c = (((int32_t) *buffer) * cd) >> 15;
- c = (c * master) >> 15;
+ c = (((int32_t) *buffer) * cd) >> 15;
+ c = (c * master) >> 15;
- *buffer = (double) c;
+ *buffer = (double) c;
}
-static inline double sinc(double x)
+
+static inline
+double sinc(double x)
{
- return sin(M_PI * x) / (M_PI * x);
+ return sin(M_PI * x) / (M_PI * x);
}
-static void generate_es1371_filter()
+
+static void
+generate_es1371_filter(void)
{
- /*Cutoff frequency = 1 / 32*/
- float fC = 1.0 / 32.0;
- float gain;
- int n;
-
- for (n = 0; n < ES1371_NCoef; n++)
- {
- /*Blackman window*/
- double w = 0.42 - (0.5 * cos((2.0*n*M_PI)/(double)(ES1371_NCoef-1))) + (0.08 * cos((4.0*n*M_PI)/(double)(ES1371_NCoef-1)));
- /*Sinc filter*/
- double h = sinc(2.0 * fC * ((double)n - ((double)(ES1371_NCoef-1) / 2.0)));
-
- /*Create windowed-sinc filter*/
- low_fir_es1371_coef[n] = w * h;
- }
-
- low_fir_es1371_coef[(ES1371_NCoef - 1) / 2] = 1.0;
+ /* Cutoff frequency = 1 / 32 */
+ float fC = 1.0 / 32.0;
+ float gain;
+ int n;
- gain = 0.0;
- for (n = 0; n < ES1371_NCoef; n++)
- gain += low_fir_es1371_coef[n] / (float)N;
+ for (n = 0; n < ES1371_NCoef; n++) {
+ /* Blackman window */
+ double w = 0.42 - (0.5 * cos((2.0*n*M_PI)/(double)(ES1371_NCoef-1))) + (0.08 * cos((4.0*n*M_PI)/(double)(ES1371_NCoef-1)));
+ /* Sinc filter */
+ double h = sinc(2.0 * fC * ((double)n - ((double)(ES1371_NCoef-1) / 2.0)));
- gain /= 0.95;
+ /* Create windowed-sinc filter */
+ low_fir_es1371_coef[n] = w * h;
+ }
- /*Normalise filter, to produce unity gain*/
- for (n = 0; n < ES1371_NCoef; n++)
- low_fir_es1371_coef[n] /= gain;
-}
+ low_fir_es1371_coef[(ES1371_NCoef - 1) / 2] = 1.0;
-static void *es1371_init(const device_t *info)
-{
- es1371_t *es1371 = malloc(sizeof(es1371_t));
- memset(es1371, 0, sizeof(es1371_t));
-
- sound_add_handler(es1371_get_buffer, es1371);
- sound_set_cd_audio_filter(es1371_filter_cd_audio, es1371);
+ gain = 0.0;
+ for (n = 0; n < ES1371_NCoef; n++)
+ gain += low_fir_es1371_coef[n] / (float)N;
- /* Add our own always-present game port to override the standalone ISAPnP one. */
- gameport_remap(gameport_add(&gameport_pnp_device), 0x200);
+ gain /= 0.95;
- es1371->card = pci_add_card(info->local ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, es1371);
-
- timer_add(&es1371->dac[1].timer, es1371_poll, es1371, 1);
-
- generate_es1371_filter();
-
- ac97_codec = &es1371->codec;
- ac97_codec_count = 1;
- ac97_codec_id = 0;
- if (!info->local) /* let the machine decide the codec on onboard implementations */
- device_add(&cs4297a_device);
-
- return es1371;
+ /* Normalise filter, to produce unity gain */
+ for (n = 0; n < ES1371_NCoef; n++)
+ low_fir_es1371_coef[n] /= gain;
}
-static void es1371_close(void *p)
+
+static void *
+es1371_init(const device_t *info)
{
- es1371_t *es1371 = (es1371_t *)p;
-
- free(es1371);
+ es1371_t *dev = malloc(sizeof(es1371_t));
+ memset(dev, 0x00, sizeof(es1371_t));
+
+ sound_add_handler(es1371_get_buffer, dev);
+ sound_set_cd_audio_filter(es1371_filter_cd_audio, dev);
+
+ /* Add our own always-present game port to override the standalone ISAPnP one. */
+ gameport_remap(gameport_add(&gameport_pnp_device), 0x200);
+
+ dev->card = pci_add_card(info->local ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, dev);
+
+ timer_add(&dev->dac[1].timer, es1371_poll, dev, 1);
+
+ generate_es1371_filter();
+
+ ac97_codec = &dev->codec;
+ ac97_codec_count = 1;
+ ac97_codec_id = 0;
+ /* Let the machine decide the codec on onboard implementations. */
+ if (!info->local)
+ device_add(&cs4297a_device);
+
+ es1371_reset(dev);
+
+ return dev;
}
-static void es1371_speed_changed(void *p)
+
+static void
+es1371_close(void *p)
{
- es1371_t *es1371 = (es1371_t *)p;
-
- es1371->dac[1].latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / 48000.0));
+ es1371_t *dev = (es1371_t *) p;
+
+ free(dev);
}
-
-void es1371_add_status_info_dac(es1371_t *es1371, char *s, int max_len, int dac_nr)
+
+
+static void
+es1371_speed_changed(void *p)
{
- int ena = dac_nr ? INT_DAC2_EN : INT_DAC1_EN;
- char *dac_name = dac_nr ? "DAC2 (Wave)" : "DAC1 (MIDI)";
- char temps[128];
+ es1371_t *dev = (es1371_t *)p;
- if (es1371->int_ctrl & ena)
- {
- int format = dac_nr ? ((es1371->si_cr >> 2) & 3) : (es1371->si_cr & 3);
- double freq = 48000.0 * ((double)es1371->dac[dac_nr].vf / (32768.0 * 16.0));
-
- switch (format)
- {
- case FORMAT_MONO_8:
- snprintf(temps, 128, "%s format : 8-bit mono\n", dac_name);
- break;
- case FORMAT_STEREO_8:
- snprintf(temps, 128, "%s format : 8-bit stereo\n", dac_name);
- break;
- case FORMAT_MONO_16:
- snprintf(temps, 128, "%s format : 16-bit mono\n", dac_name);
- break;
- case FORMAT_STEREO_16:
- snprintf(temps, 128, "%s format : 16-bit stereo\n", dac_name);
- break;
- }
-
- strncat(s, temps, max_len);
- max_len -= strlen(temps);
-
- snprintf(temps, 128, "Playback frequency : %i Hz\n", (int)freq);
- strncat(s, temps, max_len);
- }
- else
- {
- snprintf(temps, max_len, "%s stopped\n", dac_name);
- strncat(s, temps, max_len);
- }
+ dev->dac[1].latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / 48000.0));
}
+
const device_t es1371_device =
{
"Ensoniq AudioPCI (ES1371)",
@@ -1417,7 +1913,7 @@ const device_t es1371_onboard_device =
1,
es1371_init,
es1371_close,
- NULL,
+ es1371_reset,
{ NULL },
es1371_speed_changed,
NULL,
diff --git a/src/unix/unix.c b/src/unix/unix.c
index 0121d451f..4ce8d5e17 100644
--- a/src/unix/unix.c
+++ b/src/unix/unix.c
@@ -759,7 +759,7 @@ void monitor_thread(void* param)
{
exit_event = 1;
}
- else if (strncasecmp(xargv[0], "fullscreen", 1) == 0)
+ else if (strncasecmp(xargv[0], "fullscreen", 10) == 0)
{
video_fullscreen = 1;
fullscreen_pending = 1;
diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c
index 5e9a65491..c5e94194b 100644
--- a/src/video/vid_s3.c
+++ b/src/video/vid_s3.c
@@ -41,9 +41,11 @@
#define ROM_DIAMOND_STEALTH_VRAM "roms/video/s3/Diamond Stealth VRAM BIOS v2.31 U14.BIN"
#define ROM_AMI_86C924 "roms/video/s3/S3924AMI.BIN"
#define ROM_METHEUS_86C928 "roms/video/s3/928.vbi"
-#define ROM_SPEA_MIRAGE_86C801_V305I "roms/video/s3/V7MIRAGE.VBI"
-#define ROM_SPEA_MIRAGE_86C801_V401 "roms/video/s3/S3_805VL_ATT20C491_SPEAmirage_VL_4.01.BIN"
+#define ROM_SPEA_MIRAGE_86C801 "roms/video/s3/V7MIRAGE.VBI"
+#define ROM_SPEA_MIRAGE_86C805 "roms/video/s3/86c805pspeavlbus.BIN"
#define ROM_MIROCRYSTAL10SD_805 "roms/video/s3/MIROcrystal10SD_VLB.VBI"
+#define ROM_MIROCRYSTAL20SV_964_VLB "roms/video/s3/S3_964VL_BT485_27C256_miroCRYSTAL_20sv_ver1.2.bin"
+#define ROM_MIROCRYSTAL20SV_964_PCI "roms/video/s3/mirocrystal.VBI"
#define ROM_PHOENIX_86C80X "roms/video/s3/805.vbi"
#define ROM_PARADISE_BAHAMAS64 "roms/video/s3/bahamas64.bin"
#define ROM_PHOENIX_VISION864 "roms/video/s3/86c864p.bin"
@@ -90,7 +92,8 @@ enum
S3_MIROVIDEO40SV_968,
S3_MIROCRYSTAL10SD_805,
S3_SPEA_MIRAGE_P64,
- S3_SPEA_MERCURY_P64V
+ S3_SPEA_MERCURY_P64V,
+ S3_MIROCRYSTAL20SV_964
};
@@ -232,7 +235,7 @@ typedef struct s3_t
int cx, cy;
int px, py;
- int sx, sy, sx_backup;
+ int sx, sy;
int dx, dy;
uint32_t src, dest, pattern;
@@ -411,31 +414,17 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3);
#define READ_PIXTRANS_BYTE_IO(n) \
- if (s3->bpp == 0) \
- s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & s3->vram_mask]; \
- else if (s3->bpp == 1) \
- s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & (s3->vram_mask >> 1)]; \
- else \
- s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & (s3->vram_mask >> 2)];
+ s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & s3->vram_mask]; \
#define READ_PIXTRANS_BYTE_MM \
- if (s3->bpp == 0) \
- temp = svga->vram[(s3->accel.dest + s3->accel.cx) & s3->vram_mask]; \
- else if (s3->bpp == 1) \
- temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \
- else \
- temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 2)];
+ temp = svga->vram[(s3->accel.dest + s3->accel.cx) & s3->vram_mask]; \
#define READ_PIXTRANS_WORD \
if (s3->bpp == 0) { \
temp = svga->vram[(s3->accel.dest + s3->accel.cx) & s3->vram_mask]; \
temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & s3->vram_mask] << 8); \
- } else if (s3->bpp == 1) { \
- temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \
- temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 1)] << 8); \
- } else { \
- temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 2)]; \
- temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 2)] << 8); \
+ } else { \
+ temp = vram_w[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \
}
#define READ_PIXTRANS_LONG \
@@ -444,16 +433,9 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3);
temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & s3->vram_mask] << 8); \
temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 2) & s3->vram_mask] << 16); \
temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 3) & s3->vram_mask] << 24); \
- } else if (s3->bpp == 1) { \
- temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \
- temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 1)] << 8); \
- temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 2) & (s3->vram_mask >> 1)] << 16); \
- temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 3) & (s3->vram_mask >> 1)] << 24); \
- } else { \
- temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 2)]; \
- temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 2)] << 8); \
- temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 2) & (s3->vram_mask >> 2)] << 16); \
- temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 3) & (s3->vram_mask >> 2)] << 24); \
+ } else { \
+ temp = vram_w[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \
+ temp |= (vram_w[(s3->accel.dest + s3->accel.cx + 2) & (s3->vram_mask >> 1)] << 16); \
}
static int
@@ -486,32 +468,6 @@ s3_cpu_dest(s3_t *s3)
return 1;
}
-static int
-s3_accel_count(s3_t *s3)
-{
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x200) && (s3->accel.cmd & 0x100) && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
- return 8;
- else if (!(s3->accel.cmd & 0x200) && (s3->accel.cmd & 0x100))
- return 1;
- else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 0x600) == 0x200) && (s3->accel.cmd & 0x100) && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
- return 16;
- else if (((s3->accel.cmd & 0x200) == 0x200) && (s3->accel.cmd & 0x100))
- return 2;
- else
- return -1;
-}
-
-
-static int
-s3_data_len(s3_t *s3)
-{
- if (!(s3->accel.cmd & 0x200))
- return 1;
-
- return 2;
-}
-
-
static int
s3_enable_fifo(s3_t *s3)
{
@@ -531,27 +487,41 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
svga_t *svga = &s3->svga;
if (s3->accel.cmd & 0x100) {
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- if (s3->accel.cmd & 0x1000)
- val = (val >> 8) | (val << 8);
- if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V)) {
- s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
- s3_accel_start(8, 1, val & 0xff, 0, s3);
- } else if ((s3->accel.cmd & 0x600) == 0x000) {
- s3_accel_start(8, 1, val | (val << 16), 0, s3);
- } else if ((s3->accel.cmd & 0x400) && (svga->crtc[0x53] & 0x08))
- s3_accel_start(32, 1, val | (val << 16), 0, s3);
- else {
- s3_accel_start(16, 1, val | (val << 16), 0, s3);
- }
- } else {
- if ((s3->accel.cmd & 0x600) == 0x000)
- s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
- else if (s3->accel.cmd & 0x400)
- s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3);
- else {
- s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3);
- }
+ switch (s3->accel.cmd & 0x600) {
+ case 0x000:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
+ val = (val >> 8) | (val << 8);
+ s3_accel_start(8, 1, val | (val << 16), 0, s3);
+ } else
+ s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
+ break;
+ case 0x200:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
+ val = (val >> 8) | (val << 8);
+ s3_accel_start(16, 1, val | (val << 16), 0, s3);
+ } else
+ s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3);
+ break;
+ case 0x400:
+ if (svga->crtc[0x53] & 0x08) {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(32, 1, val | (val << 16), 0, s3);
+ } else
+ s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3);
+ }
+ break;
+ case 0x600:
+ if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
+ val = (val >> 8) | (val << 8);
+ s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
+ s3_accel_start(8, 1, val & 0xff, 0, s3);
+ }
+ }
+ break;
}
}
}
@@ -560,39 +530,49 @@ static void
s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val)
{
if (s3->accel.cmd & 0x100) {
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V)) {
- if (s3->accel.cmd & 0x1000)
- val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
- s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3);
- s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3);
- s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
- s3_accel_start(8, 1, val & 0xff, 0, s3);
- } else if (s3->accel.cmd & 0x400) {
- if (s3->accel.cmd & 0x1000)
- val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
- s3_accel_start(32, 1, val, 0, s3);
- } else if ((s3->accel.cmd & 0x600) == 0x200) {
- if (s3->accel.cmd & 0x1000)
- val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
- s3_accel_start(16, 1, val, 0, s3);
- s3_accel_start(16, 1, val >> 16, 0, s3);
- } else {
- if (s3->accel.cmd & 0x1000)
- val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
- s3_accel_start(8, 1, val, 0, s3);
- s3_accel_start(8, 1, val >> 16, 0, s3);
- }
- } else {
- if (s3->accel.cmd & 0x400) {
- s3_accel_start(4, 1, 0xffffffff, val, s3);
- } else if ((s3->accel.cmd & 0x600) == 0x200) {
- s3_accel_start(2, 1, 0xffffffff, val, s3);
- s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
- } else {
- s3_accel_start(1, 1, 0xffffffff, val, s3);
- s3_accel_start(1, 1, 0xffffffff, val >> 16, s3);
- }
+ switch (s3->accel.cmd & 0x600) {
+ case 0x000:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
+ val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
+ s3_accel_start(8, 1, val, 0, s3);
+ s3_accel_start(8, 1, val >> 16, 0, s3);
+ } else {
+ s3_accel_start(2, 1, 0xffffffff, val, s3);
+ s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
+ }
+ break;
+ case 0x200:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
+ val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
+ s3_accel_start(16, 1, val, 0, s3);
+ s3_accel_start(16, 1, val >> 16, 0, s3);
+ } else {
+ s3_accel_start(2, 1, 0xffffffff, val, s3);
+ s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
+ }
+ break;
+ case 0x400:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
+ val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
+ s3_accel_start(32, 1, val, 0, s3);
+ } else
+ s3_accel_start(4, 1, 0xffffffff, val, s3);
+ break;
+ case 0x600:
+ if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
+ val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
+ s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3);
+ s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3);
+ s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
+ s3_accel_start(8, 1, val & 0xff, 0, s3);
+ }
+ }
+ break;
}
}
}
@@ -1038,62 +1018,80 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
if (s3_cpu_dest(s3))
break;
s3->accel.pix_trans[0] = val;
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100) &&
- ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
- } else if (!(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100))
- s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
+ if (s3->accel.cmd & 0x100) {
+ if (!(s3->accel.cmd & 0x600)) {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
+ } else
+ s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
+ }
+ }
break;
case 0xe149: case 0xe2e9:
s3->accel.b2e8_pix = 0;
if (s3_cpu_dest(s3))
break;
s3->accel.pix_trans[1] = val;
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- if (s3->accel.cmd & 0x100) {
- switch (s3->accel.cmd & 0x600) {
- case 0x000:
+ if (s3->accel.cmd & 0x100) {
+ switch (s3->accel.cmd & 0x600) {
+ case 0x000:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
- break;
- case 0x200:
- if (s3->accel.cmd & 0x1000)
- s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3);
- else
- s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
- break;
- case 0x400:
- if (svga->crtc[0x53] & 0x08)
+ } else
+ s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
+ break;
+ case 0x200:
+ /*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9) in the 86c928*/
+ if (s3->accel.cmd & 0x1000) {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
+ s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3);
+ else {
+ if (s3->chip == S3_86C928)
+ s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
+ else
+ s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3);
+ }
+ } else {
+ if (s3->chip == S3_86C928)
+ s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
+ else
+ s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3);
+ }
+ } else {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
+ s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
+ else {
+ if (s3->chip == S3_86C928)
+ s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
+ else
+ s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
+ }
+ } else {
+ if (s3->chip == S3_86C928)
+ s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
+ else
+ s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
+ }
+ }
+ break;
+ case 0x400:
+ if (svga->crtc[0x53] & 0x08) {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
- break;
- case 0x600:
- if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) {
+ } else
+ s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
+ }
+ break;
+ case 0x600:
+ if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3);
s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
}
- break;
- }
- }
- } else {
- if (s3->accel.cmd & 0x100) {
- switch (s3->accel.cmd & 0x600) {
- case 0x000:
- s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
- break;
- case 0x200:
- if (s3->chip == S3_86C928) /*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9)*/
- s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
- else {
- if (s3->accel.cmd & 0x1000)
- s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3);
- else
- s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
- }
- break;
- case 0x400:
- if (svga->crtc[0x53] & 0x08)
- s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
- break;
- }
+ }
+ break;
}
}
break;
@@ -1106,51 +1104,66 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
if (s3_cpu_dest(s3))
break;
s3->accel.pix_trans[3] = val;
- if ((s3->accel.multifunc[0xa]& 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- if (s3->accel.cmd & 0x100) {
- switch (s3->accel.cmd & 0x600) {
- case 0x000:
+ if (s3->accel.cmd & 0x100) {
+ switch (s3->accel.cmd & 0x600) {
+ case 0x000:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
- break;
- case 0x200:
- if (s3->accel.cmd & 0x1000)
- s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3);
- else
- s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
- break;
- case 0x400:
+ } else
+ s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
+ break;
+ case 0x200:
+ /*Windows 95's built-in driver expects the upper 16 bits to be loaded instead of the whole 32-bit one, regardless of the byte swap bit (0xE2EB) in the 86c928*/
+ if (s3->accel.cmd & 0x1000) {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
+ s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3);
+ else {
+ if (s3->chip == S3_86C928)
+ s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8));
+ else
+ s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3);
+ }
+ } else {
+ if (s3->chip == S3_86C928)
+ s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
+ else
+ s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3);
+ }
+ } else {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
+ s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
+ else {
+ if (s3->chip == S3_86C928)
+ s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8));
+ else
+ s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
+ }
+ } else {
+ if (s3->chip == S3_86C928)
+ s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
+ else
+ s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
+ }
+ }
+ break;
+ case 0x400:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
- break;
- case 0x600:
- if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) {
+ } else
+ s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
+ break;
+ case 0x600:
+ if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3);
s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3);
s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3);
s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
}
- break;
- }
- }
- } else {
- if (s3->accel.cmd & 0x100) {
- switch (s3->accel.cmd & 0x600) {
- case 0x000:
- s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
- break;
- case 0x200:
- if (s3->chip == S3_86C928) /*Windows 95's built-in S3 928 driver expects the upper 16 bits to be loaded instead of the whole 32-bit one, regardless of the byte swap bit (0xE2EB)*/
- s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8));
- else {
- if (s3->accel.cmd & 0x1000)
- s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3);
- else
- s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
- }
- break;
- case 0x400:
- s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
- break;
- }
+ }
+ break;
}
}
break;
@@ -1171,7 +1184,7 @@ s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val)
static void
s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val)
-{
+{
s3_accel_out_pixtrans_l(s3, val);
}
@@ -1285,9 +1298,12 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val)
if (svga->crtc[0x53] & 0x08) {
if ((addr & 0x1ffff) < 0x8000) {
if (s3->accel.cmd & 0x100) {
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
- s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3);
- else
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
+ s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3);
+ else
+ s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3);
+ } else
s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3);
}
} else {
@@ -1332,10 +1348,16 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val)
s3_accel_out_fifo(s3, addr & 0xffff, val);
} else {
if (s3->accel.cmd & 0x100) {
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
- s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3);
- else {
- s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3);
+ if (!(s3->accel.cmd & 0x600)) {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(8, 1, val, 0, s3);
+ } else
+ s3_accel_start(1, 1, 0xffffffff, val, s3);
+ } else if ((s3->accel.cmd & 0x600) == 0x200) {
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(16, 1, val, 0, s3);
+ } else
+ s3_accel_start(2, 1, 0xffffffff, val, s3);
}
}
}
@@ -2580,7 +2602,7 @@ s3_in(uint16_t addr, void *p)
else if (s3->chip <= S3_86C924)
return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga);
else
- return sdac_ramdac_in(addr, rs2, svga->ramdac, svga);
+ return sdac_ramdac_in(addr, rs2, svga->ramdac, svga);
break;
case 0x3d4:
@@ -2688,11 +2710,11 @@ static void s3_recalctimings(svga_t *svga)
svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10));
- if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) {
- if (!(svga->crtc[0x14] & 0x40)) /*There are still accel issues with dword mode enabled, so
- disable dword mode for now.*/
- svga->crtc[0x14] |= 0x40;
-
+ if (((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) || (svga->crtc[0x3a] & 0x10)) {
+ if (svga->crtc[0x31] & 0x08) { /*If the dword mode bit is not enabled when the S3 dword mode is enabled, enable it*/
+ if (!(svga->crtc[0x14] & 0x40))
+ svga->crtc[0x14] |= 0x40;
+ }
switch (svga->bpp) {
case 8:
svga->render = svga_render_8bpp_highres;
@@ -2787,7 +2809,7 @@ static void s3_recalctimings(svga_t *svga)
}
if (s3->width == 1280 || s3->width == 1600 || (s3->card_type == S3_SPEA_MERCURY_P64V))
svga->hdisp *= 2;
- if (s3->card_type == S3_MIROVIDEO40SV_968)
+ if (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_MIROCRYSTAL20SV_964)
svga->hdisp = s3->width;
break;
}
@@ -2829,10 +2851,10 @@ static void s3_trio64v_recalctimings(svga_t *svga)
svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10));
if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) {
- if (!(svga->crtc[0x14] & 0x40)) /*There are still accel issues with dword mode enabled, so
- disable dword mode for now.*/
- svga->crtc[0x14] |= 0x40;
-
+ if (svga->crtc[0x31] & 0x08) {
+ if (!(svga->crtc[0x14] & 0x40))
+ svga->crtc[0x14] |= 0x40;
+ }
switch (svga->bpp) {
case 8:
svga->render = svga_render_8bpp_highres;
@@ -3121,6 +3143,7 @@ static uint8_t
s3_accel_in(uint16_t port, void *p)
{
s3_t *s3 = (s3_t *)p;
+ svga_t *svga = &s3->svga;
int temp;
if (!s3->enable_8514)
@@ -3452,118 +3475,77 @@ s3_accel_in(uint16_t port, void *p)
case 0xe148: case 0xe2e8:
if (!s3_cpu_dest(s3))
break;
- temp = s3->accel.pix_trans[0];
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- if (s3->accel.cmd & 0x100) {
- switch (s3->accel.cmd & 0x200) {
- case 0x000:
- s3_accel_start(8, 1, 0xffffffff, 0, s3);
- break;
- case 0x200:
- s3_accel_start(16, 1, 0xffffffff, 0, s3);
- break;
- }
- }
- } else {
- if (s3->accel.cmd & 0x100) {
- switch (s3->accel.cmd & 0x200) {
- case 0x000:
- s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3);
- break;
- case 0x200:
- s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3);
- break;
- }
+ READ_PIXTRANS_BYTE_IO(0)
+ if (s3->accel.cmd & 0x100) {
+ switch (s3->accel.cmd & 0x600) {
+ case 0x000:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
+ } else
+ s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
+ break;
+ case 0x200:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
+ s3_accel_start(16, 1, s3->accel.pix_trans[0], 0, s3);
+ else
+ s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
+ } else
+ s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
+ break;
}
}
- return temp;
+ return s3->accel.pix_trans[0];
case 0xe149: case 0xe2e9:
if (!s3_cpu_dest(s3))
break;
- temp = s3->accel.pix_trans[1];
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- if (s3->accel.cmd & 0x100) {
- switch (s3->accel.cmd & 0x200) {
- case 0x000:
- s3_accel_start(8, 1, 0xffffffff, 0, s3);
- break;
- case 0x200:
- s3_accel_start(16, 1, 0xffffffff, 0, s3);
- break;
- }
- }
- } else {
- if (s3->accel.cmd & 0x100) {
- switch (s3->accel.cmd & 0x200) {
- case 0x000:
- s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3);
- break;
- case 0x200:
- s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3);
- break;
- }
+ READ_PIXTRANS_BYTE_IO(1);
+ if (s3->accel.cmd & 0x100) {
+ switch (s3->accel.cmd & 0x600) {
+ case 0x000:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
+ } else
+ s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
+ break;
+ case 0x200:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
+ } else
+ s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
+ break;
}
}
- return temp;
+ return s3->accel.pix_trans[1];
case 0xe14a: case 0xe2ea:
if (!s3_cpu_dest(s3))
break;
- temp = s3->accel.pix_trans[2];
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- if (s3->accel.cmd & 0x100) {
- switch (s3->accel.cmd & 0x200) {
- case 0x000:
- s3_accel_start(8, 1, 0xffffffff, 0, s3);
- break;
- case 0x200:
- s3_accel_start(16, 1, 0xffffffff, 0, s3);
- break;
- }
- }
- } else {
- if (s3->accel.cmd & 0x100) {
- switch (s3->accel.cmd & 0x200) {
- case 0x000:
- s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3);
- break;
- case 0x200:
- s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3);
- break;
- }
- }
- }
- return temp;
+ READ_PIXTRANS_BYTE_IO(2);
+ return s3->accel.pix_trans[2];
case 0xe14b: case 0xe2eb:
if (!s3_cpu_dest(s3))
break;
- temp = s3->accel.pix_trans[3];
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- if (s3->accel.cmd & 0x100) {
- switch (s3->accel.cmd & 0x200) {
- case 0x000:
- s3_accel_start(8, 1, 0xffffffff, 0, s3);
- break;
- case 0x200:
- s3_accel_start(16, 1, 0xffffffff, 0, s3);
- break;
- }
+ READ_PIXTRANS_BYTE_IO(3)
+ if (s3->accel.cmd & 0x100) {
+ switch (s3->accel.cmd & 0x600) {
+ case 0x000:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
+ } else
+ s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
+ break;
+ case 0x200:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
+ } else
+ s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
+ break;
}
- } else {
- if (s3->accel.cmd & 0x100) {
- switch (s3->accel.cmd & 0x200) {
- case 0x000:
- s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3);
- break;
- case 0x200:
- s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3);
- break;
- }
- }
}
- return temp;
+ return s3->accel.pix_trans[3];
case 0xff20: case 0xff21:
temp = s3->serialport & ~(SERIAL_PORT_SCR | SERIAL_PORT_SDR);
@@ -3581,28 +3563,31 @@ static uint16_t
s3_accel_in_w(uint16_t port, void *p)
{
s3_t *s3 = (s3_t *)p;
+ svga_t *svga = &s3->svga;
uint16_t temp = 0x0000;
+ uint16_t *vram_w = (uint16_t *)svga->vram;
if (!s3->enable_8514)
return 0xffff;
if (s3_cpu_dest(s3)) {
- temp = s3->accel.pix_trans[port & 2];
- temp |= s3->accel.pix_trans[(port & 2) + 1] << 8;
+ READ_PIXTRANS_WORD
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- if ((s3->accel.cmd & 0x200) == 0x000)
- s3_accel_start(8, 1, 0xffffffff, 0, s3);
- else
- s3_accel_start(16, 1, 0xffffffff, 0, s3);
- } else {
- if ((s3->accel.cmd & 0x200) == 0x000)
- s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3);
- else
- s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3);
+ switch (s3->accel.cmd & 0x600) {
+ case 0x000:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(8, 1, temp | (temp << 16), 0, s3);
+ } else
+ s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3);
+ break;
+ case 0x200:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(16, 1, temp | (temp << 16), 0, s3);
+ } else
+ s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3);
+ break;
}
}
-
return temp;
}
@@ -3610,33 +3595,35 @@ static uint32_t
s3_accel_in_l(uint16_t port, void *p)
{
s3_t *s3 = (s3_t *)p;
+ svga_t *svga = &s3->svga;
uint32_t temp = 0x00000000;
+ uint16_t *vram_w = (uint16_t *)svga->vram;
if (!s3->enable_8514)
return 0xffffffff;
if (s3_cpu_dest(s3)) {
- temp = s3->accel.pix_trans[0];
- temp |= s3->accel.pix_trans[1] << 8;
- temp |= s3->accel.pix_trans[2] << 16;
- temp |= s3->accel.pix_trans[3] << 24;
+ READ_PIXTRANS_LONG
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- if ((s3->accel.cmd & 0x200) == 0x000) {
- s3_accel_start(8, 1, 0xffffffff, 0, s3);
- s3_accel_start(8, 1, 0xffffffff, 0, s3);
- } else {
- s3_accel_start(16, 1, 0xffffffff, 0, s3);
- s3_accel_start(16, 1, 0xffffffff, 0, s3);
- }
- } else {
- if ((s3->accel.cmd & 0x200) == 0x000) {
- s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3);
- s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3);
- } else {
- s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3);
- s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3);
- }
+ switch (s3->accel.cmd & 0x600) {
+ case 0x000:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(8, 1, temp, 0, s3);
+ s3_accel_start(8, 1, temp >> 16, 0, s3);
+ } else {
+ s3_accel_start(1, 1, 0xffffffff, temp, s3);
+ s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3);
+ }
+ break;
+ case 0x200:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(16, 1, temp, 0, s3);
+ s3_accel_start(16, 1, temp >> 16, 0, s3);
+ } else {
+ s3_accel_start(2, 1, 0xffffffff, temp, s3);
+ s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3);
+ }
+ break;
}
}
@@ -3738,18 +3725,21 @@ s3_accel_read(uint32_t addr, void *p)
if (addr & 0x8000) {
temp = s3_accel_in(addr & 0xffff, p);
} else if (s3_cpu_dest(s3)) {
- temp = s3->accel.pix_trans[addr & 3];
+ READ_PIXTRANS_BYTE_MM
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- if ((s3->accel.cmd & 0x200) == 0x000)
- s3_accel_start(8, 1, 0xffffffff, 0, s3);
- else
- s3_accel_start(16, 1, 0xffffffff, 0, s3);
- } else {
- if ((s3->accel.cmd & 0x200) == 0x000)
- s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3);
- else
- s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3);
+ switch (s3->accel.cmd & 0x600) {
+ case 0x000:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(8, 1, temp, 0, s3);
+ } else
+ s3_accel_start(1, 1, 0xffffffff, temp, s3);
+ break;
+ case 0x200:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(16, 1, temp, 0, s3);
+ } else
+ s3_accel_start(2, 1, 0xffffffff, temp, s3);
+ break;
}
}
}
@@ -3763,6 +3753,7 @@ s3_accel_read_w(uint32_t addr, void *p)
s3_t *s3 = (s3_t *)p;
svga_t *svga = &s3->svga;
uint16_t temp = 0x0000;
+ uint16_t *vram_w = (uint16_t *)svga->vram;
if (!s3->enable_8514)
return 0xffff;
@@ -3779,19 +3770,21 @@ s3_accel_read_w(uint32_t addr, void *p)
temp = s3_accel_read((addr & 0xfffe), p);
temp |= s3_accel_read((addr & 0xfffe) + 1, p) << 8;
} else if (s3_cpu_dest(s3)) {
- temp = s3->accel.pix_trans[addr & 2];
- temp |= s3->accel.pix_trans[(addr & 2) + 1] << 8;
+ READ_PIXTRANS_WORD
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- if ((s3->accel.cmd & 0x200) == 0x000)
- s3_accel_start(8, 1, 0xffff, 0, s3);
- else
- s3_accel_start(16, 1, 0xffff, 0, s3);
- } else {
- if ((s3->accel.cmd & 0x200) == 0x000)
- s3_accel_start(1, 1, 0xffffffff, 0xffff, s3);
- else
- s3_accel_start(2, 1, 0xffffffff, 0xffff, s3);
+ switch (s3->accel.cmd & 0x600) {
+ case 0x000:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(8, 1, temp | (temp << 16), 0, s3);
+ } else
+ s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3);
+ break;
+ case 0x200:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(16, 1, temp | (temp << 16), 0, s3);
+ } else
+ s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3);
+ break;
}
}
}
@@ -3806,6 +3799,7 @@ s3_accel_read_l(uint32_t addr, void *p)
s3_t *s3 = (s3_t *)p;
svga_t *svga = &s3->svga;
uint32_t temp = 0x00000000;
+ uint16_t *vram_w = (uint16_t *)svga->vram;
if (!s3->enable_8514)
return 0xffffffff;
@@ -3928,27 +3922,27 @@ s3_accel_read_l(uint32_t addr, void *p)
temp |= s3_accel_read((addr & 0xfffc) + 2, p) << 16;
temp |= s3_accel_read((addr & 0xfffc) + 3, p) << 24;
} else if (s3_cpu_dest(s3)) {
- temp = s3->accel.pix_trans[0];
- temp |= s3->accel.pix_trans[1] << 8;
- temp |= s3->accel.pix_trans[2] << 16;
- temp |= s3->accel.pix_trans[3] << 24;
+ READ_PIXTRANS_LONG
- if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) {
- if ((s3->accel.cmd & 0x200) == 0x000) {
- s3_accel_start(8, 1, 0xffffffff, 0, s3);
- s3_accel_start(8, 1, 0xffffffff, 0, s3);
- } else {
- s3_accel_start(16, 1, 0xffffffff, 0, s3);
- s3_accel_start(16, 1, 0xffffffff, 0, s3);
- }
- } else {
- if ((s3->accel.cmd & 0x200) == 0x000) {
- s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3);
- s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3);
- } else {
- s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3);
- s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3);
- }
+ switch (s3->accel.cmd & 0x600) {
+ case 0x000:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(8, 1, temp, 0, s3);
+ s3_accel_start(8, 1, temp >> 16, 0, s3);
+ } else {
+ s3_accel_start(1, 1, 0xffffffff, temp, s3);
+ s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3);
+ }
+ break;
+ case 0x200:
+ if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
+ s3_accel_start(16, 1, temp, 0, s3);
+ s3_accel_start(16, 1, temp >> 16, 0, s3);
+ } else {
+ s3_accel_start(2, 1, 0xffffffff, temp, s3);
+ s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3);
+ }
+ break;
}
}
}
@@ -4698,7 +4692,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3;
uint32_t rd_mask = s3->accel.rd_mask;
int cmd = s3->accel.cmd >> 13;
- int read = 0, byte_cnt = 0, i;
uint32_t srcbase, dstbase;
if (s3->chip <= S3_86C805) { /*Chicago 4.00.58s' s3 driver has a weird bug, not sure on real hardware*/
@@ -4738,6 +4731,32 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
if (!cpu_input)
s3->accel.dat_count = 0;
+ /*If the mask source is the CPU, the color source can't be the same as the mask, or vice versa*/
+ if (cpu_input) {
+ if (mix_dat & mix_mask) {
+ if ((s3->accel.cmd & 0x600) != 0x600) {
+ if (((s3->accel.frgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) {
+ cpu_dat = mix_dat;
+ count >>= 3;
+ }
+ }
+ } else {
+ if (cmd == 3) {
+ if (((s3->accel.frgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) {
+ cpu_dat = mix_dat;
+ count >>= 3;
+ }
+ } else {
+ if ((s3->accel.cmd & 0x600) != 0x600) {
+ if (((s3->accel.bkgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) {
+ cpu_dat = mix_dat;
+ count >>= 3;
+ }
+ }
+ }
+ }
+ }
+
if (cpu_input && (((s3->accel.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 2)))) {
if ((s3->bpp == 3) && count == 2) {
if (s3->accel.dat_count) {
@@ -4771,6 +4790,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
if (s3->bpp == 0) compare &= 0xff;
if (s3->bpp == 1) compare &= 0xffff;
+ /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled.
+ When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on
+ the NOP command)*/
switch (cmd)
{
case 0: /*NOP (Short Stroke Vectors)*/
@@ -4941,15 +4963,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
case 3: src_dat = 0; break;
}
- if ((compare_mode == 2 && src_dat != compare) ||
+ if (((compare_mode == 2 && src_dat != compare) ||
(compare_mode == 3 && src_dat == compare) ||
- compare_mode < 2)
+ compare_mode < 2))
{
READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
MIX
- if (s3->accel.cmd & 0x10) {
+ if (s3->accel.cmd & 0x10) {
WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
}
}
@@ -5005,9 +5027,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
case 3: src_dat = 0; break;
}
- if ((compare_mode == 2 && src_dat != compare) ||
+ if (((compare_mode == 2 && src_dat != compare) ||
(compare_mode == 3 && src_dat == compare) ||
- compare_mode < 2)
+ compare_mode < 2))
{
READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
@@ -5075,16 +5097,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
break;
case 2: /*Rectangle fill*/
- byte_cnt = s3_data_len(s3);
- s3->data_available = 0;
-
if (!cpu_input) /*!cpu_input is trigger to start operation*/
{
s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
s3->accel.sy = s3->accel.multifunc[0] & 0xfff;
s3->accel.cx = s3->accel.cur_x;
s3->accel.cy = s3->accel.cur_y;
-
+
if (s3->accel.cur_x_bit12) {
if (s3->accel.cx <= 0x7ff) {
s3->accel.cx = s3->accel.cur_x_bitres & 0xfff;
@@ -5098,25 +5117,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
} else {
s3->accel.cy |= ~0xfff;
}
- }
+ }
s3->accel.dest = dstbase + s3->accel.cy * s3->width;
if (s3_cpu_src(s3)) {
+ s3->data_available = 0;
return; /*Wait for data from CPU*/
} else if (s3_cpu_dest(s3)) {
- count = s3_accel_count(s3);
+ s3->data_available = 1;
+ return;
}
}
frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
- s3->accel.pix_trans[0] = 0xff;
- s3->accel.pix_trans[1] = 0xff;
- s3->accel.pix_trans[2] = 0xff;
- s3->accel.pix_trans[3] = 0xff;
-
if (s3->accel.b2e8_pix && count == 16) { /*Stupid undocumented 0xB2E8 on 911/924*/
count <<= 8;
s3->accel.temp_cnt = 16;
@@ -5130,8 +5146,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
}
if (((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r &&
- (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) || ((s3_cpu_dest(s3) &&
- (s3->accel.cy & 0xfff) >= clip_b))) /*For some reason, the SPEA v7 drivers want to draw the pixels beyond the clipping in read mode*/
+ (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b))
{
if (s3_cpu_dest(s3) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x00)) {
mix_dat = mix_mask; /* Mix data = forced to foreground register. */
@@ -5154,46 +5169,20 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
case 3: src_dat = 0; break;
}
- if ((compare_mode == 2 && src_dat != compare) ||
+ if (((compare_mode == 2 && src_dat != compare) ||
(compare_mode == 3 && src_dat == compare) ||
- compare_mode < 2)
+ compare_mode < 2))
{
- if (s3_cpu_dest(s3)) {
- dest_dat = 0xffffffff;
- } else {
- READ(s3->accel.dest + s3->accel.cx, dest_dat);
- }
+ READ(s3->accel.dest + s3->accel.cx, dest_dat);
MIX
- if (s3_cpu_dest(s3)) {
- if (s3->accel.cmd & 0x10) {
- for (i = 0; i <= s3->bpp; i++) {
- s3->accel.pix_trans[read + i] = (src_dat >> (i << 3)) & 0xff;
- /* Yes, src_dat is correct, there is no mixing/ROP's done on PIX_TRANS reads. */
- }
- }
- } else {
- if (s3->accel.cmd & 0x10) {
- WRITE(s3->accel.dest + s3->accel.cx, dest_dat);
- }
+ if (s3->accel.cmd & 0x10) {
+ WRITE(s3->accel.dest + s3->accel.cx, dest_dat);
}
}
}
- if (s3_cpu_dest(s3)) {
- if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) && ((s3->accel.cmd & 2) ||
- ((s3->accel.frgd_mix & 0x60) != 0x40 || (s3->accel.bkgd_mix != 0x40)))) {
- read++;
- if (read >= (byte_cnt << 3))
- s3->data_available = 1; /* Read data available. */
- } else {
- read += (s3->bpp + 1);
- if (read >= byte_cnt)
- s3->data_available = 1; /* Read data available. */
- }
- }
-
if (s3->accel.b2e8_pix && s3_cpu_src(s3)) {
if (s3->accel.temp_cnt > 0) {
s3->accel.temp_cnt--;
@@ -5219,39 +5208,28 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
if (s3->accel.sx < 0)
{
if (s3->accel.cmd & 0x20)
- {
s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
- }
else
- {
s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1;
- }
s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
if (s3->accel.cmd & 0x80)
s3->accel.cy++;
else
s3->accel.cy--;
-
+
s3->accel.dest = dstbase + s3->accel.cy * s3->width;
s3->accel.sy--;
if (cpu_input) {
- if (s3_cpu_dest(s3))
- s3->data_available = 1;
return;
}
if (s3->accel.sy < 0) {
s3->accel.cur_x = s3->accel.cx;
s3->accel.cur_y = s3->accel.cy;
- if (s3_cpu_dest(s3))
- s3->data_available = 1;
return;
}
}
-
- if (s3_cpu_dest(s3) && s3->data_available)
- return;
}
break;
@@ -5292,9 +5270,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
case 3: src_dat = 0; /*Not supported?*/ break;
}
- if ((compare_mode == 2 && src_dat != compare) ||
+ if (((compare_mode == 2 && src_dat != compare) ||
(compare_mode == 3 && src_dat == compare) ||
- compare_mode < 2)
+ compare_mode < 2))
{
READ(s3->accel.dest + s3->accel.poly_x, dest_dat);
@@ -5346,8 +5324,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
s3->accel.cx = s3->accel.cur_x;
s3->accel.cy = s3->accel.cur_y;
-
- if (s3->accel.dx >= 0xfffff000) { /* avoid overflow */
+
+ if (s3->accel.destx_distp >= 0xfffff000) { /* avoid overflow */
s3->accel.dx = s3->accel.destx_distp & 0xfff;
if (s3->accel.cur_x_bit12) {
if (s3->accel.cx <= 0x7ff) {
@@ -5374,7 +5352,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
}
}
}
-
+
s3->accel.src = srcbase + s3->accel.cy * s3->width;
s3->accel.dest = dstbase + s3->accel.dy * s3->width;
}
@@ -5385,7 +5363,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
-
+
if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode &&
(s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 &&
(s3->accel.bkgd_mix & 0xf) == 7)
@@ -5432,8 +5410,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
{
while (count-- && s3->accel.sy >= 0)
{
+ /*This is almost required by OS/2's software cursor or we will risk writing/reading garbage around it.*/
if ((s3->accel.dx) >= clip_l && (s3->accel.dx) <= clip_r &&
- ((s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b))
+ ((s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b))
{
if (vram_mask && (s3->accel.cmd & 0x10))
{
@@ -5460,7 +5439,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
MIX
- if (s3->accel.cmd & 0x10) {
+ if ((!(s3->accel.cmd & 0x10) && vram_mask) || (s3->accel.cmd & 0x10)) {
WRITE(s3->accel.dest + s3->accel.dx, dest_dat);
}
}
@@ -5483,7 +5462,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
}
s3->accel.sx--;
if (s3->accel.sx < 0)
- {
+ {
if (s3->accel.cmd & 0x20)
{
s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
@@ -5494,6 +5473,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1;
s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1;
}
+
s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
if (s3->accel.cmd & 0x80)
@@ -5517,7 +5497,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
if (s3->accel.sy < 0)
return;
-
}
}
}
@@ -5549,7 +5528,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width);
}
- if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
+ if ((s3->accel.cmd & 0x100) && !cpu_input) {
+ return; /*Wait for data from CPU*/
+ }
frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
@@ -5576,9 +5557,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
break;
}
- if ((compare_mode == 2 && src_dat != compare) ||
+ if (((compare_mode == 2 && src_dat != compare) ||
(compare_mode == 3 && src_dat == compare) ||
- compare_mode < 2)
+ compare_mode < 2))
{
READ(s3->accel.dest + s3->accel.dx, dest_dat);
@@ -5666,7 +5647,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
s3->accel.cy |= ~0xfff;
}
- if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
+ if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
if (s3->accel.dx > s3->accel.dy) {
error = s3->accel.dx / 2;
@@ -5676,9 +5657,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
{
src_dat = s3->accel.frgd_color;
- if ((compare_mode == 2 && src_dat != compare) ||
+ if (((compare_mode == 2 && src_dat != compare) ||
(compare_mode == 3 && src_dat == compare) ||
- compare_mode < 2)
+ compare_mode < 2) && (s3->accel.cmd & 0x10))
{
READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
@@ -5712,15 +5693,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
{
src_dat = s3->accel.frgd_color;
- if ((compare_mode == 2 && src_dat != compare) ||
+ if (((compare_mode == 2 && src_dat != compare) ||
(compare_mode == 3 && src_dat == compare) ||
- compare_mode < 2)
+ compare_mode < 2))
{
READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
MIX
-
- if (s3->accel.cmd & 0x10) {
+
+ if (s3->accel.cmd & 0x10) {
WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
}
}
@@ -5763,7 +5744,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
-
+
+
while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2))
{
int y = s3->accel.poly_cy;
@@ -5795,15 +5777,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
break;
}
- if ((compare_mode == 2 && src_dat != compare) ||
+ if (((compare_mode == 2 && src_dat != compare) ||
(compare_mode == 3 && src_dat == compare) ||
- compare_mode < 2)
+ compare_mode < 2))
{
READ(s3->accel.dest + s3->accel.poly_x, dest_dat);
MIX
-
- if (s3->accel.cmd & 0x10) {
+
+ if (s3->accel.cmd & 0x10) {
WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat);
}
}
@@ -5903,15 +5885,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
}
}
- if ((compare_mode == 2 && src_dat != compare) ||
- (compare_mode == 3 && src_dat == compare) ||
- compare_mode < 2)
+ if (((compare_mode == 2 && src_dat != compare) ||
+ (compare_mode == 3 && src_dat == compare) ||
+ compare_mode < 2))
{
READ(s3->accel.dest + s3->accel.dx, dest_dat);
ROPMIX
- if (s3->accel.cmd & 0x10) {
+ if (s3->accel.cmd & 0x10) {
WRITE(s3->accel.dest + s3->accel.dx, out);
}
}
@@ -6147,7 +6129,7 @@ static void *s3_init(const device_t *info)
int chip, stepping;
s3_t *s3 = malloc(sizeof(s3_t));
svga_t *svga = &s3->svga;
- int vram, spea_bios_ver;
+ int vram;
uint32_t vram_size;
switch(info->local) {
@@ -6167,14 +6149,15 @@ static void *s3_init(const device_t *info)
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c911);
break;
case S3_SPEA_MIRAGE_86C801:
- spea_bios_ver = device_get_config_int("bios_ver");
- if (spea_bios_ver)
- bios_fn = ROM_SPEA_MIRAGE_86C801_V401;
- else
- bios_fn = ROM_SPEA_MIRAGE_86C801_V305I;
+ bios_fn = ROM_SPEA_MIRAGE_86C801;
chip = S3_86C801;
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801);
break;
+ case S3_SPEA_MIRAGE_86C805:
+ bios_fn = ROM_SPEA_MIRAGE_86C805;
+ chip = S3_86C805;
+ video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805);
+ break;
case S3_MIROCRYSTAL10SD_805:
bios_fn = ROM_MIROCRYSTAL10SD_805;
chip = S3_86C805;
@@ -6230,6 +6213,16 @@ static void *s3_init(const device_t *info)
else
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb);
break;
+ case S3_MIROCRYSTAL20SV_964:
+ chip = S3_VISION964;
+ if (info->flags & DEVICE_PCI) {
+ bios_fn = ROM_MIROCRYSTAL20SV_964_PCI;
+ video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_pci);
+ } else {
+ bios_fn = ROM_MIROCRYSTAL20SV_964_VLB;
+ video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb);
+ }
+ break;
case S3_MIROVIDEO40SV_968:
bios_fn = ROM_MIROVIDEO40SV_968;
chip = S3_VISION968;
@@ -6334,7 +6327,8 @@ static void *s3_init(const device_t *info)
memset(s3, 0, sizeof(s3_t));
- if (info->local == S3_MIROCRYSTAL10SD_805)
+ if (info->local == S3_MIROCRYSTAL10SD_805 || info->local == S3_SPEA_MIRAGE_86C801 ||
+ info->local == S3_SPEA_MIRAGE_86C805)
vram = 1;
else
vram = device_get_config_int("memory");
@@ -6385,13 +6379,13 @@ static void *s3_init(const device_t *info)
NULL);
else {
if (chip >= S3_TRIO64V) {
- svga_init(info, &s3->svga, s3, vram_size,
+ svga_init(info, svga, s3, vram_size,
s3_trio64v_recalctimings,
s3_in, s3_out,
s3_hwcursor_draw,
s3_trio64v_overlay_draw);
} else {
- svga_init(info, &s3->svga, s3, vram_size,
+ svga_init(info, svga, s3, vram_size,
s3_recalctimings,
s3_in, s3_out,
s3_hwcursor_draw,
@@ -6494,7 +6488,6 @@ static void *s3_init(const device_t *info)
s3->id_ext = stepping;
s3->id_ext_pci = 0;
s3->packed_mmio = 0;
- s3->width = 1024;
svga->ramdac = device_add(&sc11487_ramdac_device);
svga->clock_gen = device_add(&ics2494an_305_device);
@@ -6569,7 +6562,7 @@ static void *s3_init(const device_t *info)
s3->id = stepping;
s3->id_ext = s3->id_ext_pci = stepping;
s3->packed_mmio = 0;
-
+
svga->ramdac = device_add(&sdac_ramdac_device);
svga->clock_gen = svga->ramdac;
svga->getclock = sdac_getclock;
@@ -6577,6 +6570,7 @@ static void *s3_init(const device_t *info)
case S3_DIAMOND_STEALTH64_964:
case S3_ELSAWIN2KPROX_964:
+ case S3_MIROCRYSTAL20SV_964:
svga->decode_mask = (8 << 20) - 1;
stepping = 0xd0; /*Vision964*/
s3->id = stepping;
@@ -6584,7 +6578,11 @@ static void *s3_init(const device_t *info)
s3->packed_mmio = 1;
svga->crtc[0x5a] = 0x0a;
- svga->ramdac = (info->local == S3_ELSAWIN2KPROX_964) ? device_add(&ibm_rgb528_ramdac_device) : device_add(&bt485_ramdac_device);
+ if (info->local == S3_ELSAWIN2KPROX_964)
+ svga->ramdac = device_add(&ibm_rgb528_ramdac_device);
+ else
+ svga->ramdac = device_add(&bt485_ramdac_device);
+
svga->clock_gen = device_add(&icd2061_device);
svga->getclock = icd2061_getclock;
break;
@@ -6734,7 +6732,12 @@ static int s3_ami_86c924_available(void)
static int s3_spea_mirage_86c801_available(void)
{
- return rom_present(ROM_SPEA_MIRAGE_86C801_V305I) && rom_present(ROM_SPEA_MIRAGE_86C801_V401);
+ return rom_present(ROM_SPEA_MIRAGE_86C801);
+}
+
+static int s3_spea_mirage_86c805_available(void)
+{
+ return rom_present(ROM_SPEA_MIRAGE_86C805);
}
static int s3_phoenix_86c80x_available(void)
@@ -6767,6 +6770,16 @@ static int s3_phoenix_vision868_available(void)
return rom_present(ROM_PHOENIX_VISION868);
}
+static int s3_mirocrystal_20sv_964_vlb_available(void)
+{
+ return rom_present(ROM_MIROCRYSTAL20SV_964_VLB);
+}
+
+static int s3_mirocrystal_20sv_964_pci_available(void)
+{
+ return rom_present(ROM_MIROCRYSTAL20SV_964_PCI);
+}
+
static int s3_diamond_stealth64_964_available(void)
{
return rom_present(ROM_DIAMOND_STEALTH64_964);
@@ -6908,41 +6921,6 @@ static const device_config_t s3_9fx_config[] =
};
-static const device_config_t s3_spea_mirage_config[] =
-{
- {
- "memory", "Memory size", CONFIG_SELECTION, "", 2, "", { 0 },
- {
- {
- "1 MB", 1
- },
- {
- "2 MB", 2
- },
- {
- ""
- }
- }
- },
- {
- "bios_ver", "BIOS version", CONFIG_SELECTION, "", 1, "", { 0 },
- {
- {
- "3.05I", 0
- },
- {
- "4.01", 1
- },
- {
- ""
- }
- }
- },
- {
- "", "", -1
- }
-};
-
static const device_config_t s3_phoenix_trio32_config[] =
{
{
@@ -7071,7 +7049,21 @@ const device_t s3_spea_mirage_86c801_isa_device =
{ s3_spea_mirage_86c801_available },
s3_speed_changed,
s3_force_redraw,
- s3_spea_mirage_config
+ NULL
+};
+
+const device_t s3_spea_mirage_86c805_vlb_device =
+{
+ "S3 86c805 VLB (SPEA Mirage VL)",
+ DEVICE_VLB,
+ S3_SPEA_MIRAGE_86C805,
+ s3_init,
+ s3_close,
+ NULL,
+ { s3_spea_mirage_86c805_available },
+ s3_speed_changed,
+ s3_force_redraw,
+ NULL
};
const device_t s3_mirocrystal_10sd_805_vlb_device =
@@ -7172,6 +7164,35 @@ const device_t s3_bahamas64_pci_device =
s3_9fx_config
};
+const device_t s3_mirocrystal_20sv_964_vlb_device =
+{
+ "S3 Vision964 VLB (MiroCRYSTAL 20SV)",
+ DEVICE_VLB,
+ S3_MIROCRYSTAL20SV_964,
+ s3_init,
+ s3_close,
+ NULL,
+ { s3_mirocrystal_20sv_964_vlb_available },
+ s3_speed_changed,
+ s3_force_redraw,
+ s3_9fx_config
+};
+
+const device_t s3_mirocrystal_20sv_964_pci_device =
+{
+ "S3 Vision964 PCI (MiroCRYSTAL 20SV)",
+ DEVICE_PCI,
+ S3_MIROCRYSTAL20SV_964,
+ s3_init,
+ s3_close,
+ NULL,
+ { s3_mirocrystal_20sv_964_pci_available },
+ s3_speed_changed,
+ s3_force_redraw,
+ s3_9fx_config
+};
+
+
const device_t s3_diamond_stealth64_964_vlb_device =
{
"S3 Vision964 VLB (Diamond Stealth64 VRAM)",
diff --git a/src/video/vid_table.c b/src/video/vid_table.c
index 6e4a758df..a26727e25 100644
--- a/src/video/vid_table.c
+++ b/src/video/vid_table.c
@@ -136,6 +136,7 @@ video_cards[] = {
{ "stealth32_pci", &et4000w32p_pci_device },
{ "stealth64v_pci", &s3_diamond_stealth64_964_pci_device },
{ "elsawin2kprox_964_pci", &s3_elsa_winner2000_pro_x_964_pci_device },
+ { "mirocrystal20sv_pci", &s3_mirocrystal_20sv_964_pci_device },
{ "bahamas64_pci", &s3_bahamas64_pci_device },
{ "px_vision864_pci", &s3_phoenix_vision864_pci_device },
{ "stealthse_pci", &s3_diamond_stealth_se_pci_device },
@@ -185,7 +186,9 @@ video_cards[] = {
{ "metheus928_vlb", &s3_metheus_86c928_vlb_device },
{ "mirocrystal10sd_vlb", &s3_mirocrystal_10sd_805_vlb_device },
{ "px_86c805_vlb", &s3_phoenix_86c805_vlb_device },
+ { "px_s3_v7_805_vlb", &s3_spea_mirage_86c805_vlb_device },
{ "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device },
+ { "mirocrystal20sv_vlb", &s3_mirocrystal_20sv_964_vlb_device },
{ "bahamas64_vlb", &s3_bahamas64_vlb_device },
{ "px_vision864_vlb", &s3_phoenix_vision864_vlb_device },
{ "stealthse_vlb", &s3_diamond_stealth_se_vlb_device },
@@ -201,6 +204,7 @@ video_cards[] = {
{ "virge375_vbe20_vlb", &s3_virge_375_4_vlb_device },
{ "tgui9400cxi_vlb", &tgui9400cxi_device },
{ "tgui9440_vlb", &tgui9440_vlb_device },
+ { "velocity100_agp", &velocity_100_agp_device },
{ "voodoo3_2k_agp", &voodoo_3_2000_agp_device },
{ "voodoo3_3k_agp", &voodoo_3_3000_agp_device },
{ "", NULL }
diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c
index 55ff77909..23805cb41 100644
--- a/src/video/vid_voodoo_banshee.c
+++ b/src/video/vid_voodoo_banshee.c
@@ -62,7 +62,8 @@ enum
{
TYPE_BANSHEE = 0,
TYPE_V3_2000,
- TYPE_V3_3000
+ TYPE_V3_3000,
+ TYPE_VELOCITY100
};
typedef struct banshee_t
@@ -2406,7 +2407,7 @@ static uint8_t banshee_pci_read(int func, int addr, void *p)
case 0x00: ret = 0x1a; break; /*3DFX*/
case 0x01: ret = 0x12; break;
- case 0x02: ret = (banshee->type == TYPE_BANSHEE) ? 0x03 : 0x05; break;
+ case 0x02: ret = (banshee->type == TYPE_BANSHEE) ? 0x03 : ((banshee->type == TYPE_VELOCITY100) ? 0x04 : 0x05); break;
case 0x03: ret = 0x00; break;
case 0x04: ret = banshee->pci_regs[0x04] & 0x27; break;
@@ -2750,9 +2751,12 @@ static void *banshee_init_common(const device_t *info, char *fn, int has_sgram,
if (!banshee->has_bios)
mem_size = info->local; /* fixed size for on-board chips */
- else if (has_sgram)
- mem_size = device_get_config_int("memory");
- else
+ else if (has_sgram) {
+ if (banshee->type == TYPE_VELOCITY100)
+ mem_size = 8; /* Velocity 100 only supports 8 MB */
+ else
+ mem_size = device_get_config_int("memory");
+ } else
mem_size = 16; /* SDRAM Banshee only supports 16 MB */
svga_init(info, &banshee->svga, banshee, mem_size << 20,
@@ -2889,6 +2893,10 @@ static void *v3_3000_agp_init(const device_t *info)
{
return banshee_init_common(info, "roms/video/voodoo/3k12sd.rom", 0, TYPE_V3_3000, VOODOO_3, 1);
}
+static void *velocity_100_agp_init(const device_t *info)
+{
+ return banshee_init_common(info, "roms/video/voodoo/Velocity100.VBI", 1, TYPE_VELOCITY100, VOODOO_3, 1);
+}
static int banshee_available(void)
{
@@ -2908,6 +2916,10 @@ static int v3_3000_available(void)
return rom_present("roms/video/voodoo/3k12sd.rom");
}
#define v3_3000_agp_available v3_3000_available
+static int velocity_100_available(void)
+{
+ return rom_present("roms/video/voodoo/Velocity100.VBI");
+}
static void banshee_close(void *p)
{
@@ -3034,3 +3046,17 @@ const device_t voodoo_3_3000_agp_device =
banshee_force_redraw,
banshee_sdram_config
};
+
+const device_t velocity_100_agp_device =
+{
+ "3dfx Velocity 100",
+ DEVICE_AGP,
+ 0,
+ velocity_100_agp_init,
+ banshee_close,
+ NULL,
+ { velocity_100_available },
+ banshee_speed_changed,
+ banshee_force_redraw,
+ banshee_sdram_config
+};
\ No newline at end of file