From bd1117a13fa4ce19ddae916b839a633f787555ec Mon Sep 17 00:00:00 2001 From: Daniel Gurney Date: Fri, 3 Sep 2021 19:58:08 +0300 Subject: [PATCH 01/13] Add missing include for arm64 macOS --- src/cpu/386_dynarec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index d396d122a..29d1382fa 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -31,6 +31,9 @@ #endif #include "386_common.h" +#if defined(__APPLE__) && defined(__aarch64__) +#include +#endif #define CPU_BLOCK_END() cpu_block_end = 1 From 136c136608596538c17001be10d85501fc036dd1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 3 Sep 2021 19:23:50 +0200 Subject: [PATCH 02/13] Ported some more Apple-related fixes from PCem. --- src/86box.c | 18 ++++++++++++++++++ src/cpu/386_dynarec.c | 3 +++ 2 files changed, 21 insertions(+) diff --git a/src/86box.c b/src/86box.c index 82c847eaa..b8715d991 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(); @@ -1104,7 +1117,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(), strdup(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..cf2f87e05 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 From b1c985c14c131cc8083fe2b8345dd1a59d773dab Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 3 Sep 2021 19:35:25 +0200 Subject: [PATCH 03/13] Fixed the shim. --- src/86box.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/86box.c b/src/86box.c index b8715d991..7c9d919d0 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1089,6 +1089,15 @@ pc_close(thread_t *ptr) } +#ifdef __APPLE__ +static void _ui_window_title(void *s) +{ + ui_window_title((const char *) s); + free(s); +} +#endif + + void pc_run(void) { @@ -1119,7 +1128,7 @@ pc_run(void) 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(), strdup(temp), _ui_window_title); + dispatch_async_f(dispatch_get_main_queue(), strdup((const char *) temp), _ui_window_title); #else ui_window_title(temp); #endif From 4b2402db2e50e54e28d3037bdf4664b2be9b23b2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 3 Sep 2021 19:45:28 +0200 Subject: [PATCH 04/13] And fixed it again. --- src/86box.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/86box.c b/src/86box.c index 7c9d919d0..eca8544a5 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1092,7 +1092,7 @@ pc_close(thread_t *ptr) #ifdef __APPLE__ static void _ui_window_title(void *s) { - ui_window_title((const char *) s); + ui_window_title((const wchar_t *) s); free(s); } #endif @@ -1128,7 +1128,7 @@ pc_run(void) 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(), strdup((const char *) temp), _ui_window_title); + dispatch_async_f(dispatch_get_main_queue(), wcsdup((const wchar_t *) temp), _ui_window_title); #else ui_window_title(temp); #endif From dbf1202d0c7d95d1c6ec9fe2ba956bbb49ea7c1c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 4 Sep 2021 00:28:41 +0600 Subject: [PATCH 05/13] unix.c: Fix character count in fullscreen string --- src/unix/unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From 16996ab2a20f31275adab0cd192efde4fc270ea7 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 5 Sep 2021 01:16:56 +0200 Subject: [PATCH 06/13] Added the 3dfx Velocity 100 per request, alongside its BIOS. --- src/include/86box/video.h | 1 + src/video/vid_table.c | 1 + src/video/vid_voodoo_banshee.c | 36 +++++++++++++++++++++++++++++----- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 8b9ddab84..f6856a2e4 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -406,6 +406,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/video/vid_table.c b/src/video/vid_table.c index 6e4a758df..7f7f19a79 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -201,6 +201,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 From 041d29da8aa74b21f73d8ec42ba17a5fa187e6d3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 5 Sep 2021 17:42:33 +0200 Subject: [PATCH 07/13] AudioPCI (ES1371) clean-up and overhaul. --- src/sound/snd_audiopci.c | 2694 ++++++++++++++++++++++---------------- 1 file changed, 1585 insertions(+), 1109 deletions(-) diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index e34324657..995edb6a8 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -23,69 +23,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 +146,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 +171,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 +1893,7 @@ const device_t es1371_onboard_device = 1, es1371_init, es1371_close, - NULL, + es1371_reset, { NULL }, es1371_speed_changed, NULL, From 9803ef828acc9a86ee25720863e8e05f295912df Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 5 Sep 2021 17:47:08 +0200 Subject: [PATCH 08/13] Gave sound/snd_audiopci.c a header. --- src/sound/snd_audiopci.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index 995edb6a8..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 From 0ae17cbb3ead2e4c1f3f4cb9ba2d642e97637ec9 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 5 Sep 2021 18:10:54 +0200 Subject: [PATCH 09/13] S3 changes/improvements: Overhauled the read portion of the PIX TRANS command (fixes white corruption in some instances while keeping everything already working fine). Fixed Miro 10SD recalctimings issue about losing graphics mode. DWORD mode SVGA CRTC bit fixed when S3 DWORD mode bit is enabled. --- src/include/86box/video.h | 2 + src/video/vid_s3.c | 1069 +++++++++++++++++++------------------ src/video/vid_table.c | 3 + 3 files changed, 550 insertions(+), 524 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index f6856a2e4..59fead3b9 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -344,6 +344,8 @@ extern const device_t s3_phoenix_trio64_onboard_pci_device; extern const device_t s3_phoenix_trio64_pci_device; extern const device_t s3_phoenix_trio64vplus_pci_device; extern const device_t s3_phoenix_trio64vplus_onboard_pci_device; +extern const device_t s3_mirocrystal_20sv_964_vlb_device; +extern const device_t s3_mirocrystal_20sv_964_pci_device; extern const device_t s3_phoenix_vision864_pci_device; extern const device_t s3_phoenix_vision864_vlb_device; extern const device_t s3_phoenix_vision868_pci_device; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 5e9a65491..c5e94194b 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -41,9 +41,11 @@ #define ROM_DIAMOND_STEALTH_VRAM "roms/video/s3/Diamond Stealth VRAM BIOS v2.31 U14.BIN" #define ROM_AMI_86C924 "roms/video/s3/S3924AMI.BIN" #define ROM_METHEUS_86C928 "roms/video/s3/928.vbi" -#define ROM_SPEA_MIRAGE_86C801_V305I "roms/video/s3/V7MIRAGE.VBI" -#define ROM_SPEA_MIRAGE_86C801_V401 "roms/video/s3/S3_805VL_ATT20C491_SPEAmirage_VL_4.01.BIN" +#define ROM_SPEA_MIRAGE_86C801 "roms/video/s3/V7MIRAGE.VBI" +#define ROM_SPEA_MIRAGE_86C805 "roms/video/s3/86c805pspeavlbus.BIN" #define ROM_MIROCRYSTAL10SD_805 "roms/video/s3/MIROcrystal10SD_VLB.VBI" +#define ROM_MIROCRYSTAL20SV_964_VLB "roms/video/s3/S3_964VL_BT485_27C256_miroCRYSTAL_20sv_ver1.2.bin" +#define ROM_MIROCRYSTAL20SV_964_PCI "roms/video/s3/mirocrystal.VBI" #define ROM_PHOENIX_86C80X "roms/video/s3/805.vbi" #define ROM_PARADISE_BAHAMAS64 "roms/video/s3/bahamas64.bin" #define ROM_PHOENIX_VISION864 "roms/video/s3/86c864p.bin" @@ -90,7 +92,8 @@ enum S3_MIROVIDEO40SV_968, S3_MIROCRYSTAL10SD_805, S3_SPEA_MIRAGE_P64, - S3_SPEA_MERCURY_P64V + S3_SPEA_MERCURY_P64V, + S3_MIROCRYSTAL20SV_964 }; @@ -232,7 +235,7 @@ typedef struct s3_t int cx, cy; int px, py; - int sx, sy, sx_backup; + int sx, sy; int dx, dy; uint32_t src, dest, pattern; @@ -411,31 +414,17 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); #define READ_PIXTRANS_BYTE_IO(n) \ - if (s3->bpp == 0) \ - s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & s3->vram_mask]; \ - else if (s3->bpp == 1) \ - s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & (s3->vram_mask >> 1)]; \ - else \ - s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & (s3->vram_mask >> 2)]; + s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & s3->vram_mask]; \ #define READ_PIXTRANS_BYTE_MM \ - if (s3->bpp == 0) \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & s3->vram_mask]; \ - else if (s3->bpp == 1) \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \ - else \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 2)]; + temp = svga->vram[(s3->accel.dest + s3->accel.cx) & s3->vram_mask]; \ #define READ_PIXTRANS_WORD \ if (s3->bpp == 0) { \ temp = svga->vram[(s3->accel.dest + s3->accel.cx) & s3->vram_mask]; \ temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & s3->vram_mask] << 8); \ - } else if (s3->bpp == 1) { \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 1)] << 8); \ - } else { \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 2)]; \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 2)] << 8); \ + } else { \ + temp = vram_w[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \ } #define READ_PIXTRANS_LONG \ @@ -444,16 +433,9 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & s3->vram_mask] << 8); \ temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 2) & s3->vram_mask] << 16); \ temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 3) & s3->vram_mask] << 24); \ - } else if (s3->bpp == 1) { \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 1)] << 8); \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 2) & (s3->vram_mask >> 1)] << 16); \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 3) & (s3->vram_mask >> 1)] << 24); \ - } else { \ - temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 2)]; \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 2)] << 8); \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 2) & (s3->vram_mask >> 2)] << 16); \ - temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 3) & (s3->vram_mask >> 2)] << 24); \ + } else { \ + temp = vram_w[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \ + temp |= (vram_w[(s3->accel.dest + s3->accel.cx + 2) & (s3->vram_mask >> 1)] << 16); \ } static int @@ -486,32 +468,6 @@ s3_cpu_dest(s3_t *s3) return 1; } -static int -s3_accel_count(s3_t *s3) -{ - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x200) && (s3->accel.cmd & 0x100) && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - return 8; - else if (!(s3->accel.cmd & 0x200) && (s3->accel.cmd & 0x100)) - return 1; - else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 0x600) == 0x200) && (s3->accel.cmd & 0x100) && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - return 16; - else if (((s3->accel.cmd & 0x200) == 0x200) && (s3->accel.cmd & 0x100)) - return 2; - else - return -1; -} - - -static int -s3_data_len(s3_t *s3) -{ - if (!(s3->accel.cmd & 0x200)) - return 1; - - return 2; -} - - static int s3_enable_fifo(s3_t *s3) { @@ -531,27 +487,41 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) svga_t *svga = &s3->svga; if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x1000) - val = (val >> 8) | (val << 8); - if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V)) { - s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); - s3_accel_start(8, 1, val & 0xff, 0, s3); - } else if ((s3->accel.cmd & 0x600) == 0x000) { - s3_accel_start(8, 1, val | (val << 16), 0, s3); - } else if ((s3->accel.cmd & 0x400) && (svga->crtc[0x53] & 0x08)) - s3_accel_start(32, 1, val | (val << 16), 0, s3); - else { - s3_accel_start(16, 1, val | (val << 16), 0, s3); - } - } else { - if ((s3->accel.cmd & 0x600) == 0x000) - s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); - else if (s3->accel.cmd & 0x400) - s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); - else { - s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - } + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = (val >> 8) | (val << 8); + s3_accel_start(8, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = (val >> 8) | (val << 8); + s3_accel_start(16, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + break; + case 0x400: + if (svga->crtc[0x53] & 0x08) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(32, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + } + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = (val >> 8) | (val << 8); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + } + break; } } } @@ -560,39 +530,49 @@ static void s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) { if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V)) { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); - s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); - s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); - s3_accel_start(8, 1, val & 0xff, 0, s3); - } else if (s3->accel.cmd & 0x400) { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(32, 1, val, 0, s3); - } else if ((s3->accel.cmd & 0x600) == 0x200) { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(16, 1, val, 0, s3); - s3_accel_start(16, 1, val >> 16, 0, s3); - } else { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(8, 1, val, 0, s3); - s3_accel_start(8, 1, val >> 16, 0, s3); - } - } else { - if (s3->accel.cmd & 0x400) { - s3_accel_start(4, 1, 0xffffffff, val, s3); - } else if ((s3->accel.cmd & 0x600) == 0x200) { - s3_accel_start(2, 1, 0xffffffff, val, s3); - s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); - } else { - s3_accel_start(1, 1, 0xffffffff, val, s3); - s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); - } + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(8, 1, val, 0, s3); + s3_accel_start(8, 1, val >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + } + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(16, 1, val, 0, s3); + s3_accel_start(16, 1, val >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + } + break; + case 0x400: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(32, 1, val, 0, s3); + } else + s3_accel_start(4, 1, 0xffffffff, val, s3); + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + } + break; } } } @@ -1038,62 +1018,80 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) if (s3_cpu_dest(s3)) break; s3->accel.pix_trans[0] = val; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100) && - ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); - } else if (!(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + if (s3->accel.cmd & 0x100) { + if (!(s3->accel.cmd & 0x600)) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } + } break; case 0xe149: case 0xe2e9: s3->accel.b2e8_pix = 0; if (s3_cpu_dest(s3)) break; s3->accel.pix_trans[1] = val; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - break; - case 0x200: - if (s3->accel.cmd & 0x1000) - s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); - else - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - break; - case 0x400: - if (svga->crtc[0x53] & 0x08) + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + break; + case 0x200: + /*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9) in the 86c928*/ + if (s3->accel.cmd & 0x1000) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); + else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + else + s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); + } + } else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + } + } else { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + else + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + } + } else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + } + break; + case 0x400: + if (svga->crtc[0x53] & 0x08) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - break; - case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + } else + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); } - break; - } - } - } else { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - break; - case 0x200: - if (s3->chip == S3_86C928) /*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9)*/ - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); - else { - if (s3->accel.cmd & 0x1000) - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } - break; - case 0x400: - if (svga->crtc[0x53] & 0x08) - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - break; - } + } + break; } } break; @@ -1106,51 +1104,66 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) if (s3_cpu_dest(s3)) break; s3->accel.pix_trans[3] = val; - if ((s3->accel.multifunc[0xa]& 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - break; - case 0x200: - if (s3->accel.cmd & 0x1000) - s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3); - else - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - break; - case 0x400: + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; + case 0x200: + /*Windows 95's built-in driver expects the upper 16 bits to be loaded instead of the whole 32-bit one, regardless of the byte swap bit (0xE2EB) in the 86c928*/ + if (s3->accel.cmd & 0x1000) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3); + else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); + else + s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3); + } + } else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); + } + } else { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); + else + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + } + } else { + if (s3->chip == S3_86C928) + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + } + } + break; + case 0x400: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - break; - case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + } else + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3); s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); } - break; - } - } - } else { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - break; - case 0x200: - if (s3->chip == S3_86C928) /*Windows 95's built-in S3 928 driver expects the upper 16 bits to be loaded instead of the whole 32-bit one, regardless of the byte swap bit (0xE2EB)*/ - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); - else { - if (s3->accel.cmd & 0x1000) - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - } - break; - case 0x400: - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - break; - } + } + break; } } break; @@ -1171,7 +1184,7 @@ s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) -{ +{ s3_accel_out_pixtrans_l(s3, val); } @@ -1285,9 +1298,12 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) if (svga->crtc[0x53] & 0x08) { if ((addr & 0x1ffff) < 0x8000) { if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); - else + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } else s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } } else { @@ -1332,10 +1348,16 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3_accel_out_fifo(s3, addr & 0xffff, val); } else { if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); - else { - s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + if (!(s3->accel.cmd & 0x600)) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, val, 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, val, s3); + } else if ((s3->accel.cmd & 0x600) == 0x200) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, val, 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, val, s3); } } } @@ -2580,7 +2602,7 @@ s3_in(uint16_t addr, void *p) else if (s3->chip <= S3_86C924) return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); else - return sdac_ramdac_in(addr, rs2, svga->ramdac, svga); + return sdac_ramdac_in(addr, rs2, svga->ramdac, svga); break; case 0x3d4: @@ -2688,11 +2710,11 @@ static void s3_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); - if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - if (!(svga->crtc[0x14] & 0x40)) /*There are still accel issues with dword mode enabled, so - disable dword mode for now.*/ - svga->crtc[0x14] |= 0x40; - + if (((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) || (svga->crtc[0x3a] & 0x10)) { + if (svga->crtc[0x31] & 0x08) { /*If the dword mode bit is not enabled when the S3 dword mode is enabled, enable it*/ + if (!(svga->crtc[0x14] & 0x40)) + svga->crtc[0x14] |= 0x40; + } switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -2787,7 +2809,7 @@ static void s3_recalctimings(svga_t *svga) } if (s3->width == 1280 || s3->width == 1600 || (s3->card_type == S3_SPEA_MERCURY_P64V)) svga->hdisp *= 2; - if (s3->card_type == S3_MIROVIDEO40SV_968) + if (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_MIROCRYSTAL20SV_964) svga->hdisp = s3->width; break; } @@ -2829,10 +2851,10 @@ static void s3_trio64v_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - if (!(svga->crtc[0x14] & 0x40)) /*There are still accel issues with dword mode enabled, so - disable dword mode for now.*/ - svga->crtc[0x14] |= 0x40; - + if (svga->crtc[0x31] & 0x08) { + if (!(svga->crtc[0x14] & 0x40)) + svga->crtc[0x14] |= 0x40; + } switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -3121,6 +3143,7 @@ static uint8_t s3_accel_in(uint16_t port, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; int temp; if (!s3->enable_8514) @@ -3452,118 +3475,77 @@ s3_accel_in(uint16_t port, void *p) case 0xe148: case 0xe2e8: if (!s3_cpu_dest(s3)) break; - temp = s3->accel.pix_trans[0]; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(8, 1, 0xffffffff, 0, s3); - break; - case 0x200: - s3_accel_start(16, 1, 0xffffffff, 0, s3); - break; - } - } - } else { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - break; - case 0x200: - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - break; - } + READ_PIXTRANS_BYTE_IO(0) + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, s3->accel.pix_trans[0], 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + break; } } - return temp; + return s3->accel.pix_trans[0]; case 0xe149: case 0xe2e9: if (!s3_cpu_dest(s3)) break; - temp = s3->accel.pix_trans[1]; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(8, 1, 0xffffffff, 0, s3); - break; - case 0x200: - s3_accel_start(16, 1, 0xffffffff, 0, s3); - break; - } - } - } else { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - break; - case 0x200: - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - break; - } + READ_PIXTRANS_BYTE_IO(1); + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + break; } } - return temp; + return s3->accel.pix_trans[1]; case 0xe14a: case 0xe2ea: if (!s3_cpu_dest(s3)) break; - temp = s3->accel.pix_trans[2]; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(8, 1, 0xffffffff, 0, s3); - break; - case 0x200: - s3_accel_start(16, 1, 0xffffffff, 0, s3); - break; - } - } - } else { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - break; - case 0x200: - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - break; - } - } - } - return temp; + READ_PIXTRANS_BYTE_IO(2); + return s3->accel.pix_trans[2]; case 0xe14b: case 0xe2eb: if (!s3_cpu_dest(s3)) break; - temp = s3->accel.pix_trans[3]; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(8, 1, 0xffffffff, 0, s3); - break; - case 0x200: - s3_accel_start(16, 1, 0xffffffff, 0, s3); - break; - } + READ_PIXTRANS_BYTE_IO(3) + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; } - } else { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x200) { - case 0x000: - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - break; - case 0x200: - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - break; - } - } } - return temp; + return s3->accel.pix_trans[3]; case 0xff20: case 0xff21: temp = s3->serialport & ~(SERIAL_PORT_SCR | SERIAL_PORT_SDR); @@ -3581,28 +3563,31 @@ static uint16_t s3_accel_in_w(uint16_t port, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; uint16_t temp = 0x0000; + uint16_t *vram_w = (uint16_t *)svga->vram; if (!s3->enable_8514) return 0xffff; if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans[port & 2]; - temp |= s3->accel.pix_trans[(port & 2) + 1] << 8; + READ_PIXTRANS_WORD - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x200) == 0x000) - s3_accel_start(8, 1, 0xffffffff, 0, s3); - else - s3_accel_start(16, 1, 0xffffffff, 0, s3); - } else { - if ((s3->accel.cmd & 0x200) == 0x000) - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - else - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + break; } } - return temp; } @@ -3610,33 +3595,35 @@ static uint32_t s3_accel_in_l(uint16_t port, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; uint32_t temp = 0x00000000; + uint16_t *vram_w = (uint16_t *)svga->vram; if (!s3->enable_8514) return 0xffffffff; if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans[0]; - temp |= s3->accel.pix_trans[1] << 8; - temp |= s3->accel.pix_trans[2] << 16; - temp |= s3->accel.pix_trans[3] << 24; + READ_PIXTRANS_LONG - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x200) == 0x000) { - s3_accel_start(8, 1, 0xffffffff, 0, s3); - s3_accel_start(8, 1, 0xffffffff, 0, s3); - } else { - s3_accel_start(16, 1, 0xffffffff, 0, s3); - s3_accel_start(16, 1, 0xffffffff, 0, s3); - } - } else { - if ((s3->accel.cmd & 0x200) == 0x000) { - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - } else { - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - } + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, temp, 0, s3); + s3_accel_start(8, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); + } + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, temp, 0, s3); + s3_accel_start(16, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); + } + break; } } @@ -3738,18 +3725,21 @@ s3_accel_read(uint32_t addr, void *p) if (addr & 0x8000) { temp = s3_accel_in(addr & 0xffff, p); } else if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans[addr & 3]; + READ_PIXTRANS_BYTE_MM - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x200) == 0x000) - s3_accel_start(8, 1, 0xffffffff, 0, s3); - else - s3_accel_start(16, 1, 0xffffffff, 0, s3); - } else { - if ((s3->accel.cmd & 0x200) == 0x000) - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - else - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, temp, 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, temp, s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, temp, 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp, s3); + break; } } } @@ -3763,6 +3753,7 @@ s3_accel_read_w(uint32_t addr, void *p) s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; uint16_t temp = 0x0000; + uint16_t *vram_w = (uint16_t *)svga->vram; if (!s3->enable_8514) return 0xffff; @@ -3779,19 +3770,21 @@ s3_accel_read_w(uint32_t addr, void *p) temp = s3_accel_read((addr & 0xfffe), p); temp |= s3_accel_read((addr & 0xfffe) + 1, p) << 8; } else if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans[addr & 2]; - temp |= s3->accel.pix_trans[(addr & 2) + 1] << 8; + READ_PIXTRANS_WORD - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x200) == 0x000) - s3_accel_start(8, 1, 0xffff, 0, s3); - else - s3_accel_start(16, 1, 0xffff, 0, s3); - } else { - if ((s3->accel.cmd & 0x200) == 0x000) - s3_accel_start(1, 1, 0xffffffff, 0xffff, s3); - else - s3_accel_start(2, 1, 0xffffffff, 0xffff, s3); + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + break; } } } @@ -3806,6 +3799,7 @@ s3_accel_read_l(uint32_t addr, void *p) s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; uint32_t temp = 0x00000000; + uint16_t *vram_w = (uint16_t *)svga->vram; if (!s3->enable_8514) return 0xffffffff; @@ -3928,27 +3922,27 @@ s3_accel_read_l(uint32_t addr, void *p) temp |= s3_accel_read((addr & 0xfffc) + 2, p) << 16; temp |= s3_accel_read((addr & 0xfffc) + 3, p) << 24; } else if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans[0]; - temp |= s3->accel.pix_trans[1] << 8; - temp |= s3->accel.pix_trans[2] << 16; - temp |= s3->accel.pix_trans[3] << 24; + READ_PIXTRANS_LONG - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x200) == 0x000) { - s3_accel_start(8, 1, 0xffffffff, 0, s3); - s3_accel_start(8, 1, 0xffffffff, 0, s3); - } else { - s3_accel_start(16, 1, 0xffffffff, 0, s3); - s3_accel_start(16, 1, 0xffffffff, 0, s3); - } - } else { - if ((s3->accel.cmd & 0x200) == 0x000) { - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - } else { - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - } + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(8, 1, temp, 0, s3); + s3_accel_start(8, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); + } + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + s3_accel_start(16, 1, temp, 0, s3); + s3_accel_start(16, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); + } + break; } } } @@ -4698,7 +4692,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; uint32_t rd_mask = s3->accel.rd_mask; int cmd = s3->accel.cmd >> 13; - int read = 0, byte_cnt = 0, i; uint32_t srcbase, dstbase; if (s3->chip <= S3_86C805) { /*Chicago 4.00.58s' s3 driver has a weird bug, not sure on real hardware*/ @@ -4738,6 +4731,32 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (!cpu_input) s3->accel.dat_count = 0; + /*If the mask source is the CPU, the color source can't be the same as the mask, or vice versa*/ + if (cpu_input) { + if (mix_dat & mix_mask) { + if ((s3->accel.cmd & 0x600) != 0x600) { + if (((s3->accel.frgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) { + cpu_dat = mix_dat; + count >>= 3; + } + } + } else { + if (cmd == 3) { + if (((s3->accel.frgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) { + cpu_dat = mix_dat; + count >>= 3; + } + } else { + if ((s3->accel.cmd & 0x600) != 0x600) { + if (((s3->accel.bkgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) { + cpu_dat = mix_dat; + count >>= 3; + } + } + } + } + } + if (cpu_input && (((s3->accel.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 2)))) { if ((s3->bpp == 3) && count == 2) { if (s3->accel.dat_count) { @@ -4771,6 +4790,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->bpp == 0) compare &= 0xff; if (s3->bpp == 1) compare &= 0xffff; + /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. + When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on + the NOP command)*/ switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ @@ -4941,15 +4963,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 3: src_dat = 0; break; } - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX - if (s3->accel.cmd & 0x10) { + if (s3->accel.cmd & 0x10) { WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); } } @@ -5005,9 +5027,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 3: src_dat = 0; break; } - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); @@ -5075,16 +5097,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ break; case 2: /*Rectangle fill*/ - byte_cnt = s3_data_len(s3); - s3->data_available = 0; - if (!cpu_input) /*!cpu_input is trigger to start operation*/ { s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; s3->accel.sy = s3->accel.multifunc[0] & 0xfff; s3->accel.cx = s3->accel.cur_x; s3->accel.cy = s3->accel.cur_y; - + if (s3->accel.cur_x_bit12) { if (s3->accel.cx <= 0x7ff) { s3->accel.cx = s3->accel.cur_x_bitres & 0xfff; @@ -5098,25 +5117,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } else { s3->accel.cy |= ~0xfff; } - } + } s3->accel.dest = dstbase + s3->accel.cy * s3->width; if (s3_cpu_src(s3)) { + s3->data_available = 0; return; /*Wait for data from CPU*/ } else if (s3_cpu_dest(s3)) { - count = s3_accel_count(s3); + s3->data_available = 1; + return; } } frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - s3->accel.pix_trans[0] = 0xff; - s3->accel.pix_trans[1] = 0xff; - s3->accel.pix_trans[2] = 0xff; - s3->accel.pix_trans[3] = 0xff; - if (s3->accel.b2e8_pix && count == 16) { /*Stupid undocumented 0xB2E8 on 911/924*/ count <<= 8; s3->accel.temp_cnt = 16; @@ -5130,8 +5146,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } if (((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && - (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) || ((s3_cpu_dest(s3) && - (s3->accel.cy & 0xfff) >= clip_b))) /*For some reason, the SPEA v7 drivers want to draw the pixels beyond the clipping in read mode*/ + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b)) { if (s3_cpu_dest(s3) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x00)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ @@ -5154,46 +5169,20 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 3: src_dat = 0; break; } - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { - if (s3_cpu_dest(s3)) { - dest_dat = 0xffffffff; - } else { - READ(s3->accel.dest + s3->accel.cx, dest_dat); - } + READ(s3->accel.dest + s3->accel.cx, dest_dat); MIX - if (s3_cpu_dest(s3)) { - if (s3->accel.cmd & 0x10) { - for (i = 0; i <= s3->bpp; i++) { - s3->accel.pix_trans[read + i] = (src_dat >> (i << 3)) & 0xff; - /* Yes, src_dat is correct, there is no mixing/ROP's done on PIX_TRANS reads. */ - } - } - } else { - if (s3->accel.cmd & 0x10) { - WRITE(s3->accel.dest + s3->accel.cx, dest_dat); - } + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.cx, dest_dat); } } } - if (s3_cpu_dest(s3)) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) && ((s3->accel.cmd & 2) || - ((s3->accel.frgd_mix & 0x60) != 0x40 || (s3->accel.bkgd_mix != 0x40)))) { - read++; - if (read >= (byte_cnt << 3)) - s3->data_available = 1; /* Read data available. */ - } else { - read += (s3->bpp + 1); - if (read >= byte_cnt) - s3->data_available = 1; /* Read data available. */ - } - } - if (s3->accel.b2e8_pix && s3_cpu_src(s3)) { if (s3->accel.temp_cnt > 0) { s3->accel.temp_cnt--; @@ -5219,39 +5208,28 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->accel.sx < 0) { if (s3->accel.cmd & 0x20) - { s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } else - { s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; if (s3->accel.cmd & 0x80) s3->accel.cy++; else s3->accel.cy--; - + s3->accel.dest = dstbase + s3->accel.cy * s3->width; s3->accel.sy--; if (cpu_input) { - if (s3_cpu_dest(s3)) - s3->data_available = 1; return; } if (s3->accel.sy < 0) { s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; - if (s3_cpu_dest(s3)) - s3->data_available = 1; return; } } - - if (s3_cpu_dest(s3) && s3->data_available) - return; } break; @@ -5292,9 +5270,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 3: src_dat = 0; /*Not supported?*/ break; } - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { READ(s3->accel.dest + s3->accel.poly_x, dest_dat); @@ -5346,8 +5324,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx = s3->accel.cur_x; s3->accel.cy = s3->accel.cur_y; - - if (s3->accel.dx >= 0xfffff000) { /* avoid overflow */ + + if (s3->accel.destx_distp >= 0xfffff000) { /* avoid overflow */ s3->accel.dx = s3->accel.destx_distp & 0xfff; if (s3->accel.cur_x_bit12) { if (s3->accel.cx <= 0x7ff) { @@ -5374,7 +5352,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } } - + s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; } @@ -5385,7 +5363,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - + if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 && (s3->accel.bkgd_mix & 0xf) == 7) @@ -5432,8 +5410,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { while (count-- && s3->accel.sy >= 0) { + /*This is almost required by OS/2's software cursor or we will risk writing/reading garbage around it.*/ if ((s3->accel.dx) >= clip_l && (s3->accel.dx) <= clip_r && - ((s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b)) + ((s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b)) { if (vram_mask && (s3->accel.cmd & 0x10)) { @@ -5460,7 +5439,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ MIX - if (s3->accel.cmd & 0x10) { + if ((!(s3->accel.cmd & 0x10) && vram_mask) || (s3->accel.cmd & 0x10)) { WRITE(s3->accel.dest + s3->accel.dx, dest_dat); } } @@ -5483,7 +5462,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } s3->accel.sx--; if (s3->accel.sx < 0) - { + { if (s3->accel.cmd & 0x20) { s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; @@ -5494,6 +5473,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; } + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; if (s3->accel.cmd & 0x80) @@ -5517,7 +5497,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->accel.sy < 0) return; - } } } @@ -5549,7 +5528,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width); } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + if ((s3->accel.cmd & 0x100) && !cpu_input) { + return; /*Wait for data from CPU*/ + } frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; @@ -5576,9 +5557,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ break; } - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { READ(s3->accel.dest + s3->accel.dx, dest_dat); @@ -5666,7 +5647,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy |= ~0xfff; } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ if (s3->accel.dx > s3->accel.dy) { error = s3->accel.dx / 2; @@ -5676,9 +5657,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { src_dat = s3->accel.frgd_color; - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2) && (s3->accel.cmd & 0x10)) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); @@ -5712,15 +5693,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { src_dat = s3->accel.frgd_color; - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX - - if (s3->accel.cmd & 0x10) { + + if (s3->accel.cmd & 0x10) { WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); } } @@ -5763,7 +5744,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - + + while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) { int y = s3->accel.poly_cy; @@ -5795,15 +5777,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ break; } - if ((compare_mode == 2 && src_dat != compare) || + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + compare_mode < 2)) { READ(s3->accel.dest + s3->accel.poly_x, dest_dat); MIX - - if (s3->accel.cmd & 0x10) { + + if (s3->accel.cmd & 0x10) { WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); } } @@ -5903,15 +5885,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) + if (((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2)) { READ(s3->accel.dest + s3->accel.dx, dest_dat); ROPMIX - if (s3->accel.cmd & 0x10) { + if (s3->accel.cmd & 0x10) { WRITE(s3->accel.dest + s3->accel.dx, out); } } @@ -6147,7 +6129,7 @@ static void *s3_init(const device_t *info) int chip, stepping; s3_t *s3 = malloc(sizeof(s3_t)); svga_t *svga = &s3->svga; - int vram, spea_bios_ver; + int vram; uint32_t vram_size; switch(info->local) { @@ -6167,14 +6149,15 @@ static void *s3_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c911); break; case S3_SPEA_MIRAGE_86C801: - spea_bios_ver = device_get_config_int("bios_ver"); - if (spea_bios_ver) - bios_fn = ROM_SPEA_MIRAGE_86C801_V401; - else - bios_fn = ROM_SPEA_MIRAGE_86C801_V305I; + bios_fn = ROM_SPEA_MIRAGE_86C801; chip = S3_86C801; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); break; + case S3_SPEA_MIRAGE_86C805: + bios_fn = ROM_SPEA_MIRAGE_86C805; + chip = S3_86C805; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + break; case S3_MIROCRYSTAL10SD_805: bios_fn = ROM_MIROCRYSTAL10SD_805; chip = S3_86C805; @@ -6230,6 +6213,16 @@ static void *s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); break; + case S3_MIROCRYSTAL20SV_964: + chip = S3_VISION964; + if (info->flags & DEVICE_PCI) { + bios_fn = ROM_MIROCRYSTAL20SV_964_PCI; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_pci); + } else { + bios_fn = ROM_MIROCRYSTAL20SV_964_VLB; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); + } + break; case S3_MIROVIDEO40SV_968: bios_fn = ROM_MIROVIDEO40SV_968; chip = S3_VISION968; @@ -6334,7 +6327,8 @@ static void *s3_init(const device_t *info) memset(s3, 0, sizeof(s3_t)); - if (info->local == S3_MIROCRYSTAL10SD_805) + if (info->local == S3_MIROCRYSTAL10SD_805 || info->local == S3_SPEA_MIRAGE_86C801 || + info->local == S3_SPEA_MIRAGE_86C805) vram = 1; else vram = device_get_config_int("memory"); @@ -6385,13 +6379,13 @@ static void *s3_init(const device_t *info) NULL); else { if (chip >= S3_TRIO64V) { - svga_init(info, &s3->svga, s3, vram_size, + svga_init(info, svga, s3, vram_size, s3_trio64v_recalctimings, s3_in, s3_out, s3_hwcursor_draw, s3_trio64v_overlay_draw); } else { - svga_init(info, &s3->svga, s3, vram_size, + svga_init(info, svga, s3, vram_size, s3_recalctimings, s3_in, s3_out, s3_hwcursor_draw, @@ -6494,7 +6488,6 @@ static void *s3_init(const device_t *info) s3->id_ext = stepping; s3->id_ext_pci = 0; s3->packed_mmio = 0; - s3->width = 1024; svga->ramdac = device_add(&sc11487_ramdac_device); svga->clock_gen = device_add(&ics2494an_305_device); @@ -6569,7 +6562,7 @@ static void *s3_init(const device_t *info) s3->id = stepping; s3->id_ext = s3->id_ext_pci = stepping; s3->packed_mmio = 0; - + svga->ramdac = device_add(&sdac_ramdac_device); svga->clock_gen = svga->ramdac; svga->getclock = sdac_getclock; @@ -6577,6 +6570,7 @@ static void *s3_init(const device_t *info) case S3_DIAMOND_STEALTH64_964: case S3_ELSAWIN2KPROX_964: + case S3_MIROCRYSTAL20SV_964: svga->decode_mask = (8 << 20) - 1; stepping = 0xd0; /*Vision964*/ s3->id = stepping; @@ -6584,7 +6578,11 @@ static void *s3_init(const device_t *info) s3->packed_mmio = 1; svga->crtc[0x5a] = 0x0a; - svga->ramdac = (info->local == S3_ELSAWIN2KPROX_964) ? device_add(&ibm_rgb528_ramdac_device) : device_add(&bt485_ramdac_device); + if (info->local == S3_ELSAWIN2KPROX_964) + svga->ramdac = device_add(&ibm_rgb528_ramdac_device); + else + svga->ramdac = device_add(&bt485_ramdac_device); + svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; break; @@ -6734,7 +6732,12 @@ static int s3_ami_86c924_available(void) static int s3_spea_mirage_86c801_available(void) { - return rom_present(ROM_SPEA_MIRAGE_86C801_V305I) && rom_present(ROM_SPEA_MIRAGE_86C801_V401); + return rom_present(ROM_SPEA_MIRAGE_86C801); +} + +static int s3_spea_mirage_86c805_available(void) +{ + return rom_present(ROM_SPEA_MIRAGE_86C805); } static int s3_phoenix_86c80x_available(void) @@ -6767,6 +6770,16 @@ static int s3_phoenix_vision868_available(void) return rom_present(ROM_PHOENIX_VISION868); } +static int s3_mirocrystal_20sv_964_vlb_available(void) +{ + return rom_present(ROM_MIROCRYSTAL20SV_964_VLB); +} + +static int s3_mirocrystal_20sv_964_pci_available(void) +{ + return rom_present(ROM_MIROCRYSTAL20SV_964_PCI); +} + static int s3_diamond_stealth64_964_available(void) { return rom_present(ROM_DIAMOND_STEALTH64_964); @@ -6908,41 +6921,6 @@ static const device_config_t s3_9fx_config[] = }; -static const device_config_t s3_spea_mirage_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 2, "", { 0 }, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "" - } - } - }, - { - "bios_ver", "BIOS version", CONFIG_SELECTION, "", 1, "", { 0 }, - { - { - "3.05I", 0 - }, - { - "4.01", 1 - }, - { - "" - } - } - }, - { - "", "", -1 - } -}; - static const device_config_t s3_phoenix_trio32_config[] = { { @@ -7071,7 +7049,21 @@ const device_t s3_spea_mirage_86c801_isa_device = { s3_spea_mirage_86c801_available }, s3_speed_changed, s3_force_redraw, - s3_spea_mirage_config + NULL +}; + +const device_t s3_spea_mirage_86c805_vlb_device = +{ + "S3 86c805 VLB (SPEA Mirage VL)", + DEVICE_VLB, + S3_SPEA_MIRAGE_86C805, + s3_init, + s3_close, + NULL, + { s3_spea_mirage_86c805_available }, + s3_speed_changed, + s3_force_redraw, + NULL }; const device_t s3_mirocrystal_10sd_805_vlb_device = @@ -7172,6 +7164,35 @@ const device_t s3_bahamas64_pci_device = s3_9fx_config }; +const device_t s3_mirocrystal_20sv_964_vlb_device = +{ + "S3 Vision964 VLB (MiroCRYSTAL 20SV)", + DEVICE_VLB, + S3_MIROCRYSTAL20SV_964, + s3_init, + s3_close, + NULL, + { s3_mirocrystal_20sv_964_vlb_available }, + s3_speed_changed, + s3_force_redraw, + s3_9fx_config +}; + +const device_t s3_mirocrystal_20sv_964_pci_device = +{ + "S3 Vision964 PCI (MiroCRYSTAL 20SV)", + DEVICE_PCI, + S3_MIROCRYSTAL20SV_964, + s3_init, + s3_close, + NULL, + { s3_mirocrystal_20sv_964_pci_available }, + s3_speed_changed, + s3_force_redraw, + s3_9fx_config +}; + + const device_t s3_diamond_stealth64_964_vlb_device = { "S3 Vision964 VLB (Diamond Stealth64 VRAM)", diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 7f7f19a79..a26727e25 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -136,6 +136,7 @@ video_cards[] = { { "stealth32_pci", &et4000w32p_pci_device }, { "stealth64v_pci", &s3_diamond_stealth64_964_pci_device }, { "elsawin2kprox_964_pci", &s3_elsa_winner2000_pro_x_964_pci_device }, + { "mirocrystal20sv_pci", &s3_mirocrystal_20sv_964_pci_device }, { "bahamas64_pci", &s3_bahamas64_pci_device }, { "px_vision864_pci", &s3_phoenix_vision864_pci_device }, { "stealthse_pci", &s3_diamond_stealth_se_pci_device }, @@ -185,7 +186,9 @@ video_cards[] = { { "metheus928_vlb", &s3_metheus_86c928_vlb_device }, { "mirocrystal10sd_vlb", &s3_mirocrystal_10sd_805_vlb_device }, { "px_86c805_vlb", &s3_phoenix_86c805_vlb_device }, + { "px_s3_v7_805_vlb", &s3_spea_mirage_86c805_vlb_device }, { "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device }, + { "mirocrystal20sv_vlb", &s3_mirocrystal_20sv_964_vlb_device }, { "bahamas64_vlb", &s3_bahamas64_vlb_device }, { "px_vision864_vlb", &s3_phoenix_vision864_vlb_device }, { "stealthse_vlb", &s3_diamond_stealth_se_vlb_device }, From b834365f30b3c965d7d84edaa1b568e458d320b3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 5 Sep 2021 19:03:32 +0200 Subject: [PATCH 10/13] Fixed CRTC register readout on the Hercules, fixes #1656. --- src/video/vid_hercules.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 5ff73287a..54d0a891a 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: From 1c634759c53d3cbc6993c9d168554f14b0f0ec36 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 5 Sep 2021 19:25:16 +0200 Subject: [PATCH 11/13] Fix the dword mode fix in the S3 code. --- src/video/vid_s3.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index c5e94194b..2e6a00e62 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2713,8 +2713,10 @@ static void s3_recalctimings(svga_t *svga) if (((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) || (svga->crtc[0x3a] & 0x10)) { if (svga->crtc[0x31] & 0x08) { /*If the dword mode bit is not enabled when the S3 dword mode is enabled, enable it*/ if (!(svga->crtc[0x14] & 0x40)) - svga->crtc[0x14] |= 0x40; - } + svga->force_dword_mode = 1; + } else + svga->force_dword_mode = 0; + switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -2851,10 +2853,12 @@ 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[0x31] & 0x08) { + if (svga->crtc[0x31] & 0x08) { /*If the dword mode bit is not enabled when the S3 dword mode is enabled, enable it*/ if (!(svga->crtc[0x14] & 0x40)) - svga->crtc[0x14] |= 0x40; - } + svga->force_dword_mode = 1; + } else + svga->force_dword_mode = 0; + switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; From e37f477ebfdd55b2808c4d66ae636207c7886efa Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 5 Sep 2021 19:53:03 +0200 Subject: [PATCH 12/13] S3 dword mode: CRTC14 bit 6 (standard dword mode) has the highest priority over CRTC31 bit 3 (S3 dword mode), so if the latter is enabled while the former is disabled, it's byte mode. Fixes both Duke3D, LXPIC and Win3.1 running at the same time (once and for all). --- src/video/vid_s3.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 2e6a00e62..d3fb9c468 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2711,12 +2711,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)) || (svga->crtc[0x3a] & 0x10)) { - if (svga->crtc[0x31] & 0x08) { /*If the dword mode bit is not enabled when the S3 dword mode is enabled, enable it*/ - if (!(svga->crtc[0x14] & 0x40)) + 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: svga->render = svga_render_8bpp_highres; @@ -2853,8 +2853,8 @@ 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[0x31] & 0x08) { /*If the dword mode bit is not enabled when the S3 dword mode is enabled, enable it*/ - if (!(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; From 6536a04590b55614478ddde3990c17f69bcd1218 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 5 Sep 2021 20:30:43 +0200 Subject: [PATCH 13/13] Implemented Hercules overscan, closes #1638. --- src/video/vid_hercules.c | 90 +++++++++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 14 deletions(-) diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 54d0a891a..650d9e5b0 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -275,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) { @@ -283,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; @@ -304,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) @@ -316,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++) { @@ -334,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; @@ -351,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; @@ -436,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) { @@ -493,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);