diff --git a/src/86box.c b/src/86box.c index 82c847eaa..eca8544a5 100644 --- a/src/86box.c +++ b/src/86box.c @@ -26,6 +26,13 @@ #include #include #include +#ifdef __APPLE__ +#include +#include +#ifdef __aarch64__ +#include +#endif +#endif #define HAVE_STDARG_H #include <86box/86box.h> @@ -780,7 +787,13 @@ pc_init_modules(void) mem_init(); #ifdef USE_DYNAREC +#if defined(__APPLE__) && defined(__aarch64__) + pthread_jit_write_protect_np(0); +#endif codegen_init(); +#if defined(__APPLE__) && defined(__aarch64__) + pthread_jit_write_protect_np(1); +#endif #endif keyboard_init(); @@ -1076,6 +1089,15 @@ pc_close(thread_t *ptr) } +#ifdef __APPLE__ +static void _ui_window_title(void *s) +{ + ui_window_title((const wchar_t *) s); + free(s); +} +#endif + + void pc_run(void) { @@ -1104,7 +1126,12 @@ pc_run(void) if (title_update) { swprintf(temp, sizeof_w(temp), mouse_msg[!!mouse_capture], fps); +#ifdef __APPLE__ + /* Needed due to modifying the UI on the non-main thread is a big no-no. */ + dispatch_async_f(dispatch_get_main_queue(), wcsdup((const wchar_t *) temp), _ui_window_title); +#else ui_window_title(temp); +#endif title_update = 0; } } diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index d396d122a..a030ac915 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -3,6 +3,9 @@ #include #include #include +#if defined(__APPLE__) && defined(__aarch64__) +#include +#endif #include #include #ifndef INFINITY @@ -31,6 +34,9 @@ #endif #include "386_common.h" +#if defined(__APPLE__) && defined(__aarch64__) +#include +#endif #define CPU_BLOCK_END() cpu_block_end = 1 diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 60af6c1b6..41a4a6f9c 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -348,6 +348,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; @@ -412,6 +414,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_hercules.c b/src/video/vid_hercules.c index 5ff73287a..650d9e5b0 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -203,11 +203,12 @@ hercules_in(uint16_t addr, void *priv) case 0x03b3: case 0x03b5: case 0x03b7: - ret = dev->crtc[dev->crtcreg]; - if (dev->crtcreg == 12) + if (dev->crtcreg == 0x0c) ret = (dev->ma >> 8) & 0x3f; - else + else if (dev->crtcreg == 0x0d) ret = dev->ma & 0xff; + else + ret = dev->crtc[dev->crtcreg]; break; case 0x03ba: @@ -274,6 +275,38 @@ hercules_read(uint32_t addr, void *priv) } +static void +hercules_render_overscan_left(hercules_t *dev) +{ + int i; + + if ((dev->displine + 14) < 0) + return; + + if ((((uint32_t) dev->crtc[1]) * 9) == 0) + return; + + for (i = 0; i < 8; i++) + buffer32->line[dev->displine + 14][i] = 0x00000000; +} + + +static void +hercules_render_overscan_right(hercules_t *dev) +{ + int i; + + if ((dev->displine + 14) < 0) + return; + + if ((((uint32_t) dev->crtc[1]) * 9) == 0) + return; + + for (i = 0; i < 8; i++) + buffer32->line[dev->displine + 14][8 + (((uint32_t) dev->crtc[1]) * 9) + i] = 0x00000000; +} + + static void hercules_poll(void *priv) { @@ -282,8 +315,9 @@ hercules_poll(void *priv) uint16_t ca, dat; uint16_t pa; int oldsc, blink; - int x, c, oldvc; + int x, xx, y, yy, c, oldvc; int drawcursor; + uint32_t *p; ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; @@ -303,6 +337,8 @@ hercules_poll(void *priv) } dev->lastline = dev->displine; + hercules_render_overscan_left(dev); + if (dev->ctrl & 0x02) { ca = (dev->sc & 3) * 0x2000; if (dev->ctrl & 0x80) @@ -315,9 +351,9 @@ hercules_poll(void *priv) dat = 0; dev->ma++; for (c = 0; c < 16; c++) - buffer32->line[dev->displine][(x << 4) + c] = (dat & (32768 >> c)) ? 7 : 0; + buffer32->line[dev->displine + 14][(x << 4) + c + 8] = (dat & (32768 >> c)) ? 7 : 0; for (c = 0; c < 16; c += 8) - video_blend((x << 4) + c, dev->displine); + video_blend((x << 4) + c + 8, dev->displine + 14); } } else { for (x = 0; x < dev->crtc[1]; x++) { @@ -333,15 +369,15 @@ hercules_poll(void *priv) if (dev->sc == 12 && ((attr & 7) == 1)) { for (c = 0; c < 9; c++) - buffer32->line[dev->displine][(x * 9) + c] = dev->cols[attr][blink][1]; + buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][1]; } else { for (c = 0; c < 8; c++) - buffer32->line[dev->displine][(x * 9) + c] = dev->cols[attr][blink][(fontdatm[chr][dev->sc] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][(fontdatm[chr][dev->sc] & (1 << (c ^ 7))) ? 1 : 0]; if ((chr & ~0x1f) == 0xc0) - buffer32->line[dev->displine][(x * 9) + 8] = dev->cols[attr][blink][fontdatm[chr][dev->sc] & 1]; + buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][fontdatm[chr][dev->sc] & 1]; else - buffer32->line[dev->displine][(x * 9) + 8] = dev->cols[attr][blink][0]; + buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][0]; } if (dev->ctrl2 & 0x01) dev->ma = (dev->ma + 1) & 0x3fff; @@ -350,10 +386,12 @@ hercules_poll(void *priv) if (drawcursor) { for (c = 0; c < 9; c++) - buffer32->line[dev->displine][(x * 9) + c] ^= dev->cols[attr][0][1]; + buffer32->line[dev->displine + 14][(x * 9) + c + 8] ^= dev->cols[attr][0][1]; } } } + + hercules_render_overscan_right(dev); } dev->sc = oldsc; @@ -435,19 +473,41 @@ hercules_poll(void *priv) x = dev->crtc[1] * 9; dev->lastline++; - if ((dev->ctrl & 8) && x && (dev->lastline - dev->firstline) && - ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get())) { + y = (dev->lastline - dev->firstline); + + if ((dev->ctrl & 8) && x && y && ((x != xsize) || (y != ysize) || video_force_resize_get())) { xsize = x; - ysize = dev->lastline - dev->firstline; - if (xsize < 64) xsize = 656; + ysize = y; + if (xsize < 64) xsize = enable_overscan ? 640 : 656; if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); + + set_screen_size(xsize + (enable_overscan ? 16 : 0), ysize + (enable_overscan ? 28 : 0)); if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, dev->firstline, 0, ysize, xsize, ysize); + if ((x >= 160) && ((y + 1) >= 120)) { + /* Draw (overscan_size) lines of overscan on top and bottom. */ + for (yy = 0; yy < 14; yy++) { + p = &(buffer32->line[(dev->firstline + yy) & 0x7ff][0]); + + for (xx = 0; xx < (x + 16); xx++) + p[xx] = 0x00000000; + } + + for (yy = 0; yy < 14; yy++) { + p = &(buffer32->line[(dev->firstline + 14 + y + yy) & 0x7ff][0]); + + for (xx = 0; xx < (x + 16); xx++) + p[xx] = 0x00000000; + } + } + + if (enable_overscan) + video_blit_memtoscreen_8(0, dev->firstline, 0, ysize + 28, xsize + 16, ysize + 28); + else + video_blit_memtoscreen_8(8, dev->firstline + 14, 0, ysize + 14, xsize, ysize); frames++; // if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) { if (dev->ctrl & 0x02) { @@ -492,6 +552,9 @@ hercules_init(const device_t *info) dev = (hercules_t *)malloc(sizeof(hercules_t)); memset(dev, 0x00, sizeof(hercules_t)); + overscan_x = 16; + overscan_y = 28; + dev->vram = (uint8_t *)malloc(0x10000); timer_add(&dev->timer, hercules_poll, dev, 1); diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index c78f28a10..38f8ebfba 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" @@ -91,7 +93,8 @@ enum S3_MIROVIDEO40SV_968, S3_MIROCRYSTAL10SD_805, S3_SPEA_MIRAGE_P64, - S3_SPEA_MERCURY_P64V + S3_SPEA_MERCURY_P64V, + S3_MIROCRYSTAL20SV_964 }; @@ -233,7 +236,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; @@ -412,31 +415,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 \ @@ -445,16 +434,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 @@ -487,32 +469,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) { @@ -532,27 +488,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; } } } @@ -561,39 +531,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; } } } @@ -1039,62 +1019,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; @@ -1107,51 +1105,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; @@ -1172,7 +1185,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); } @@ -1286,9 +1299,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 { @@ -1333,10 +1349,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); } } } @@ -2587,7 +2609,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: @@ -2695,10 +2717,12 @@ 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 (!(svga->crtc[0x17] & 0x40) && (svga->crtc[0x14] & 0x40)) /*Disable dword mode addressing when CRTC14 bit 6 is not enabled, regardless of the S3 dword mode bit.*/ + svga->force_dword_mode = 1; + } else + svga->force_dword_mode = 0; switch (svga->bpp) { case 8: @@ -2794,7 +2818,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; } @@ -2858,9 +2882,11 @@ 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[0x17] & 0x40) && (svga->crtc[0x14] & 0x40)) /*Disable dword mode addressing when CRTC14 bit 6 is not enabled, regardless of the S3 dword mode bit.*/ + svga->force_dword_mode = 1; + } else + svga->force_dword_mode = 0; switch (svga->bpp) { case 8: @@ -3150,6 +3176,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) @@ -3481,118 +3508,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); @@ -3610,28 +3596,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; } @@ -3639,33 +3628,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; } } @@ -3767,18 +3758,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; } } } @@ -3792,6 +3786,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; @@ -3808,19 +3803,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; } } } @@ -3835,6 +3832,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; @@ -3957,27 +3955,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; } } } @@ -4727,7 +4725,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*/ @@ -4767,6 +4764,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) { @@ -4800,6 +4823,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)*/ @@ -4970,15 +4996,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); } } @@ -5034,9 +5060,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); @@ -5104,16 +5130,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; @@ -5127,25 +5150,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; @@ -5159,8 +5179,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. */ @@ -5183,46 +5202,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--; @@ -5248,39 +5241,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; @@ -5321,9 +5303,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); @@ -5375,8 +5357,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) { @@ -5403,7 +5385,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; } @@ -5414,7 +5396,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) @@ -5461,8 +5443,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)) { @@ -5489,7 +5472,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); } } @@ -5512,7 +5495,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; @@ -5523,6 +5506,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) @@ -5546,7 +5530,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->accel.sy < 0) return; - } } } @@ -5578,7 +5561,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; @@ -5605,9 +5590,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); @@ -5695,7 +5680,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; @@ -5705,9 +5690,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); @@ -5741,15 +5726,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); } } @@ -5792,7 +5777,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; @@ -5824,15 +5810,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); } } @@ -5932,15 +5918,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); } } @@ -6176,7 +6162,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) { @@ -6196,14 +6182,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; @@ -6259,6 +6246,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; @@ -6368,7 +6365,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"); @@ -6419,13 +6417,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, @@ -6528,7 +6526,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); @@ -6603,7 +6600,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; @@ -6611,6 +6608,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; @@ -6618,7 +6616,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; @@ -6769,7 +6771,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) @@ -6802,6 +6809,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); @@ -6943,41 +6960,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[] = { { @@ -7106,7 +7088,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 = @@ -7207,6 +7203,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 f4a7d38ee..b16862b40 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -138,6 +138,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 }, @@ -187,7 +188,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 }, @@ -203,6 +206,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