2016-06-26 00:34:39 +02:00
|
|
|
/*Jazz sample rates :
|
|
|
|
|
386-33 - 12kHz
|
|
|
|
|
486-33 - 20kHz
|
|
|
|
|
486-50 - 32kHz
|
|
|
|
|
Pentium - 45kHz*/
|
2017-10-14 07:03:19 +02:00
|
|
|
|
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-09-25 04:31:20 -04:00
|
|
|
#include <string.h>
|
2017-10-14 13:38:05 -04:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <wchar.h>
|
2018-05-21 19:04:05 +02:00
|
|
|
#define HAVE_STDARG_H
|
2017-10-17 01:59:09 -04:00
|
|
|
#include "../86box.h"
|
2017-05-06 17:48:33 +02:00
|
|
|
#include "../io.h"
|
|
|
|
|
#include "../pic.h"
|
|
|
|
|
#include "../dma.h"
|
|
|
|
|
#include "../timer.h"
|
2017-06-04 02:11:19 -04:00
|
|
|
#include "../device.h"
|
2018-02-15 23:14:44 +01:00
|
|
|
#include "filters.h"
|
2016-06-26 00:34:39 +02:00
|
|
|
#include "sound.h"
|
2017-09-25 04:31:20 -04:00
|
|
|
#include "midi.h"
|
2017-05-10 18:29:16 +02:00
|
|
|
#include "snd_mpu401.h"
|
2017-11-05 01:57:04 -05:00
|
|
|
#include "snd_sb.h"
|
2017-05-06 17:48:33 +02:00
|
|
|
#include "snd_sb_dsp.h"
|
|
|
|
|
|
2019-12-21 20:03:07 +01:00
|
|
|
|
|
|
|
|
#define ADPCM_4 1
|
|
|
|
|
#define ADPCM_26 2
|
|
|
|
|
#define ADPCM_2 3
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
void pollsb(void *p);
|
|
|
|
|
void sb_poll_i(void *p);
|
|
|
|
|
|
|
|
|
|
static int sbe2dat[4][9] = {
|
|
|
|
|
{ 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 }
|
|
|
|
|
};
|
|
|
|
|
|
2017-10-16 06:19:18 +02:00
|
|
|
static mpu_t *mpu;
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
static int sb_commands[256]=
|
|
|
|
|
{
|
|
|
|
|
-1, 2,-1,-1, 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,-1,-1,-1,-1,-1,-1, 1, 2,-1,-1,-1,-1, 0
|
|
|
|
|
};
|
|
|
|
|
|
2019-12-21 20:03:07 +01:00
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
|
|
|
|
|
uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40d};
|
|
|
|
|
|
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] = {
|
|
|
|
|
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,
|
|
|
|
|
4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
uint8_t adjustMap4[64] = {
|
|
|
|
|
0, 0, 0, 0, 0, 16, 16, 16,
|
|
|
|
|
0, 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,
|
|
|
|
|
240, 0, 0, 0, 0, 16, 16, 16,
|
|
|
|
|
240, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
|
240, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int8_t scaleMap26[40] = {
|
|
|
|
|
0, 1, 2, 3, 0, -1, -2, -3,
|
|
|
|
|
1, 3, 5, 7, -1, -3, -5, -7,
|
|
|
|
|
2, 6, 10, 14, -2, -6, -10, -14,
|
|
|
|
|
4, 12, 20, 28, -4, -12, -20, -28,
|
|
|
|
|
5, 15, 25, 35, -5, -15, -25, -35
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
uint8_t adjustMap26[40] = {
|
|
|
|
|
0, 0, 0, 8, 0, 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, 8,
|
|
|
|
|
248, 0, 0, 0, 248, 0, 0, 0
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int8_t scaleMap2[24] = {
|
|
|
|
|
0, 1, 0, -1, 1, 3, -1, -3,
|
|
|
|
|
2, 6, -2, -6, 4, 12, -4, -12,
|
|
|
|
|
8, 24, -8, -24, 6, 48, -16, -48
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
uint8_t adjustMap2[24] = {
|
|
|
|
|
0, 4, 0, 4,
|
|
|
|
|
252, 4, 252, 4, 252, 4, 252, 4,
|
|
|
|
|
252, 4, 252, 4, 252, 4, 252, 4,
|
|
|
|
|
252, 0, 252, 0
|
|
|
|
|
};
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2018-02-15 23:14:44 +01:00
|
|
|
float low_fir_sb16_coef[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, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
if (sb_dsp_do_log) {
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
pclog_ex(fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-19 00:39:32 +02:00
|
|
|
#else
|
|
|
|
|
#define sb_dsp_log(fmt, ...)
|
|
|
|
|
#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
|
|
|
{
|
2019-12-21 20:03:07 +01: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
|
|
|
|
|
recalc_sb16_filter(int playback_freq)
|
2018-02-15 23:14:44 +01:00
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
/* Cutoff frequency = playback / 2 */
|
|
|
|
|
float fC = ((float)playback_freq / 2.0) / 48000.0;
|
|
|
|
|
float gain;
|
|
|
|
|
int n;
|
|
|
|
|
double w, h;
|
|
|
|
|
|
|
|
|
|
for (n = 0; n < SB16_NCoef; n++) {
|
|
|
|
|
/* 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)));
|
|
|
|
|
|
|
|
|
|
/* Create windowed-sinc filter */
|
|
|
|
|
low_fir_sb16_coef[n] = w * h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
low_fir_sb16_coef[(SB16_NCoef - 1) / 2] = 1.0;
|
2018-02-15 23:14:44 +01:00
|
|
|
|
2019-12-21 20:03:07 +01:00
|
|
|
gain = 0.0;
|
|
|
|
|
for (n = 0; n < SB16_NCoef; n++)
|
|
|
|
|
gain += low_fir_sb16_coef[n];
|
2018-02-15 23:14:44 +01:00
|
|
|
|
2019-12-21 20:03:07 +01:00
|
|
|
/* Normalise filter, to produce unity gain */
|
|
|
|
|
for (n = 0; n < SB16_NCoef; n++)
|
|
|
|
|
low_fir_sb16_coef[n] /= gain;
|
2018-02-15 23:14:44 +01:00
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
|
|
|
|
|
|
2019-12-21 20:03:07 +01:00
|
|
|
void
|
|
|
|
|
sb_irq(sb_dsp_t *dsp, int irq8)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
sb_dsp_log("IRQ %i %02X\n", irq8, pic.mask);
|
|
|
|
|
if (irq8)
|
|
|
|
|
dsp->sb_irq8 = 1;
|
|
|
|
|
else
|
|
|
|
|
dsp->sb_irq16 = 1;
|
|
|
|
|
|
|
|
|
|
picint(1 << dsp->sb_irqnum);
|
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
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
if (irq8)
|
|
|
|
|
dsp->sb_irq8 = 0;
|
|
|
|
|
else
|
|
|
|
|
dsp->sb_irq16 = 0;
|
|
|
|
|
|
|
|
|
|
picintc(1 << dsp->sb_irqnum);
|
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
|
|
|
{
|
2020-01-01 20:20:16 +01:00
|
|
|
midi_clear_buffer();
|
|
|
|
|
|
2019-12-21 20:03:07 +01:00
|
|
|
timer_disable(&dsp->output_timer);
|
|
|
|
|
timer_disable(&dsp->input_timer);
|
|
|
|
|
|
|
|
|
|
dsp->sb_command = 0;
|
|
|
|
|
|
|
|
|
|
dsp->sb_8_length = 0xffff;
|
|
|
|
|
dsp->sb_8_autolen = 0xffff;
|
|
|
|
|
|
|
|
|
|
sb_irqc(dsp, 0);
|
|
|
|
|
sb_irqc(dsp, 1);
|
|
|
|
|
dsp->sb_16_pause = 0;
|
2020-01-01 20:20:16 +01:00
|
|
|
dsp->sb_read_wp = dsp->sb_read_rp = 0;
|
2019-12-21 20:03:07 +01:00
|
|
|
dsp->sb_data_stat = -1;
|
|
|
|
|
dsp->sb_speaker = 0;
|
|
|
|
|
dsp->sb_pausetime = -1LL;
|
|
|
|
|
dsp->sbe2 = 0xAA;
|
|
|
|
|
dsp->sbe2count = 0;
|
|
|
|
|
|
|
|
|
|
dsp->sbreset = 0;
|
|
|
|
|
|
|
|
|
|
dsp->record_pos_read = 0;
|
|
|
|
|
dsp->record_pos_write = SB_DSP_REC_SAFEFTY_MARGIN;
|
|
|
|
|
|
|
|
|
|
picintc(1 << dsp->sb_irqnum);
|
|
|
|
|
|
|
|
|
|
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
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
int c;
|
|
|
|
|
|
|
|
|
|
sb_dsp_reset(dsp);
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
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
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
if (dsp->sb_timeo < 256)
|
|
|
|
|
dsp->sblatcho = TIMER_USEC * (256 - dsp->sb_timeo);
|
|
|
|
|
else
|
|
|
|
|
dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timeo - 256)));
|
|
|
|
|
|
|
|
|
|
if (dsp->sb_timei < 256)
|
|
|
|
|
dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_timei);
|
|
|
|
|
else
|
|
|
|
|
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
|
|
|
{
|
2019-12-21 20:03:07 +01: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
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
dsp->sb_pausetime = -1;
|
|
|
|
|
|
|
|
|
|
if (dma8) {
|
|
|
|
|
dsp->sb_8_length = len;
|
|
|
|
|
dsp->sb_8_format = format;
|
|
|
|
|
dsp->sb_8_autoinit = autoinit;
|
|
|
|
|
dsp->sb_8_pause = 0;
|
|
|
|
|
dsp->sb_8_enable = 1;
|
|
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho);
|
|
|
|
|
dsp->sbleftright = 0;
|
|
|
|
|
dsp->sbdacpos = 0;
|
|
|
|
|
} else {
|
|
|
|
|
dsp->sb_16_length = len;
|
|
|
|
|
dsp->sb_16_format = format;
|
|
|
|
|
dsp->sb_16_autoinit = autoinit;
|
|
|
|
|
dsp->sb_16_pause = 0;
|
|
|
|
|
dsp->sb_16_enable = 1;
|
|
|
|
|
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))
|
|
|
|
|
timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho);
|
|
|
|
|
}
|
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
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
if (dma8) {
|
|
|
|
|
dsp->sb_8_length = len;
|
|
|
|
|
dsp->sb_8_format = format;
|
|
|
|
|
dsp->sb_8_autoinit = autoinit;
|
|
|
|
|
dsp->sb_8_pause = 0;
|
|
|
|
|
dsp->sb_8_enable = 1;
|
|
|
|
|
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))
|
|
|
|
|
timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi);
|
|
|
|
|
} else {
|
|
|
|
|
dsp->sb_16_length = len;
|
|
|
|
|
dsp->sb_16_format = format;
|
|
|
|
|
dsp->sb_16_autoinit = autoinit;
|
|
|
|
|
dsp->sb_16_pause = 0;
|
|
|
|
|
dsp->sb_16_enable = 1;
|
|
|
|
|
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))
|
|
|
|
|
timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
sb_8_read_dma(sb_dsp_t *dsp)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:03:07 +01: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
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
sb_8_write_dma(sb_dsp_t *dsp, uint8_t val)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
dma_channel_write(dsp->sb_8_dmanum, val);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2019-12-21 20:03:07 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sb_16_read_dma(sb_dsp_t *dsp)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
return dma_channel_read(dsp->sb_16_dmanum);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2019-12-21 20:03:07 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sb_16_write_dma(sb_dsp_t *dsp, uint16_t val)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
int ret = dma_channel_write(dsp->sb_16_dmanum, val);
|
|
|
|
|
|
|
|
|
|
return (ret == DMA_NODATA);
|
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
|
|
|
{
|
2019-12-21 20:03:07 +01: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
|
|
|
{
|
2019-12-21 20:03:07 +01: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
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
dsp->sb_16_dmanum = dma;
|
2016-11-13 18:21:15 +01:00
|
|
|
}
|
2019-12-21 20:03:07 +01:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
sb_exec_command(sb_dsp_t *dsp)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
int temp, c;
|
|
|
|
|
|
|
|
|
|
sb_dsp_log("sb_exec_command : SB command %02X\n", dsp->sb_command);
|
|
|
|
|
|
|
|
|
|
switch (dsp->sb_command) {
|
|
|
|
|
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 */
|
|
|
|
|
sb_add_data(dsp, 0);
|
|
|
|
|
break;
|
|
|
|
|
case 0x10: /* 8-bit direct mode */
|
|
|
|
|
sb_dsp_update(dsp);
|
|
|
|
|
dsp->sbdat = dsp->sbdatl = dsp->sbdatr = (dsp->sb_data[0] ^ 0x80) << 8;
|
2017-10-14 07:03:19 +02:00
|
|
|
break;
|
2019-12-21 20:03:07 +01:00
|
|
|
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 */
|
|
|
|
|
dsp->sbref = sb_8_read_dma(dsp);
|
|
|
|
|
dsp->sbstep = 0;
|
|
|
|
|
/* Fall through */
|
|
|
|
|
case 0x16: /* 2-bit ADPCM output */
|
|
|
|
|
sb_start_dma(dsp, 1, 0, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8));
|
|
|
|
|
dsp->sbdat2 = sb_8_read_dma(dsp);
|
|
|
|
|
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));
|
|
|
|
|
dsp->sbdat2 = sb_8_read_dma(dsp);
|
|
|
|
|
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;
|
|
|
|
|
dsp->sblatchi = TIMER_USEC * 22;
|
|
|
|
|
temp = 1000000 / 22;
|
|
|
|
|
dsp->sb_freq = temp;
|
|
|
|
|
timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi);
|
|
|
|
|
}
|
|
|
|
|
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 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;
|
2020-01-01 20:20:16 +01:00
|
|
|
case 0x30: /* MIDI Polling mode input */
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_dsp_log("MIDI polling mode input\n");
|
2020-01-01 20:20:16 +01:00
|
|
|
dsp->midi_in_poll = 1;
|
|
|
|
|
dsp->uart_irq = 0;
|
2019-12-21 20:03:07 +01:00
|
|
|
break;
|
2020-01-01 20:20:16 +01:00
|
|
|
case 0x31: /* MIDI Interrupt mode input */
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_dsp_log("MIDI interrupt mode input\n");
|
2020-01-01 20:20:16 +01:00
|
|
|
dsp->midi_in_poll = 0;
|
|
|
|
|
dsp->uart_irq = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 0x34: /* MIDI In poll */
|
|
|
|
|
if (dsp->sb_type < SB2)
|
|
|
|
|
break;
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_dsp_log("MIDI poll in\n");
|
2020-01-01 20:20:16 +01:00
|
|
|
dsp->midi_in_poll = 1;
|
2017-10-14 07:03:19 +02:00
|
|
|
dsp->uart_midi = 1;
|
|
|
|
|
dsp->uart_irq = 0;
|
|
|
|
|
break;
|
2020-01-01 20:20:16 +01:00
|
|
|
case 0x35: /* MIDI In irq */
|
|
|
|
|
if (dsp->sb_type < SB2)
|
|
|
|
|
break;
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_dsp_log("MIDI irq in\n");
|
2020-01-01 20:20:16 +01:00
|
|
|
dsp->midi_in_poll = 0;
|
2017-10-14 07:03:19 +02:00
|
|
|
dsp->uart_midi = 1;
|
|
|
|
|
dsp->uart_irq = 1;
|
|
|
|
|
break;
|
2020-01-01 20:20:16 +01:00
|
|
|
case 0x36: case 0x37: /* MIDI timestamps */
|
2017-10-14 07:03:19 +02:00
|
|
|
break;
|
2020-01-01 20:20:16 +01:00
|
|
|
case 0x38: /* Write to SB MIDI Output (Raw) */
|
2017-10-14 07:03:19 +02:00
|
|
|
dsp->onebyte_midi = 1;
|
|
|
|
|
break;
|
2019-12-21 20:03:07 +01:00
|
|
|
case 0x40: /* Set time constant */
|
|
|
|
|
dsp->sb_timei = dsp->sb_timeo = dsp->sb_data[0];
|
|
|
|
|
dsp->sblatcho = dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_data[0]);
|
|
|
|
|
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(temp);
|
|
|
|
|
dsp->sb_freq = temp;
|
|
|
|
|
break;
|
|
|
|
|
case 0x41: /* Set output sampling rate */
|
|
|
|
|
case 0x42: /* Set input sampling rate */
|
|
|
|
|
if (dsp->sb_type >= SB16) {
|
|
|
|
|
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);
|
|
|
|
|
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(dsp->sb_freq);
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
break;
|
2019-12-21 20:03:07 +01:00
|
|
|
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 */
|
|
|
|
|
dsp->sbref = sb_8_read_dma(dsp);
|
|
|
|
|
dsp->sbstep = 0;
|
|
|
|
|
/* Fall through */
|
|
|
|
|
case 0x74: /* 4-bit ADPCM output */
|
|
|
|
|
sb_start_dma(dsp, 1, 0, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8));
|
|
|
|
|
dsp->sbdat2 = sb_8_read_dma(dsp);
|
|
|
|
|
dsp->sb_8_length--;
|
|
|
|
|
if (dsp->sb_command == 0x75)
|
|
|
|
|
dsp->sb_8_length--;
|
|
|
|
|
break;
|
|
|
|
|
case 0x77: /* 2.6-bit ADPCM output with reference */
|
|
|
|
|
dsp->sbref = sb_8_read_dma(dsp);
|
|
|
|
|
dsp->sbstep = 0;
|
|
|
|
|
/* Fall through */
|
|
|
|
|
case 0x76: /* 2.6-bit ADPCM output */
|
|
|
|
|
sb_start_dma(dsp, 1, 0, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8));
|
|
|
|
|
dsp->sbdat2 = sb_8_read_dma(dsp);
|
|
|
|
|
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));
|
|
|
|
|
dsp->sbdat2 = sb_8_read_dma(dsp);
|
|
|
|
|
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));
|
|
|
|
|
dsp->sbdat2 = sb_8_read_dma(dsp);
|
|
|
|
|
dsp->sb_8_length--;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0x80: /* Pause DAC */
|
|
|
|
|
dsp->sb_pausetime = dsp->sb_data[0] + (dsp->sb_data[1] << 8);
|
Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port;
Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX);
Finished the 586MC1;
Added 8087 emulation;
Moved Cyrix 6x86'es to the Dev branch;
Sanitized/cleaned up memregs.c/h and intel.c/h;
Split the chipsets from machines and sanitized Port 92 emulation;
Added support for the 15bpp mode to the Compaq ATI 28800;
Moved the MR 386DX and 486 machines to the Dev branch;
Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00;
Ported the new timer code from PCem;
Cleaned up the CPU table of unused stuff and better optimized its structure;
Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch;
Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem;
Added the AHA-1540A and the BusTek BT-542B;
Moved the Sumo SCSI-AT to the Dev branch;
Minor IDE, FDC, and floppy drive code clean-ups;
Made NCR 5380/53C400-based cards' BIOS address configurable;
Got rid of the legacy romset variable;
Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit;
Added the Amstead PPC512 per PCem patch by John Elliott;
Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages);
Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing;
Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem;
Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit;
Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement;
Amstrad MegaPC does now works correctly with non-internal graphics card;
The SLiRP code no longer casts a packed struct type to a non-packed struct type;
The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present;
The S3 Virge on BeOS is no longer broken (was broken by build #1591);
OS/2 2.0 build 6.167 now sees key presses again;
Xi8088 now work on CGA again;
86F images converted from either the old or new variants of the HxC MFM format now work correctly;
Hardware interrupts with a vector of 0xFF are now handled correctly;
OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct;
Fixed VNC keyboard input bugs;
Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver;
Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly;
Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4;
Compaq Portable now works with all graphics cards;
Fixed various MDSI Genius bugs;
Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly;
Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355;
OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400.
Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391.
Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389.
Fixed a minor IDE timing bug, fixes #388.
Fixed Toshiba T1000 RAM issues, fixes #379.
Fixed EGA/(S)VGA overscan border handling, fixes #378;
Got rid of the now long useless IDE channel 2 auto-removal, fixes #370;
Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366;
Ported the Unicode CD image file name fix from VARCem, fixes #365;
Fixed high density floppy disks on the Xi8088, fixes #359;
Fixed some bugs in the Hercules emulation, fixes #346, fixes #358;
Fixed the SCSI hard disk mode sense pages, fixes #356;
Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349;
Fixed bugs in the serial mouse emulation, fixes #344;
Compiled 86Box binaries now include all the required .DLL's, fixes #341;
Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
|
|
|
if (!timer_is_enabled(&dsp->output_timer))
|
|
|
|
|
timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho);
|
2019-12-21 20:03:07 +01: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;
|
2018-05-21 19:04:05 +02:00
|
|
|
/* TODO: Implement. 3.xx-only command. */
|
2019-12-21 20:03:07 +01:00
|
|
|
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) {
|
|
|
|
|
sb_start_dma(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8));
|
|
|
|
|
dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8);
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
break;
|
2019-12-21 20:03:07 +01:00
|
|
|
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) {
|
|
|
|
|
sb_start_dma_i(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8));
|
|
|
|
|
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) {
|
|
|
|
|
sb_start_dma(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8));
|
|
|
|
|
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) {
|
|
|
|
|
sb_start_dma_i(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8));
|
|
|
|
|
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 */
|
|
|
|
|
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++;
|
|
|
|
|
sb_8_write_dma(dsp, dsp->sbe2);
|
|
|
|
|
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;
|
|
|
|
|
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 0xE7: case 0xFA: /* ???? */
|
|
|
|
|
break;
|
|
|
|
|
case 0x07: case 0xFF: /* No, that's not how you program auto-init DMA */
|
|
|
|
|
break;
|
|
|
|
|
case 0x08: /* ASP get version */
|
|
|
|
|
if (dsp->sb_type >= SB16)
|
|
|
|
|
sb_add_data(dsp, 0x18);
|
|
|
|
|
break;
|
|
|
|
|
case 0x0E: /* ASP set register */
|
|
|
|
|
if (dsp->sb_type >= SB16)
|
|
|
|
|
dsp->sb_asp_regs[dsp->sb_data[0]] = dsp->sb_data[1];
|
|
|
|
|
break;
|
|
|
|
|
case 0x0F: /* ASP get register */
|
|
|
|
|
if (dsp->sb_type >= SB16)
|
|
|
|
|
sb_add_data(dsp, dsp->sb_asp_regs[dsp->sb_data[0]]);
|
|
|
|
|
break;
|
|
|
|
|
case 0xF8:
|
|
|
|
|
if (dsp->sb_type < SB16)
|
|
|
|
|
sb_add_data(dsp, 0);
|
|
|
|
|
break;
|
|
|
|
|
case 0xF9:
|
|
|
|
|
if (dsp->sb_type >= SB16) {
|
|
|
|
|
if (dsp->sb_data[0] == 0x0e)
|
|
|
|
|
sb_add_data(dsp, 0xff);
|
|
|
|
|
else if (dsp->sb_data[0] == 0x0f)
|
|
|
|
|
sb_add_data(dsp, 0x07);
|
|
|
|
|
else if (dsp->sb_data[0] == 0x37)
|
|
|
|
|
sb_add_data(dsp, 0x38);
|
|
|
|
|
else
|
|
|
|
|
sb_add_data(dsp, 0x00);
|
|
|
|
|
}
|
|
|
|
|
case 0x04: case 0x05:
|
|
|
|
|
break;
|
2018-05-21 19:04:05 +02:00
|
|
|
|
2019-12-21 20:03:07 +01:00
|
|
|
/* 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/
|
|
|
|
|
* 0E3h DSP Copyright SBPro2???
|
|
|
|
|
* 0F0h Sine Generator SB
|
|
|
|
|
* 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2
|
|
|
|
|
* 0F2h IRQ Request, 8-bit SB
|
|
|
|
|
* 0F3h IRQ Request, 16-bit SB16
|
|
|
|
|
* 0FBh DSP Status SB16
|
|
|
|
|
* 0FCh DSP Auxiliary Status SB16
|
|
|
|
|
* 0FDh DSP Command Status SB16
|
|
|
|
|
*/
|
|
|
|
|
}
|
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
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
sb_dsp_t *dsp = (sb_dsp_t *) priv;
|
|
|
|
|
|
|
|
|
|
switch (a & 0xF) {
|
|
|
|
|
case 6: /* Reset */
|
2020-01-01 20:20:16 +01:00
|
|
|
if (!dsp->uart_midi) {
|
|
|
|
|
if (!(v & 1) && (dsp->sbreset & 1)) {
|
|
|
|
|
sb_dsp_reset(dsp);
|
|
|
|
|
sb_add_data(dsp, 0xAA);
|
|
|
|
|
}
|
|
|
|
|
dsp->sbreset = v;
|
2019-12-21 20:03:07 +01:00
|
|
|
}
|
2020-01-01 20:20:16 +01:00
|
|
|
dsp->uart_midi = 0;
|
|
|
|
|
dsp->uart_irq = 0;
|
|
|
|
|
dsp->onebyte_midi = 0;
|
2019-12-21 20:03:07 +01:00
|
|
|
return;
|
|
|
|
|
case 0xC: /* Command/data write */
|
2020-01-01 20:20:16 +01:00
|
|
|
if (dsp->uart_midi || dsp->onebyte_midi ) {
|
|
|
|
|
midi_raw_out_byte(v);
|
2019-12-21 20:03:07 +01:00
|
|
|
dsp->onebyte_midi = 0;
|
2020-01-01 20:20:16 +01:00
|
|
|
return;
|
2019-12-21 20:03:07 +01:00
|
|
|
}
|
|
|
|
|
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 (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1) {
|
|
|
|
|
sb_exec_command(dsp);
|
|
|
|
|
dsp->sb_data_stat = -1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
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
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
sb_dsp_t *dsp = (sb_dsp_t *) priv;
|
|
|
|
|
uint8_t ret = 0x00;
|
|
|
|
|
|
|
|
|
|
switch (a & 0xf) {
|
|
|
|
|
case 0xA: /* Read data */
|
2020-01-01 20:20:16 +01:00
|
|
|
if (mpu && dsp->uart_midi) {
|
2019-12-21 20:03:07 +01:00
|
|
|
ret = MPU401_ReadData(mpu);
|
2020-01-01 20:20:16 +01:00
|
|
|
} else {
|
2019-12-21 20:03:07 +01:00
|
|
|
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);
|
|
|
|
|
return 0xff;
|
2017-10-16 06:19:18 +02:00
|
|
|
}
|
2019-12-21 20:03:07 +01:00
|
|
|
ret = 0x7f;
|
|
|
|
|
break;
|
|
|
|
|
case 0xE: /* Read data ready */
|
|
|
|
|
picintc(1 << dsp->sb_irqnum);
|
|
|
|
|
dsp->sb_irq8 = dsp->sb_irq16 = 0;
|
|
|
|
|
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)
|
|
|
|
|
picintc(1 << dsp->sb_irqnum);
|
|
|
|
|
ret = 0xff;
|
|
|
|
|
break;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-21 20:03:07 +01:00
|
|
|
return ret;
|
2017-10-16 06:19:18 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-21 20:03:07 +01:00
|
|
|
|
|
|
|
|
/* This should not even be needed. */
|
|
|
|
|
void
|
|
|
|
|
sb_dsp_set_mpu(mpu_t *src_mpu)
|
2017-10-16 06:19:18 +02:00
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
mpu = src_mpu;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2020-01-01 20:20:16 +01:00
|
|
|
void
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_dsp_input_msg(void *p, uint8_t *msg)
|
2020-01-01 20:20:16 +01:00
|
|
|
{
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_dsp_t *dsp = (sb_dsp_t *) p;
|
|
|
|
|
|
|
|
|
|
sb_dsp_log("MIDI in sysex = %d, uart irq = %d, msg = %d\n", dsp->midi_in_sysex, dsp->uart_irq, msg[3]);
|
2020-01-19 05:45:05 +01:00
|
|
|
|
|
|
|
|
if (!dsp->uart_irq && !dsp->midi_in_poll && (mpu != NULL)) {
|
|
|
|
|
MPU401_InputMsg(mpu, msg);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-02 18:19:22 +01:00
|
|
|
if (dsp->midi_in_sysex) {
|
2020-01-01 20:20:16 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t len = msg[3];
|
|
|
|
|
uint8_t i = 0;
|
2020-01-02 18:19:22 +01:00
|
|
|
if (dsp->uart_irq) {
|
2020-01-01 20:20:16 +01:00
|
|
|
for (i=0;i<len;i++)
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_add_data(dsp, msg[i]);
|
|
|
|
|
sb_dsp_log("SB IRQ8 = %d\n", dsp->sb_irq8);
|
|
|
|
|
if (!dsp->sb_irq8)
|
|
|
|
|
picint(1 << dsp->sb_irqnum);
|
|
|
|
|
} else if (dsp->midi_in_poll) {
|
2020-01-01 20:20:16 +01:00
|
|
|
for (i=0;i<len;i++)
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_add_data(dsp, msg[i]);
|
2020-01-01 20:20:16 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
|
2020-01-01 20:20:16 +01:00
|
|
|
{
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_dsp_t *dsp = (sb_dsp_t *) p;
|
|
|
|
|
|
2020-01-01 20:20:16 +01:00
|
|
|
uint32_t i;
|
|
|
|
|
|
2020-01-19 05:45:05 +01:00
|
|
|
if (!dsp->uart_irq && !dsp->midi_in_poll && (mpu != NULL))
|
|
|
|
|
return MPU401_InputSysex(mpu, buffer, len, abort);
|
|
|
|
|
|
2020-01-01 20:20:16 +01:00
|
|
|
if (abort) {
|
2020-01-02 18:19:22 +01:00
|
|
|
dsp->midi_in_sysex = 0;
|
2020-01-01 20:20:16 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
2020-01-02 18:19:22 +01:00
|
|
|
dsp->midi_in_sysex = 1;
|
2020-01-01 20:20:16 +01:00
|
|
|
for (i=0;i<len;i++) {
|
2020-01-02 18:19:22 +01:00
|
|
|
if (dsp->sb_read_rp == dsp->sb_read_wp) {
|
|
|
|
|
sb_dsp_log("Length sysex SB = %d\n", len-i);
|
2020-01-01 20:20:16 +01:00
|
|
|
return (len-i);
|
|
|
|
|
}
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_add_data(dsp, buffer[i]);
|
2020-01-01 20:20:16 +01:00
|
|
|
}
|
2020-01-02 18:19:22 +01:00
|
|
|
dsp->midi_in_sysex = 0;
|
2020-01-01 20:20:16 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
2019-12-21 20:03:07 +01:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
sb_dsp_init(sb_dsp_t *dsp, int type)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
dsp->sb_type = type;
|
|
|
|
|
|
|
|
|
|
/* Default values. Use sb_dsp_setxxx() methods to change. */
|
|
|
|
|
dsp->sb_irqnum = 7;
|
|
|
|
|
dsp->sb_8_dmanum = 1;
|
|
|
|
|
dsp->sb_16_dmanum = 5;
|
|
|
|
|
mpu = NULL;
|
|
|
|
|
|
|
|
|
|
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. */
|
|
|
|
|
recalc_sb16_filter(3200*2);
|
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
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
sb_dsp_log("sb_dsp_setaddr : %04X\n", addr);
|
|
|
|
|
if (dsp->sb_addr != 0) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
dsp->sb_addr = addr;
|
|
|
|
|
if (dsp->sb_addr != 0) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
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
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
dsp->stereo = stereo;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-21 20:03:07 +01:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
pollsb(void *p)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
sb_dsp_t *dsp = (sb_dsp_t *) p;
|
|
|
|
|
int tempi, ref;
|
|
|
|
|
int data[2];
|
|
|
|
|
|
|
|
|
|
timer_advance_u64(&dsp->output_timer, dsp->sblatcho);
|
|
|
|
|
if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && dsp->sb_8_output) {
|
|
|
|
|
sb_dsp_update(dsp);
|
|
|
|
|
|
|
|
|
|
switch (dsp->sb_8_format) {
|
|
|
|
|
case 0x00: /* Mono unsigned */
|
|
|
|
|
data[0] = sb_8_read_dma(dsp);
|
|
|
|
|
/* 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;
|
|
|
|
|
if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) {
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_dsp_log("pollsb: Mono unsigned, dsp->stereo, %s channel, %04X\n",
|
2019-12-21 20:03:07 +01:00
|
|
|
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 */
|
|
|
|
|
data[0] = sb_8_read_dma(dsp);
|
|
|
|
|
if (data[0] == DMA_NODATA)
|
|
|
|
|
break;
|
|
|
|
|
dsp->sbdat = data[0] << 8;
|
|
|
|
|
if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) {
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_dsp_log("pollsb: Mono signed, dsp->stereo, %s channel, %04X\n",
|
2019-12-21 20:03:07 +01:00
|
|
|
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 */
|
|
|
|
|
data[0] = sb_8_read_dma(dsp);
|
|
|
|
|
data[1] = sb_8_read_dma(dsp);
|
|
|
|
|
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 */
|
|
|
|
|
data[0] = sb_8_read_dma(dsp);
|
|
|
|
|
data[1] = sb_8_read_dma(dsp);
|
|
|
|
|
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;
|
|
|
|
|
dsp->sbdat2 = sb_8_read_dma(dsp);
|
|
|
|
|
dsp->sb_8_length--;
|
Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port;
Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX);
Finished the 586MC1;
Added 8087 emulation;
Moved Cyrix 6x86'es to the Dev branch;
Sanitized/cleaned up memregs.c/h and intel.c/h;
Split the chipsets from machines and sanitized Port 92 emulation;
Added support for the 15bpp mode to the Compaq ATI 28800;
Moved the MR 386DX and 486 machines to the Dev branch;
Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00;
Ported the new timer code from PCem;
Cleaned up the CPU table of unused stuff and better optimized its structure;
Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch;
Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem;
Added the AHA-1540A and the BusTek BT-542B;
Moved the Sumo SCSI-AT to the Dev branch;
Minor IDE, FDC, and floppy drive code clean-ups;
Made NCR 5380/53C400-based cards' BIOS address configurable;
Got rid of the legacy romset variable;
Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit;
Added the Amstead PPC512 per PCem patch by John Elliott;
Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages);
Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing;
Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem;
Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit;
Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement;
Amstrad MegaPC does now works correctly with non-internal graphics card;
The SLiRP code no longer casts a packed struct type to a non-packed struct type;
The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present;
The S3 Virge on BeOS is no longer broken (was broken by build #1591);
OS/2 2.0 build 6.167 now sees key presses again;
Xi8088 now work on CGA again;
86F images converted from either the old or new variants of the HxC MFM format now work correctly;
Hardware interrupts with a vector of 0xFF are now handled correctly;
OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct;
Fixed VNC keyboard input bugs;
Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver;
Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly;
Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4;
Compaq Portable now works with all graphics cards;
Fixed various MDSI Genius bugs;
Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly;
Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355;
OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400.
Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391.
Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389.
Fixed a minor IDE timing bug, fixes #388.
Fixed Toshiba T1000 RAM issues, fixes #379.
Fixed EGA/(S)VGA overscan border handling, fixes #378;
Got rid of the now long useless IDE channel 2 auto-removal, fixes #370;
Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366;
Ported the Unicode CD image file name fix from VARCem, fixes #365;
Fixed high density floppy disks on the Xi8088, fixes #359;
Fixed some bugs in the Hercules emulation, fixes #346, fixes #358;
Fixed the SCSI hard disk mode sense pages, fixes #356;
Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349;
Fixed bugs in the serial mouse emulation, fixes #344;
Compiled 86Box binaries now include all the required .DLL's, fixes #341;
Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
|
|
|
}
|
2019-12-21 20:03:07 +01:00
|
|
|
|
|
|
|
|
if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) {
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_dsp_log("pollsb: ADPCM 4, dsp->stereo, %s channel, %04X\n",
|
2019-12-21 20:03:07 +01:00
|
|
|
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;
|
|
|
|
|
dsp->sbdat2 = sb_8_read_dma(dsp);
|
|
|
|
|
dsp->sb_8_length--;
|
Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port;
Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX);
Finished the 586MC1;
Added 8087 emulation;
Moved Cyrix 6x86'es to the Dev branch;
Sanitized/cleaned up memregs.c/h and intel.c/h;
Split the chipsets from machines and sanitized Port 92 emulation;
Added support for the 15bpp mode to the Compaq ATI 28800;
Moved the MR 386DX and 486 machines to the Dev branch;
Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00;
Ported the new timer code from PCem;
Cleaned up the CPU table of unused stuff and better optimized its structure;
Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch;
Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem;
Added the AHA-1540A and the BusTek BT-542B;
Moved the Sumo SCSI-AT to the Dev branch;
Minor IDE, FDC, and floppy drive code clean-ups;
Made NCR 5380/53C400-based cards' BIOS address configurable;
Got rid of the legacy romset variable;
Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit;
Added the Amstead PPC512 per PCem patch by John Elliott;
Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages);
Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing;
Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem;
Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit;
Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement;
Amstrad MegaPC does now works correctly with non-internal graphics card;
The SLiRP code no longer casts a packed struct type to a non-packed struct type;
The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present;
The S3 Virge on BeOS is no longer broken (was broken by build #1591);
OS/2 2.0 build 6.167 now sees key presses again;
Xi8088 now work on CGA again;
86F images converted from either the old or new variants of the HxC MFM format now work correctly;
Hardware interrupts with a vector of 0xFF are now handled correctly;
OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct;
Fixed VNC keyboard input bugs;
Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver;
Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly;
Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4;
Compaq Portable now works with all graphics cards;
Fixed various MDSI Genius bugs;
Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly;
Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355;
OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400.
Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391.
Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389.
Fixed a minor IDE timing bug, fixes #388.
Fixed Toshiba T1000 RAM issues, fixes #379.
Fixed EGA/(S)VGA overscan border handling, fixes #378;
Got rid of the now long useless IDE channel 2 auto-removal, fixes #370;
Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366;
Ported the Unicode CD image file name fix from VARCem, fixes #365;
Fixed high density floppy disks on the Xi8088, fixes #359;
Fixed some bugs in the Hercules emulation, fixes #346, fixes #358;
Fixed the SCSI hard disk mode sense pages, fixes #356;
Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349;
Fixed bugs in the serial mouse emulation, fixes #344;
Compiled 86Box binaries now include all the required .DLL's, fixes #341;
Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
|
|
|
}
|
2019-12-21 20:03:07 +01:00
|
|
|
|
|
|
|
|
if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) {
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_dsp_log("pollsb: ADPCM 26, dsp->stereo, %s channel, %04X\n",
|
2019-12-21 20:03:07 +01:00
|
|
|
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;
|
|
|
|
|
dsp->sbdat2 = sb_8_read_dma(dsp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) {
|
2020-01-02 18:19:22 +01:00
|
|
|
sb_dsp_log("pollsb: ADPCM 2, dsp->stereo, %s channel, %04X\n",
|
2019-12-21 20:03:07 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dsp->sb_8_length < 0) {
|
|
|
|
|
if (dsp->sb_8_autoinit)
|
|
|
|
|
dsp->sb_8_length = dsp->sb_8_autolen;
|
|
|
|
|
else {
|
|
|
|
|
dsp->sb_8_enable = 0;
|
|
|
|
|
timer_disable(&dsp->output_timer);
|
|
|
|
|
}
|
|
|
|
|
sb_irq(dsp, 1);
|
|
|
|
|
}
|
|
|
|
|
} if (dsp->sb_16_enable && !dsp->sb_16_pause && (dsp->sb_pausetime < 0LL) && dsp->sb_16_output) {
|
|
|
|
|
sb_dsp_update(dsp);
|
|
|
|
|
|
|
|
|
|
switch (dsp->sb_16_format) {
|
|
|
|
|
case 0x00: /* Mono unsigned */
|
|
|
|
|
data[0] = sb_16_read_dma(dsp);
|
|
|
|
|
if (data[0] == DMA_NODATA)
|
|
|
|
|
break;
|
|
|
|
|
dsp->sbdatl = dsp->sbdatr = data[0] ^ 0x8000;
|
|
|
|
|
dsp->sb_16_length--;
|
|
|
|
|
break;
|
|
|
|
|
case 0x10: /* Mono signed */
|
|
|
|
|
data[0] = sb_16_read_dma(dsp);
|
|
|
|
|
if (data[0] == DMA_NODATA)
|
|
|
|
|
break;
|
|
|
|
|
dsp->sbdatl = dsp->sbdatr = data[0];
|
|
|
|
|
dsp->sb_16_length--;
|
|
|
|
|
break;
|
|
|
|
|
case 0x20: /* Stereo unsigned */
|
|
|
|
|
data[0] = sb_16_read_dma(dsp);
|
|
|
|
|
data[1] = sb_16_read_dma(dsp);
|
|
|
|
|
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 */
|
|
|
|
|
data[0] = sb_16_read_dma(dsp);
|
|
|
|
|
data[1] = sb_16_read_dma(dsp);
|
|
|
|
|
if ((data[0] == DMA_NODATA) || (data[1] == DMA_NODATA))
|
|
|
|
|
break;
|
|
|
|
|
dsp->sbdatl = data[0];
|
|
|
|
|
dsp->sbdatr = data[1];
|
|
|
|
|
dsp->sb_16_length -= 2;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dsp->sb_16_length < 0) {
|
|
|
|
|
sb_dsp_log("16DMA over %i\n", dsp->sb_16_autoinit);
|
|
|
|
|
if (dsp->sb_16_autoinit)
|
|
|
|
|
dsp->sb_16_length = dsp->sb_16_autolen;
|
|
|
|
|
else {
|
|
|
|
|
dsp->sb_16_enable = 0;
|
|
|
|
|
timer_disable(&dsp->output_timer);
|
|
|
|
|
}
|
|
|
|
|
sb_irq(dsp, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (dsp->sb_pausetime > -1) {
|
|
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-21 20:03:07 +01:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
sb_poll_i(void *p)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
sb_dsp_t *dsp = (sb_dsp_t *) p;
|
|
|
|
|
int processed = 0;
|
|
|
|
|
|
|
|
|
|
timer_advance_u64(&dsp->input_timer, dsp->sblatchi);
|
|
|
|
|
|
|
|
|
|
if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && !dsp->sb_8_output) {
|
|
|
|
|
switch (dsp->sb_8_format) {
|
|
|
|
|
case 0x00: /* Mono unsigned As the manual says, only the left channel is recorded */
|
|
|
|
|
sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80);
|
|
|
|
|
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 */
|
|
|
|
|
sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8));
|
|
|
|
|
dsp->sb_8_length--;
|
|
|
|
|
dsp->record_pos_read += 2;
|
|
|
|
|
dsp->record_pos_read &= 0xFFFF;
|
|
|
|
|
break;
|
|
|
|
|
case 0x20: /* Stereo unsigned */
|
|
|
|
|
sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)^0x80);
|
|
|
|
|
sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read+1]>>8)^0x80);
|
|
|
|
|
dsp->sb_8_length -= 2;
|
|
|
|
|
dsp->record_pos_read += 2;
|
|
|
|
|
dsp->record_pos_read &= 0xFFFF;
|
|
|
|
|
break;
|
|
|
|
|
case 0x30: /* Stereo signed */
|
|
|
|
|
sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8));
|
|
|
|
|
sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read+1]>>8));
|
|
|
|
|
dsp->sb_8_length -= 2;
|
|
|
|
|
dsp->record_pos_read += 2;
|
|
|
|
|
dsp->record_pos_read &= 0xFFFF;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dsp->sb_8_length < 0) {
|
|
|
|
|
if (dsp->sb_8_autoinit)
|
|
|
|
|
dsp->sb_8_length = dsp->sb_8_autolen;
|
|
|
|
|
else {
|
|
|
|
|
dsp->sb_8_enable = 0;
|
|
|
|
|
timer_disable(&dsp->input_timer);
|
|
|
|
|
}
|
|
|
|
|
sb_irq(dsp, 1);
|
|
|
|
|
}
|
|
|
|
|
processed = 1;
|
|
|
|
|
}
|
|
|
|
|
if (dsp->sb_16_enable && !dsp->sb_16_pause && (dsp->sb_pausetime < 0LL) && !dsp->sb_16_output) {
|
|
|
|
|
switch (dsp->sb_16_format) {
|
|
|
|
|
case 0x00: /* Unsigned mono. As the manual says, only the left channel is recorded */
|
|
|
|
|
if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000))
|
|
|
|
|
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 */
|
|
|
|
|
if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]))
|
|
|
|
|
return;
|
|
|
|
|
dsp->sb_16_length--;
|
|
|
|
|
dsp->record_pos_read += 2;
|
|
|
|
|
dsp->record_pos_read &= 0xFFFF;
|
|
|
|
|
break;
|
|
|
|
|
case 0x20: /* Unsigned stereo */
|
|
|
|
|
if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000))
|
|
|
|
|
return;
|
|
|
|
|
sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read+1]^0x8000);
|
|
|
|
|
dsp->sb_16_length -= 2;
|
|
|
|
|
dsp->record_pos_read += 2;
|
|
|
|
|
dsp->record_pos_read &= 0xFFFF;
|
|
|
|
|
break;
|
|
|
|
|
case 0x30: /* Signed stereo */
|
|
|
|
|
if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]))
|
|
|
|
|
return;
|
|
|
|
|
sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read+1]);
|
|
|
|
|
dsp->sb_16_length -= 2;
|
|
|
|
|
dsp->record_pos_read += 2;
|
|
|
|
|
dsp->record_pos_read &= 0xFFFF;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dsp->sb_16_length < 0) {
|
|
|
|
|
if (dsp->sb_16_autoinit)
|
|
|
|
|
dsp->sb_16_length = dsp->sb_16_autolen;
|
|
|
|
|
else {
|
|
|
|
|
dsp->sb_16_enable = 0;
|
|
|
|
|
timer_disable(&dsp->input_timer);
|
|
|
|
|
}
|
|
|
|
|
sb_irq(dsp, 0);
|
|
|
|
|
}
|
|
|
|
|
processed = 1;
|
|
|
|
|
}
|
|
|
|
|
/* Assume this is direct mode */
|
|
|
|
|
if (!processed) {
|
|
|
|
|
dsp->record_pos_read += 2;
|
|
|
|
|
dsp->record_pos_read &= 0xFFFF;
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-21 20:03:07 +01:00
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
void sb_dsp_update(sb_dsp_t *dsp)
|
|
|
|
|
{
|
2019-12-21 20:03:07 +01:00
|
|
|
if (dsp->muted) {
|
|
|
|
|
dsp->sbdatl = 0;
|
|
|
|
|
dsp->sbdatr = 0;
|
|
|
|
|
}
|
|
|
|
|
for (; dsp->pos < sound_pos_global; dsp->pos++) {
|
|
|
|
|
dsp->buffer[dsp->pos*2] = dsp->sbdatl;
|
|
|
|
|
dsp->buffer[dsp->pos*2 + 1] = dsp->sbdatr;
|
|
|
|
|
}
|
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
|
|
|
|
|
sb_dsp_close(sb_dsp_t *dsp)
|
2017-10-14 07:03:19 +02:00
|
|
|
{
|
|
|
|
|
}
|