Added Aztech Sound Galaxy Pro 16 AB (Washington, AZ2316A) and Aztech Sound

Galaxy Nova 16 Extra (Clinton, AZ1605) emulation. Patch from EluanCM.
Clinton is currently marked as DEVICE_NOT_WORKING due to issues with DOS drivers.
This commit is contained in:
SarahW 2020-03-11 21:21:09 +00:00
commit 1181b13c2d
17 changed files with 2051 additions and 179 deletions

View file

@ -40,7 +40,7 @@ mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xebec.c model.c mouse.c mouse_msystems
neat.c nmi.c nvr.c olivetti_m24.c opti495.c paths.c pc.c pc87306.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c \ neat.c nmi.c nvr.c olivetti_m24.c opti495.c paths.c pc.c pc87306.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c \
ps2_nvr.c nvr_tc8521.c pzx.c rom.c rtc.c rtc_tc8521.c scamp.c scat.c scsi.c scsi_53c400.c scsi_aha1540.c scsi_cd.c scsi_hd.c \ ps2_nvr.c nvr_tc8521.c pzx.c rom.c rtc.c rtc_tc8521.c scamp.c scat.c scsi.c scsi_53c400.c scsi_aha1540.c scsi_cd.c scsi_hd.c \
scsi_ibm.c scsi_zip.c serial.c sio.c sis496.c sl82c460.c sound.c sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_audiopci.c \ scsi_ibm.c scsi_zip.c serial.c sio.c sis496.c sl82c460.c sound.c sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_audiopci.c \
sound_cms.c sound_emu8k.c sound_gus.c sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c \ sound_azt2316a.c sound_cms.c sound_emu8k.c sound_gus.c sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c \
sound_sb.c sound_sb_dsp.c sound_sn76489.c sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c \ sound_sb.c sound_sb_dsp.c sound_sn76489.c sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c \
sst39sf010.c tandy_eeprom.c tandy_rom.c t1000.c t3100e.c timer.c um8669f.c um8881f.c vid_ati_eeprom.c vid_ati_mach64.c \ sst39sf010.c tandy_eeprom.c tandy_rom.c t1000.c t3100e.c timer.c um8669f.c um8881f.c vid_ati_eeprom.c vid_ati_mach64.c \
vid_ati18800.c vid_ati28800.c vid_ati68860_ramdac.c vid_cga.c vid_cl5429.c vid_colorplus.c vid_compaq_cga.c vid_ega.c \ vid_ati18800.c vid_ati28800.c vid_ati68860_ramdac.c vid_cga.c vid_cl5429.c vid_colorplus.c vid_compaq_cga.c vid_ega.c \

View file

@ -26,7 +26,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203
mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o \ mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o \
piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scamp.o scat.o scsi.o \ piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scamp.o scat.o scsi.o \
scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_ibm.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \ scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_ibm.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \
sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \ sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_azt2316a.o sound_cms.o sound_dbopl.o \
sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \ sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \
sound_resid.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \ sound_resid.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \
sound_ym7128.o soundopenal.o sst39sf010.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \ sound_ym7128.o soundopenal.o sst39sf010.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \

View file

@ -26,7 +26,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203
mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o \ mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o \
piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scamp.o scat.o scsi.o \ piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scamp.o scat.o scsi.o \
scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_ibm.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \ scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_ibm.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \
sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \ sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_azt2316a.o sound_cms.o sound_dbopl.o \
sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \ sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \
sound_resid.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \ sound_resid.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \
sound_ym7128.o soundopenal.o sst39sf010.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \ sound_ym7128.o soundopenal.o sst39sf010.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \

View file

@ -15,6 +15,7 @@
#include "sound_adlib.h" #include "sound_adlib.h"
#include "sound_adlibgold.h" #include "sound_adlibgold.h"
#include "sound_audiopci.h" #include "sound_audiopci.h"
#include "sound_azt2316a.h"
#include "sound_pas16.h" #include "sound_pas16.h"
#include "sound_sb.h" #include "sound_sb.h"
#include "sound_sb_dsp.h" #include "sound_sb_dsp.h"
@ -35,23 +36,25 @@ typedef struct
static SOUND_CARD sound_cards[] = static SOUND_CARD sound_cards[] =
{ {
{"None", "none", NULL}, {"None", "none", NULL},
{"Adlib", "adlib", &adlib_device}, {"Adlib", "adlib", &adlib_device},
{"Adlib", "adlib_mca", &adlib_mca_device}, {"Adlib", "adlib_mca", &adlib_mca_device},
{"Sound Blaster 1.0", "sb", &sb_1_device}, {"Sound Blaster 1.0", "sb", &sb_1_device},
{"Sound Blaster 1.5", "sb1.5", &sb_15_device}, {"Sound Blaster 1.5", "sb1.5", &sb_15_device},
{"Sound Blaster MCV", "sbmcv", &sb_mcv_device}, {"Sound Blaster MCV", "sbmcv", &sb_mcv_device},
{"Sound Blaster 2.0", "sb2.0", &sb_2_device}, {"Sound Blaster 2.0", "sb2.0", &sb_2_device},
{"Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device}, {"Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device},
{"Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device}, {"Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device},
{"Sound Blaster Pro MCV", "sbpromcv", &sb_pro_mcv_device}, {"Sound Blaster Pro MCV", "sbpromcv", &sb_pro_mcv_device},
{"Sound Blaster 16", "sb16", &sb_16_device}, {"Sound Blaster 16", "sb16", &sb_16_device},
{"Sound Blaster AWE32", "sbawe32", &sb_awe32_device}, {"Sound Blaster AWE32", "sbawe32", &sb_awe32_device},
{"Adlib Gold", "adlibgold", &adgold_device}, {"Adlib Gold", "adlibgold", &adgold_device},
{"Windows Sound System", "wss", &wss_device}, {"Windows Sound System", "wss", &wss_device},
{"Pro Audio Spectrum 16", "pas16", &pas16_device}, {"Aztech Sound Galaxy Pro 16 AB (Washington)", "azt2316a", &azt2316a_device},
{"Ensoniq AudioPCI (ES1371)", "es1371", &es1371_device}, {"Aztech Sound Galaxy Nova 16 Extra (Clinton)", "azt1605", &azt1605_device},
{"Sound Blaster PCI 128", "sbpci128", &es1371_device}, {"Pro Audio Spectrum 16", "pas16", &pas16_device},
{"Ensoniq AudioPCI (ES1371)", "es1371", &es1371_device},
{"Sound Blaster PCI 128", "sbpci128", &es1371_device},
{"", "", NULL} {"", "", NULL}
}; };

View file

@ -4,8 +4,10 @@
#include "pic.h" #include "pic.h"
#include "sound.h" #include "sound.h"
#include "sound_ad1848.h" #include "sound_ad1848.h"
#include "x86.h"
static int ad1848_vols[64]; static int ad1848_vols_6bits[64];
static uint32_t ad1848_vols_5bits_aux_gain[32];
void ad1848_setirq(ad1848_t *ad1848, int irq) void ad1848_setirq(ad1848_t *ad1848, int irq)
{ {
@ -21,7 +23,7 @@ uint8_t ad1848_read(uint16_t addr, void *p)
{ {
ad1848_t *ad1848 = (ad1848_t *)p; ad1848_t *ad1848 = (ad1848_t *)p;
uint8_t temp = 0xff; uint8_t temp = 0xff;
// pclog("ad1848_read - addr %04X %04X(%08X):%08X ", addr, CS, cs, pc);
switch (addr & 3) switch (addr & 3)
{ {
case 0: /*Index*/ case 0: /*Index*/
@ -34,7 +36,10 @@ uint8_t ad1848_read(uint16_t addr, void *p)
temp = ad1848->status; temp = ad1848->status;
break; break;
} }
// pclog("return %02X\n", temp); // if ((addr & 3) == 1 && (ad1848->index & 0x1f) > 0x0f)
// pclog("ad1848_read_EXTENDED - addr %04X %04X(%08X):%08X return %02X\n", addr, CS, cs, cpu_state.pc, temp);
// else
// pclog("ad1848_read - addr %04X %04X(%08X):%08X return %02X\n", addr, CS, cs, cpu_state.pc, temp);
return temp; return temp;
} }
@ -42,11 +47,18 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
{ {
ad1848_t *ad1848 = (ad1848_t *)p; ad1848_t *ad1848 = (ad1848_t *)p;
double freq; double freq;
// pclog("ad1848_write - addr %04X val %02X %04X(%08X):%08X\n", addr, val, CS, cs, pc); uint32_t new_cd_vol_l, new_cd_vol_r;
// if ((addr & 3) == 0 && (val & 0x1f) > 0x0f)
// pclog("ad1848_write_EXTENDED - addr %04X val %02X %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc);
// else
// pclog("ad1848_write - addr %04X val %02X %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc);
switch (addr & 3) switch (addr & 3)
{ {
case 0: /*Index*/ case 0: /*Index*/
ad1848->index = val & 0xf; if (ad1848->regs[12] & 0x40 && ad1848->type == AD1848_TYPE_CS4231)
ad1848->index = val & 0x1f; // cs4231a extended mode enabled
else
ad1848->index = val & 0x0f; // ad1848/cs4248 mode TODO: some variants/clones DO NOT mirror, just ignore the writes?
ad1848->trd = val & 0x20; ad1848->trd = val & 0x20;
ad1848->mce = val & 0x40; ad1848->mce = val & 0x40;
break; break;
@ -71,29 +83,49 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
break; break;
case 9: case 9:
if (!ad1848->enable && (val & 0x41) == 0x01) if (!ad1848->enable && (val & 0x41) == 0x01)
{ {
if (ad1848->timer_latch) if (ad1848->timer_latch)
timer_set_delay_u64(&ad1848->timer, ad1848->timer_latch); timer_set_delay_u64(&ad1848->timer, ad1848->timer_latch);
else else
timer_set_delay_u64(&ad1848->timer, TIMER_USEC); timer_set_delay_u64(&ad1848->timer, TIMER_USEC);
} }
ad1848->enable = ((val & 0x41) == 0x01); ad1848->enable = ((val & 0x41) == 0x01);
if (!ad1848->enable) if (!ad1848->enable)
{ {
timer_disable(&ad1848->timer); timer_disable(&ad1848->timer);
ad1848->out_l = ad1848->out_r = 0; ad1848->out_l = ad1848->out_r = 0;
} }
break; break;
case 12: case 12:
ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80;
return; return;
case 14: case 14:
ad1848->count = ad1848->regs[15] | (val << 8); ad1848->count = ad1848->regs[15] | (val << 8);
break; break;
// TODO: see which of the extended registers should be read only
} }
ad1848->regs[ad1848->index] = val; ad1848->regs[ad1848->index] = val;
if (ad1848->type == AD1848_TYPE_CS4231) // TODO: configure CD volume for CS4248/AD1848 too
{
if (ad1848->regs[0x12] & 0x80)
new_cd_vol_l = 0;
else
new_cd_vol_l = ad1848_vols_5bits_aux_gain[ad1848->regs[0x12] & 0x1f];
if (ad1848->regs[0x13] & 0x80)
new_cd_vol_r = 0;
else
new_cd_vol_r = ad1848_vols_5bits_aux_gain[ad1848->regs[0x13] & 0x1f];
// Apparently there is no master volume to modulate here
// (The windows mixer just adjusts all registers at the same
// time when the master slider is adjusted)
sound_set_cd_volume(new_cd_vol_l, new_cd_vol_r);
}
break; break;
case 2: case 2:
ad1848->status &= 0xfe; ad1848->status &= 0xfe;
@ -125,7 +157,7 @@ static void ad1848_poll(void *p)
timer_advance_u64(&ad1848->timer, TIMER_USEC*1000); timer_advance_u64(&ad1848->timer, TIMER_USEC*1000);
ad1848_update(ad1848); ad1848_update(ad1848);
// TODO: line in, mic, etc...
if (ad1848->enable) if (ad1848->enable)
{ {
int32_t temp; int32_t temp;
@ -155,12 +187,12 @@ static void ad1848_poll(void *p)
if (ad1848->regs[6] & 0x80) if (ad1848->regs[6] & 0x80)
ad1848->out_l = 0; ad1848->out_l = 0;
else else
ad1848->out_l = (ad1848->out_l * ad1848_vols[ad1848->regs[6] & 0x3f]) >> 16; ad1848->out_l = (ad1848->out_l * ad1848_vols_6bits[ad1848->regs[6] & 0x3f]) >> 16;
if (ad1848->regs[7] & 0x80) if (ad1848->regs[7] & 0x80)
ad1848->out_r = 0; ad1848->out_r = 0;
else else
ad1848->out_r = (ad1848->out_r * ad1848_vols[ad1848->regs[7] & 0x3f]) >> 16; ad1848->out_r = (ad1848->out_r * ad1848_vols_6bits[ad1848->regs[7] & 0x3f]) >> 16;
if (ad1848->count < 0) if (ad1848->count < 0)
{ {
@ -179,15 +211,17 @@ static void ad1848_poll(void *p)
else else
{ {
ad1848->out_l = ad1848->out_r = 0; ad1848->out_l = ad1848->out_r = 0;
sound_set_cd_volume(0, 0);
// pclog("ad1848_poll : not enable\n"); // pclog("ad1848_poll : not enable\n");
} }
} }
void ad1848_init(ad1848_t *ad1848) void ad1848_init(ad1848_t *ad1848, int type)
{ {
int c; int c;
double attenuation; double attenuation;
ad1848->type = type;
ad1848->enable = 0; ad1848->enable = 0;
ad1848->status = 0xcc; ad1848->status = 0xcc;
@ -195,16 +229,25 @@ void ad1848_init(ad1848_t *ad1848)
ad1848->mce = 0x40; ad1848->mce = 0x40;
ad1848->regs[0] = ad1848->regs[1] = 0; ad1848->regs[0] = ad1848->regs[1] = 0;
ad1848->regs[2] = ad1848->regs[3] = 0x80; ad1848->regs[2] = ad1848->regs[3] = 0x80; // AZT2316A Line-in
ad1848->regs[4] = ad1848->regs[5] = 0x80; ad1848->regs[4] = ad1848->regs[5] = 0x80;
ad1848->regs[6] = ad1848->regs[7] = 0x80; ad1848->regs[6] = ad1848->regs[7] = 0x80; // AZT2316A Master?
ad1848->regs[8] = 0; ad1848->regs[8] = 0;
ad1848->regs[9] = 0x08; ad1848->regs[9] = 0x08;
ad1848->regs[10] = ad1848->regs[11] = 0; ad1848->regs[10] = ad1848->regs[11] = 0;
ad1848->regs[12] = 0xa; if (ad1848->type == AD1848_TYPE_CS4248 || ad1848->type == AD1848_TYPE_CS4231)
ad1848->regs[12] = 0x8a;
else
ad1848->regs[12] = 0xa;
ad1848->regs[13] = 0; ad1848->regs[13] = 0;
ad1848->regs[14] = ad1848->regs[15] = 0; ad1848->regs[14] = ad1848->regs[15] = 0;
if (ad1848->type == AD1848_TYPE_CS4231)
{
ad1848->regs[0x12] = ad1848->regs[0x13] = 0x80; // AZT2316A CD
ad1848->regs[0x1A] = 0x80; // AZT2316A Mic
}
ad1848->out_l = 0; ad1848->out_l = 0;
ad1848->out_r = 0; ad1848->out_r = 0;
@ -220,8 +263,22 @@ void ad1848_init(ad1848_t *ad1848)
attenuation = pow(10, attenuation / 10); attenuation = pow(10, attenuation / 10);
ad1848_vols[c] = (int)(attenuation * 65536); ad1848_vols_6bits[c] = (int)(attenuation * 65536);
// pclog("ad1848_vols %i = %f %i\n", c, attenuation, ad1848_vols[c]); // pclog("ad1848_vols_6bits %i = %f %i\n", c, attenuation, ad1848_vols_6bits[c]);
}
for (c = 0; c < 32; c++)
{
attenuation = 12.0;
if (c & 0x01) attenuation -= 1.5;
if (c & 0x02) attenuation -= 3.0;
if (c & 0x04) attenuation -= 6.0;
if (c & 0x08) attenuation -= 12.0;
if (c & 0x10) attenuation -= 24.0;
attenuation = pow(10, attenuation / 10);
ad1848_vols_5bits_aux_gain[c] = (int)(attenuation * 65536);
// pclog("ad1848_vols_5bits_aux_gain %i = %f %i\n", c, attenuation, ad1848_vols_5bits_aux_gain[c]);
} }
timer_add(&ad1848->timer, ad1848_poll, ad1848, 0); timer_add(&ad1848->timer, ad1848_poll, ad1848, 0);

View file

@ -1,9 +1,13 @@
#include "timer.h" #include "timer.h"
#define AD1848_TYPE_DEFAULT 0
#define AD1848_TYPE_CS4248 1
#define AD1848_TYPE_CS4231 2
typedef struct ad1848_t typedef struct ad1848_t
{ {
int index; int index;
uint8_t regs[16]; uint8_t regs[32]; // 16 original + 16 CS4231A extensions
uint8_t status; uint8_t status;
int trd; int trd;
@ -20,10 +24,12 @@ typedef struct ad1848_t
int freq; int freq;
pc_timer_t timer; pc_timer_t timer;
uint64_t timer_latch; uint64_t timer_latch;
int16_t buffer[MAXSOUNDBUFLEN * 2]; int16_t buffer[MAXSOUNDBUFLEN * 2];
int pos; int pos;
int type;
} ad1848_t; } ad1848_t;
void ad1848_setirq(ad1848_t *ad1848, int irq); void ad1848_setirq(ad1848_t *ad1848, int irq);
@ -35,4 +41,4 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p);
void ad1848_update(ad1848_t *ad1848); void ad1848_update(ad1848_t *ad1848);
void ad1848_speed_changed(ad1848_t *ad1848); void ad1848_speed_changed(ad1848_t *ad1848);
void ad1848_init(ad1848_t *ad1848); void ad1848_init(ad1848_t *ad1848, int type);

1620
src/sound_azt2316a.c Normal file

File diff suppressed because it is too large Load diff

4
src/sound_azt2316a.h Normal file
View file

@ -0,0 +1,4 @@
extern device_t azt2316a_device;
extern device_t azt1605_device;
void azt2316a_enable_wss(uint8_t enable, void *p);

View file

@ -1,3 +1,5 @@
#ifndef SOUND_EMU8K_H
#define SOUND_EMU8K_H
/* All these defines are in samples, not in bytes. */ /* All these defines are in samples, not in bytes. */
#define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF #define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF
@ -773,3 +775,5 @@ Treble Parameters:
0xD308 0xD308 0xD308 0xD308 0xD308 0xD308 0xD3019 0xD32A 0xD34C 0xD36E 0xD36E 0xD36E 0xD308 0xD308 0xD308 0xD308 0xD308 0xD308 0xD3019 0xD32A 0xD34C 0xD36E 0xD36E 0xD36E
0x0001 0x0001 0x0001 0x0001 0x0001 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002 0x0001 0x0001 0x0001 0x0001 0x0001 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002
*/ */
#endif /* SOUND_EMU8K_H */

View file

@ -1,5 +1,6 @@
#include "ibm.h" #include "ibm.h"
#include "io.h" #include "io.h"
#include "pic.h"
#include "plat-midi.h" #include "plat-midi.h"
#include "sound_mpu401_uart.h" #include "sound_mpu401_uart.h"
@ -9,6 +10,14 @@ enum
STATUS_INPUT_NOT_READY = 0x80 STATUS_INPUT_NOT_READY = 0x80
}; };
static void mpu401_uart_raise_irq(void *p)
{
mpu401_uart_t *mpu = (mpu401_uart_t *)p;
if (mpu->irq != -1)
picint(1 << mpu->irq);
}
static void mpu401_uart_write(uint16_t addr, uint8_t val, void *p) static void mpu401_uart_write(uint16_t addr, uint8_t val, void *p)
{ {
mpu401_uart_t *mpu = (mpu401_uart_t *)p; mpu401_uart_t *mpu = (mpu401_uart_t *)p;
@ -18,15 +27,20 @@ static void mpu401_uart_write(uint16_t addr, uint8_t val, void *p)
switch (val) switch (val)
{ {
case 0xff: /*Reset*/ case 0xff: /*Reset*/
// From Roland: "An ACK will not be sent back upon sending a SYSTEM RESET to leave the UART MODE ($3F)."
// But actual behaviour is weird. For example, the MPU401 port test in the AZT1605 drivers for Windows NT
// want this to return an Ack but the IRQ test in the same driver wants this to raise no interrupts!
mpu->rx_data = 0xfe; /*Acknowledge*/ mpu->rx_data = 0xfe; /*Acknowledge*/
mpu->status = 0; mpu->status = STATUS_OUTPUT_NOT_READY;
mpu->uart_mode = 0; mpu->uart_mode = 0;
//mpu401_uart_raise_irq(p);
break; break;
case 0x3f: /*Enter UART mode*/ case 0x3f: /*Enter UART mode*/
mpu->rx_data = 0xfe; /*Acknowledge*/ mpu->rx_data = 0xfe; /*Acknowledge*/
mpu->status = 0; mpu->status = STATUS_OUTPUT_NOT_READY;
mpu->uart_mode = 1; mpu->uart_mode = 1;
mpu401_uart_raise_irq(p);
break; break;
} }
return; return;
@ -45,14 +59,30 @@ static uint8_t mpu401_uart_read(uint16_t addr, void *p)
return mpu->status; return mpu->status;
/*Data*/ /*Data*/
mpu->status |= STATUS_INPUT_NOT_READY; mpu->status = STATUS_INPUT_NOT_READY;
return mpu->rx_data; return mpu->rx_data;
} }
void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr) void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr, int irq)
{ {
mpu->status = STATUS_INPUT_NOT_READY; mpu->status = STATUS_INPUT_NOT_READY;
mpu->uart_mode = 0; mpu->uart_mode = 0;
mpu->addr = addr;
mpu->irq = irq;
io_sethandler(addr, 0x0002, mpu401_uart_read, NULL, NULL, mpu401_uart_write, NULL, NULL, mpu); io_sethandler(addr, 0x0002, mpu401_uart_read, NULL, NULL, mpu401_uart_write, NULL, NULL, mpu);
} }
void mpu401_uart_update_addr(mpu401_uart_t *mpu, uint16_t addr)
{
io_removehandler(mpu->addr, 0x0002, mpu401_uart_read, NULL, NULL, mpu401_uart_write, NULL, NULL, mpu);
mpu->addr = addr;
if (addr != 0)
io_sethandler(addr, 0x0002, mpu401_uart_read, NULL, NULL, mpu401_uart_write, NULL, NULL, mpu);
}
void mpu401_uart_update_irq(mpu401_uart_t *mpu, int irq)
{
mpu->irq = irq;
}

View file

@ -1,9 +1,18 @@
#ifndef SOUND_MPU401_UART
#define SOUND_MPU401_UART
typedef struct mpu401_uart_t typedef struct mpu401_uart_t
{ {
uint8_t status; uint8_t status;
uint8_t rx_data; uint8_t rx_data;
int uart_mode; int uart_mode;
uint16_t addr;
int irq;
} mpu401_uart_t; } mpu401_uart_t;
void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr); void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr, int irq);
void mpu401_uart_update_addr(mpu401_uart_t *mpu, uint16_t addr);
void mpu401_uart_update_irq(mpu401_uart_t *mpu, int irq);
#endif /* SOUND_MPU401_UART */

View file

@ -737,7 +737,7 @@ void *pas16_init()
memset(pas16, 0, sizeof(pas16_t)); memset(pas16, 0, sizeof(pas16_t));
opl3_init(&pas16->opl, 0); opl3_init(&pas16->opl, 0);
sb_dsp_init(&pas16->dsp, SB2); sb_dsp_init(&pas16->dsp, SB2, SB_SUBTYPE_DEFAULT, pas16);
io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16); io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16);

View file

@ -21,102 +21,6 @@ FILE* soundfsb = 0/*NULL*/;
FILE* soundfsbin = 0/*NULL*/; FILE* soundfsbin = 0/*NULL*/;
#endif #endif
/* SB 2.0 CD version */
typedef struct sb_ct1335_mixer_t
{
int32_t master;
int32_t voice;
int32_t fm;
int32_t cd;
uint8_t index;
uint8_t regs[256];
} sb_ct1335_mixer_t;
/* SB PRO */
typedef struct sb_ct1345_mixer_t
{
int32_t master_l, master_r;
int32_t voice_l, voice_r;
int32_t fm_l, fm_r;
int32_t cd_l, cd_r;
int32_t line_l, line_r;
int32_t mic;
/*see sb_ct1745_mixer for values for input selector*/
int32_t input_selector;
int input_filter;
int in_filter_freq;
int output_filter;
int stereo;
int stereo_isleft;
uint8_t index;
uint8_t regs[256];
} sb_ct1345_mixer_t;
/* SB16 and AWE32 */
typedef struct sb_ct1745_mixer_t
{
int32_t master_l, master_r;
int32_t voice_l, voice_r;
int32_t fm_l, fm_r;
int32_t cd_l, cd_r;
int32_t line_l, line_r;
int32_t mic;
int32_t speaker;
int bass_l, bass_r;
int treble_l, treble_r;
int output_selector;
#define OUTPUT_MIC 1
#define OUTPUT_CD_R 2
#define OUTPUT_CD_L 4
#define OUTPUT_LINE_R 8
#define OUTPUT_LINE_L 16
int input_selector_left;
int input_selector_right;
#define INPUT_MIC 1
#define INPUT_CD_R 2
#define INPUT_CD_L 4
#define INPUT_LINE_R 8
#define INPUT_LINE_L 16
#define INPUT_MIDI_R 32
#define INPUT_MIDI_L 64
int mic_agc;
int32_t input_gain_L;
int32_t input_gain_R;
int32_t output_gain_L;
int32_t output_gain_R;
uint8_t index;
uint8_t regs[256];
} sb_ct1745_mixer_t;
typedef struct sb_t
{
opl_t opl;
sb_dsp_t dsp;
union {
sb_ct1335_mixer_t mixer_sb2;
sb_ct1345_mixer_t mixer_sbpro;
sb_ct1745_mixer_t mixer_sb16;
};
mpu401_uart_t mpu;
emu8k_t emu8k;
int pos;
uint8_t pos_regs[8];
int opl_emu;
} sb_t;
/* 0 to 7 -> -14dB to 0dB i 2dB steps. 8 to 15 -> 0 to +14dB in 2dB steps. /* 0 to 7 -> -14dB to 0dB i 2dB steps. 8 to 15 -> 0 to +14dB in 2dB steps.
Note that for positive dB values, this is not amplitude, it is amplitude-1. */ Note that for positive dB values, this is not amplitude, it is amplitude-1. */
const float sb_bass_treble_4bits[]= { const float sb_bass_treble_4bits[]= {
@ -195,7 +99,7 @@ static void sb_get_buffer_sb2_mixer(int32_t *buffer, int len, void *p)
sb->dsp.pos = 0; sb->dsp.pos = 0;
} }
static void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p) void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p)
{ {
sb_t *sb = (sb_t *)p; sb_t *sb = (sb_t *)p;
sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro;
@ -950,7 +854,7 @@ void *sb_1_init()
memset(sb, 0, sizeof(sb_t)); memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl); opl2_init(&sb->opl);
sb_dsp_init(&sb->dsp, SB1); sb_dsp_init(&sb->dsp, SB1, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@ -972,7 +876,7 @@ void *sb_15_init()
memset(sb, 0, sizeof(sb_t)); memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl); opl2_init(&sb->opl);
sb_dsp_init(&sb->dsp, SB15); sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@ -993,7 +897,7 @@ void *sb_mcv_init()
memset(sb, 0, sizeof(sb_t)); memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl); opl2_init(&sb->opl);
sb_dsp_init(&sb->dsp, SB15); sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, 0);//addr); sb_dsp_setaddr(&sb->dsp, 0);//addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@ -1024,7 +928,7 @@ void *sb_2_init()
memset(sb, 0, sizeof(sb_t)); memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl); opl2_init(&sb->opl);
sb_dsp_init(&sb->dsp, SB2); sb_dsp_init(&sb->dsp, SB2, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@ -1061,7 +965,7 @@ void *sb_pro_v1_init()
memset(sb, 0, sizeof(sb_t)); memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl); opl2_init(&sb->opl);
sb_dsp_init(&sb->dsp, SBPRO); sb_dsp_init(&sb->dsp, SBPRO, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@ -1091,7 +995,7 @@ void *sb_pro_v2_init()
uint16_t addr = device_get_config_int("addr"); uint16_t addr = device_get_config_int("addr");
sb->opl_emu = device_get_config_int("opl_emu"); sb->opl_emu = device_get_config_int("opl_emu");
opl3_init(&sb->opl, sb->opl_emu); opl3_init(&sb->opl, sb->opl_emu);
sb_dsp_init(&sb->dsp, SBPRO2); sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@ -1118,7 +1022,7 @@ void *sb_pro_mcv_init()
sb->opl_emu = device_get_config_int("opl_emu"); sb->opl_emu = device_get_config_int("opl_emu");
opl3_init(&sb->opl, sb->opl_emu); opl3_init(&sb->opl, sb->opl_emu);
sb_dsp_init(&sb->dsp, SBPRO2); sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb);
sb_ct1345_mixer_reset(sb); sb_ct1345_mixer_reset(sb);
/* I/O handlers activated in sb_mcv_write */ /* I/O handlers activated in sb_mcv_write */
sound_add_handler(sb_get_buffer_sbpro, sb); sound_add_handler(sb_get_buffer_sbpro, sb);
@ -1139,7 +1043,7 @@ void *sb_16_init()
uint16_t addr = device_get_config_int("addr"); uint16_t addr = device_get_config_int("addr");
sb->opl_emu = device_get_config_int("opl_emu"); sb->opl_emu = device_get_config_int("opl_emu");
opl3_init(&sb->opl, sb->opl_emu); opl3_init(&sb->opl, sb->opl_emu);
sb_dsp_init(&sb->dsp, SB16); sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setaddr(&sb->dsp, addr);
// TODO: irq and dma options too? // TODO: irq and dma options too?
sb_ct1745_mixer_reset(sb); sb_ct1745_mixer_reset(sb);
@ -1148,7 +1052,7 @@ void *sb_16_init()
io_sethandler(0x0388, 0x0004, 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_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb); io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb);
sound_add_handler(sb_get_buffer_sb16, sb); sound_add_handler(sb_get_buffer_sb16, sb);
mpu401_uart_init(&sb->mpu, 0x330); mpu401_uart_init(&sb->mpu, 0x330, -1);
return sb; return sb;
@ -1169,7 +1073,7 @@ void *sb_awe32_init()
uint16_t emu_addr = device_get_config_int("emu_addr"); uint16_t emu_addr = device_get_config_int("emu_addr");
sb->opl_emu = device_get_config_int("opl_emu"); sb->opl_emu = device_get_config_int("opl_emu");
opl3_init(&sb->opl, sb->opl_emu); opl3_init(&sb->opl, sb->opl_emu);
sb_dsp_init(&sb->dsp, SB16 + 1); sb_dsp_init(&sb->dsp, SB16 + 1, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setaddr(&sb->dsp, addr);
// TODO: irq and dma options too? // TODO: irq and dma options too?
sb_ct1745_mixer_reset(sb); sb_ct1745_mixer_reset(sb);
@ -1178,7 +1082,7 @@ void *sb_awe32_init()
io_sethandler(0x0388, 0x0004, 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_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb); io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb);
sound_add_handler(sb_get_buffer_emu8k, sb); sound_add_handler(sb_get_buffer_emu8k, sb);
mpu401_uart_init(&sb->mpu, 0x330); mpu401_uart_init(&sb->mpu, 0x330, -1);
emu8k_init(&sb->emu8k, emu_addr, onboard_ram); emu8k_init(&sb->emu8k, emu_addr, onboard_ram);
return sb; return sb;

View file

@ -1,3 +1,10 @@
#ifndef SOUND_SB_H
#define SOUND_SB_H
#include "sound_emu8k.h"
#include "sound_mpu401_uart.h"
#include "sound_sb_dsp.h"
extern device_t sb_1_device; extern device_t sb_1_device;
extern device_t sb_15_device; extern device_t sb_15_device;
extern device_t sb_mcv_device; extern device_t sb_mcv_device;
@ -7,3 +14,110 @@ extern device_t sb_pro_v2_device;
extern device_t sb_pro_mcv_device; extern device_t sb_pro_mcv_device;
extern device_t sb_16_device; extern device_t sb_16_device;
extern device_t sb_awe32_device; extern device_t sb_awe32_device;
/* SB 2.0 CD version */
typedef struct sb_ct1335_mixer_t
{
int32_t master;
int32_t voice;
int32_t fm;
int32_t cd;
uint8_t index;
uint8_t regs[256];
} sb_ct1335_mixer_t;
/* SB PRO */
typedef struct sb_ct1345_mixer_t
{
int32_t master_l, master_r;
int32_t voice_l, voice_r;
int32_t fm_l, fm_r;
int32_t cd_l, cd_r;
int32_t line_l, line_r;
int32_t mic;
/*see sb_ct1745_mixer for values for input selector*/
int32_t input_selector;
int input_filter;
int in_filter_freq;
int output_filter;
int stereo;
int stereo_isleft;
uint8_t index;
uint8_t regs[256];
} sb_ct1345_mixer_t;
/* SB16 and AWE32 */
typedef struct sb_ct1745_mixer_t
{
int32_t master_l, master_r;
int32_t voice_l, voice_r;
int32_t fm_l, fm_r;
int32_t cd_l, cd_r;
int32_t line_l, line_r;
int32_t mic;
int32_t speaker;
int bass_l, bass_r;
int treble_l, treble_r;
int output_selector;
#define OUTPUT_MIC 1
#define OUTPUT_CD_R 2
#define OUTPUT_CD_L 4
#define OUTPUT_LINE_R 8
#define OUTPUT_LINE_L 16
int input_selector_left;
int input_selector_right;
#define INPUT_MIC 1
#define INPUT_CD_R 2
#define INPUT_CD_L 4
#define INPUT_LINE_R 8
#define INPUT_LINE_L 16
#define INPUT_MIDI_R 32
#define INPUT_MIDI_L 64
int mic_agc;
int32_t input_gain_L;
int32_t input_gain_R;
int32_t output_gain_L;
int32_t output_gain_R;
uint8_t index;
uint8_t regs[256];
} sb_ct1745_mixer_t;
typedef struct sb_t
{
opl_t opl;
sb_dsp_t dsp;
union {
sb_ct1335_mixer_t mixer_sb2;
sb_ct1345_mixer_t mixer_sbpro;
sb_ct1745_mixer_t mixer_sb16;
};
mpu401_uart_t mpu;
emu8k_t emu8k;
int pos;
uint8_t pos_regs[8];
int opl_emu;
} sb_t;
// exported for clone cards
void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p);
void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p);
uint8_t sb_ct1345_mixer_read(uint16_t addr, void *p);
void sb_ct1345_mixer_reset(sb_t* sb);
void sb_close(void *p);
void sb_speed_changed(void *p);
void sb_add_status_info(char *s, int max_len, void *p);
#endif /* SOUND_SB_H */

View file

@ -10,13 +10,16 @@
#include "ibm.h" #include "ibm.h"
#include "device.h"
#include "dma.h" #include "dma.h"
#include "filters.h" #include "filters.h"
#include "io.h" #include "io.h"
#include "pic.h" #include "pic.h"
#include "sound.h" #include "sound.h"
#include "sound_azt2316a.h"
#include "sound_sb_dsp.h" #include "sound_sb_dsp.h"
#include "timer.h" #include "timer.h"
#include "x86.h"
/*The recording safety margin is intended for uneven "len" calls to the get_buffer mixer calls on sound_sb*/ /*The recording safety margin is intended for uneven "len" calls to the get_buffer mixer calls on sound_sb*/
#define SB_DSP_REC_SAFEFTY_MARGIN 4096 #define SB_DSP_REC_SAFEFTY_MARGIN 4096
@ -206,8 +209,16 @@ void sb_doreset(sb_dsp_t *dsp)
sb_dsp_reset(dsp); sb_dsp_reset(dsp);
if (dsp->sb_type==SB16) sb_commands[8] = 1; if (IS_AZTECH(dsp))
else sb_commands[8] = -1; {
sb_commands[8] = 1;
sb_commands[9] = 1;
}
else
{
if (dsp->sb_type==SB16) sb_commands[8] = 1;
else sb_commands[8] = -1;
}
for (c = 0; c < 256; c++) for (c = 0; c < 256; c++)
dsp->sb_asp_regs[c] = 0; dsp->sb_asp_regs[c] = 0;
@ -579,6 +590,20 @@ void sb_exec_command(sb_dsp_t *dsp)
sb_add_data(dsp, ~dsp->sb_data[0]); sb_add_data(dsp, ~dsp->sb_data[0]);
break; break;
case 0xE1: /*Get DSP version*/ case 0xE1: /*Get DSP version*/
if (IS_AZTECH(dsp))
{
if (dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11)
{
sb_add_data(dsp, 0x3);
sb_add_data(dsp, 0x1);
}
else if (dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C)
{
sb_add_data(dsp, 0x2);
sb_add_data(dsp, 0x1);
}
break;
}
sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] >> 8); sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] >> 8);
sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] & 0xff); sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] & 0xff);
break; break;
@ -617,6 +642,32 @@ void sb_exec_command(sb_dsp_t *dsp)
case 0xFF: case 0xFF:
break; break;
case 0x08: /*ASP get version*/ case 0x08: /*ASP get version*/
if (IS_AZTECH(dsp))
{
if ((dsp->sb_data[0] == 0x55 || dsp->sb_data[0] == 0x05) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11)
sb_add_data(dsp, 0x11); /* AZTECH get type, WASHINGTON/latest - according to devkit. E.g.: The one in the Itautec Infoway Multimidia */
else if ((dsp->sb_data[0] == 0x55 || dsp->sb_data[0] == 0x05) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C)
sb_add_data(dsp, 0x0C); /* AZTECH get type, CLINTON - according to devkit. E.g.: The one in the Packard Bell Legend 100CD */
else if (dsp->sb_data[0] == 0x08)
{
// EEPROM address to write followed by byte
if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE)
fatal("AZT EEPROM: out of bounds write to %02X\n", dsp->sb_data[1]);
dsp->azt_eeprom[dsp->sb_data[1]] = dsp->sb_data[2];
break;
}
else if (dsp->sb_data[0] == 0x07)
{
// EEPROM address to read
if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE)
fatal("AZT EEPROM: out of bounds read to %02X\n", dsp->sb_data[1]);
sb_add_data(dsp, dsp->azt_eeprom[dsp->sb_data[1]]);
break;
}
else
pclog("AZT2316A: UNKNOWN 0x08 COMMAND: %02X\n", dsp->sb_data[0]); // 0x08 (when shutting down, driver tries to read 1 byte of response), 0x55, 0x0D, 0x08D seen
break;
}
if (dsp->sb_type < SB16) break; if (dsp->sb_type < SB16) break;
sb_add_data(dsp, 0x18); sb_add_data(dsp, 0x18);
break; break;
@ -644,8 +695,24 @@ void sb_exec_command(sb_dsp_t *dsp)
case 0x04: case 0x04:
case 0x05: case 0x05:
break; break;
// default: case 0x09: /*AZTECH mode set*/
// fatal("Exec bad SB command %02X\n",sb_command); if (dsp->sb_data[0] == 0x00)
{
pclog("AZT2316A: WSS MODE!\n");
azt2316a_enable_wss(1, dsp->parent);
}
else if (dsp->sb_data[0] == 0x01)
{
pclog("AZT2316A: SB8PROV2 MODE!\n");
azt2316a_enable_wss(0, dsp->parent);
}
else
pclog("AZT2316A: UNKNOWN MODE!\n"); // sequences 0x02->0xFF, 0x04->0xFF seen
break;
case 0x38: /*TODO: AZTECH MIDI-related? */
break;
default:
fatal("Exec bad SB command %02X\n",dsp->sb_command);
/*TODO: Some more data about the DSP registeres /*TODO: Some more data about the DSP registeres
@ -680,7 +747,7 @@ void sb_write(uint16_t a, uint8_t v, void *priv)
dsp->sbreset = v; dsp->sbreset = v;
return; return;
case 0xC: /*Command/data write*/ case 0xC: /*Command/data write*/
timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1); timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1);
if (dsp->asp_data_len) if (dsp->asp_data_len)
{ {
// pclog("ASP data %i\n", dsp->asp_data_len); // pclog("ASP data %i\n", dsp->asp_data_len);
@ -699,11 +766,27 @@ void sb_write(uint16_t a, uint8_t v, void *priv)
dsp->sb_data_stat++; dsp->sb_data_stat++;
} }
else else
dsp->sb_data[dsp->sb_data_stat++] = v; {
dsp->sb_data[dsp->sb_data_stat++] = v;
if (IS_AZTECH(dsp))
{
// variable length commands
if (dsp->sb_command == 0x08 && dsp->sb_data_stat == 1 && dsp->sb_data[0] == 0x08)
sb_commands[dsp->sb_command] = 3;
else if (dsp->sb_command == 0x08 && dsp->sb_data_stat == 1 && dsp->sb_data[0] == 0x07)
sb_commands[dsp->sb_command] = 2;
}
}
if (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1) if (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1)
{ {
sb_exec_command(dsp); sb_exec_command(dsp);
dsp->sb_data_stat = -1; dsp->sb_data_stat = -1;
if (IS_AZTECH(dsp))
{
// variable length commands
if (dsp->sb_command == 0x08)
sb_commands[dsp->sb_command] = 1;
}
} }
break; break;
} }
@ -732,13 +815,31 @@ uint8_t sb_read(uint16_t a, void *priv)
if (dsp->wb_full || (dsp->busy_count & 2)) if (dsp->wb_full || (dsp->busy_count & 2))
{ {
dsp->wb_full = timer_is_enabled(&dsp->wb_timer); dsp->wb_full = timer_is_enabled(&dsp->wb_timer);
return 0xff; // pclog("SB read 0x80\n");
if (IS_AZTECH(dsp))
return 0x80;
else
return 0xFF;
} }
return 0x7f; // pclog("SB read 0x00\n");
if (IS_AZTECH(dsp))
return 0x00;
else
return 0x7F;
case 0xE: /*Read data ready*/ case 0xE: /*Read data ready*/
picintc(1 << dsp->sb_irqnum); picintc(1 << dsp->sb_irqnum);
dsp->sb_irq8 = dsp->sb_irq16 = 0; dsp->sb_irq8 = dsp->sb_irq16 = 0;
return (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff; // Only bit 7 is defined but aztech diagnostics fail if the others are set. Keep the original behavior to not interfere with what's already working.
if (IS_AZTECH(dsp))
{
// pclog("SB read %02X\n",(dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80);
return (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80;
}
else
{
// pclog("SB read %02X\n",(dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7F : 0xFF);
return (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7F : 0xFF;
}
case 0xF: /*16-bit ack*/ case 0xF: /*16-bit ack*/
dsp->sb_irq16 = 0; dsp->sb_irq16 = 0;
if (!dsp->sb_irq8) picintc(1 << dsp->sb_irqnum); if (!dsp->sb_irq8) picintc(1 << dsp->sb_irqnum);
@ -751,9 +852,11 @@ static void sb_wb_clear(void *p)
{ {
} }
void sb_dsp_init(sb_dsp_t *dsp, int type) void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent)
{ {
dsp->sb_type = type; dsp->sb_type = type;
dsp->sb_subtype = subtype;
dsp->parent = parent;
// Default values. Use sb_dsp_setxxx() methods to change. // Default values. Use sb_dsp_setxxx() methods to change.
dsp->sb_irqnum = 7; dsp->sb_irqnum = 7;

View file

@ -1,6 +1,20 @@
#ifndef SOUND_SB_DSP_H
#define SOUND_SB_DSP_H
/*Sound Blaster Clones, for quirks*/
#define SB_SUBTYPE_DEFAULT 0 /*Handle as a Creative card*/
#define SB_SUBTYPE_CLONE_AZT2316A_0X11 1 /*Aztech Sound Galaxy Pro 16 AB, DSP 3.1 - SBPRO2 clone*/
#define SB_SUBTYPE_CLONE_AZT1605_0X0C 2 /*Aztech Sound Galaxy Nova 16 Extra / Packard Bell Forte 16, DSP 2.1 - SBPRO2 clone*/
// aztech-related
#define IS_AZTECH(dsp) ((dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11 || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) // check for future AZT cards here
#define AZTECH_EEPROM_SIZE 16
typedef struct sb_dsp_t typedef struct sb_dsp_t
{ {
int sb_type; int sb_type;
int sb_subtype; // which clone
void *parent; // "sb_t *" if default subtype, "azt2316a_t *" if aztech.
int sb_8_length, sb_8_format, sb_8_autoinit, sb_8_pause, sb_8_enable, sb_8_autolen, sb_8_output; int sb_8_length, sb_8_format, sb_8_autoinit, sb_8_pause, sb_8_enable, sb_8_autolen, sb_8_output;
int sb_8_dmanum; int sb_8_dmanum;
@ -67,9 +81,11 @@ typedef struct sb_dsp_t
int16_t record_buffer[0xFFFF]; int16_t record_buffer[0xFFFF];
int16_t buffer[MAXSOUNDBUFLEN * 2]; int16_t buffer[MAXSOUNDBUFLEN * 2];
int pos; int pos;
uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; // the eeprom in the Aztech cards is attached to the DSP
} sb_dsp_t; } sb_dsp_t;
void sb_dsp_init(sb_dsp_t *dsp, int type); void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent);
void sb_dsp_close(sb_dsp_t *dsp); void sb_dsp_close(sb_dsp_t *dsp);
void sb_dsp_setirq(sb_dsp_t *dsp, int irq); void sb_dsp_setirq(sb_dsp_t *dsp, int irq);
@ -86,3 +102,5 @@ void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo);
void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp); void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp);
void sb_dsp_update(sb_dsp_t *dsp); void sb_dsp_update(sb_dsp_t *dsp);
#endif /* SOUND_SB_DSP_H */

View file

@ -84,7 +84,7 @@ void *wss_init()
opl_emu = device_get_config_int("opl_emu"); opl_emu = device_get_config_int("opl_emu");
opl3_init(&wss->opl, opl_emu); opl3_init(&wss->opl, opl_emu);
ad1848_init(&wss->ad1848); ad1848_init(&wss->ad1848, AD1848_TYPE_DEFAULT);
ad1848_setirq(&wss->ad1848, 7); ad1848_setirq(&wss->ad1848, 7);
ad1848_setdma(&wss->ad1848, 3); ad1848_setdma(&wss->ad1848, 3);