From 26e46bf61a3acb62746066f3d168cb48e284ef0b Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 6 Apr 2017 22:01:31 +0100 Subject: [PATCH] Add Adlib MCA, Sound Blaster MCV and Sound Blaster Pro MCV emulation. --- src/sound.c | 3 + src/sound_adlib.c | 59 +++++++++++++ src/sound_adlib.h | 1 + src/sound_sb.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++ src/sound_sb.h | 2 + 5 files changed, 273 insertions(+) diff --git a/src/sound.c b/src/sound.c index b69b6bd..f464591 100644 --- a/src/sound.c +++ b/src/sound.c @@ -32,11 +32,14 @@ static SOUND_CARD sound_cards[] = { {"None", "none", NULL}, {"Adlib", "adlib", &adlib_device}, + {"Adlib", "adlib_mca", &adlib_mca_device}, {"Sound Blaster 1.0", "sb", &sb_1_device}, {"Sound Blaster 1.5", "sb1.5", &sb_15_device}, + {"Sound Blaster MCV", "sbmcv", &sb_mcv_device}, {"Sound Blaster 2.0", "sb2.0", &sb_2_device}, {"Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device}, {"Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device}, + {"Sound Blaster Pro MCV", "sbpromcv", &sb_pro_mcv_device}, {"Sound Blaster 16", "sb16", &sb_16_device}, {"Sound Blaster AWE32", "sbawe32", &sb_awe32_device}, {"Adlib Gold", "adlibgold", &adgold_device}, diff --git a/src/sound_adlib.c b/src/sound_adlib.c index e4bc492..0be5259 100644 --- a/src/sound_adlib.c +++ b/src/sound_adlib.c @@ -1,7 +1,9 @@ #include #include "ibm.h" #include "device.h" +#include "io.h" #include "sound.h" +#include "mca.h" #include "sound_adlib.h" #include "sound_opl.h" @@ -9,6 +11,8 @@ typedef struct adlib_t { opl_t opl; + + uint8_t pos_regs[8]; } adlib_t; static void adlib_get_buffer(int32_t *buffer, int len, void *p) @@ -24,6 +28,36 @@ static void adlib_get_buffer(int32_t *buffer, int len, void *p) adlib->opl.pos = 0; } +uint8_t adlib_mca_read(int port, void *p) +{ + adlib_t *adlib = (adlib_t *)p; + + pclog("adlib_mca_read: port=%04x\n", port); + + return adlib->pos_regs[port & 7]; +} + +void adlib_mca_write(int port, uint8_t val, void *p) +{ + adlib_t *adlib = (adlib_t *)p; + + if (port < 0x102) + return; + + pclog("adlib_mca_write: port=%04x val=%02x\n", port, val); + + switch (port) + { + case 0x102: + if ((adlib->pos_regs[2] & 1) && !(val & 1)) + io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); + if (!(adlib->pos_regs[2] & 1) && (val & 1)) + io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); + break; + } + adlib->pos_regs[port & 7] = val; +} + void *adlib_init() { adlib_t *adlib = malloc(sizeof(adlib_t)); @@ -33,6 +67,19 @@ void *adlib_init() opl2_init(&adlib->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); sound_add_handler(adlib_get_buffer, adlib); + + return adlib; +} + +void *adlib_mca_init() +{ + adlib_t *adlib = adlib_init(); + + io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); + mca_add(adlib_mca_read, adlib_mca_write, adlib); + adlib->pos_regs[0] = 0xd7; + adlib->pos_regs[1] = 0x70; + return adlib; } @@ -54,3 +101,15 @@ device_t adlib_device = NULL, NULL }; + +device_t adlib_mca_device = +{ + "AdLib (MCA)", + DEVICE_MCA, + adlib_init, + adlib_close, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/sound_adlib.h b/src/sound_adlib.h index dc0db0c..669737d 100644 --- a/src/sound_adlib.h +++ b/src/sound_adlib.h @@ -1 +1,2 @@ extern device_t adlib_device; +extern device_t adlib_mca_device; diff --git a/src/sound_sb.c b/src/sound_sb.c index 0b5c529..ba43ef4 100644 --- a/src/sound_sb.c +++ b/src/sound_sb.c @@ -1,6 +1,8 @@ #include #include "ibm.h" #include "device.h" +#include "io.h" +#include "mca.h" #include "sound_emu8k.h" #include "sound_mpu401_uart.h" #include "sound_opl.h" @@ -32,6 +34,8 @@ typedef struct sb_t emu8k_t emu8k; int pos; + + uint8_t pos_regs[8]; } sb_t; static int sb_att[]= @@ -335,6 +339,89 @@ void sb_mixer_init(sb_mixer_t *mixer) mixer->treble_l = mixer->treble_r = 8; mixer->filter = 1; } + +static uint16_t sb_mcv_addr[8] = {0x200, 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x270}; + +uint8_t sb_mcv_read(int port, void *p) +{ + sb_t *sb = (sb_t *)p; + + pclog("sb_mcv_read: port=%04x\n", port); + + return sb->pos_regs[port & 7]; +} + +void sb_mcv_write(int port, uint8_t val, void *p) +{ + uint16_t addr; + sb_t *sb = (sb_t *)p; + + if (port < 0x102) + return; + + pclog("sb_mcv_write: port=%04x val=%02x\n", port, val); + + addr = sb_mcv_addr[sb->pos_regs[4] & 7]; + io_removehandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); + io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); + sb_dsp_setaddr(&sb->dsp, 0); + + sb->pos_regs[port & 7] = val; + + if (sb->pos_regs[2] & 1) + { + addr = sb_mcv_addr[sb->pos_regs[4] & 7]; + + io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); + io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); + sb_dsp_setaddr(&sb->dsp, addr); + } +} + +static int sb_pro_mcv_irqs[4] = {7, 5, 3, 3}; + +uint8_t sb_pro_mcv_read(int port, void *p) +{ + sb_t *sb = (sb_t *)p; + + pclog("sb_pro_mcv_read: port=%04x\n", port); + + return sb->pos_regs[port & 7]; +} + +void sb_pro_mcv_write(int port, uint8_t val, void *p) +{ + uint16_t addr; + sb_t *sb = (sb_t *)p; + + if (port < 0x102) + return; + + pclog("sb_pro_mcv_write: port=%04x val=%02x\n", port, val); + + addr = (sb->pos_regs[2] & 0x20) ? 0x220 : 0x240; + io_removehandler(addr+0, 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_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb); + sb_dsp_setaddr(&sb->dsp, 0); + + sb->pos_regs[port & 7] = val; + + if (sb->pos_regs[2] & 1) + { + addr = (sb->pos_regs[2] & 0x20) ? 0x220 : 0x240; + + io_sethandler(addr+0, 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(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr+4, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb); + + sb_dsp_setaddr(&sb->dsp, addr); + } + sb_dsp_setirq(&sb->dsp, sb_pro_mcv_irqs[(sb->pos_regs[5] >> 4) & 3]); + sb_dsp_setdma8(&sb->dsp, sb->pos_regs[4] & 3); +} void *sb_1_init() { @@ -370,6 +457,25 @@ void *sb_15_init() sound_add_handler(sb_get_buffer_opl2, sb); return sb; } + +void *sb_mcv_init() +{ + sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_int("addr"); + memset(sb, 0, sizeof(sb_t)); + + opl2_init(&sb->opl); + sb_dsp_init(&sb->dsp, SB15); + sb_dsp_setaddr(&sb->dsp, 0);//addr); + sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); + sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); + sb_mixer_init(&sb->mixer); + sound_add_handler(sb_get_buffer_opl2, sb); + mca_add(sb_mcv_read, sb_mcv_write, sb); + sb->pos_regs[0] = 0x84; + sb->pos_regs[1] = 0x50; + return sb; +} void *sb_2_init() { sb_t *sb = malloc(sizeof(sb_t)); @@ -441,6 +547,33 @@ void *sb_pro_v2_init() return sb; } +void *sb_pro_mcv_init() +{ + sb_t *sb = malloc(sizeof(sb_t)); + //uint16_t addr = device_get_config_int("addr"); + memset(sb, 0, sizeof(sb_t)); + + opl3_init(&sb->opl); + sb_dsp_init(&sb->dsp, SBPRO2); + /*sb_dsp_setaddr(&sb->dsp, addr); + sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); + sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));*/ + sb_mixer_init(&sb->mixer); + io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); + sound_add_handler(sb_get_buffer_opl3, sb); + + sb->mixer.regs[0x22] = 0xff; + sb->mixer.regs[0x04] = 0xff; + sb->mixer.regs[0x26] = 0xff; + sb->mixer.regs[0xe] = 0; + + mca_add(sb_pro_mcv_read, sb_pro_mcv_write, sb); + sb->pos_regs[0] = 0x03; + sb->pos_regs[1] = 0x51; + + return sb; +} + void *sb_16_init() { sb_t *sb = malloc(sizeof(sb_t)); @@ -620,6 +753,57 @@ static device_config_t sb_config[] = } }; +static device_config_t sb_mcv_config[] = +{ + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "IRQ 3", + .value = 3 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { + .description = "" + } + }, + .default_int = 7 + }, + { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { + .description = "" + } + }, + .default_int = 1 + }, + { + .type = -1 + } +}; + static device_config_t sb_pro_config[] = { { @@ -778,6 +962,18 @@ device_t sb_15_device = sb_add_status_info, sb_config }; +device_t sb_mcv_device = +{ + "Sound Blaster MCV", + DEVICE_MCA, + sb_mcv_init, + sb_close, + NULL, + sb_speed_changed, + NULL, + sb_add_status_info, + sb_mcv_config +}; device_t sb_2_device = { "Sound Blaster v2.0", @@ -814,6 +1010,18 @@ device_t sb_pro_v2_device = sb_add_status_info, sb_pro_config }; +device_t sb_pro_mcv_device = +{ + "Sound Blaster Pro MCV", + DEVICE_MCA, + sb_pro_mcv_init, + sb_close, + NULL, + sb_speed_changed, + NULL, + sb_add_status_info, + NULL +}; device_t sb_16_device = { "Sound Blaster 16", diff --git a/src/sound_sb.h b/src/sound_sb.h index c2eada6..fb856c8 100644 --- a/src/sound_sb.h +++ b/src/sound_sb.h @@ -1,7 +1,9 @@ extern device_t sb_1_device; extern device_t sb_15_device; +extern device_t sb_mcv_device; extern device_t sb_2_device; extern device_t sb_pro_v1_device; extern device_t sb_pro_v2_device; +extern device_t sb_pro_mcv_device; extern device_t sb_16_device; extern device_t sb_awe32_device;