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:
parent
47e557e9ce
commit
1181b13c2d
17 changed files with 2051 additions and 179 deletions
|
|
@ -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 \
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
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 \
|
||||
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_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 \
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
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 \
|
||||
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_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 \
|
||||
|
|
|
|||
37
src/sound.c
37
src/sound.c
|
|
@ -15,6 +15,7 @@
|
|||
#include "sound_adlib.h"
|
||||
#include "sound_adlibgold.h"
|
||||
#include "sound_audiopci.h"
|
||||
#include "sound_azt2316a.h"
|
||||
#include "sound_pas16.h"
|
||||
#include "sound_sb.h"
|
||||
#include "sound_sb_dsp.h"
|
||||
|
|
@ -35,23 +36,25 @@ typedef struct
|
|||
|
||||
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},
|
||||
{"Windows Sound System", "wss", &wss_device},
|
||||
{"Pro Audio Spectrum 16", "pas16", &pas16_device},
|
||||
{"Ensoniq AudioPCI (ES1371)", "es1371", &es1371_device},
|
||||
{"Sound Blaster PCI 128", "sbpci128", &es1371_device},
|
||||
{"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},
|
||||
{"Windows Sound System", "wss", &wss_device},
|
||||
{"Aztech Sound Galaxy Pro 16 AB (Washington)", "azt2316a", &azt2316a_device},
|
||||
{"Aztech Sound Galaxy Nova 16 Extra (Clinton)", "azt1605", &azt1605_device},
|
||||
{"Pro Audio Spectrum 16", "pas16", &pas16_device},
|
||||
{"Ensoniq AudioPCI (ES1371)", "es1371", &es1371_device},
|
||||
{"Sound Blaster PCI 128", "sbpci128", &es1371_device},
|
||||
{"", "", NULL}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@
|
|||
#include "pic.h"
|
||||
#include "sound.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)
|
||||
{
|
||||
|
|
@ -21,7 +23,7 @@ uint8_t ad1848_read(uint16_t addr, void *p)
|
|||
{
|
||||
ad1848_t *ad1848 = (ad1848_t *)p;
|
||||
uint8_t temp = 0xff;
|
||||
// pclog("ad1848_read - addr %04X %04X(%08X):%08X ", addr, CS, cs, pc);
|
||||
|
||||
switch (addr & 3)
|
||||
{
|
||||
case 0: /*Index*/
|
||||
|
|
@ -34,7 +36,10 @@ uint8_t ad1848_read(uint16_t addr, void *p)
|
|||
temp = ad1848->status;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -42,11 +47,18 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
|
|||
{
|
||||
ad1848_t *ad1848 = (ad1848_t *)p;
|
||||
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)
|
||||
{
|
||||
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->mce = val & 0x40;
|
||||
break;
|
||||
|
|
@ -71,29 +83,49 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
|
|||
break;
|
||||
|
||||
case 9:
|
||||
if (!ad1848->enable && (val & 0x41) == 0x01)
|
||||
{
|
||||
if (ad1848->timer_latch)
|
||||
timer_set_delay_u64(&ad1848->timer, ad1848->timer_latch);
|
||||
else
|
||||
timer_set_delay_u64(&ad1848->timer, TIMER_USEC);
|
||||
}
|
||||
if (!ad1848->enable && (val & 0x41) == 0x01)
|
||||
{
|
||||
if (ad1848->timer_latch)
|
||||
timer_set_delay_u64(&ad1848->timer, ad1848->timer_latch);
|
||||
else
|
||||
timer_set_delay_u64(&ad1848->timer, TIMER_USEC);
|
||||
}
|
||||
ad1848->enable = ((val & 0x41) == 0x01);
|
||||
if (!ad1848->enable)
|
||||
{
|
||||
timer_disable(&ad1848->timer);
|
||||
{
|
||||
timer_disable(&ad1848->timer);
|
||||
ad1848->out_l = ad1848->out_r = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 12:
|
||||
ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80;
|
||||
return;
|
||||
|
||||
case 14:
|
||||
ad1848->count = ad1848->regs[15] | (val << 8);
|
||||
break;
|
||||
// TODO: see which of the extended registers should be read only
|
||||
}
|
||||
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;
|
||||
case 2:
|
||||
ad1848->status &= 0xfe;
|
||||
|
|
@ -125,7 +157,7 @@ static void ad1848_poll(void *p)
|
|||
timer_advance_u64(&ad1848->timer, TIMER_USEC*1000);
|
||||
|
||||
ad1848_update(ad1848);
|
||||
|
||||
// TODO: line in, mic, etc...
|
||||
if (ad1848->enable)
|
||||
{
|
||||
int32_t temp;
|
||||
|
|
@ -155,12 +187,12 @@ static void ad1848_poll(void *p)
|
|||
if (ad1848->regs[6] & 0x80)
|
||||
ad1848->out_l = 0;
|
||||
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)
|
||||
ad1848->out_r = 0;
|
||||
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)
|
||||
{
|
||||
|
|
@ -179,15 +211,17 @@ static void ad1848_poll(void *p)
|
|||
else
|
||||
{
|
||||
ad1848->out_l = ad1848->out_r = 0;
|
||||
sound_set_cd_volume(0, 0);
|
||||
// pclog("ad1848_poll : not enable\n");
|
||||
}
|
||||
}
|
||||
|
||||
void ad1848_init(ad1848_t *ad1848)
|
||||
void ad1848_init(ad1848_t *ad1848, int type)
|
||||
{
|
||||
int c;
|
||||
double attenuation;
|
||||
|
||||
ad1848->type = type;
|
||||
ad1848->enable = 0;
|
||||
|
||||
ad1848->status = 0xcc;
|
||||
|
|
@ -195,15 +229,24 @@ void ad1848_init(ad1848_t *ad1848)
|
|||
ad1848->mce = 0x40;
|
||||
|
||||
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[6] = ad1848->regs[7] = 0x80;
|
||||
ad1848->regs[6] = ad1848->regs[7] = 0x80; // AZT2316A Master?
|
||||
ad1848->regs[8] = 0;
|
||||
ad1848->regs[9] = 0x08;
|
||||
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[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_r = 0;
|
||||
|
|
@ -220,9 +263,23 @@ void ad1848_init(ad1848_t *ad1848)
|
|||
|
||||
attenuation = pow(10, attenuation / 10);
|
||||
|
||||
ad1848_vols[c] = (int)(attenuation * 65536);
|
||||
// pclog("ad1848_vols %i = %f %i\n", c, attenuation, ad1848_vols[c]);
|
||||
ad1848_vols_6bits[c] = (int)(attenuation * 65536);
|
||||
// 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
#include "timer.h"
|
||||
|
||||
#define AD1848_TYPE_DEFAULT 0
|
||||
#define AD1848_TYPE_CS4248 1
|
||||
#define AD1848_TYPE_CS4231 2
|
||||
|
||||
typedef struct ad1848_t
|
||||
{
|
||||
int index;
|
||||
uint8_t regs[16];
|
||||
uint8_t regs[32]; // 16 original + 16 CS4231A extensions
|
||||
uint8_t status;
|
||||
|
||||
int trd;
|
||||
|
|
@ -20,10 +24,12 @@ typedef struct ad1848_t
|
|||
int freq;
|
||||
|
||||
pc_timer_t timer;
|
||||
uint64_t timer_latch;
|
||||
uint64_t timer_latch;
|
||||
|
||||
int16_t buffer[MAXSOUNDBUFLEN * 2];
|
||||
int pos;
|
||||
|
||||
int type;
|
||||
} ad1848_t;
|
||||
|
||||
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_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
1620
src/sound_azt2316a.c
Normal file
File diff suppressed because it is too large
Load diff
4
src/sound_azt2316a.h
Normal file
4
src/sound_azt2316a.h
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
extern device_t azt2316a_device;
|
||||
extern device_t azt1605_device;
|
||||
|
||||
void azt2316a_enable_wss(uint8_t enable, void *p);
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
#ifndef SOUND_EMU8K_H
|
||||
#define SOUND_EMU8K_H
|
||||
|
||||
/* All these defines are in samples, not in bytes. */
|
||||
#define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF
|
||||
|
|
@ -773,3 +775,5 @@ Treble Parameters:
|
|||
0xD308 0xD308 0xD308 0xD308 0xD308 0xD308 0xD3019 0xD32A 0xD34C 0xD36E 0xD36E 0xD36E
|
||||
0x0001 0x0001 0x0001 0x0001 0x0001 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002
|
||||
*/
|
||||
|
||||
#endif /* SOUND_EMU8K_H */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "ibm.h"
|
||||
#include "io.h"
|
||||
#include "pic.h"
|
||||
#include "plat-midi.h"
|
||||
#include "sound_mpu401_uart.h"
|
||||
|
||||
|
|
@ -9,6 +10,14 @@ enum
|
|||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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->status = 0;
|
||||
mpu->status = STATUS_OUTPUT_NOT_READY;
|
||||
mpu->uart_mode = 0;
|
||||
//mpu401_uart_raise_irq(p);
|
||||
break;
|
||||
|
||||
case 0x3f: /*Enter UART mode*/
|
||||
mpu->rx_data = 0xfe; /*Acknowledge*/
|
||||
mpu->status = 0;
|
||||
mpu->status = STATUS_OUTPUT_NOT_READY;
|
||||
mpu->uart_mode = 1;
|
||||
mpu401_uart_raise_irq(p);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
|
@ -45,14 +59,30 @@ static uint8_t mpu401_uart_read(uint16_t addr, void *p)
|
|||
return mpu->status;
|
||||
|
||||
/*Data*/
|
||||
mpu->status |= STATUS_INPUT_NOT_READY;
|
||||
mpu->status = STATUS_INPUT_NOT_READY;
|
||||
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->uart_mode = 0;
|
||||
mpu->addr = addr;
|
||||
mpu->irq = irq;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,18 @@
|
|||
#ifndef SOUND_MPU401_UART
|
||||
#define SOUND_MPU401_UART
|
||||
|
||||
typedef struct mpu401_uart_t
|
||||
{
|
||||
uint8_t status;
|
||||
uint8_t rx_data;
|
||||
|
||||
int uart_mode;
|
||||
int uart_mode;
|
||||
uint16_t addr;
|
||||
int irq;
|
||||
} 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 */
|
||||
|
|
|
|||
|
|
@ -737,7 +737,7 @@ void *pas16_init()
|
|||
memset(pas16, 0, sizeof(pas16_t));
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
|||
120
src/sound_sb.c
120
src/sound_sb.c
|
|
@ -21,102 +21,6 @@ FILE* soundfsb = 0/*NULL*/;
|
|||
FILE* soundfsbin = 0/*NULL*/;
|
||||
#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.
|
||||
Note that for positive dB values, this is not amplitude, it is amplitude-1. */
|
||||
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;
|
||||
}
|
||||
|
||||
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_ct1345_mixer_t *mixer = &sb->mixer_sbpro;
|
||||
|
|
@ -950,7 +854,7 @@ void *sb_1_init()
|
|||
memset(sb, 0, sizeof(sb_t));
|
||||
|
||||
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_setirq(&sb->dsp, device_get_config_int("irq"));
|
||||
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
|
||||
|
|
@ -972,7 +876,7 @@ void *sb_15_init()
|
|||
memset(sb, 0, sizeof(sb_t));
|
||||
|
||||
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_setirq(&sb->dsp, device_get_config_int("irq"));
|
||||
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
|
||||
|
|
@ -993,7 +897,7 @@ void *sb_mcv_init()
|
|||
memset(sb, 0, sizeof(sb_t));
|
||||
|
||||
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_setirq(&sb->dsp, device_get_config_int("irq"));
|
||||
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
|
||||
|
|
@ -1024,7 +928,7 @@ void *sb_2_init()
|
|||
memset(sb, 0, sizeof(sb_t));
|
||||
|
||||
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_setirq(&sb->dsp, device_get_config_int("irq"));
|
||||
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));
|
||||
|
||||
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_setirq(&sb->dsp, device_get_config_int("irq"));
|
||||
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");
|
||||
sb->opl_emu = device_get_config_int("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_setirq(&sb->dsp, device_get_config_int("irq"));
|
||||
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");
|
||||
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);
|
||||
/* I/O handlers activated in sb_mcv_write */
|
||||
sound_add_handler(sb_get_buffer_sbpro, sb);
|
||||
|
|
@ -1139,7 +1043,7 @@ void *sb_16_init()
|
|||
uint16_t addr = device_get_config_int("addr");
|
||||
sb->opl_emu = device_get_config_int("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);
|
||||
// TODO: irq and dma options too?
|
||||
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(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb);
|
||||
sound_add_handler(sb_get_buffer_sb16, sb);
|
||||
mpu401_uart_init(&sb->mpu, 0x330);
|
||||
mpu401_uart_init(&sb->mpu, 0x330, -1);
|
||||
|
||||
|
||||
return sb;
|
||||
|
|
@ -1169,7 +1073,7 @@ void *sb_awe32_init()
|
|||
uint16_t emu_addr = device_get_config_int("emu_addr");
|
||||
sb->opl_emu = device_get_config_int("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);
|
||||
// TODO: irq and dma options too?
|
||||
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(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, 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);
|
||||
|
||||
return sb;
|
||||
|
|
|
|||
114
src/sound_sb.h
114
src/sound_sb.h
|
|
@ -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_15_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_16_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 */
|
||||
|
|
|
|||
|
|
@ -10,13 +10,16 @@
|
|||
#include "ibm.h"
|
||||
|
||||
|
||||
#include "device.h"
|
||||
#include "dma.h"
|
||||
#include "filters.h"
|
||||
#include "io.h"
|
||||
#include "pic.h"
|
||||
#include "sound.h"
|
||||
#include "sound_azt2316a.h"
|
||||
#include "sound_sb_dsp.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*/
|
||||
#define SB_DSP_REC_SAFEFTY_MARGIN 4096
|
||||
|
|
@ -205,10 +208,18 @@ void sb_doreset(sb_dsp_t *dsp)
|
|||
int c;
|
||||
|
||||
sb_dsp_reset(dsp);
|
||||
|
||||
if (dsp->sb_type==SB16) sb_commands[8] = 1;
|
||||
else sb_commands[8] = -1;
|
||||
|
||||
|
||||
if (IS_AZTECH(dsp))
|
||||
{
|
||||
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++)
|
||||
dsp->sb_asp_regs[c] = 0;
|
||||
dsp->sb_asp_regs[5] = 0x01;
|
||||
|
|
@ -579,6 +590,20 @@ void sb_exec_command(sb_dsp_t *dsp)
|
|||
sb_add_data(dsp, ~dsp->sb_data[0]);
|
||||
break;
|
||||
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] & 0xff);
|
||||
break;
|
||||
|
|
@ -617,6 +642,32 @@ void sb_exec_command(sb_dsp_t *dsp)
|
|||
case 0xFF:
|
||||
break;
|
||||
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;
|
||||
sb_add_data(dsp, 0x18);
|
||||
break;
|
||||
|
|
@ -644,10 +695,26 @@ void sb_exec_command(sb_dsp_t *dsp)
|
|||
case 0x04:
|
||||
case 0x05:
|
||||
break;
|
||||
// default:
|
||||
// fatal("Exec bad SB command %02X\n",sb_command);
|
||||
|
||||
|
||||
case 0x09: /*AZTECH mode set*/
|
||||
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
|
||||
* http://the.earth.li/~tfm/oldpage/sb_dsp.html
|
||||
* http://www.synchrondata.com/pheaven/www/area19.htm
|
||||
|
|
@ -680,7 +747,7 @@ void sb_write(uint16_t a, uint8_t v, void *priv)
|
|||
dsp->sbreset = v;
|
||||
return;
|
||||
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)
|
||||
{
|
||||
// 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++;
|
||||
}
|
||||
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)
|
||||
{
|
||||
sb_exec_command(dsp);
|
||||
dsp->sb_data_stat = -1;
|
||||
if (IS_AZTECH(dsp))
|
||||
{
|
||||
// variable length commands
|
||||
if (dsp->sb_command == 0x08)
|
||||
sb_commands[dsp->sb_command] = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -732,13 +815,31 @@ uint8_t sb_read(uint16_t a, void *priv)
|
|||
if (dsp->wb_full || (dsp->busy_count & 2))
|
||||
{
|
||||
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*/
|
||||
picintc(1 << dsp->sb_irqnum);
|
||||
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*/
|
||||
dsp->sb_irq16 = 0;
|
||||
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_subtype = subtype;
|
||||
dsp->parent = parent;
|
||||
|
||||
// Default values. Use sb_dsp_setxxx() methods to change.
|
||||
dsp->sb_irqnum = 7;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
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_dmanum;
|
||||
|
|
@ -67,9 +81,11 @@ typedef struct sb_dsp_t
|
|||
int16_t record_buffer[0xFFFF];
|
||||
int16_t buffer[MAXSOUNDBUFLEN * 2];
|
||||
int pos;
|
||||
|
||||
uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; // the eeprom in the Aztech cards is attached to the DSP
|
||||
} 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_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_update(sb_dsp_t *dsp);
|
||||
|
||||
#endif /* SOUND_SB_DSP_H */
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ void *wss_init()
|
|||
|
||||
opl_emu = device_get_config_int("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_setdma(&wss->ad1848, 3);
|
||||
|
|
|
|||
Loading…
Reference in a new issue