From 5e5992247c68be35d8344671360e4dce6daa9e92 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 20 Mar 2021 01:21:42 -0300 Subject: [PATCH] Add PnP variants of the Sound Blaster 16 and AWE32 --- src/include/86box/snd_emu8k.h | 3 + src/include/86box/sound.h | 2 + src/sound/snd_emu8k.c | 22 ++- src/sound/snd_sb.c | 309 ++++++++++++++++++++++++++++++++++ src/sound/sound.c | 2 + 5 files changed, 335 insertions(+), 3 deletions(-) diff --git a/src/include/86box/snd_emu8k.h b/src/include/86box/snd_emu8k.h index 16323a13b..effab0f79 100644 --- a/src/include/86box/snd_emu8k.h +++ b/src/include/86box/snd_emu8k.h @@ -377,10 +377,13 @@ typedef struct emu8k_t int pos; int32_t buffer[SOUNDBUFLEN * 2]; + + uint16_t addr; } emu8k_t; +void emu8k_change_addr(emu8k_t *emu8k, uint16_t emu_addr); void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram); void emu8k_close(emu8k_t *emu8k); diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index c4b03f1a5..3b4222a37 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -111,7 +111,9 @@ extern const device_t sb_pro_v1_device; extern const device_t sb_pro_v2_device; extern const device_t sb_pro_mcv_device; extern const device_t sb_16_device; +extern const device_t sb_16_pnp_device; extern const device_t sb_awe32_device; +extern const device_t sb_awe32_pnp_device; /* Innovation SSI-2001 */ extern const device_t ssi2001_device; diff --git a/src/sound/snd_emu8k.c b/src/sound/snd_emu8k.c index 9fdbff67e..2854330ba 100644 --- a/src/sound/snd_emu8k.c +++ b/src/sound/snd_emu8k.c @@ -2134,6 +2134,24 @@ I've recopilated these sentences to get an idea of how to loop emu8k->pos = new_pos; } + +void +emu8k_change_addr(emu8k_t *emu8k, uint16_t emu_addr) +{ + if (emu8k->addr) { + io_removehandler(emu8k->addr, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + io_removehandler(emu8k->addr+0x400, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + io_removehandler(emu8k->addr+0x800, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + emu8k->addr = 0; + } + if (emu_addr) { + emu8k->addr = emu_addr; + io_sethandler(emu8k->addr, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + io_sethandler(emu8k->addr+0x400, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + io_sethandler(emu8k->addr+0x800, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + } +} + /* onboard_ram in kilobytes */ void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram) { @@ -2196,9 +2214,7 @@ void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram) } - io_sethandler(emu_addr, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); - io_sethandler(emu_addr+0x400, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); - io_sethandler(emu_addr+0x800, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + emu8k_change_addr(emu8k, emu_addr); /*Create frequency table. (Convert initial pitch register value to a linear speed change) * The input is encoded such as 0xe000 is center note (no pitch shift) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index e1cc18f7e..6b04254a0 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -35,6 +35,7 @@ #include <86box/sound.h> #include <86box/midi.h> #include <86box/filters.h> +#include <86box/isapnp.h> #include <86box/snd_sb.h> @@ -70,6 +71,91 @@ static const uint16_t sb_mcv_addr[8] = {0x200, 0x210, 0x220, 0x230, 0x240, 0x250 static const int sb_pro_mcv_irqs[4] = {7, 5, 3, 3}; +static uint8_t sb_16_pnp_rom[] = { + 0x0e, 0x8c, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, /* CTL0028, dummy checksum (filled in by isapnp_add_card) */ + 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ + 0x82, 0x11, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x53, 0x42, 0x31, 0x36, 0x20, 0x50, 0x6e, 0x50, /* ANSI identifier "Creative SB16 PnP" */ + + 0x15, 0x0e, 0x8c, 0x00, 0x31, 0x00, /* logical device CTL0031 */ + 0x82, 0x05, 0x00, 0x41, 0x75, 0x64, 0x69, 0x6f, /* ANSI identifier "Audio" */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ + 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ + 0x2a, 0xe0, 0x16, /* DMA 5/6/7, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x01, 0x04, /* I/O 0x388, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x38, /* end dependent functions */ + 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ +}; +static uint8_t sb_awe32_pnp_rom[] = { + 0x0e, 0x8c, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, /* CTL009C, dummy checksum (filled in by isapnp_add_card) */ + 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ + 0x82, 0x11, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x53, 0x42, 0x33, 0x32, 0x20, 0x50, 0x6e, 0x50, /* ANSI identifier "Creative SB32 PnP" */ + + 0x16, 0x0e, 0x8c, 0x00, 0x41, 0x00, 0xa9, /* logical device CTL0041, supports vendor-specific registers 0x38/0x3a/0x3c/0x3f */ + 0x82, 0x05, 0x00, 0x41, 0x75, 0x64, 0x69, 0x6f, /* ANSI identifier "Audio" */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x22, 0x20, 0x00, /* IRQ 5 */ + 0x2a, 0x01, 0x0c, /* DMA 1, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0x20, 0x16, /* DMA 5, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x20, 0x02, 0x01, 0x10, /* I/O 0x220, decodes 16-bit, 1-byte alignment, 16 addresses */ + 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x01, 0x02, /* I/O 0x330, decodes 16-bit, 1-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x01, 0x04, /* I/O 0x388, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0xe0, 0x16, /* DMA 5/6/7, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x01, 0x04, /* I/O 0x388, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0xe0, 0x16, /* DMA 5/6/7, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0xe0, 0x16, /* DMA 5/6/7, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x01, 0x04, /* I/O 0x388, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0xe0, 0x16, /* DMA 5/6/7, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0x94, 0x03, 0x04, 0x04, /* I/O 0x388-0x394, decodes 16-bit, 4-byte alignment, 4 addresses */ + 0x38, /* end dependent functions */ + + 0x16, 0x0e, 0x8c, 0x00, 0x21, 0x00, 0xa9, /* logical device CTL0021, supports vendor-specific registers 0x38/0x3a/0x3c/0x3f */ + 0x82, 0x09, 0x00, 0x57, 0x61, 0x76, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, /* ANSI identifier "WaveTable" */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x47, 0x01, 0x20, 0x06, 0x20, 0x06, 0x01, 0x04, /* I/O 0x620, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x47, 0x01, 0x20, 0x06, 0x20, 0x06, 0x20, 0x04, /* I/O 0x620-0x680, decodes 16-bit, 32-byte alignment, 4 addresses */ + 0x38, /* end dependent functions */ + + 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ +}; + + #ifdef ENABLE_SB_LOG int sb_do_log = ENABLE_SB_LOG; @@ -1031,6 +1117,93 @@ sb_pro_mcv_write(int port, uint8_t val, void *p) } +static void +sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +{ + if (ld != 0) + return; + + sb_t *sb = (sb_t *) priv; + uint16_t addr = sb->dsp.sb_addr; + uint8_t val; + + io_removehandler(addr, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_removehandler(addr + 8, 0x0002, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_removehandler(0x0388, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_removehandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, sb); + + sb_dsp_setaddr(&sb->dsp, 0); + sb_dsp_setirq(&sb->dsp, 0); + sb_dsp_setdma8(&sb->dsp, 0); + sb_dsp_setdma16(&sb->dsp, 0); + + mpu401_change_addr(sb->mpu, 0); + + if (config->activate) { + addr = config->io[0].base; + if (addr != ISAPNP_IO_DISABLED) { + io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, sb); + + sb_dsp_setaddr(&sb->dsp, addr); + } + + addr = config->io[1].base; + if (addr != ISAPNP_IO_DISABLED) + mpu401_change_addr(sb->mpu, addr); + + addr = config->io[2].base; + if (addr != ISAPNP_IO_DISABLED) + io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + + val = config->irq[0].irq; + if (val != ISAPNP_IRQ_DISABLED) + sb_dsp_setirq(&sb->dsp, val); + + val = config->dma[0].dma; + if (val != ISAPNP_DMA_DISABLED) + sb_dsp_setdma8(&sb->dsp, val); + + val = config->dma[1].dma; + if (val != ISAPNP_DMA_DISABLED) + sb_dsp_setdma16(&sb->dsp, val); + } +} + + +static void +sb_awe32_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +{ + sb_t *sb = (sb_t *) priv; + uint16_t addr; + + switch (ld) { + case 0: + sb_16_pnp_config_changed(0, config, sb); + break; + + case 1: + emu8k_change_addr(&sb->emu8k, 0); + + if (config->activate) { + addr = config->io[0].base; + if (addr != ISAPNP_IO_DISABLED) + emu8k_change_addr(&sb->emu8k, addr); + } + break; + } +} + + void * sb_1_init(const device_t *info) { @@ -1404,6 +1577,36 @@ sb_16_init(const device_t *info) } +static void * +sb_16_pnp_init(const device_t *info) +{ + sb_t *sb = malloc(sizeof(sb_t)); + memset(sb, 0x00, sizeof(sb_t)); + + sb->opl_enabled = 1; + opl3_init(&sb->opl); + + sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); + sb_ct1745_mixer_reset(sb); + + sb->mixer_enabled = 1; + sound_add_handler(sb_get_buffer_sb16_awe32, sb); + sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb); + + sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + memset(sb->mpu, 0, sizeof(mpu_t)); + mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); + sb_dsp_set_mpu(&sb->dsp, sb->mpu); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + isapnp_add_card(sb_16_pnp_rom, sizeof(sb_16_pnp_rom), sb_16_pnp_config_changed, NULL, NULL, NULL, sb); + + return sb; +} + + static int sb_awe32_available() { @@ -1465,6 +1668,40 @@ sb_awe32_init(const device_t *info) } +static void * +sb_awe32_pnp_init(const device_t *info) +{ + sb_t *sb = malloc(sizeof(sb_t)); + int onboard_ram = device_get_config_int("onboard_ram"); + + memset(sb, 0x00, sizeof(sb_t)); + + sb->opl_enabled = 1; + opl3_init(&sb->opl); + + sb_dsp_init(&sb->dsp, SB16 + 1, SB_SUBTYPE_DEFAULT, sb); + sb_ct1745_mixer_reset(sb); + + sb->mixer_enabled = 1; + sound_add_handler(sb_get_buffer_sb16_awe32, sb); + sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb); + + sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + memset(sb->mpu, 0, sizeof(mpu_t)); + mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); + sb_dsp_set_mpu(&sb->dsp, sb->mpu); + + emu8k_init(&sb->emu8k, 0, onboard_ram); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + isapnp_add_card(sb_awe32_pnp_rom, sizeof(sb_awe32_pnp_rom), sb_awe32_pnp_config_changed, NULL, NULL, NULL, sb); + + return sb; +} + + void sb_close(void *p) { @@ -1856,6 +2093,19 @@ static const device_config_t sb_16_config[] = } }; +static const device_config_t sb_16_pnp_config[] = +{ + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, + { + "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 + }, + { + "", "", -1 + } +}; + static const device_config_t sb_awe32_config[] = { { @@ -2006,6 +2256,42 @@ static const device_config_t sb_awe32_config[] = } }; +static const device_config_t sb_awe32_pnp_config[] = +{ + { + "onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 512, "", { 0 }, + { + { + "None", 0 + }, + { + "512 KB", 512 + }, + { + "2 MB", 2048 + }, + { + "8 MB", 8192 + }, + { + "28 MB", 28*1024 + }, + { + "" + } + } + }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, + { + "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 + }, + { + "", "", -1 + } +}; + const device_t sb_1_device = { "Sound Blaster v1.0", @@ -2094,6 +2380,17 @@ const device_t sb_16_device = sb_16_config }; +const device_t sb_16_pnp_device = +{ + "Sound Blaster 16 PnP", + DEVICE_ISA | DEVICE_AT, + 0, + sb_16_pnp_init, sb_close, NULL, { NULL }, + sb_speed_changed, + NULL, + sb_16_pnp_config +}; + const device_t sb_awe32_device = { "Sound Blaster AWE32", @@ -2105,3 +2402,15 @@ const device_t sb_awe32_device = NULL, sb_awe32_config }; + +const device_t sb_awe32_pnp_device = +{ + "Sound Blaster AWE32 PnP", + DEVICE_ISA | DEVICE_AT, + 0, + sb_awe32_pnp_init, sb_awe32_close, NULL, + { sb_awe32_available }, + sb_speed_changed, + NULL, + sb_awe32_pnp_config +}; diff --git a/src/sound/sound.c b/src/sound/sound.c index 3751cb15a..8f363c0d5 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -94,7 +94,9 @@ static const SOUND_CARD sound_cards[] = { "sbprov1", &sb_pro_v1_device }, { "sbprov2", &sb_pro_v2_device }, { "sb16", &sb_16_device }, + { "sb16_pnp", &sb_16_pnp_device }, { "sbawe32", &sb_awe32_device }, + { "sbawe32_pnp", &sb_awe32_pnp_device }, #if defined(DEV_BRANCH) && defined(USE_PAS16) { "pas16", &pas16_device }, #endif