From 8576e2523bce461f9bf24694d0f7ec0e714955cf Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 10 May 2017 18:29:16 +0200 Subject: [PATCH] Implemented Sound Blaster MIDI through the DSP (was surprisingly missing before). Native Windows 3.1 and NT Sound Blaster drivers can now use their DSP to drive the MIDI out. Added MIDI out config to pre-SB16's for this new change. --- src/SOUND/snd_mpu401.c | 75 +++++++++++++++++++++++------------------- src/SOUND/snd_mpu401.h | 2 ++ src/SOUND/snd_sb.c | 9 +++++ src/SOUND/snd_sb_dsp.c | 35 ++++++++++++++++++++ src/SOUND/snd_sb_dsp.h | 6 +++- 5 files changed, 93 insertions(+), 34 deletions(-) diff --git a/src/SOUND/snd_mpu401.c b/src/SOUND/snd_mpu401.c index 526eecf84..5fcb15484 100644 --- a/src/SOUND/snd_mpu401.c +++ b/src/SOUND/snd_mpu401.c @@ -528,6 +528,47 @@ static void MPU401_EOIHandlerDispatch(void *p) MPU401_EOIHandler(mpu, 0); } +uint8_t MPU401_ReadData(mpu_t *mpu) +{ + uint8_t ret; + + ret = MSG_MPU_ACK; + if (mpu->queue_used) + { + if (mpu->queue_pos>=MPU401_QUEUE) mpu->queue_pos-=MPU401_QUEUE; + ret=mpu->queue[mpu->queue_pos]; + mpu->queue_pos++;mpu->queue_used--; + } + if (!mpu->intelligent) return ret; + + if (mpu->queue_used == 0) picintc(1 << mpu->irq); + + if (ret>=0xf0 && ret<=0xf7) + { /* MIDI data request */ + mpu->state.channel=ret&7; + mpu->state.data_onoff=0; + mpu->state.cond_req=0; + } + if (ret==MSG_MPU_COMMAND_REQ) + { + mpu->state.data_onoff=0; + mpu->state.cond_req=1; + if (mpu->condbuf.type!=T_OVERFLOW) + { + mpu->state.block_ack=1; + MPU401_WriteCommand(mpu, mpu->condbuf.value[0]); + if (mpu->state.command_byte) MPU401_WriteData(mpu, mpu->condbuf.value[1]); + } + mpu->condbuf.type=T_OVERFLOW; + } + if (ret==MSG_MPU_END || ret==MSG_MPU_CLOCK || ret==MSG_MPU_ACK) { + mpu->state.data_onoff=-1; + MPU401_EOIHandlerDispatch(mpu); + } + + return ret; +} + static void mpu401_write(uint16_t addr, uint8_t val, void *p) { mpu_t *mpu = (mpu_t *)p; @@ -554,39 +595,7 @@ static uint8_t mpu401_read(uint16_t addr, void *p) switch (addr & 1) { case 0: //Read Data - ret = MSG_MPU_ACK; - if (mpu->queue_used) - { - if (mpu->queue_pos>=MPU401_QUEUE) mpu->queue_pos-=MPU401_QUEUE; - ret=mpu->queue[mpu->queue_pos]; - mpu->queue_pos++;mpu->queue_used--; - } - if (!mpu->intelligent) return ret; - - if (mpu->queue_used == 0) picintc(1 << mpu->irq); - - if (ret>=0xf0 && ret<=0xf7) - { /* MIDI data request */ - mpu->state.channel=ret&7; - mpu->state.data_onoff=0; - mpu->state.cond_req=0; - } - if (ret==MSG_MPU_COMMAND_REQ) - { - mpu->state.data_onoff=0; - mpu->state.cond_req=1; - if (mpu->condbuf.type!=T_OVERFLOW) - { - mpu->state.block_ack=1; - MPU401_WriteCommand(mpu, mpu->condbuf.value[0]); - if (mpu->state.command_byte) MPU401_WriteData(mpu, mpu->condbuf.value[1]); - } - mpu->condbuf.type=T_OVERFLOW; - } - if (ret==MSG_MPU_END || ret==MSG_MPU_CLOCK || ret==MSG_MPU_ACK) { - mpu->state.data_onoff=-1; - MPU401_EOIHandlerDispatch(mpu); - } + ret = MPU401_ReadData(mpu); break; case 1: //Read Status diff --git a/src/SOUND/snd_mpu401.h b/src/SOUND/snd_mpu401.h index d8eedc25b..8cb721883 100644 --- a/src/SOUND/snd_mpu401.h +++ b/src/SOUND/snd_mpu401.h @@ -58,4 +58,6 @@ typedef struct mpu_t } clock; } mpu_t; +uint8_t MPU401_ReadData(mpu_t *mpu); + void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode); diff --git a/src/SOUND/snd_sb.c b/src/SOUND/snd_sb.c index 0308fa632..d5dee73d0 100644 --- a/src/SOUND/snd_sb.c +++ b/src/SOUND/snd_sb.c @@ -780,6 +780,9 @@ static device_config_t sb_config[] = } } }, + { + "midi", "MIDI out device", CONFIG_MIDI, "", 0 + }, { "", "", -1 } @@ -818,6 +821,9 @@ static device_config_t sb_mcv_config[] = } } }, + { + "midi", "MIDI out device", CONFIG_MIDI, "", 0 + }, { "", "", -1 } @@ -873,6 +879,9 @@ static device_config_t sb_pro_config[] = } } }, + { + "midi", "MIDI out device", CONFIG_MIDI, "", 0 + }, { "", "", -1 } diff --git a/src/SOUND/snd_sb_dsp.c b/src/SOUND/snd_sb_dsp.c index 16215d05e..f078cede9 100644 --- a/src/SOUND/snd_sb_dsp.c +++ b/src/SOUND/snd_sb_dsp.c @@ -11,8 +11,10 @@ #include "../dma.h" #include "../timer.h" #include "sound.h" +#include "snd_mpu401.h" #include "snd_sb_dsp.h" +mpu_t mpu; void pollsb(void *p); void sb_poll_i(void *p); @@ -321,6 +323,29 @@ void sb_exec_command(sb_dsp_t *dsp) temp = 1000000 / temp; dsp->sb_freq = temp; break; + + case 0x30: + case 0x31: + break; + + case 0x34: + dsp->uart_midi = 1; + dsp->uart_irq = 0; + break; + + case 0x35: + dsp->uart_midi = 1; + dsp->uart_irq = 1; + break; + + case 0x36: + case 0x37: + break; + + case 0x38: + dsp->onebyte_midi = 1; + break; + case 0x41: /*Set output sampling rate*/ case 0x42: /*Set input sampling rate*/ if (dsp->sb_type < SB16) break; @@ -514,6 +539,12 @@ void sb_write(uint16_t a, uint8_t v, void *priv) dsp->sbreset = v; return; case 0xC: /*Command/data write*/ + if (dsp->uart_midi || dsp->onebyte_midi) + { + midi_write(v); + dsp->onebyte_midi = 0; + return; + } timer_process(); dsp->wb_time = TIMER_USEC * 1; dsp->wb_full = 1; @@ -549,6 +580,10 @@ uint8_t sb_read(uint16_t a, void *priv) switch (a & 0xf) { case 0xA: /*Read data*/ + if (dsp->uart_midi) + { + return MPU401_ReadData(&mpu); + } dsp->sbreaddat = dsp->sb_read_data[dsp->sb_read_rp]; if (dsp->sb_read_rp != dsp->sb_read_wp) { diff --git a/src/SOUND/snd_sb_dsp.h b/src/SOUND/snd_sb_dsp.h index 9d4dee133..fb14284fa 100644 --- a/src/SOUND/snd_sb_dsp.h +++ b/src/SOUND/snd_sb_dsp.h @@ -1,5 +1,9 @@ typedef struct sb_dsp_t -{ +{ + int uart_midi; + int uart_irq; + int onebyte_midi; + int sb_type; int sb_8_length, sb_8_format, sb_8_autoinit, sb_8_pause, sb_8_enable, sb_8_autolen, sb_8_output;