2016-06-26 00:34:39 +02:00
/*Jazz sample rates :
386 - 33 - 12 kHz
486 - 33 - 20 kHz
486 - 50 - 32 kHz
Pentium - 45 kHz */
2017-10-14 07:03:19 +02:00
2020-04-04 12:45:47 +02:00
# define _USE_MATH_DEFINES
2018-02-15 23:14:44 +01:00
# include <math.h>
2018-05-21 19:04:05 +02:00
# include <stdarg.h>
2017-09-25 04:31:20 -04:00
# include <stdint.h>
2018-05-21 19:04:05 +02:00
# include <stdio.h>
2017-10-14 13:38:05 -04:00
# include <stdlib.h>
2022-02-22 20:28:56 -05:00
# include <string.h>
2017-10-14 13:38:05 -04:00
# include <wchar.h>
2018-05-21 19:04:05 +02:00
# define HAVE_STDARG_H
2022-02-22 20:28:56 -05:00
2020-03-29 14:24:42 +02:00
# include <86box/86box.h>
# include <86box/device.h>
2022-02-22 20:28:56 -05:00
# include <86box/dma.h>
2020-03-29 14:24:42 +02:00
# include <86box/filters.h>
2022-02-22 20:28:56 -05:00
# include <86box/io.h>
2020-03-29 14:24:42 +02:00
# include <86box/midi.h>
2022-02-22 20:28:56 -05:00
# include <86box/pic.h>
2020-03-29 14:24:42 +02:00
# include <86box/snd_azt2316a.h>
2022-02-22 20:28:56 -05:00
# include <86box/sound.h>
# include <86box/timer.h>
2020-03-29 14:24:42 +02:00
# include <86box/snd_sb.h>
2023-07-26 10:57:01 -04:00
# include <86box/plat_fallthrough.h>
2023-06-09 23:46:54 -04:00
# include <86box/plat_unused.h>
2017-05-06 17:48:33 +02:00
2022-02-22 20:28:56 -05:00
# define ADPCM_4 1
# define ADPCM_26 2
# define ADPCM_2 3
2019-12-21 20:03:07 +01:00
2017-10-14 07:03:19 +02:00
/*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
2016-06-26 00:34:39 +02:00
2023-06-09 23:46:54 -04:00
void pollsb ( void * priv ) ;
void sb_poll_i ( void * priv ) ;
2016-06-26 00:34:39 +02:00
static int sbe2dat [ 4 ] [ 9 ] = {
2022-02-22 20:28:56 -05:00
{ 0x01 , - 0x02 , - 0x04 , 0x08 , - 0x10 , 0x20 , 0x40 , - 0x80 , - 106 } ,
{ - 0x01 , 0x02 , - 0x04 , 0x08 , 0x10 , - 0x20 , 0x40 , - 0x80 , 165 } ,
{ - 0x01 , 0x02 , 0x04 , - 0x08 , 0x10 , - 0x20 , - 0x40 , 0x80 , - 151 } ,
{ 0x01 , - 0x02 , 0x04 , - 0x08 , - 0x10 , 0x20 , - 0x40 , 0x80 , 90 }
2016-06-26 00:34:39 +02:00
} ;
2022-02-22 20:28:56 -05:00
static int sb_commands [ 256 ] = {
- 1 , 2 , - 1 , 0 , 1 , 2 , - 1 , 0 , 1 , - 1 , - 1 , - 1 , - 1 , - 1 , 2 , 1 ,
1 , - 1 , - 1 , - 1 , 2 , - 1 , 2 , 2 , - 1 , - 1 , - 1 , - 1 , 0 , - 1 , - 1 , 0 ,
0 , - 1 , - 1 , - 1 , 2 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , 0 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
1 , 2 , 2 , - 1 , - 1 , - 1 , - 1 , - 1 , 2 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , 2 , 2 , 2 , 2 , - 1 , - 1 , - 1 , - 1 , - 1 , 0 , - 1 , 0 ,
2 , 2 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , 2 , 2 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
0 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , 0 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ,
3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ,
0 , 0 , - 1 , 0 , 0 , 0 , 0 , - 1 , 0 , 0 , 0 , - 1 , - 1 , - 1 , - 1 , - 1 ,
1 , 0 , 1 , 0 , 1 , - 1 , - 1 , 0 , 0 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , 0 , 0 , - 1 , - 1 , - 1 , - 1 , - 1 , 1 , 2 , - 1 , - 1 , - 1 , - 1 , 0
2016-06-26 00:34:39 +02:00
} ;
2022-02-22 20:28:56 -05:00
char sb16_copyright [ ] = " COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992. " ;
2023-10-20 21:02:35 +02:00
uint16_t sb_dsp_versions [ ] = { 0 , 0 , 0x105 , 0x200 , 0x201 , 0x300 , 0x302 , 0x405 , 0x40c , 0x40d , 0x410 } ;
2019-12-21 20:03:07 +01:00
2016-06-26 00:34:39 +02:00
/*These tables were 'borrowed' from DOSBox*/
2019-12-21 20:03:07 +01:00
int8_t scaleMap4 [ 64 ] = {
2022-02-22 20:28:56 -05:00
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 0 , - 1 , - 2 , - 3 , - 4 , - 5 , - 6 , - 7 ,
1 , 3 , 5 , 7 , 9 , 11 , 13 , 15 , - 1 , - 3 , - 5 , - 7 , - 9 , - 11 , - 13 , - 15 ,
2 , 6 , 10 , 14 , 18 , 22 , 26 , 30 , - 2 , - 6 , - 10 , - 14 , - 18 , - 22 , - 26 , - 30 ,
2021-11-07 06:30:40 +05:00
4 , 12 , 20 , 28 , 36 , 44 , 52 , 60 , - 4 , - 12 , - 20 , - 28 , - 36 , - 44 , - 52 , - 60
2019-12-21 20:03:07 +01:00
} ;
uint8_t adjustMap4 [ 64 ] = {
2022-02-22 20:28:56 -05:00
0 , 0 , 0 , 0 , 0 , 16 , 16 , 16 ,
0 , 0 , 0 , 0 , 0 , 16 , 16 , 16 ,
2021-11-07 06:30:40 +05:00
240 , 0 , 0 , 0 , 0 , 16 , 16 , 16 ,
240 , 0 , 0 , 0 , 0 , 16 , 16 , 16 ,
240 , 0 , 0 , 0 , 0 , 16 , 16 , 16 ,
240 , 0 , 0 , 0 , 0 , 16 , 16 , 16 ,
2022-02-22 20:28:56 -05:00
240 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
240 , 0 , 0 , 0 , 0 , 0 , 0 , 0
2019-12-21 20:03:07 +01:00
} ;
int8_t scaleMap26 [ 40 ] = {
2022-02-22 20:28:56 -05:00
0 , 1 , 2 , 3 , 0 , - 1 , - 2 , - 3 ,
1 , 3 , 5 , 7 , - 1 , - 3 , - 5 , - 7 ,
2 , 6 , 10 , 14 , - 2 , - 6 , - 10 , - 14 ,
2021-11-07 06:30:40 +05:00
4 , 12 , 20 , 28 , - 4 , - 12 , - 20 , - 28 ,
5 , 15 , 25 , 35 , - 5 , - 15 , - 25 , - 35
2019-12-21 20:03:07 +01:00
} ;
uint8_t adjustMap26 [ 40 ] = {
2022-02-22 20:28:56 -05:00
0 , 0 , 0 , 8 , 0 , 0 , 0 , 8 ,
2021-11-07 06:30:40 +05:00
248 , 0 , 0 , 8 , 248 , 0 , 0 , 8 ,
248 , 0 , 0 , 8 , 248 , 0 , 0 , 8 ,
248 , 0 , 0 , 8 , 248 , 0 , 0 , 8 ,
248 , 0 , 0 , 0 , 248 , 0 , 0 , 0
2019-12-21 20:03:07 +01:00
} ;
int8_t scaleMap2 [ 24 ] = {
2022-02-22 20:28:56 -05:00
0 , 1 , 0 , - 1 , 1 , 3 , - 1 , - 3 ,
2 , 6 , - 2 , - 6 , 4 , 12 , - 4 , - 12 ,
2021-11-07 06:30:40 +05:00
8 , 24 , - 8 , - 24 , 6 , 48 , - 16 , - 48
2019-12-21 20:03:07 +01:00
} ;
uint8_t adjustMap2 [ 24 ] = {
2022-02-22 20:28:56 -05:00
0 , 4 , 0 , 4 ,
2021-11-07 06:30:40 +05:00
252 , 4 , 252 , 4 , 252 , 4 , 252 , 4 ,
252 , 4 , 252 , 4 , 252 , 4 , 252 , 4 ,
252 , 0 , 252 , 0
2019-12-21 20:03:07 +01:00
} ;
2016-06-26 00:34:39 +02:00
2023-10-21 06:53:11 +02:00
double low_fir_sb16_coef [ 3 ] [ SB16_NCoef ] ;
2020-01-02 18:19:22 +01:00
2018-05-21 19:04:05 +02:00
# ifdef ENABLE_SB_DSP_LOG
int sb_dsp_do_log = ENABLE_SB_DSP_LOG ;
static void
sb_dsp_log ( const char * fmt , . . . )
{
2021-11-07 06:30:40 +05:00
va_list ap ;
2018-05-21 19:04:05 +02:00
2021-11-07 06:30:40 +05:00
if ( sb_dsp_do_log ) {
2022-02-22 20:28:56 -05:00
va_start ( ap , fmt ) ;
pclog_ex ( fmt , ap ) ;
va_end ( ap ) ;
2021-11-07 06:30:40 +05:00
}
2018-05-21 19:04:05 +02:00
}
2018-10-19 00:39:32 +02:00
# else
2022-02-22 20:28:56 -05:00
# define sb_dsp_log(fmt, ...)
2018-10-19 00:39:32 +02:00
# endif
2018-05-21 19:04:05 +02:00
2019-12-21 20:03:07 +01:00
static __inline double
sinc ( double x )
2018-02-15 23:14:44 +01:00
{
2021-11-07 06:30:40 +05:00
return sin ( M_PI * x ) / ( M_PI * x ) ;
2018-02-15 23:14:44 +01:00
}
2019-12-21 20:03:07 +01:00
static void
2020-10-21 02:46:50 +02:00
recalc_sb16_filter ( int c , int playback_freq )
2018-02-15 23:14:44 +01:00
{
2021-11-07 06:30:40 +05:00
/* Cutoff frequency = playback / 2 */
2022-02-22 20:28:56 -05:00
int n ;
2023-05-29 01:30:51 -04:00
double w ;
double h ;
2022-11-06 23:45:35 -05:00
double fC = ( ( double ) playback_freq ) / ( double ) FREQ_96000 ;
2021-11-07 06:30:40 +05:00
double gain ;
2020-10-21 02:46:50 +02:00
2021-11-07 06:30:40 +05:00
for ( n = 0 ; n < SB16_NCoef ; n + + ) {
2022-02-22 20:28:56 -05:00
/* Blackman window */
w = 0.42 - ( 0.5 * cos ( ( 2.0 * n * M_PI ) / ( double ) ( SB16_NCoef - 1 ) ) ) + ( 0.08 * cos ( ( 4.0 * n * M_PI ) / ( double ) ( SB16_NCoef - 1 ) ) ) ;
/* Sinc filter */
h = sinc ( 2.0 * fC * ( ( double ) n - ( ( double ) ( SB16_NCoef - 1 ) / 2.0 ) ) ) ;
2019-12-21 20:03:07 +01:00
2022-02-22 20:28:56 -05:00
/* Create windowed-sinc filter */
low_fir_sb16_coef [ c ] [ n ] = w * h ;
2021-11-07 06:30:40 +05:00
}
2019-12-21 20:03:07 +01:00
2021-11-07 06:30:40 +05:00
low_fir_sb16_coef [ c ] [ ( SB16_NCoef - 1 ) / 2 ] = 1.0 ;
2018-02-15 23:14:44 +01:00
2021-11-07 06:30:40 +05:00
gain = 0.0 ;
for ( n = 0 ; n < SB16_NCoef ; n + + )
2022-02-22 20:28:56 -05:00
gain + = low_fir_sb16_coef [ c ] [ n ] ;
2018-02-15 23:14:44 +01:00
2021-11-07 06:30:40 +05:00
/* Normalise filter, to produce unity gain */
for ( n = 0 ; n < SB16_NCoef ; n + + )
2022-02-22 20:28:56 -05:00
low_fir_sb16_coef [ c ] [ n ] / = gain ;
2018-02-15 23:14:44 +01:00
}
2016-06-26 00:34:39 +02:00
2022-03-06 19:59:14 -03:00
static void
sb_irq_update_pic ( void * priv , int set )
{
2023-07-20 18:58:26 -04:00
const sb_dsp_t * dsp = ( sb_dsp_t * ) priv ;
2022-03-06 19:59:14 -03:00
if ( set )
2022-03-16 14:12:45 -03:00
picint ( 1 < < dsp - > sb_irqnum ) ;
2022-03-06 19:59:14 -03:00
else
2022-03-16 14:12:45 -03:00
picintc ( 1 < < dsp - > sb_irqnum ) ;
2022-03-06 19:59:14 -03:00
}
2019-12-21 20:03:07 +01:00
void
2021-04-02 08:51:39 +02:00
sb_update_mask ( sb_dsp_t * dsp , int irqm8 , int irqm16 , int irqm401 )
2020-04-12 00:18:55 +02:00
{
2021-11-07 06:30:40 +05:00
int clear = 0 ;
2021-04-02 08:51:39 +02:00
2021-11-07 06:30:40 +05:00
if ( ! dsp - > sb_irqm8 & & irqm8 )
2022-02-22 20:28:56 -05:00
clear | = 1 ;
2021-11-07 06:30:40 +05:00
dsp - > sb_irqm8 = irqm8 ;
if ( ! dsp - > sb_irqm16 & & irqm16 )
2022-02-22 20:28:56 -05:00
clear | = 1 ;
2021-11-07 06:30:40 +05:00
dsp - > sb_irqm16 = irqm16 ;
if ( ! dsp - > sb_irqm401 & & irqm401 )
2022-02-22 20:28:56 -05:00
clear | = 1 ;
2021-11-07 06:30:40 +05:00
dsp - > sb_irqm401 = irqm401 ;
2021-04-02 08:51:39 +02:00
2021-11-07 06:30:40 +05:00
if ( clear )
2022-03-06 19:59:14 -03:00
dsp - > irq_update ( dsp - > irq_priv , 0 ) ;
2020-04-12 00:18:55 +02:00
}
void
sb_update_status ( sb_dsp_t * dsp , int bit , int set )
2016-06-26 00:34:39 +02:00
{
2021-11-07 06:30:40 +05:00
int masked = 0 ;
2021-04-02 08:51:39 +02:00
2021-11-07 06:30:40 +05:00
switch ( bit ) {
2022-02-22 20:28:56 -05:00
default :
2023-06-09 23:46:54 -04:00
case 0 :
2022-02-22 20:28:56 -05:00
dsp - > sb_irq8 = set ;
masked = dsp - > sb_irqm8 ;
break ;
case 1 :
dsp - > sb_irq16 = set ;
masked = dsp - > sb_irqm16 ;
break ;
case 2 :
dsp - > sb_irq401 = set ;
masked = dsp - > sb_irqm401 ;
break ;
2021-11-07 06:30:40 +05:00
}
2019-12-21 20:03:07 +01:00
2021-11-07 06:30:40 +05:00
if ( set & & ! masked )
2022-03-06 19:59:14 -03:00
dsp - > irq_update ( dsp - > irq_priv , 1 ) ;
2021-11-07 06:30:40 +05:00
else if ( ! set )
2022-03-06 19:59:14 -03:00
dsp - > irq_update ( dsp - > irq_priv , 0 ) ;
2020-04-12 00:18:55 +02:00
}
void
sb_irq ( sb_dsp_t * dsp , int irq8 )
{
2021-11-07 06:30:40 +05:00
sb_update_status ( dsp , ! irq8 , 1 ) ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
sb_irqc ( sb_dsp_t * dsp , int irq8 )
2016-06-26 00:34:39 +02:00
{
2021-11-07 06:30:40 +05:00
sb_update_status ( dsp , ! irq8 , 0 ) ;
2020-04-12 00:18:55 +02:00
}
2019-12-21 20:03:07 +01:00
2020-04-12 00:18:55 +02:00
static void
sb_dsp_irq_update ( void * priv , int set )
{
2021-11-07 06:30:40 +05:00
sb_dsp_t * dsp = ( sb_dsp_t * ) priv ;
2020-04-12 00:18:55 +02:00
2021-11-07 06:30:40 +05:00
sb_update_status ( dsp , 2 , set ) ;
2020-04-12 00:18:55 +02:00
}
static int
sb_dsp_irq_pending ( void * priv )
{
2023-07-20 18:58:26 -04:00
const sb_dsp_t * dsp = ( sb_dsp_t * ) priv ;
2020-04-12 00:18:55 +02:00
2021-11-07 06:30:40 +05:00
return dsp - > sb_irq401 ;
2020-04-12 00:18:55 +02:00
}
void
sb_dsp_set_mpu ( sb_dsp_t * dsp , mpu_t * mpu )
{
2021-11-07 06:30:40 +05:00
dsp - > mpu = mpu ;
2020-04-12 00:18:55 +02:00
2021-11-07 06:30:40 +05:00
if ( mpu ! = NULL )
2022-02-22 20:28:56 -05:00
mpu401_irq_attach ( mpu , sb_dsp_irq_update , sb_dsp_irq_pending , dsp ) ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
sb_dsp_reset ( sb_dsp_t * dsp )
2016-06-26 00:34:39 +02:00
{
2021-11-07 06:30:40 +05:00
midi_clear_buffer ( ) ;
2021-04-02 08:51:39 +02:00
2021-11-07 06:30:40 +05:00
timer_disable ( & dsp - > output_timer ) ;
timer_disable ( & dsp - > input_timer ) ;
2019-12-21 20:03:07 +01:00
2021-11-07 06:30:40 +05:00
dsp - > sb_command = 0 ;
2019-12-21 20:03:07 +01:00
2022-02-22 20:28:56 -05:00
dsp - > sb_8_length = 0xffff ;
2021-11-07 06:30:40 +05:00
dsp - > sb_8_autolen = 0xffff ;
2019-12-21 20:03:07 +01:00
2022-02-22 20:28:56 -05:00
dsp - > sb_irq8 = 0 ;
dsp - > sb_irq16 = 0 ;
dsp - > sb_irq401 = 0 ;
2021-11-07 06:30:40 +05:00
dsp - > sb_16_pause = 0 ;
dsp - > sb_read_wp = dsp - > sb_read_rp = 0 ;
2022-02-22 20:28:56 -05:00
dsp - > sb_data_stat = - 1 ;
dsp - > sb_speaker = 0 ;
dsp - > sb_pausetime = - 1LL ;
dsp - > sbe2 = 0xAA ;
dsp - > sbe2count = 0 ;
2019-12-21 20:03:07 +01:00
2021-11-07 06:30:40 +05:00
dsp - > sbreset = 0 ;
2019-12-21 20:03:07 +01:00
2022-02-22 20:28:56 -05:00
dsp - > record_pos_read = 0 ;
2021-11-07 06:30:40 +05:00
dsp - > record_pos_write = SB_DSP_REC_SAFEFTY_MARGIN ;
2019-12-21 20:03:07 +01:00
2022-03-06 19:59:14 -03:00
dsp - > irq_update ( dsp - > irq_priv , 0 ) ;
2019-12-21 20:03:07 +01:00
2021-11-07 06:30:40 +05:00
dsp - > asp_data_len = 0 ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
sb_doreset ( sb_dsp_t * dsp )
2016-06-26 00:34:39 +02:00
{
2021-11-07 06:30:40 +05:00
sb_dsp_reset ( dsp ) ;
2019-12-21 20:03:07 +01:00
2021-11-07 06:30:40 +05:00
if ( IS_AZTECH ( dsp ) ) {
2022-02-22 20:28:56 -05:00
sb_commands [ 8 ] = 1 ;
sb_commands [ 9 ] = 1 ;
2021-11-07 06:30:40 +05:00
} else {
2022-02-22 20:28:56 -05:00
if ( dsp - > sb_type > = SB16 )
sb_commands [ 8 ] = 1 ;
else
sb_commands [ 8 ] = - 1 ;
2021-11-07 06:30:40 +05:00
}
2019-12-21 20:03:07 +01:00
2022-02-22 20:28:56 -05:00
dsp - > sb_asp_mode = 0 ;
2021-12-22 06:33:35 +05:00
dsp - > sb_asp_ram_index = 0 ;
2023-05-29 01:30:51 -04:00
for ( uint16_t c = 0 ; c < 256 ; c + + )
2022-02-22 20:28:56 -05:00
dsp - > sb_asp_regs [ c ] = 0 ;
2019-12-21 20:03:07 +01:00
2021-11-07 06:30:40 +05:00
dsp - > sb_asp_regs [ 5 ] = 0x01 ;
dsp - > sb_asp_regs [ 9 ] = 0xf8 ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
sb_dsp_speed_changed ( sb_dsp_t * dsp )
2016-06-26 00:34:39 +02:00
{
2021-11-07 06:30:40 +05:00
if ( dsp - > sb_timeo < 256 )
2022-07-23 17:53:26 +02:00
dsp - > sblatcho = TIMER_USEC * ( 256 - dsp - > sb_timeo ) ;
2021-11-07 06:30:40 +05:00
else
2022-07-23 17:53:26 +02:00
dsp - > sblatcho = ( uint64_t ) ( TIMER_USEC * ( 1000000.0f / ( float ) ( dsp - > sb_timeo - 256 ) ) ) ;
2019-12-21 20:03:07 +01:00
2021-11-07 06:30:40 +05:00
if ( dsp - > sb_timei < 256 )
2022-07-23 17:53:26 +02:00
dsp - > sblatchi = TIMER_USEC * ( 256 - dsp - > sb_timei ) ;
2021-11-07 06:30:40 +05:00
else
2022-07-23 17:53:26 +02:00
dsp - > sblatchi = ( uint64_t ) ( TIMER_USEC * ( 1000000.0f / ( float ) ( dsp - > sb_timei - 256 ) ) ) ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
sb_add_data ( sb_dsp_t * dsp , uint8_t v )
2016-06-26 00:34:39 +02:00
{
2021-11-07 06:30:40 +05:00
dsp - > sb_read_data [ dsp - > sb_read_wp + + ] = v ;
dsp - > sb_read_wp & = 0xff ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
sb_start_dma ( sb_dsp_t * dsp , int dma8 , int autoinit , uint8_t format , int len )
2016-06-26 00:34:39 +02:00
{
2021-11-07 06:30:40 +05:00
dsp - > sb_pausetime = - 1 ;
2019-12-21 20:03:07 +01:00
2021-11-07 06:30:40 +05:00
if ( dma8 ) {
2022-09-18 17:16:40 -04:00
dsp - > sb_8_length = dsp - > sb_8_origlength = len ;
dsp - > sb_8_format = format ;
dsp - > sb_8_autoinit = autoinit ;
dsp - > sb_8_pause = 0 ;
dsp - > sb_8_enable = 1 ;
2022-02-22 20:28:56 -05:00
if ( dsp - > sb_16_enable & & dsp - > sb_16_output )
dsp - > sb_16_enable = 0 ;
dsp - > sb_8_output = 1 ;
if ( ! timer_is_enabled ( & dsp - > output_timer ) )
2022-07-23 17:53:26 +02:00
timer_set_delay_u64 ( & dsp - > output_timer , dsp - > sblatcho ) ;
2022-03-06 19:59:14 -03:00
dsp - > sbleftright = dsp - > sbleftright_default ;
2022-02-22 20:28:56 -05:00
dsp - > sbdacpos = 0 ;
2021-11-07 06:30:40 +05:00
} else {
2022-09-18 17:16:40 -04:00
dsp - > sb_16_length = dsp - > sb_16_origlength = len ;
dsp - > sb_16_format = format ;
dsp - > sb_16_autoinit = autoinit ;
dsp - > sb_16_pause = 0 ;
dsp - > sb_16_enable = 1 ;
2022-02-22 20:28:56 -05:00
if ( dsp - > sb_8_enable & & dsp - > sb_8_output )
dsp - > sb_8_enable = 0 ;
dsp - > sb_16_output = 1 ;
if ( ! timer_is_enabled ( & dsp - > output_timer ) )
2022-07-23 17:53:26 +02:00
timer_set_delay_u64 ( & dsp - > output_timer , dsp - > sblatcho ) ;
2021-11-07 06:30:40 +05:00
}
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
sb_start_dma_i ( sb_dsp_t * dsp , int dma8 , int autoinit , uint8_t format , int len )
2016-06-26 00:34:39 +02:00
{
2021-11-07 06:30:40 +05:00
if ( dma8 ) {
2022-09-18 17:16:40 -04:00
dsp - > sb_8_length = dsp - > sb_8_origlength = len ;
dsp - > sb_8_format = format ;
dsp - > sb_8_autoinit = autoinit ;
dsp - > sb_8_pause = 0 ;
dsp - > sb_8_enable = 1 ;
2022-02-22 20:28:56 -05:00
if ( dsp - > sb_16_enable & & ! dsp - > sb_16_output )
dsp - > sb_16_enable = 0 ;
dsp - > sb_8_output = 0 ;
if ( ! timer_is_enabled ( & dsp - > input_timer ) )
2022-07-23 17:53:26 +02:00
timer_set_delay_u64 ( & dsp - > input_timer , dsp - > sblatchi ) ;
2021-11-07 06:30:40 +05:00
} else {
2022-09-18 17:16:40 -04:00
dsp - > sb_16_length = dsp - > sb_16_origlength = len ;
dsp - > sb_16_format = format ;
dsp - > sb_16_autoinit = autoinit ;
dsp - > sb_16_pause = 0 ;
dsp - > sb_16_enable = 1 ;
2022-02-22 20:28:56 -05:00
if ( dsp - > sb_8_enable & & ! dsp - > sb_8_output )
dsp - > sb_8_enable = 0 ;
dsp - > sb_16_output = 0 ;
if ( ! timer_is_enabled ( & dsp - > input_timer ) )
2022-07-23 17:53:26 +02:00
timer_set_delay_u64 ( & dsp - > input_timer , dsp - > sblatchi ) ;
2021-11-07 06:30:40 +05:00
}
2019-12-21 20:03:07 +01:00
2022-02-22 20:28:56 -05:00
memset ( dsp - > record_buffer , 0 , sizeof ( dsp - > record_buffer ) ) ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
int
2022-03-06 19:59:14 -03:00
sb_8_read_dma ( void * priv )
2016-06-26 00:34:39 +02:00
{
2023-07-20 18:58:26 -04:00
const sb_dsp_t * dsp = ( sb_dsp_t * ) priv ;
2021-11-07 06:30:40 +05:00
return dma_channel_read ( dsp - > sb_8_dmanum ) ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
2022-03-06 19:59:14 -03:00
int
sb_8_write_dma ( void * priv , uint8_t val )
2016-06-26 00:34:39 +02:00
{
2023-07-20 18:58:26 -04:00
const sb_dsp_t * dsp = ( sb_dsp_t * ) priv ;
2022-03-06 19:59:14 -03:00
return dma_channel_write ( dsp - > sb_8_dmanum , val ) = = DMA_NODATA ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
2023-10-23 01:01:17 +02:00
/*
Supported High DMA Translation Channel
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0 0 0 First 8 - bit
0 0 1 First 8 - bit
0 1 0 Second 8 - bit
0 1 1 Second 8 - bit
1 0 0 First 8 - bit
1 0 1 First 8 - bit
1 1 0 16 - bit
1 1 1 Second 8 - bit
*/
2019-12-21 20:03:07 +01:00
int
2022-03-06 19:59:14 -03:00
sb_16_read_dma ( void * priv )
2016-06-26 00:34:39 +02:00
{
2023-07-20 18:58:26 -04:00
const sb_dsp_t * dsp = ( sb_dsp_t * ) priv ;
2023-10-20 21:02:35 +02:00
int temp , ret = 0 ;
2023-10-21 06:53:11 +02:00
int dma_flags , dma_ch = dsp - > sb_16_dmanum ;
2023-10-20 21:02:35 +02:00
2023-10-23 01:01:17 +02:00
if ( dsp - > sb_16_dma_enabled & & dsp - > sb_16_dma_supported & & ! dsp - > sb_16_dma_translate )
ret = dma_channel_read ( dma_ch ) ;
else {
if ( dsp - > sb_16_dma_enabled ) {
/* High DMA channel enabled, either translation is enabled or
16 - bit transfers are not supported . */
if ( dsp - > sb_16_dma_translate | | ! dsp - > sb_16_dma_supported )
dma_ch = dsp - > sb_16_8_dmanum ;
} else
/* High DMA channel disabled, always use the first 8-bit channel. */
2023-10-21 06:53:11 +02:00
dma_ch = dsp - > sb_8_dmanum ;
temp = dma_channel_read ( dma_ch ) ;
2023-10-20 21:02:35 +02:00
ret = temp ;
if ( ( temp ! = DMA_NODATA ) & & ! ( temp & DMA_OVER ) ) {
2023-10-21 06:53:11 +02:00
temp = dma_channel_read ( dma_ch ) ;
2023-10-20 21:02:35 +02:00
if ( temp = = DMA_NODATA )
ret = DMA_NODATA ;
else {
dma_flags = temp & DMA_OVER ;
temp & = ~ DMA_OVER ;
ret | = ( temp < < 8 ) | dma_flags ;
}
}
2023-10-23 01:01:17 +02:00
}
2023-10-20 21:02:35 +02:00
return ret ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
int
2022-03-06 19:59:14 -03:00
sb_16_write_dma ( void * priv , uint16_t val )
2016-06-26 00:34:39 +02:00
{
2023-07-20 18:58:26 -04:00
const sb_dsp_t * dsp = ( sb_dsp_t * ) priv ;
2023-10-20 21:02:35 +02:00
int temp , ret = 0 ;
2023-10-21 06:53:11 +02:00
int dma_ch = dsp - > sb_16_dmanum ;
2023-10-20 21:02:35 +02:00
2023-10-23 01:01:17 +02:00
if ( dsp - > sb_16_dma_enabled & & dsp - > sb_16_dma_supported & & ! dsp - > sb_16_dma_translate )
ret = dma_channel_write ( dma_ch , val ) = = DMA_NODATA ;
else {
if ( dsp - > sb_16_dma_enabled ) {
/* High DMA channel enabled, either translation is enabled or
16 - bit transfers are not supported . */
if ( dsp - > sb_16_dma_translate | | ! dsp - > sb_16_dma_supported )
dma_ch = dsp - > sb_16_8_dmanum ;
} else
/* High DMA channel disabled, always use the first 8-bit channel. */
2023-10-21 06:53:11 +02:00
dma_ch = dsp - > sb_8_dmanum ;
temp = dma_channel_write ( dma_ch , val & 0xff ) ;
2023-10-20 21:02:35 +02:00
ret = temp ;
if ( ( temp ! = DMA_NODATA ) & & ( temp ! = DMA_OVER ) ) {
2023-10-21 06:53:11 +02:00
temp = dma_channel_write ( dma_ch , val > > 8 ) ;
2023-10-20 21:02:35 +02:00
ret = temp ;
}
2023-10-23 01:01:17 +02:00
}
2023-10-20 21:02:35 +02:00
return ret ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
sb_dsp_setirq ( sb_dsp_t * dsp , int irq )
2016-06-26 00:34:39 +02:00
{
2023-10-24 00:28:28 +02:00
sb_dsp_log ( " IRQ now: %i \n " , irq ) ;
2021-11-07 06:30:40 +05:00
dsp - > sb_irqnum = irq ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
sb_dsp_setdma8 ( sb_dsp_t * dsp , int dma )
2016-06-26 00:34:39 +02:00
{
2023-10-23 01:01:17 +02:00
sb_dsp_log ( " 8-bit DMA now: %i \n " , dma ) ;
2021-11-07 06:30:40 +05:00
dsp - > sb_8_dmanum = dma ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
sb_dsp_setdma16 ( sb_dsp_t * dsp , int dma )
2016-11-13 18:21:15 +01:00
{
2023-10-23 01:01:17 +02:00
sb_dsp_log ( " 16-bit DMA now: %i \n " , dma ) ;
2021-11-07 06:30:40 +05:00
dsp - > sb_16_dmanum = dma ;
2016-11-13 18:21:15 +01:00
}
2019-12-21 20:03:07 +01:00
2023-10-23 01:01:17 +02:00
void
sb_dsp_setdma16_8 ( sb_dsp_t * dsp , int dma )
{
sb_dsp_log ( " 16-bit to 8-bit translation DMA now: %i \n " , dma ) ;
dsp - > sb_16_8_dmanum = dma ;
}
void
sb_dsp_setdma16_enabled ( sb_dsp_t * dsp , int enabled )
{
sb_dsp_log ( " 16-bit DMA now: %sabled \n " , enabled ? " en " : " dis " ) ;
dsp - > sb_16_dma_enabled = enabled ;
}
void
sb_dsp_setdma16_supported ( sb_dsp_t * dsp , int supported )
{
sb_dsp_log ( " 16-bit DMA now: %ssupported \n " , supported ? " " : " not " ) ;
dsp - > sb_16_dma_supported = supported ;
}
void
sb_dsp_setdma16_translate ( sb_dsp_t * dsp , int translate )
{
sb_dsp_log ( " 16-bit to 8-bit translation now: %sabled \n " , translate ? " en " : " dis " ) ;
dsp - > sb_16_dma_translate = translate ;
}
2019-12-21 20:03:07 +01:00
void
sb_exec_command ( sb_dsp_t * dsp )
2016-06-26 00:34:39 +02:00
{
2023-05-29 01:30:51 -04:00
int temp ;
int c ;
2019-12-21 20:03:07 +01:00
2021-11-07 06:30:40 +05:00
sb_dsp_log ( " sb_exec_command : SB command %02X \n " , dsp - > sb_command ) ;
2019-12-21 20:03:07 +01:00
2021-12-22 06:33:35 +05:00
/* Update 8051 ram with the current DSP command.
See https : //github.com/joncampbell123/dosbox-x/issues/1044 */
if ( dsp - > sb_type > = SB16 )
2022-02-22 20:28:56 -05:00
dsp - > sb_8051_ram [ 0x20 ] = dsp - > sb_command ;
2021-12-22 06:33:35 +05:00
2021-11-07 06:30:40 +05:00
switch ( dsp - > sb_command ) {
2022-02-22 20:28:56 -05:00
case 0x01 : /* ???? */
if ( dsp - > sb_type > = SB16 )
dsp - > asp_data_len = dsp - > sb_data [ 0 ] + ( dsp - > sb_data [ 1 ] < < 8 ) + 1 ;
break ;
case 0x03 : /* ASP status */
if ( dsp - > sb_type > = SB16 )
sb_add_data ( dsp , 0 ) ;
break ;
2023-10-22 00:46:06 +02:00
case 0x04 : /* ASP set mode register */
if ( dsp - > sb_type > = SB16 ) {
dsp - > sb_asp_mode = dsp - > sb_data [ 0 ] ;
if ( dsp - > sb_asp_mode & 4 )
dsp - > sb_asp_ram_index = 0 ;
sb_dsp_log ( " SB16 ASP set mode %02X \n " , dsp - > sb_asp_mode ) ;
} /* else DSP Status (Obsolete) */
break ;
case 0x05 : /* ASP set codec parameter */
if ( dsp - > sb_type > = SB16 )
sb_dsp_log ( " SB16 ASP unknown codec params %02X, %02X \n " , dsp - > sb_data [ 0 ] , dsp - > sb_data [ 1 ] ) ;
break ;
case 0x07 :
break ;
case 0x08 : /* ASP get version / AZTECH type/EEPROM access */
if ( IS_AZTECH ( dsp ) ) {
if ( ( dsp - > sb_data [ 0 ] = = 0x05 | | dsp - > sb_data [ 0 ] = = 0x55 ) & & 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 ] = = 0x05 | | dsp - > sb_data [ 0 ] = = 0x55 ) & & 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 ] ) ;
sb_dsp_log ( " EEPROM write = %02x \n " , dsp - > sb_data [ 2 ] ) ;
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_dsp_log ( " EEPROM read = %02x \n " , dsp - > azt_eeprom [ dsp - > sb_data [ 1 ] ] ) ;
sb_add_data ( dsp , dsp - > azt_eeprom [ dsp - > sb_data [ 1 ] ] ) ;
break ;
} else
sb_dsp_log ( " 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 = = SBAWE64 ) /* AWE64 has no ASP or a socket for it */
sb_add_data ( dsp , 0xFF ) ;
else if ( dsp - > sb_type > = SB16 )
sb_add_data ( dsp , 0x18 ) ;
break ;
case 0x09 : /* AZTECH mode set */
if ( IS_AZTECH ( dsp ) ) {
if ( dsp - > sb_data [ 0 ] = = 0x00 ) {
sb_dsp_log ( " AZT2316A: WSS MODE! \n " ) ;
azt2316a_enable_wss ( 1 , dsp - > parent ) ;
} else if ( dsp - > sb_data [ 0 ] = = 0x01 ) {
sb_dsp_log ( " AZT2316A: SB8PROV2 MODE! \n " ) ;
azt2316a_enable_wss ( 0 , dsp - > parent ) ;
} else
sb_dsp_log ( " AZT2316A: UNKNOWN MODE! = %02x \n " , dsp - > sb_data [ 0 ] ) ; // sequences 0x02->0xFF, 0x04->0xFF seen
}
break ;
case 0x0E : /* ASP set register */
if ( dsp - > sb_type > = SB16 ) {
dsp - > sb_asp_regs [ dsp - > sb_data [ 0 ] ] = dsp - > sb_data [ 1 ] ;
if ( ( dsp - > sb_data [ 0 ] = = 0x83 ) & & ( dsp - > sb_asp_mode & 128 ) & & ( dsp - > sb_asp_mode & 8 ) ) { /* ASP memory write */
if ( dsp - > sb_asp_mode & 8 )
dsp - > sb_asp_ram_index = 0 ;
dsp - > sb_asp_ram [ dsp - > sb_asp_ram_index ] = dsp - > sb_data [ 1 ] ;
if ( dsp - > sb_asp_mode & 2 ) {
dsp - > sb_asp_ram_index + + ;
if ( dsp - > sb_asp_ram_index > = 2048 )
dsp - > sb_asp_ram_index = 0 ;
}
}
sb_dsp_log ( " SB16 ASP write reg %02X, val %02X \n " , dsp - > sb_data [ 0 ] , dsp - > sb_data [ 1 ] ) ;
}
break ;
case 0x0F : /* ASP get register */
if ( dsp - > sb_type > = SB16 ) {
if ( ( dsp - > sb_data [ 0 ] = = 0x83 ) & & ( dsp - > sb_asp_mode & 128 ) & & ( dsp - > sb_asp_mode & 8 ) ) { /* ASP memory read */
if ( dsp - > sb_asp_mode & 8 )
dsp - > sb_asp_ram_index = 0 ;
dsp - > sb_asp_regs [ 0x83 ] = dsp - > sb_asp_ram [ dsp - > sb_asp_ram_index ] ;
if ( dsp - > sb_asp_mode & 1 ) {
dsp - > sb_asp_ram_index + + ;
if ( dsp - > sb_asp_ram_index > = 2048 )
dsp - > sb_asp_ram_index = 0 ;
}
} else if ( dsp - > sb_data [ 0 ] = = 0x83 ) {
dsp - > sb_asp_regs [ 0x83 ] = 0x18 ;
}
sb_add_data ( dsp , dsp - > sb_asp_regs [ dsp - > sb_data [ 0 ] ] ) ;
sb_dsp_log ( " SB16 ASP read reg %02X, val %02X \n " , dsp - > sb_data [ 0 ] , dsp - > sb_asp_regs [ dsp - > sb_data [ 0 ] ] ) ;
}
break ;
2022-02-22 20:28:56 -05:00
case 0x10 : /* 8-bit direct mode */
sb_dsp_update ( dsp ) ;
dsp - > sbdat = dsp - > sbdatl = dsp - > sbdatr = ( dsp - > sb_data [ 0 ] ^ 0x80 ) < < 8 ;
break ;
case 0x14 : /* 8-bit single cycle DMA output */
sb_start_dma ( dsp , 1 , 0 , 0 , dsp - > sb_data [ 0 ] + ( dsp - > sb_data [ 1 ] < < 8 ) ) ;
break ;
case 0x17 : /* 2-bit ADPCM output with reference */
2022-03-06 19:59:14 -03:00
dsp - > sbref = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
dsp - > sbstep = 0 ;
2023-08-21 20:24:51 -04:00
fallthrough ;
2022-02-22 20:28:56 -05:00
case 0x16 : /* 2-bit ADPCM output */
sb_start_dma ( dsp , 1 , 0 , ADPCM_2 , dsp - > sb_data [ 0 ] + ( dsp - > sb_data [ 1 ] < < 8 ) ) ;
2022-03-06 19:59:14 -03:00
dsp - > sbdat2 = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_length - - ;
if ( dsp - > sb_command = = 0x17 )
dsp - > sb_8_length - - ;
break ;
case 0x1C : /* 8-bit autoinit DMA output */
if ( dsp - > sb_type > = SB15 )
sb_start_dma ( dsp , 1 , 1 , 0 , dsp - > sb_8_autolen ) ;
break ;
case 0x1F : /* 2-bit ADPCM autoinit output */
if ( dsp - > sb_type > = SB15 ) {
sb_start_dma ( dsp , 1 , 1 , ADPCM_2 , dsp - > sb_data [ 0 ] + ( dsp - > sb_data [ 1 ] < < 8 ) ) ;
2022-03-06 19:59:14 -03:00
dsp - > sbdat2 = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_length - - ;
}
break ;
case 0x20 : /* 8-bit direct input */
sb_add_data ( dsp , ( dsp - > record_buffer [ dsp - > record_pos_read ] > > 8 ) ^ 0x80 ) ;
/* Due to the current implementation, I need to emulate a samplerate, even if this
mode does not imply such samplerate . Position is increased in sb_poll_i ( ) . */
if ( ! timer_is_enabled ( & dsp - > input_timer ) ) {
dsp - > sb_timei = 256 - 22 ;
2022-07-23 17:53:26 +02:00
dsp - > sblatchi = TIMER_USEC * 22 ;
2022-02-22 20:28:56 -05:00
temp = 1000000 / 22 ;
dsp - > sb_freq = temp ;
2022-07-23 17:53:26 +02:00
timer_set_delay_u64 ( & dsp - > input_timer , dsp - > sblatchi ) ;
2022-02-22 20:28:56 -05:00
}
break ;
case 0x24 : /* 8-bit single cycle DMA input */
sb_start_dma_i ( dsp , 1 , 0 , 0 , dsp - > sb_data [ 0 ] + ( dsp - > sb_data [ 1 ] < < 8 ) ) ;
break ;
case 0x28 : /* Direct ADC, 8-bit (Burst) */
break ;
case 0x2C : /* 8-bit autoinit DMA input */
if ( dsp - > sb_type > = SB15 )
sb_start_dma_i ( dsp , 1 , 1 , 0 , dsp - > sb_data [ 0 ] + ( dsp - > sb_data [ 1 ] < < 8 ) ) ;
break ;
case 0x30 : /* MIDI Polling mode input */
sb_dsp_log ( " MIDI polling mode input \n " ) ;
dsp - > midi_in_poll = 1 ;
dsp - > uart_irq = 0 ;
break ;
case 0x31 : /* MIDI Interrupt mode input */
sb_dsp_log ( " MIDI interrupt mode input \n " ) ;
dsp - > midi_in_poll = 0 ;
dsp - > uart_irq = 1 ;
break ;
case 0x32 : /* MIDI Read Timestamp Poll */
break ;
case 0x33 : /* MIDI Read Timestamp Interrupt */
break ;
case 0x34 : /* MIDI In poll */
if ( dsp - > sb_type < SB2 )
break ;
sb_dsp_log ( " MIDI poll in \n " ) ;
dsp - > midi_in_poll = 1 ;
dsp - > uart_midi = 1 ;
dsp - > uart_irq = 0 ;
break ;
case 0x35 : /* MIDI In irq */
if ( dsp - > sb_type < SB2 )
break ;
sb_dsp_log ( " MIDI irq in \n " ) ;
dsp - > midi_in_poll = 0 ;
dsp - > uart_midi = 1 ;
dsp - > uart_irq = 1 ;
break ;
case 0x36 :
case 0x37 : /* MIDI timestamps */
break ;
case 0x38 : /* Write to SB MIDI Output (Raw) */
dsp - > onebyte_midi = 1 ;
break ;
case 0x40 : /* Set time constant */
dsp - > sb_timei = dsp - > sb_timeo = dsp - > sb_data [ 0 ] ;
2022-07-23 17:53:26 +02:00
dsp - > sblatcho = dsp - > sblatchi = TIMER_USEC * ( 256 - dsp - > sb_data [ 0 ] ) ;
2022-02-22 20:28:56 -05:00
temp = 256 - dsp - > sb_data [ 0 ] ;
temp = 1000000 / temp ;
sb_dsp_log ( " Sample rate - %ihz (%i) \n " , temp , dsp - > sblatcho ) ;
if ( ( dsp - > sb_freq ! = temp ) & & ( dsp - > sb_type > = SB16 ) )
recalc_sb16_filter ( 0 , temp ) ;
dsp - > sb_freq = temp ;
break ;
case 0x41 : /* Set output sampling rate */
case 0x42 : /* Set input sampling rate */
if ( dsp - > sb_type > = SB16 ) {
2022-07-23 17:53:26 +02:00
dsp - > sblatcho = ( uint64_t ) ( TIMER_USEC * ( 1000000.0f / ( float ) ( dsp - > sb_data [ 1 ] + ( dsp - > sb_data [ 0 ] < < 8 ) ) ) ) ;
sb_dsp_log ( " Sample rate - %ihz (%i) \n " , dsp - > sb_data [ 1 ] + ( dsp - > sb_data [ 0 ] < < 8 ) , dsp - > sblatcho ) ;
2022-02-22 20:28:56 -05:00
temp = dsp - > sb_freq ;
dsp - > sb_freq = dsp - > sb_data [ 1 ] + ( dsp - > sb_data [ 0 ] < < 8 ) ;
dsp - > sb_timeo = 256LL + dsp - > sb_freq ;
dsp - > sblatchi = dsp - > sblatcho ;
dsp - > sb_timei = dsp - > sb_timeo ;
if ( dsp - > sb_freq ! = temp & & dsp - > sb_type > = SB16 )
recalc_sb16_filter ( 0 , dsp - > sb_freq ) ;
dsp - > sb_8051_ram [ 0x13 ] = dsp - > sb_freq & 0xff ;
dsp - > sb_8051_ram [ 0x14 ] = ( dsp - > sb_freq > > 8 ) & 0xff ;
}
break ;
case 0x45 : /* Continue Auto-Initialize DMA, 8-bit */
break ;
case 0x47 : /* Continue Auto-Initialize DMA, 16-bit */
break ;
case 0x48 : /* Set DSP block transfer size */
dsp - > sb_8_autolen = dsp - > sb_data [ 0 ] + ( dsp - > sb_data [ 1 ] < < 8 ) ;
break ;
case 0x75 : /* 4-bit ADPCM output with reference */
2022-03-06 19:59:14 -03:00
dsp - > sbref = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
dsp - > sbstep = 0 ;
2023-08-09 19:44:56 -04:00
fallthrough ;
2022-02-22 20:28:56 -05:00
case 0x74 : /* 4-bit ADPCM output */
sb_start_dma ( dsp , 1 , 0 , ADPCM_4 , dsp - > sb_data [ 0 ] + ( dsp - > sb_data [ 1 ] < < 8 ) ) ;
2022-03-06 19:59:14 -03:00
dsp - > sbdat2 = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_length - - ;
if ( dsp - > sb_command = = 0x75 )
dsp - > sb_8_length - - ;
break ;
case 0x77 : /* 2.6-bit ADPCM output with reference */
2022-03-06 19:59:14 -03:00
dsp - > sbref = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
dsp - > sbstep = 0 ;
2023-08-21 20:24:51 -04:00
fallthrough ;
2022-02-22 20:28:56 -05:00
case 0x76 : /* 2.6-bit ADPCM output */
sb_start_dma ( dsp , 1 , 0 , ADPCM_26 , dsp - > sb_data [ 0 ] + ( dsp - > sb_data [ 1 ] < < 8 ) ) ;
2022-03-06 19:59:14 -03:00
dsp - > sbdat2 = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_length - - ;
if ( dsp - > sb_command = = 0x77 )
dsp - > sb_8_length - - ;
break ;
case 0x7D : /* 4-bit ADPCM autoinit output */
if ( dsp - > sb_type > = SB15 ) {
sb_start_dma ( dsp , 1 , 1 , ADPCM_4 , dsp - > sb_data [ 0 ] + ( dsp - > sb_data [ 1 ] < < 8 ) ) ;
2022-03-06 19:59:14 -03:00
dsp - > sbdat2 = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_length - - ;
}
break ;
case 0x7F : /* 2.6-bit ADPCM autoinit output */
if ( dsp - > sb_type > = SB15 ) {
sb_start_dma ( dsp , 1 , 1 , ADPCM_26 , dsp - > sb_data [ 0 ] + ( dsp - > sb_data [ 1 ] < < 8 ) ) ;
2022-03-06 19:59:14 -03:00
dsp - > sbdat2 = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_length - - ;
}
break ;
case 0x80 : /* Pause DAC */
dsp - > sb_pausetime = dsp - > sb_data [ 0 ] + ( dsp - > sb_data [ 1 ] < < 8 ) ;
if ( ! timer_is_enabled ( & dsp - > output_timer ) )
2022-07-23 17:53:26 +02:00
timer_set_delay_u64 ( & dsp - > output_timer , dsp - > sblatcho ) ;
2022-02-22 20:28:56 -05:00
break ;
case 0x90 : /* High speed 8-bit autoinit DMA output */
if ( dsp - > sb_type > = SB2 )
sb_start_dma ( dsp , 1 , 1 , 0 , dsp - > sb_8_autolen ) ;
break ;
case 0x91 : /* High speed 8-bit single cycle DMA output */
if ( dsp - > sb_type > = SB2 )
sb_start_dma ( dsp , 1 , 0 , 0 , dsp - > sb_8_autolen ) ;
break ;
case 0x98 : /* High speed 8-bit autoinit DMA input */
if ( dsp - > sb_type > = SB2 )
sb_start_dma_i ( dsp , 1 , 1 , 0 , dsp - > sb_8_autolen ) ;
break ;
case 0x99 : /* High speed 8-bit single cycle DMA input */
if ( dsp - > sb_type > = SB2 )
sb_start_dma_i ( dsp , 1 , 0 , 0 , dsp - > sb_8_autolen ) ;
break ;
case 0xA0 : /* Set input mode to mono */
case 0xA8 : /* Set input mode to stereo */
if ( ( dsp - > sb_type < SB2 ) | | ( dsp - > sb_type > SBPRO2 ) )
break ;
/* TODO: Implement. 3.xx-only command. */
break ;
case 0xB0 :
case 0xB1 :
case 0xB2 :
case 0xB3 :
case 0xB4 :
case 0xB5 :
case 0xB6 :
case 0xB7 : /* 16-bit DMA output */
if ( dsp - > sb_type > = SB16 ) {
2023-10-20 21:02:35 +02:00
sb_start_dma ( dsp , 0 , dsp - > sb_command & 4 , dsp - > sb_data [ 0 ] ,
dsp - > sb_data [ 1 ] + ( dsp - > sb_data [ 2 ] < < 8 ) ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_16_autolen = dsp - > sb_data [ 1 ] + ( dsp - > sb_data [ 2 ] < < 8 ) ;
}
break ;
case 0xB8 :
case 0xB9 :
case 0xBA :
case 0xBB :
case 0xBC :
case 0xBD :
case 0xBE :
case 0xBF : /* 16-bit DMA input */
if ( dsp - > sb_type > = SB16 ) {
2023-10-20 21:02:35 +02:00
sb_start_dma_i ( dsp , 0 , dsp - > sb_command & 4 , dsp - > sb_data [ 0 ] ,
dsp - > sb_data [ 1 ] + ( dsp - > sb_data [ 2 ] < < 8 ) ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_16_autolen = dsp - > sb_data [ 1 ] + ( dsp - > sb_data [ 2 ] < < 8 ) ;
}
break ;
case 0xC0 :
case 0xC1 :
case 0xC2 :
case 0xC3 :
case 0xC4 :
case 0xC5 :
case 0xC6 :
case 0xC7 : /* 8-bit DMA output */
if ( dsp - > sb_type > = SB16 ) {
2023-10-20 21:02:35 +02:00
sb_start_dma ( dsp , 1 , dsp - > sb_command & 4 , dsp - > sb_data [ 0 ] ,
dsp - > sb_data [ 1 ] + ( dsp - > sb_data [ 2 ] < < 8 ) ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_autolen = dsp - > sb_data [ 1 ] + ( dsp - > sb_data [ 2 ] < < 8 ) ;
}
break ;
case 0xC8 :
case 0xC9 :
case 0xCA :
case 0xCB :
case 0xCC :
case 0xCD :
case 0xCE :
case 0xCF : /* 8-bit DMA input */
if ( dsp - > sb_type > = SB16 ) {
2023-10-20 21:02:35 +02:00
sb_start_dma_i ( dsp , 1 , dsp - > sb_command & 4 , dsp - > sb_data [ 0 ] ,
dsp - > sb_data [ 1 ] + ( dsp - > sb_data [ 2 ] < < 8 ) ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_autolen = dsp - > sb_data [ 1 ] + ( dsp - > sb_data [ 2 ] < < 8 ) ;
}
break ;
case 0xD0 : /* Pause 8-bit DMA */
dsp - > sb_8_pause = 1 ;
break ;
case 0xD1 : /* Speaker on */
if ( dsp - > sb_type < SB15 )
dsp - > sb_8_pause = 1 ;
else if ( dsp - > sb_type < SB16 )
dsp - > muted = 0 ;
dsp - > sb_speaker = 1 ;
break ;
case 0xD3 : /* Speaker off */
if ( dsp - > sb_type < SB15 )
dsp - > sb_8_pause = 1 ;
else if ( dsp - > sb_type < SB16 )
dsp - > muted = 1 ;
dsp - > sb_speaker = 0 ;
break ;
case 0xD4 : /* Continue 8-bit DMA */
dsp - > sb_8_pause = 0 ;
break ;
case 0xD5 : /* Pause 16-bit DMA */
if ( dsp - > sb_type > = SB16 )
dsp - > sb_16_pause = 1 ;
break ;
case 0xD6 : /* Continue 16-bit DMA */
if ( dsp - > sb_type > = SB16 )
dsp - > sb_16_pause = 0 ;
break ;
case 0xD8 : /* Get speaker status */
sb_add_data ( dsp , dsp - > sb_speaker ? 0xff : 0 ) ;
break ;
case 0xD9 : /* Exit 16-bit auto-init mode */
if ( dsp - > sb_type > = SB16 )
dsp - > sb_16_autoinit = 0 ;
break ;
case 0xDA : /* Exit 8-bit auto-init mode */
dsp - > sb_8_autoinit = 0 ;
break ;
case 0xE0 : /* DSP identification */
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 ;
case 0xE2 : /* Stupid ID/protection */
for ( c = 0 ; c < 8 ; c + + ) {
if ( dsp - > sb_data [ 0 ] & ( 1 < < c ) )
dsp - > sbe2 + = sbe2dat [ dsp - > sbe2count & 3 ] [ c ] ;
}
dsp - > sbe2 + = sbe2dat [ dsp - > sbe2count & 3 ] [ 8 ] ;
dsp - > sbe2count + + ;
2022-03-06 19:59:14 -03:00
dsp - > dma_writeb ( dsp - > dma_priv , dsp - > sbe2 ) ;
2022-02-22 20:28:56 -05:00
break ;
case 0xE3 : /* DSP copyright */
if ( dsp - > sb_type > = SB16 ) {
c = 0 ;
while ( sb16_copyright [ c ] )
sb_add_data ( dsp , sb16_copyright [ c + + ] ) ;
sb_add_data ( dsp , 0 ) ;
}
break ;
case 0xE4 : /* Write test register */
dsp - > sb_test = dsp - > sb_data [ 0 ] ;
break ;
2023-10-22 00:46:06 +02:00
case 0xE7 : /* ???? */
break ;
2022-02-22 20:28:56 -05:00
case 0xE8 : /* Read test register */
sb_add_data ( dsp , dsp - > sb_test ) ;
break ;
case 0xF2 : /* Trigger 8-bit IRQ */
sb_dsp_log ( " Trigger IRQ \n " ) ;
sb_irq ( dsp , 1 ) ;
break ;
case 0xF3 : /* Trigger 16-bit IRQ */
sb_dsp_log ( " Trigger IRQ \n " ) ;
sb_irq ( dsp , 0 ) ;
break ;
case 0xF8 :
if ( dsp - > sb_type < SB16 )
sb_add_data ( dsp , 0 ) ;
break ;
case 0xF9 : /* SB16 8051 RAM read */
if ( dsp - > sb_type > = SB16 )
sb_add_data ( dsp , dsp - > sb_8051_ram [ dsp - > sb_data [ 0 ] ] ) ;
break ;
case 0xFA : /* SB16 8051 RAM write */
if ( dsp - > sb_type > = SB16 )
dsp - > sb_8051_ram [ dsp - > sb_data [ 0 ] ] = dsp - > sb_data [ 1 ] ;
break ;
2023-10-22 00:46:06 +02:00
case 0xFF : /* No, that's not how you program auto-init DMA */
2022-02-22 20:28:56 -05:00
break ;
/* 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
* http : //www.dcee.net/Files/Programm/Sound/
* 0E3 h DSP Copyright SBPro2 ? ? ?
* 0F 0 h Sine Generator SB
* 0F 1 h DSP Auxiliary Status ( Obsolete ) SB - Pro2
* 0F 2 h IRQ Request , 8 - bit SB
* 0F 3 h IRQ Request , 16 - bit SB16
* 0F Bh DSP Status SB16
* 0F Ch DSP Auxiliary Status SB16
* 0F Dh DSP Command Status SB16
*/
2023-06-09 23:46:54 -04:00
default :
2023-10-22 16:43:51 +02:00
sb_dsp_log ( " Unknown DSP command: %02X \n " , dsp - > sb_command ) ;
2023-06-09 23:46:54 -04:00
break ;
2021-11-07 06:30:40 +05:00
}
2021-12-22 06:33:35 +05:00
/* Update 8051 ram with the last DSP command.
See https : //github.com/joncampbell123/dosbox-x/issues/1044 */
if ( dsp - > sb_type > = SB16 )
2022-02-22 20:28:56 -05:00
dsp - > sb_8051_ram [ 0x30 ] = dsp - > sb_command ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
sb_write ( uint16_t a , uint8_t v , void * priv )
2016-06-26 00:34:39 +02:00
{
2021-11-07 06:30:40 +05:00
sb_dsp_t * dsp = ( sb_dsp_t * ) priv ;
2019-12-21 20:03:07 +01:00
2023-10-21 06:53:11 +02:00
/* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */
if ( dsp - > sb_type < SB16 )
a & = 0xfffe ;
2021-11-07 06:30:40 +05:00
switch ( a & 0xF ) {
2022-02-22 20:28:56 -05:00
case 6 : /* Reset */
if ( ! dsp - > uart_midi ) {
if ( ! ( v & 1 ) & & ( dsp - > sbreset & 1 ) ) {
sb_dsp_reset ( dsp ) ;
sb_add_data ( dsp , 0xAA ) ;
}
dsp - > sbreset = v ;
}
dsp - > uart_midi = 0 ;
dsp - > uart_irq = 0 ;
dsp - > onebyte_midi = 0 ;
return ;
case 0xC : /* Command/data write */
if ( dsp - > uart_midi | | dsp - > onebyte_midi ) {
midi_raw_out_byte ( v ) ;
dsp - > onebyte_midi = 0 ;
return ;
}
timer_set_delay_u64 ( & dsp - > wb_timer , TIMER_USEC * 1 ) ;
if ( dsp - > asp_data_len ) {
sb_dsp_log ( " ASP data %i \n " , dsp - > asp_data_len ) ;
dsp - > asp_data_len - - ;
if ( ! dsp - > asp_data_len )
sb_add_data ( dsp , 0 ) ;
return ;
}
if ( dsp - > sb_data_stat = = - 1 ) {
dsp - > sb_command = v ;
if ( v = = 0x01 )
sb_add_data ( dsp , 0 ) ;
dsp - > sb_data_stat + + ;
} else {
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 ;
2023-08-21 20:24:51 -04:00
default :
break ;
2021-11-07 06:30:40 +05:00
}
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
uint8_t
sb_read ( uint16_t a , void * priv )
2016-06-26 00:34:39 +02:00
{
2021-11-07 06:30:40 +05:00
sb_dsp_t * dsp = ( sb_dsp_t * ) priv ;
2022-02-22 20:28:56 -05:00
uint8_t ret = 0x00 ;
2019-12-21 20:03:07 +01:00
2023-10-21 06:53:11 +02:00
/* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */
if ( dsp - > sb_type < SB16 )
a & = 0xfffe ;
2021-11-07 06:30:40 +05:00
switch ( a & 0xf ) {
2022-02-22 20:28:56 -05:00
case 0xA : /* Read data */
if ( dsp - > mpu & & dsp - > uart_midi ) {
ret = MPU401_ReadData ( dsp - > mpu ) ;
} else {
dsp - > sbreaddat = dsp - > sb_read_data [ dsp - > sb_read_rp ] ;
if ( dsp - > sb_read_rp ! = dsp - > sb_read_wp ) {
dsp - > sb_read_rp + + ;
dsp - > sb_read_rp & = 0xff ;
}
return dsp - > sbreaddat ;
}
break ;
case 0xC : /* Write data ready */
if ( dsp - > sb_8_enable | | dsp - > sb_type > = SB16 )
dsp - > busy_count = ( dsp - > busy_count + 1 ) & 3 ;
else
dsp - > busy_count = 0 ;
if ( dsp - > wb_full | | ( dsp - > busy_count & 2 ) ) {
dsp - > wb_full = timer_is_enabled ( & dsp - > wb_timer ) ;
if ( IS_AZTECH ( dsp ) ) {
sb_dsp_log ( " SB Write Data Aztech read 0x80 \n " ) ;
return 0x80 ;
} else {
sb_dsp_log ( " SB Write Data Creative read 0xff \n " ) ;
return 0xff ;
}
}
if ( IS_AZTECH ( dsp ) ) {
sb_dsp_log ( " SB Write Data Aztech read 0x00 \n " ) ;
ret = 0x00 ;
} else {
sb_dsp_log ( " SB Write Data Creative read 0x7f \n " ) ;
ret = 0x7f ;
}
break ;
case 0xE : /* Read data ready */
2022-03-06 19:59:14 -03:00
dsp - > irq_update ( dsp - > irq_priv , 0 ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_irq8 = dsp - > sb_irq16 = 0 ;
/* 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 ) ) {
sb_dsp_log ( " SB Read Data Aztech read %02X, Read RP = %d, Read WP = %d \n " , ( dsp - > sb_read_rp = = dsp - > sb_read_wp ) ? 0x00 : 0x80 , dsp - > sb_read_rp , dsp - > sb_read_wp ) ;
ret = ( dsp - > sb_read_rp = = dsp - > sb_read_wp ) ? 0x00 : 0x80 ;
} else {
sb_dsp_log ( " SB Read Data Creative read %02X \n " , ( dsp - > sb_read_rp = = dsp - > sb_read_wp ) ? 0x7f : 0xff ) ;
ret = ( dsp - > sb_read_rp = = dsp - > sb_read_wp ) ? 0x7f : 0xff ;
}
break ;
case 0xF : /* 16-bit ack */
dsp - > sb_irq16 = 0 ;
if ( ! dsp - > sb_irq8 )
2022-03-06 19:59:14 -03:00
dsp - > irq_update ( dsp - > irq_priv , 0 ) ;
2022-02-22 20:28:56 -05:00
sb_dsp_log ( " SB 16-bit ACK read 0xFF \n " ) ;
ret = 0xff ;
break ;
2023-06-09 23:46:54 -04:00
default :
break ;
2022-02-22 20:28:56 -05:00
}
2016-06-26 00:34:39 +02:00
2022-02-22 20:28:56 -05:00
return ret ;
2017-10-16 06:19:18 +02:00
}
2022-02-20 02:26:27 -05:00
void
2023-08-21 20:24:51 -04:00
sb_dsp_input_msg ( void * priv , uint8_t * msg , uint32_t len )
2020-01-01 20:20:16 +01:00
{
2023-08-21 20:24:51 -04:00
sb_dsp_t * dsp = ( sb_dsp_t * ) priv ;
2020-01-19 05:45:05 +01:00
2022-01-07 08:18:15 +02:00
sb_dsp_log ( " MIDI in sysex = %d, uart irq = %d, msg = %d \n " , dsp - > midi_in_sysex , dsp - > uart_irq , len ) ;
2020-01-19 05:45:05 +01:00
2021-11-07 06:30:40 +05:00
if ( ! dsp - > uart_irq & & ! dsp - > midi_in_poll & & ( dsp - > mpu ! = NULL ) ) {
2022-02-22 20:28:56 -05:00
MPU401_InputMsg ( dsp - > mpu , msg , len ) ;
return ;
2021-11-07 06:30:40 +05:00
}
2020-04-12 00:18:55 +02:00
2021-11-07 06:30:40 +05:00
if ( dsp - > midi_in_sysex )
2022-02-22 20:28:56 -05:00
return ;
2020-04-12 00:18:55 +02:00
2021-11-07 06:30:40 +05:00
if ( dsp - > uart_irq ) {
2023-05-02 02:18:17 -04:00
for ( uint32_t i = 0 ; i < len ; i + + )
2022-02-22 20:28:56 -05:00
sb_add_data ( dsp , msg [ i ] ) ;
sb_irq ( dsp , 1 ) ;
2022-02-20 02:26:27 -05:00
} else if ( dsp - > midi_in_poll ) {
2023-05-02 02:18:17 -04:00
for ( uint32_t i = 0 ; i < len ; i + + )
2022-02-22 20:28:56 -05:00
sb_add_data ( dsp , msg [ i ] ) ;
2021-11-07 06:30:40 +05:00
}
2020-01-01 20:20:16 +01:00
}
2022-02-20 02:26:27 -05:00
int
2023-08-21 20:24:51 -04:00
sb_dsp_input_sysex ( void * priv , uint8_t * buffer , uint32_t len , int abort )
2020-01-01 20:20:16 +01:00
{
2023-08-21 20:24:51 -04:00
sb_dsp_t * dsp = ( sb_dsp_t * ) priv ;
2020-01-19 05:45:05 +01:00
2021-11-07 06:30:40 +05:00
if ( ! dsp - > uart_irq & & ! dsp - > midi_in_poll & & ( dsp - > mpu ! = NULL ) )
2022-02-22 20:28:56 -05:00
return MPU401_InputSysex ( dsp - > mpu , buffer , len , abort ) ;
2020-04-12 00:18:55 +02:00
2021-11-07 06:30:40 +05:00
if ( abort ) {
2022-02-22 20:28:56 -05:00
dsp - > midi_in_sysex = 0 ;
return 0 ;
2021-11-07 06:30:40 +05:00
}
2020-04-12 00:18:55 +02:00
2021-11-07 06:30:40 +05:00
dsp - > midi_in_sysex = 1 ;
2020-04-12 00:18:55 +02:00
2023-05-29 01:30:51 -04:00
for ( uint32_t i = 0 ; i < len ; i + + ) {
2022-02-22 20:28:56 -05:00
if ( dsp - > sb_read_rp = = dsp - > sb_read_wp ) {
sb_dsp_log ( " Length sysex SB = %d \n " , len - i ) ;
return ( len - i ) ;
}
2020-04-12 00:18:55 +02:00
2022-02-22 20:28:56 -05:00
sb_add_data ( dsp , buffer [ i ] ) ;
2021-11-07 06:30:40 +05:00
}
2020-04-12 00:18:55 +02:00
2021-11-07 06:30:40 +05:00
dsp - > midi_in_sysex = 0 ;
2020-04-12 00:18:55 +02:00
2021-11-07 06:30:40 +05:00
return 0 ;
2020-01-01 20:20:16 +01:00
}
2019-12-21 20:03:07 +01:00
void
2020-03-25 00:49:25 +01:00
sb_dsp_init ( sb_dsp_t * dsp , int type , int subtype , void * parent )
2016-06-26 00:34:39 +02:00
{
2022-02-22 20:28:56 -05:00
dsp - > sb_type = type ;
2021-11-07 06:30:40 +05:00
dsp - > sb_subtype = subtype ;
2022-02-22 20:28:56 -05:00
dsp - > parent = parent ;
2021-11-07 06:30:40 +05:00
/* Default values. Use sb_dsp_setxxx() methods to change. */
2022-02-22 20:28:56 -05:00
dsp - > sb_irqnum = 7 ;
dsp - > sb_8_dmanum = 1 ;
2021-11-07 06:30:40 +05:00
dsp - > sb_16_dmanum = 5 ;
2022-02-22 20:28:56 -05:00
dsp - > mpu = NULL ;
2021-11-07 06:30:40 +05:00
2022-03-06 19:59:14 -03:00
dsp - > sbleftright_default = 0 ;
dsp - > irq_update = sb_irq_update_pic ;
dsp - > irq_priv = dsp ;
dsp - > dma_readb = sb_8_read_dma ;
dsp - > dma_readw = sb_16_read_dma ;
dsp - > dma_writeb = sb_8_write_dma ;
dsp - > dma_writew = sb_16_write_dma ;
dsp - > dma_priv = dsp ;
2021-11-07 06:30:40 +05:00
sb_doreset ( dsp ) ;
timer_add ( & dsp - > output_timer , pollsb , dsp , 0 ) ;
timer_add ( & dsp - > input_timer , sb_poll_i , dsp , 0 ) ;
timer_add ( & dsp - > wb_timer , NULL , dsp , 0 ) ;
/* Initialise SB16 filter to same cutoff as 8-bit SBs (3.2 kHz). This will be recalculated when
a set frequency command is sent . */
2022-02-22 20:28:56 -05:00
recalc_sb16_filter ( 0 , 3200 * 2 ) ;
2022-11-06 23:45:35 -05:00
recalc_sb16_filter ( 1 , FREQ_44100 ) ;
2023-10-21 06:53:11 +02:00
recalc_sb16_filter ( 2 , 18939 ) ;
2021-11-07 06:30:40 +05:00
2021-12-22 06:33:35 +05:00
/* Initialize SB16 8051 RAM and ASP internal RAM */
memset ( dsp - > sb_8051_ram , 0x00 , sizeof ( dsp - > sb_8051_ram ) ) ;
2021-11-07 06:30:40 +05:00
dsp - > sb_8051_ram [ 0x0e ] = 0xff ;
dsp - > sb_8051_ram [ 0x0f ] = 0x07 ;
dsp - > sb_8051_ram [ 0x37 ] = 0x38 ;
2021-12-22 06:33:35 +05:00
memset ( dsp - > sb_asp_ram , 0xff , sizeof ( dsp - > sb_asp_ram ) ) ;
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
sb_dsp_setaddr ( sb_dsp_t * dsp , uint16_t addr )
2016-06-26 00:34:39 +02:00
{
2021-11-07 06:30:40 +05:00
sb_dsp_log ( " sb_dsp_setaddr : %04X \n " , addr ) ;
if ( dsp - > sb_addr ! = 0 ) {
2022-02-22 20:28:56 -05:00
io_removehandler ( dsp - > sb_addr + 6 , 0x0002 , sb_read , NULL , NULL , sb_write , NULL , NULL , dsp ) ;
io_removehandler ( dsp - > sb_addr + 0xa , 0x0006 , sb_read , NULL , NULL , sb_write , NULL , NULL , dsp ) ;
2021-11-07 06:30:40 +05:00
}
dsp - > sb_addr = addr ;
if ( dsp - > sb_addr ! = 0 ) {
2022-02-22 20:28:56 -05:00
io_sethandler ( dsp - > sb_addr + 6 , 0x0002 , sb_read , NULL , NULL , sb_write , NULL , NULL , dsp ) ;
io_sethandler ( dsp - > sb_addr + 0xa , 0x0006 , sb_read , NULL , NULL , sb_write , NULL , NULL , dsp ) ;
2021-11-07 06:30:40 +05:00
}
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
sb_dsp_set_stereo ( sb_dsp_t * dsp , int stereo )
2016-06-26 00:34:39 +02:00
{
2021-11-07 06:30:40 +05:00
dsp - > stereo = stereo ;
2016-06-26 00:34:39 +02:00
}
2022-03-06 19:59:14 -03:00
void
sb_dsp_irq_attach ( sb_dsp_t * dsp , void ( * irq_update ) ( void * priv , int set ) , void * priv )
{
dsp - > irq_update = irq_update ;
dsp - > irq_priv = priv ;
}
void
sb_dsp_dma_attach ( sb_dsp_t * dsp ,
int ( * dma_readb ) ( void * priv ) ,
int ( * dma_readw ) ( void * priv ) ,
int ( * dma_writeb ) ( void * priv , uint8_t val ) ,
int ( * dma_writew ) ( void * priv , uint16_t val ) ,
void * priv )
{
dsp - > dma_readb = dma_readb ;
dsp - > dma_readw = dma_readw ;
dsp - > dma_writeb = dma_writeb ;
dsp - > dma_writew = dma_writew ;
dsp - > dma_priv = priv ;
}
2019-12-21 20:03:07 +01:00
void
2023-06-09 23:46:54 -04:00
pollsb ( void * priv )
2016-06-26 00:34:39 +02:00
{
2023-06-09 23:46:54 -04:00
sb_dsp_t * dsp = ( sb_dsp_t * ) priv ;
2023-05-29 01:30:51 -04:00
int tempi ;
int ref ;
2022-02-22 20:28:56 -05:00
int data [ 2 ] ;
2019-12-21 20:03:07 +01:00
2022-07-23 17:53:26 +02:00
timer_advance_u64 ( & dsp - > output_timer , dsp - > sblatcho ) ;
2021-11-07 06:30:40 +05:00
if ( dsp - > sb_8_enable & & ! dsp - > sb_8_pause & & dsp - > sb_pausetime < 0 & & dsp - > sb_8_output ) {
2022-02-22 20:28:56 -05:00
sb_dsp_update ( dsp ) ;
switch ( dsp - > sb_8_format ) {
case 0x00 : /* Mono unsigned */
2022-03-06 19:59:14 -03:00
data [ 0 ] = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
/* Needed to prevent clicking in Worms, which programs the DSP to
auto - init DMA but programs the DMA controller to single cycle */
if ( data [ 0 ] = = DMA_NODATA )
break ;
dsp - > sbdat = ( data [ 0 ] ^ 0x80 ) < < 8 ;
2022-03-07 11:19:58 -03:00
if ( dsp - > stereo ) {
2022-02-22 20:28:56 -05:00
sb_dsp_log ( " pollsb: Mono unsigned, dsp->stereo, %s channel, %04X \n " ,
dsp - > sbleftright ? " left " : " right " , dsp - > sbdat ) ;
if ( dsp - > sbleftright )
dsp - > sbdatl = dsp - > sbdat ;
else
dsp - > sbdatr = dsp - > sbdat ;
dsp - > sbleftright = ! dsp - > sbleftright ;
} else
dsp - > sbdatl = dsp - > sbdatr = dsp - > sbdat ;
dsp - > sb_8_length - - ;
break ;
case 0x10 : /* Mono signed */
2022-03-06 19:59:14 -03:00
data [ 0 ] = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
if ( data [ 0 ] = = DMA_NODATA )
break ;
dsp - > sbdat = data [ 0 ] < < 8 ;
2022-03-07 11:19:58 -03:00
if ( dsp - > stereo ) {
2022-02-22 20:28:56 -05:00
sb_dsp_log ( " pollsb: Mono signed, dsp->stereo, %s channel, %04X \n " ,
dsp - > sbleftright ? " left " : " right " , data [ 0 ] , dsp - > sbdat ) ;
if ( dsp - > sbleftright )
dsp - > sbdatl = dsp - > sbdat ;
else
dsp - > sbdatr = dsp - > sbdat ;
dsp - > sbleftright = ! dsp - > sbleftright ;
} else
dsp - > sbdatl = dsp - > sbdatr = dsp - > sbdat ;
dsp - > sb_8_length - - ;
break ;
case 0x20 : /* Stereo unsigned */
2022-03-06 19:59:14 -03:00
data [ 0 ] = dsp - > dma_readb ( dsp - > dma_priv ) ;
data [ 1 ] = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
if ( ( data [ 0 ] = = DMA_NODATA ) | | ( data [ 1 ] = = DMA_NODATA ) )
break ;
dsp - > sbdatl = ( data [ 0 ] ^ 0x80 ) < < 8 ;
dsp - > sbdatr = ( data [ 1 ] ^ 0x80 ) < < 8 ;
dsp - > sb_8_length - = 2 ;
break ;
case 0x30 : /* Stereo signed */
2022-03-06 19:59:14 -03:00
data [ 0 ] = dsp - > dma_readb ( dsp - > dma_priv ) ;
data [ 1 ] = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
if ( ( data [ 0 ] = = DMA_NODATA ) | | ( data [ 1 ] = = DMA_NODATA ) )
break ;
dsp - > sbdatl = data [ 0 ] < < 8 ;
dsp - > sbdatr = data [ 1 ] < < 8 ;
dsp - > sb_8_length - = 2 ;
break ;
case ADPCM_4 :
if ( dsp - > sbdacpos )
tempi = ( dsp - > sbdat2 & 0xF ) + dsp - > sbstep ;
else
tempi = ( dsp - > sbdat2 > > 4 ) + dsp - > sbstep ;
if ( tempi < 0 )
tempi = 0 ;
if ( tempi > 63 )
tempi = 63 ;
ref = dsp - > sbref + scaleMap4 [ tempi ] ;
if ( ref > 0xff )
dsp - > sbref = 0xff ;
else if ( ref < 0x00 )
dsp - > sbref = 0x00 ;
else
dsp - > sbref = ref ;
dsp - > sbstep = ( dsp - > sbstep + adjustMap4 [ tempi ] ) & 0xff ;
dsp - > sbdat = ( dsp - > sbref ^ 0x80 ) < < 8 ;
dsp - > sbdacpos + + ;
if ( dsp - > sbdacpos > = 2 ) {
dsp - > sbdacpos = 0 ;
2022-03-06 19:59:14 -03:00
dsp - > sbdat2 = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_length - - ;
}
2022-03-07 11:19:58 -03:00
if ( dsp - > stereo ) {
2022-02-22 20:28:56 -05:00
sb_dsp_log ( " pollsb: ADPCM 4, dsp->stereo, %s channel, %04X \n " ,
dsp - > sbleftright ? " left " : " right " , dsp - > sbdat ) ;
if ( dsp - > sbleftright )
dsp - > sbdatl = dsp - > sbdat ;
else
dsp - > sbdatr = dsp - > sbdat ;
dsp - > sbleftright = ! dsp - > sbleftright ;
} else
dsp - > sbdatl = dsp - > sbdatr = dsp - > sbdat ;
break ;
case ADPCM_26 :
if ( ! dsp - > sbdacpos )
tempi = ( dsp - > sbdat2 > > 5 ) + dsp - > sbstep ;
else if ( dsp - > sbdacpos = = 1 )
tempi = ( ( dsp - > sbdat2 > > 2 ) & 7 ) + dsp - > sbstep ;
else
tempi = ( ( dsp - > sbdat2 < < 1 ) & 7 ) + dsp - > sbstep ;
if ( tempi < 0 )
tempi = 0 ;
if ( tempi > 39 )
tempi = 39 ;
ref = dsp - > sbref + scaleMap26 [ tempi ] ;
if ( ref > 0xff )
dsp - > sbref = 0xff ;
else if ( ref < 0x00 )
dsp - > sbref = 0x00 ;
else
dsp - > sbref = ref ;
dsp - > sbstep = ( dsp - > sbstep + adjustMap26 [ tempi ] ) & 0xff ;
dsp - > sbdat = ( dsp - > sbref ^ 0x80 ) < < 8 ;
dsp - > sbdacpos + + ;
if ( dsp - > sbdacpos > = 3 ) {
dsp - > sbdacpos = 0 ;
2022-03-06 19:59:14 -03:00
dsp - > sbdat2 = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_length - - ;
}
2022-03-07 11:19:58 -03:00
if ( dsp - > stereo ) {
2022-02-22 20:28:56 -05:00
sb_dsp_log ( " pollsb: ADPCM 26, dsp->stereo, %s channel, %04X \n " ,
dsp - > sbleftright ? " left " : " right " , dsp - > sbdat ) ;
if ( dsp - > sbleftright )
dsp - > sbdatl = dsp - > sbdat ;
else
dsp - > sbdatr = dsp - > sbdat ;
dsp - > sbleftright = ! dsp - > sbleftright ;
} else
dsp - > sbdatl = dsp - > sbdatr = dsp - > sbdat ;
break ;
case ADPCM_2 :
tempi = ( ( dsp - > sbdat2 > > ( ( 3 - dsp - > sbdacpos ) * 2 ) ) & 3 ) + dsp - > sbstep ;
if ( tempi < 0 )
tempi = 0 ;
if ( tempi > 23 )
tempi = 23 ;
ref = dsp - > sbref + scaleMap2 [ tempi ] ;
if ( ref > 0xff )
dsp - > sbref = 0xff ;
else if ( ref < 0x00 )
dsp - > sbref = 0x00 ;
else
dsp - > sbref = ref ;
dsp - > sbstep = ( dsp - > sbstep + adjustMap2 [ tempi ] ) & 0xff ;
dsp - > sbdat = ( dsp - > sbref ^ 0x80 ) < < 8 ;
dsp - > sbdacpos + + ;
if ( dsp - > sbdacpos > = 4 ) {
dsp - > sbdacpos = 0 ;
2022-03-06 19:59:14 -03:00
dsp - > sbdat2 = dsp - > dma_readb ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
}
2022-03-07 11:19:58 -03:00
if ( dsp - > stereo ) {
2022-02-22 20:28:56 -05:00
sb_dsp_log ( " pollsb: ADPCM 2, dsp->stereo, %s channel, %04X \n " ,
dsp - > sbleftright ? " left " : " right " , dsp - > sbdat ) ;
if ( dsp - > sbleftright )
dsp - > sbdatl = dsp - > sbdat ;
else
dsp - > sbdatr = dsp - > sbdat ;
dsp - > sbleftright = ! dsp - > sbleftright ;
} else
dsp - > sbdatl = dsp - > sbdatr = dsp - > sbdat ;
break ;
2023-06-09 23:46:54 -04:00
default :
break ;
2022-02-22 20:28:56 -05:00
}
if ( dsp - > sb_8_length < 0 ) {
if ( dsp - > sb_8_autoinit )
2022-03-17 15:47:25 -03:00
dsp - > sb_8_length = dsp - > sb_8_origlength = dsp - > sb_8_autolen ;
2022-02-22 20:28:56 -05:00
else {
dsp - > sb_8_enable = 0 ;
timer_disable ( & dsp - > output_timer ) ;
}
sb_irq ( dsp , 1 ) ;
}
2021-11-07 06:30:40 +05:00
}
if ( dsp - > sb_16_enable & & ! dsp - > sb_16_pause & & ( dsp - > sb_pausetime < 0LL ) & & dsp - > sb_16_output ) {
2022-02-22 20:28:56 -05:00
sb_dsp_update ( dsp ) ;
switch ( dsp - > sb_16_format ) {
case 0x00 : /* Mono unsigned */
2022-03-06 19:59:14 -03:00
data [ 0 ] = dsp - > dma_readw ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
if ( data [ 0 ] = = DMA_NODATA )
break ;
dsp - > sbdatl = dsp - > sbdatr = data [ 0 ] ^ 0x8000 ;
dsp - > sb_16_length - - ;
break ;
case 0x10 : /* Mono signed */
2022-03-06 19:59:14 -03:00
data [ 0 ] = dsp - > dma_readw ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
if ( data [ 0 ] = = DMA_NODATA )
break ;
dsp - > sbdatl = dsp - > sbdatr = data [ 0 ] ;
dsp - > sb_16_length - - ;
break ;
case 0x20 : /* Stereo unsigned */
2022-03-06 19:59:14 -03:00
data [ 0 ] = dsp - > dma_readw ( dsp - > dma_priv ) ;
data [ 1 ] = dsp - > dma_readw ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
if ( ( data [ 0 ] = = DMA_NODATA ) | | ( data [ 1 ] = = DMA_NODATA ) )
break ;
dsp - > sbdatl = data [ 0 ] ^ 0x8000 ;
dsp - > sbdatr = data [ 1 ] ^ 0x8000 ;
dsp - > sb_16_length - = 2 ;
break ;
case 0x30 : /* Stereo signed */
2022-03-06 19:59:14 -03:00
data [ 0 ] = dsp - > dma_readw ( dsp - > dma_priv ) ;
data [ 1 ] = dsp - > dma_readw ( dsp - > dma_priv ) ;
2022-02-22 20:28:56 -05:00
if ( ( data [ 0 ] = = DMA_NODATA ) | | ( data [ 1 ] = = DMA_NODATA ) )
break ;
dsp - > sbdatl = data [ 0 ] ;
dsp - > sbdatr = data [ 1 ] ;
dsp - > sb_16_length - = 2 ;
break ;
2023-06-09 23:46:54 -04:00
default :
break ;
2022-02-22 20:28:56 -05:00
}
if ( dsp - > sb_16_length < 0 ) {
sb_dsp_log ( " 16DMA over %i \n " , dsp - > sb_16_autoinit ) ;
if ( dsp - > sb_16_autoinit )
2022-03-17 15:47:25 -03:00
dsp - > sb_16_length = dsp - > sb_16_origlength = dsp - > sb_16_autolen ;
2022-02-22 20:28:56 -05:00
else {
dsp - > sb_16_enable = 0 ;
timer_disable ( & dsp - > output_timer ) ;
}
sb_irq ( dsp , 0 ) ;
}
2021-11-07 06:30:40 +05:00
}
if ( dsp - > sb_pausetime > - 1 ) {
2022-02-22 20:28:56 -05:00
dsp - > sb_pausetime - - ;
if ( dsp - > sb_pausetime < 0 ) {
sb_irq ( dsp , 1 ) ;
if ( ! dsp - > sb_8_enable )
timer_disable ( & dsp - > output_timer ) ;
sb_dsp_log ( " SB pause over \n " ) ;
}
2021-11-07 06:30:40 +05:00
}
2016-06-26 00:34:39 +02:00
}
2019-12-21 20:03:07 +01:00
void
2023-06-09 23:46:54 -04:00
sb_poll_i ( void * priv )
2016-06-26 00:34:39 +02:00
{
2023-06-09 23:46:54 -04:00
sb_dsp_t * dsp = ( sb_dsp_t * ) priv ;
2022-02-22 20:28:56 -05:00
int processed = 0 ;
2019-12-21 20:03:07 +01:00
2022-07-23 17:53:26 +02:00
timer_advance_u64 ( & dsp - > input_timer , dsp - > sblatchi ) ;
2019-12-21 20:03:07 +01:00
2021-11-07 06:30:40 +05:00
if ( dsp - > sb_8_enable & & ! dsp - > sb_8_pause & & dsp - > sb_pausetime < 0 & & ! dsp - > sb_8_output ) {
2022-02-22 20:28:56 -05:00
switch ( dsp - > sb_8_format ) {
case 0x00 : /* Mono unsigned As the manual says, only the left channel is recorded */
2022-03-06 19:59:14 -03:00
dsp - > dma_writeb ( dsp - > dma_priv , ( dsp - > record_buffer [ dsp - > record_pos_read ] > > 8 ) ^ 0x80 ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_length - - ;
dsp - > record_pos_read + = 2 ;
dsp - > record_pos_read & = 0xFFFF ;
break ;
case 0x10 : /* Mono signed As the manual says, only the left channel is recorded */
2022-03-06 19:59:14 -03:00
dsp - > dma_writeb ( dsp - > dma_priv , ( dsp - > record_buffer [ dsp - > record_pos_read ] > > 8 ) ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_length - - ;
dsp - > record_pos_read + = 2 ;
dsp - > record_pos_read & = 0xFFFF ;
break ;
case 0x20 : /* Stereo unsigned */
2022-03-06 19:59:14 -03:00
dsp - > dma_writeb ( dsp - > dma_priv , ( dsp - > record_buffer [ dsp - > record_pos_read ] > > 8 ) ^ 0x80 ) ;
dsp - > dma_writeb ( dsp - > dma_priv , ( dsp - > record_buffer [ dsp - > record_pos_read + 1 ] > > 8 ) ^ 0x80 ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_length - = 2 ;
dsp - > record_pos_read + = 2 ;
dsp - > record_pos_read & = 0xFFFF ;
break ;
case 0x30 : /* Stereo signed */
2022-03-06 19:59:14 -03:00
dsp - > dma_writeb ( dsp - > dma_priv , ( dsp - > record_buffer [ dsp - > record_pos_read ] > > 8 ) ) ;
dsp - > dma_writeb ( dsp - > dma_priv , ( dsp - > record_buffer [ dsp - > record_pos_read + 1 ] > > 8 ) ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_8_length - = 2 ;
dsp - > record_pos_read + = 2 ;
dsp - > record_pos_read & = 0xFFFF ;
break ;
2023-06-09 23:46:54 -04:00
default :
break ;
2022-02-22 20:28:56 -05:00
}
if ( dsp - > sb_8_length < 0 ) {
if ( dsp - > sb_8_autoinit )
2022-03-17 15:47:25 -03:00
dsp - > sb_8_length = dsp - > sb_8_origlength = dsp - > sb_8_autolen ;
2022-02-22 20:28:56 -05:00
else {
dsp - > sb_8_enable = 0 ;
timer_disable ( & dsp - > input_timer ) ;
}
sb_irq ( dsp , 1 ) ;
}
processed = 1 ;
2021-11-07 06:30:40 +05:00
}
if ( dsp - > sb_16_enable & & ! dsp - > sb_16_pause & & ( dsp - > sb_pausetime < 0LL ) & & ! dsp - > sb_16_output ) {
2022-02-22 20:28:56 -05:00
switch ( dsp - > sb_16_format ) {
case 0x00 : /* Unsigned mono. As the manual says, only the left channel is recorded */
2022-03-06 19:59:14 -03:00
if ( dsp - > dma_writew ( dsp - > dma_priv , dsp - > record_buffer [ dsp - > record_pos_read ] ^ 0x8000 ) )
2022-02-22 20:28:56 -05:00
return ;
dsp - > sb_16_length - - ;
dsp - > record_pos_read + = 2 ;
dsp - > record_pos_read & = 0xFFFF ;
break ;
case 0x10 : /* Signed mono. As the manual says, only the left channel is recorded */
2022-03-06 19:59:14 -03:00
if ( dsp - > dma_writew ( dsp - > dma_priv , dsp - > record_buffer [ dsp - > record_pos_read ] ) )
2022-02-22 20:28:56 -05:00
return ;
dsp - > sb_16_length - - ;
dsp - > record_pos_read + = 2 ;
dsp - > record_pos_read & = 0xFFFF ;
break ;
case 0x20 : /* Unsigned stereo */
2022-03-06 19:59:14 -03:00
if ( dsp - > dma_writew ( dsp - > dma_priv , dsp - > record_buffer [ dsp - > record_pos_read ] ^ 0x8000 ) )
2022-02-22 20:28:56 -05:00
return ;
2022-03-06 19:59:14 -03:00
dsp - > dma_writew ( dsp - > dma_priv , dsp - > record_buffer [ dsp - > record_pos_read + 1 ] ^ 0x8000 ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_16_length - = 2 ;
dsp - > record_pos_read + = 2 ;
dsp - > record_pos_read & = 0xFFFF ;
break ;
case 0x30 : /* Signed stereo */
2022-03-06 19:59:14 -03:00
if ( dsp - > dma_writew ( dsp - > dma_priv , dsp - > record_buffer [ dsp - > record_pos_read ] ) )
2022-02-22 20:28:56 -05:00
return ;
2022-03-06 19:59:14 -03:00
dsp - > dma_writew ( dsp - > dma_priv , dsp - > record_buffer [ dsp - > record_pos_read + 1 ] ) ;
2022-02-22 20:28:56 -05:00
dsp - > sb_16_length - = 2 ;
dsp - > record_pos_read + = 2 ;
dsp - > record_pos_read & = 0xFFFF ;
break ;
2023-06-09 23:46:54 -04:00
default :
break ;
2022-02-22 20:28:56 -05:00
}
if ( dsp - > sb_16_length < 0 ) {
if ( dsp - > sb_16_autoinit )
2022-03-17 15:47:25 -03:00
dsp - > sb_16_length = dsp - > sb_16_origlength = dsp - > sb_16_autolen ;
2022-02-22 20:28:56 -05:00
else {
dsp - > sb_16_enable = 0 ;
timer_disable ( & dsp - > input_timer ) ;
}
sb_irq ( dsp , 0 ) ;
}
processed = 1 ;
2021-11-07 06:30:40 +05:00
}
/* Assume this is direct mode */
if ( ! processed ) {
2022-02-22 20:28:56 -05:00
dsp - > record_pos_read + = 2 ;
dsp - > record_pos_read & = 0xFFFF ;
2021-11-07 06:30:40 +05:00
}
2016-06-26 00:34:39 +02:00
}
2022-02-22 20:28:56 -05:00
void
sb_dsp_update ( sb_dsp_t * dsp )
2016-06-26 00:34:39 +02:00
{
2021-11-07 06:30:40 +05:00
if ( dsp - > muted ) {
2022-02-22 20:28:56 -05:00
dsp - > sbdatl = 0 ;
dsp - > sbdatr = 0 ;
2021-11-07 06:30:40 +05:00
}
for ( ; dsp - > pos < sound_pos_global ; dsp - > pos + + ) {
2022-02-22 20:28:56 -05:00
dsp - > buffer [ dsp - > pos * 2 ] = dsp - > sbdatl ;
dsp - > buffer [ dsp - > pos * 2 + 1 ] = dsp - > sbdatr ;
2021-11-07 06:30:40 +05:00
}
2016-06-26 00:34:39 +02:00
}
2018-05-21 19:04:05 +02:00
2019-12-21 20:03:07 +01:00
void
2023-06-09 23:46:54 -04:00
sb_dsp_close ( UNUSED ( sb_dsp_t * dsp ) )
2017-10-14 07:03:19 +02:00
{
2023-06-09 23:46:54 -04:00
//
2017-10-14 07:03:19 +02:00
}