Add Adlib MCA, Sound Blaster MCV and Sound Blaster Pro MCV emulation.
This commit is contained in:
parent
4d164c4c37
commit
26e46bf61a
5 changed files with 273 additions and 0 deletions
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#include <stdlib.h>
|
||||
#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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
extern device_t adlib_device;
|
||||
extern device_t adlib_mca_device;
|
||||
|
|
|
|||
208
src/sound_sb.c
208
src/sound_sb.c
|
|
@ -1,6 +1,8 @@
|
|||
#include <stdlib.h>
|
||||
#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",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue