sound patch

Stas Sergeev
2009-09-23T13:40:37Z

[-- Attachment #1: Type: text/plain, Size: 463 bytes --]

Hello.

I extracted the sound code from my
3 years old local dosemu branch and
re-diffed it against the current svn.
This took lot of a hand-work, so the
mistakes are possible.
A quick test shows that the adlib
now works on x86-64. But many progs
(non-adlib ones) are still mute because
the cpuemu doesn't exit after every port
I/O the way vm86() did. The result is
that run_irqs() doesn't come in time.

If someone is willing to work on this,
here's the patch.

[-- Attachment #2: sound.diff --]
[-- Type: text/plain, Size: 32683 bytes --]

--- src/base/dev/sb16/adlib.c 2009-09-23 13:45:45.000000000 +0400
+++ src/base/dev/sb16/adlib.c 2008-03-06 11:26:38.000000000 +0300
@@ -39,6 +39,7 @@
#define ADLIB_BASE 0x388
#define OPL3_INTERNAL_FREQ 14400000 // The OPL3 operates at 14.4MHz
#define OPL3_MAX_BUF 512
+#define ADLIB_CHANNELS 2

#define ADLIB_THRESHOLD 2000000
#define ADLIB_RUNNING() (adlib_time_cur > 0)
@@ -64,11 +65,15 @@

Bit8u adlib_io_read_base(ioport_t port)
{
+ Bit8u ret;
#ifdef HAS_YMF262
- return YMF262Read(opl3, port);
+ adlib_timer();
+ ret = YMF262Read(opl3, port);
#else
- return 0xff;
+ ret = 0xff;
#endif
+ S_printf("Adlib: Read %hhx from port %x\n", ret, port);
+ return ret;
}

static Bit8u adlib_io_read(ioport_t port)
@@ -79,8 +84,10 @@
void adlib_io_write_base(ioport_t port, Bit8u value)
{
adlib_time_last = GETusTIME(0);
+ S_printf("Adlib: Write %hhx to port %x\n", value, port);
#ifdef HAS_YMF262
YMF262Write(opl3, port, value);
+ adlib_timer();
#endif
}

@@ -93,8 +100,10 @@
static void opl3_set_timer(void *param, int num, double interval_Sec)
{
long long *timers = param;
- timers[num] =
- interval_Sec > 0 ? GETusTIME(0) + interval_Sec * 1000000 : 0;
+ if (interval_Sec > 0)
+ timers[num] += GETusTIME(0) + interval_Sec * 1000000;
+ else
+ timers[num] = 0;
S_printf("Adlib: timer %i set to %ius\n", num,
(int) (interval_Sec * 1000000));
}
@@ -105,6 +114,12 @@
ADLIB_RUN();
run_new_sb();
}
+
+static void opl3_irq(void *param, int irq)
+{
+ S_printf("SB: OPL3 IRQ (%i)\n", irq);
+ /* this IRQ is not wired, nothing to do */
+}
#endif

void opl3_init(void)
@@ -120,7 +135,7 @@
io_device.write_portw = NULL;
io_device.read_portd = NULL;
io_device.write_portd = NULL;
- io_device.handler_name = "Adlib (+ Advanced) Emulation";
+ io_device.handler_name = "OPL3";
io_device.start_addr = ADLIB_BASE;
io_device.end_addr = ADLIB_BASE + 3;
io_device.irq = EMU_NO_IRQ;
@@ -130,14 +145,15 @@
}
#ifdef HAS_YMF262
opl3 = YMF262Init(OPL3_INTERNAL_FREQ, opl3_rate);
- YMF262SetTimerHandler(opl3, opl3_set_timer, &opl3_timers);
+ YMF262SetTimerHandler(opl3, opl3_set_timer, opl3_timers);
YMF262SetUpdateHandler(opl3, opl3_update, NULL);
+ YMF262SetIRQHandler(opl3, opl3_irq, NULL);
#endif
}

void adlib_init(void)
{
- adlib_strm = pcm_allocate_stream(2, "Adlib");
+ adlib_strm = pcm_allocate_stream(ADLIB_CHANNELS, "Adlib");
}

void adlib_reset(void)
@@ -157,13 +173,24 @@
}

#ifdef HAS_YMF262
-static void adlib_process_samples(int samps)
+static void adlib_process_samples(int mono_samps)
{
- const int chan_map[] = { 0, 1, 0, 1 };
- int i, j, k;
+ const int chan_map[] =
+#if ADLIB_CHANNELS == 2
+ { 0, 1, 0, 1 };
+#elif ADLIB_CHANNELS == 1
+ { 0, 0, 0, 0 };
+#elif ADLIB_CHANNELS == 4
+ { 0, 1, 2, 3 };
+#else
+#error ADLIB_CHANNELS is wrong
+ { -1, -1, -1, -1 };
+#endif
+ int i, j, k, samps;
OPL3SAMPLE *chans[4], buf[4][OPL3_MAX_BUF], buf3;
- int buf2[OPL3_MAX_BUF][2];
+ int buf2[OPL3_MAX_BUF][ADLIB_CHANNELS];

+ samps = mono_samps / ADLIB_CHANNELS;
if (samps > OPL3_MAX_BUF) {
error("Adlib: too many samples requested (%i)\n", samps);
samps = OPL3_MAX_BUF;
@@ -174,17 +201,13 @@
YMF262UpdateOne(opl3, chans, samps);

for (i = 0; i < samps; i++) {
- for (j = 0; j < 2; j++) {
+ for (j = 0; j < ADLIB_CHANNELS; j++) {
buf2[i][j] = 0;
for (k = 0; k < ARRAY_SIZE(chan_map); k++) {
if (chan_map[k] == j)
buf2[i][j] += buf[k][i];
}
- if (buf2[i][j] > SHRT_MAX)
- buf2[i][j] = SHRT_MAX;
- if (buf2[i][j] < SHRT_MIN)
- buf2[i][j] = SHRT_MIN;
- buf3 = buf2[i][j];
+ buf3 = pcm_samp_cutoff(buf2[i][j], opl3_format);
pcm_write_samples(&buf3, pcm_format_size(opl3_format),
opl3_rate, opl3_format, adlib_strm);
}
@@ -204,13 +227,13 @@
pcm_flush(adlib_strm);
}
if (ADLIB_RUNNING()) {
- period = pcm_samp_period(opl3_rate, 2);
+ period = pcm_samp_period(opl3_rate, ADLIB_CHANNELS);
nsamps = (now - adlib_time_cur) / period;
if (nsamps > OPL3_MAX_BUF)
nsamps = OPL3_MAX_BUF;
- nsamps -= nsamps % 2;
+ nsamps -= nsamps % ADLIB_CHANNELS;
if (nsamps) {
- adlib_process_samples(nsamps / 2);
+ adlib_process_samples(nsamps);
adlib_time_cur += nsamps * period;
S_printf("SB: processed %i Adlib samples\n", nsamps);
}
@@ -219,7 +242,7 @@
for (i = 0; i < 2; i++) {
if (opl3_timers[i] > 0 && now > opl3_timers[i]) {
S_printf("Adlib: timer %i expired\n", i);
- opl3_timers[i] = 0;
+ opl3_timers[i] = now - opl3_timers[i];
YMF262TimerOver(opl3, i);
}
}
--- src/base/dev/sb16/dspio.c.orig 2009-09-23 13:00:56.000000000 +0400
+++ src/base/dev/sb16/dspio.c 2009-09-23 13:59:19.000000000 +0400
@@ -36,7 +36,7 @@
#include "sound/sndpcm.h"
#include "sound/midi.h"
#include "adlib.h"
-#include "dma.h"
+#include "dmanew.h"
#include "sb16.h"
#include "dspio.h"
#include <string.h>
@@ -65,22 +65,6 @@

#define DSPIO ((struct dspio_state *)dspio)

-static int dma8_get_format(int is_signed)
-{
- return is_signed ? PCM_FORMAT_S8 : PCM_FORMAT_U8;
-}
-
-static int dma16_get_format(int is_signed)
-{
- return is_signed ? PCM_FORMAT_S16_LE : PCM_FORMAT_U16_LE;
-}
-
-static int dma_get_format(int is_16, int is_signed)
-{
- return is_16 ? dma16_get_format(is_signed) :
- dma8_get_format(is_signed);
-}
-
static void dma_get_silence(int is_signed, int is16bit, void *ptr)
{
if (is16bit) {
@@ -163,9 +147,10 @@
if (state->output_running)
return;
S_printf("SB: starting output\n");
- /* We would need real time here, but the HACK is to use stream time instead.
+ /* We would need real time here, but the HACK is to use stream
+ * timestamp instead.
* That compensates the hack of dspio_process_dma() */
- state->output_time_cur = pcm_get_stream_time(state->dma_strm);
+ state->output_time_cur = pcm_calc_tstamp(state->dma.rate, state->dma_strm);
state->output_running = 1;
}

@@ -296,6 +281,7 @@
if (state->dma.running) {
state->dma.stereo = sb_dma_samp_stereo();
state->dma.rate = sb_get_dma_sampling_rate();
+ state->dma.samp_signed = sb_dma_samp_signed();
}

while (state->output_running && (state->output_time_cur <= time_dst ||
@@ -308,13 +294,13 @@
if (state->speaker) {
pcm_write_samples(&buf, 1 << state->dma.is16bit,
state->dma.rate,
- dma_get_format(state->dma.is16bit,
+ pcm_get_format(state->dma.is16bit,
state->dma.samp_signed),
state->dma_strm);
if (!state->dma.stereo)
pcm_write_samples(&buf, 1 << state->dma.is16bit,
state->dma.rate,
- dma_get_format(state->dma.is16bit,
+ pcm_get_format(state->dma.is16bit,
state->dma.
samp_signed),
state->dma_strm);
--- src/base/dev/sb16/sb16.c 2009-09-23 13:01:30.000000000 +0400
+++ src/base/dev/sb16/sb16.c 2009-09-23 14:13:20.000000000 +0400
@@ -636,6 +636,7 @@
hdma_idx = config.sb_hdma ? 1 << config.sb_hdma : 0;
sb.mixer_regs[0x80] = irq_idx;
sb.mixer_regs[0x81] = dma_idx | hdma_idx;
+ sb.mixer_regs[0x82] = SB16_ID82;
}

static void sb_reset(void)
@@ -920,8 +921,8 @@
case 0xE1:
/* DSP Version - SB */
S_printf("SB: Query Version\n");
- dsp_write_output(SB_16 >> 8);
- dsp_write_output(SB_16 & 0xFF);
+ dsp_write_output(SB16_ID >> 8);
+ dsp_write_output(SB16_ID & 0xFF);
break;

case 0xE2: {
--- src/base/dev/sb16/sb16.h 2009-09-23 13:00:56.000000000 +0400
+++ src/base/dev/sb16/sb16.h 2006-12-11 18:07:05.000000000 +0300
@@ -26,11 +26,15 @@
#include "utilities.h" // for rng_s

#define SB_NONE 0x000
-#define SB_OLD 0x105
-#define SB_20 0x201
-#define SB_PRO 0x300
-#define SB_16 0x405
-#define SB_AWE32 0x40C
+#define SB_ID 0x105
+#define SB20_ID 0x201
+#define SBPRO_ID 0x300
+#define SB16_ID 0x405
+#define SBAWE32_ID 0x40C
+
+/* bochs and the old dosemu code disagree on that value.
+ * Of course I trust bochs. :) */
+#define SB16_ID82 (2 << 5)

/*
* Various Status values
Index: dmanew.c
===================================================================
--- src/base/dev/dma/dmanew.c (revision 1964)
+++ src/base/dev/dma/dmanew.c (working copy)
@@ -32,7 +32,8 @@
#include "utilities.h"
#include "port.h"
#include "timers.h"
-#include "dma.h"
+#include "dmanew.h"
+#include "dmaregs.h"
#include <string.h>

typedef union {
@@ -82,7 +83,7 @@
#define HAVE_SRQ(contr, chan) (dma[contr].request & (1 << (chan)))
#define SW_ACTIVE(contr, chan) \
(HAVE_SRQ(contr, chan) && \
- (dma[contr].chans[chan].mode & 0x30) == 0x20)
+ (DMA_TRANSFER_MODE(dma[contr].chans[chan].mode) == BLOCK))

static void dma_soft_reset(int dma_idx)
@@ -105,18 +106,18 @@

static void dma_update_DRQ(int dma_idx, int chan_idx)
{
- switch (dma[dma_idx].chans[chan_idx].mode & 0x30) {
- case 0x00: // demand
+ switch (DMA_TRANSFER_MODE(dma[dma_idx].chans[chan_idx].mode)) {
+ case DEMAND:
dma_poll_DRQ(dma_idx, chan_idx);
break;
- case 0x10: // single
+ case SINGLE:
dma[dma_idx].status &= ~(1 << (chan_idx + 4));
break;
- case 0x20: // block
+ case BLOCK:
if (REACHED_TC(dma_idx, chan_idx))
dma_poll_DRQ(dma_idx, chan_idx);
break;
- case 0x30: // cascade
+ case CASCADE:
dma_poll_DRQ(dma_idx, chan_idx);
break;
}
@@ -126,38 +127,37 @@
{
struct dma_channel *chan = &dma[dma_idx].chans[chan_idx];
Bit32u addr = (chan->page << 16) | (chan->cur_addr.value << dma_idx);
- Bit8u mode = chan->mode;

/* first, do the transfer */
- switch (mode & 3) {
- case 0: /* verify */
+ switch (DMA_TRANSFER_OP(chan->mode)) {
+ case VERIFY:
q_printf("DMA: verify mode does nothing\n");
break;
- case 1: /* write */
+ case WRITE:
MEMCPY_2DOS(addr, dma_data_bus, 1 << dma_idx);
break;
- case 2: /* read */
+ case READ:
MEMCPY_2UNIX(dma_data_bus, addr, 1 << dma_idx);
break;
- case 3: /* invalid */
+ case INVALID:
q_printf("DMA: invalid mode does nothing\n");
break;
}

/* now advance the address */
- if (!(dma[dma_idx].command & 2))
- chan->cur_addr.value += (mode & 8) ? -1 : 1;
+ if ((dma[dma_idx].command & 3) != 3)
+ chan->cur_addr.value += (DMA_ADDR_DEC(chan->mode) ? -1 : 1);

/* and the counter */
chan->cur_count.value--;
if (chan->cur_count.value == 0xffff) { /* overflow */
- if (mode & 4) { /* auto-init */
+ if (DMA_AUTOINIT(chan->mode)) {
q_printf("DMA: controller %i, channel %i reinitialized\n",
dma_idx, chan_idx);
chan->cur_addr.value = chan->base_addr.value;
chan->cur_count.value = chan->base_count.value;
- } else { /* eop */
- q_printf("DMA: controller %i, channel %i EOP\n", dma_idx,
+ } else { /* TC */
+ q_printf("DMA: controller %i, channel %i TC\n", dma_idx,
chan_idx);
dma[dma_idx].status |= 1 << chan_idx;
dma[dma_idx].request &= ~(1 << chan_idx);
@@ -176,7 +176,7 @@
if (!MASKED(dma_idx, chan_idx) &&
!REACHED_TC(dma_idx, chan_idx) &&
!(dma[dma_idx].command & 4) &&
- ((dma[dma_idx].chans[chan_idx].mode & 0x30) != 0x30)) {
+ (DMA_TRANSFER_MODE(dma[dma_idx].chans[chan_idx].mode) != CASCADE)) {
dma_process_channel(dma_idx, chan_idx);
ticks++;
} else {
@@ -232,66 +232,48 @@
}

+/* lets ride on the cpp ass */
#define d(x) (x-1)
+#define HANDLE_X(n) \
+ HANDLE_##n(1, 1); \
+ HANDLE_##n(1, 2); \
+ HANDLE_##n(1, 3); \
+ HANDLE_##n(1, 4); \
+ HANDLE_##n(2, 1); \
+ HANDLE_##n(2, 2); \
+ HANDLE_##n(2, 3); \
+ HANDLE_##n(2, 4)
static Bit8u dma_io_read(ioport_t port)
{
Bit8u r = 0xff;
switch (port) {

-/* lets ride on the cpp ass */
#define HANDLE_CUR_ADDR_READ(d_n, c_n) \
- case DMA##d_n##_ADDR_##c_n: \
- r = dma[d(d_n)].chans[d(c_n)].cur_addr.byte[dma[d(d_n)].ff]; \
- q_printf("DMA%i: cur_addr read: %#x from Channel %d byte %d\n", \
- d_n, r, d(c_n), dma[d(d_n)].ff); \
- dma[d(d_n)].ff ^= 1; \
- break
- HANDLE_CUR_ADDR_READ(1, 1);
- HANDLE_CUR_ADDR_READ(1, 2);
- HANDLE_CUR_ADDR_READ(1, 3);
- HANDLE_CUR_ADDR_READ(1, 4);
+ case DMA##d_n##_ADDR_##c_n: \
+ r = dma[d(d_n)].chans[d(c_n)].cur_addr.byte[dma[d(d_n)].ff]; \
+ q_printf("DMA%i: cur_addr read: %#x from Channel %d byte %d\n", \
+ d_n, r, d(c_n), dma[d(d_n)].ff); \
+ dma[d(d_n)].ff ^= 1; \
+ break
+ HANDLE_X(CUR_ADDR_READ);

- HANDLE_CUR_ADDR_READ(2, 1);
- HANDLE_CUR_ADDR_READ(2, 2);
- HANDLE_CUR_ADDR_READ(2, 3);
- HANDLE_CUR_ADDR_READ(2, 4);
-#undef HANDLE_CUR_ADDR_READ
-
#define HANDLE_CUR_CNT_READ(d_n, c_n) \
- case DMA##d_n##_CNT_##c_n: \
- r = dma[d(d_n)].chans[d(c_n)].cur_count.byte[dma[d(d_n)].ff]; \
- q_printf("DMA%i: cur_cnt read: %#x from Channel %d byte %d\n", \
- d_n, r, d(c_n), dma[d(d_n)].ff); \
- dma[d(d_n)].ff ^= 1; \
- break
- HANDLE_CUR_CNT_READ(1, 1);
- HANDLE_CUR_CNT_READ(1, 2);
- HANDLE_CUR_CNT_READ(1, 3);
- HANDLE_CUR_CNT_READ(1, 4);
+ case DMA##d_n##_CNT_##c_n: \
+ r = dma[d(d_n)].chans[d(c_n)].cur_count.byte[dma[d(d_n)].ff]; \
+ q_printf("DMA%i: cur_cnt read: %#x from Channel %d byte %d\n", \
+ d_n, r, d(c_n), dma[d(d_n)].ff); \
+ dma[d(d_n)].ff ^= 1; \
+ break
+ HANDLE_X(CUR_CNT_READ);

- HANDLE_CUR_CNT_READ(2, 1);
- HANDLE_CUR_CNT_READ(2, 2);
- HANDLE_CUR_CNT_READ(2, 3);
- HANDLE_CUR_CNT_READ(2, 4);
-#undef HANDLE_CUR_CNT_READ
-
#define HANDLE_PAGE_READ(d_n, c_n) \
- case DMA##d_n##_PAGE_##c_n: \
- r = dma[d(d_n)].chans[d(c_n)].page; \
- q_printf("DMA%i: page read: %#x from Channel %d\n", \
- d_n, r, d(c_n)); \
- break
- HANDLE_PAGE_READ(1, 1);
- HANDLE_PAGE_READ(1, 2);
- HANDLE_PAGE_READ(1, 3);
- HANDLE_PAGE_READ(1, 4);
+ case DMA##d_n##_PAGE_##c_n: \
+ r = dma[d(d_n)].chans[d(c_n)].page; \
+ q_printf("DMA%i: page read: %#x from Channel %d\n", \
+ d_n, r, d(c_n)); \
+ break
+ HANDLE_X(PAGE_READ);

- HANDLE_PAGE_READ(2, 1);
- HANDLE_PAGE_READ(2, 2);
- HANDLE_PAGE_READ(2, 3);
- HANDLE_PAGE_READ(2, 4);
-#undef HANDLE_PAGE_READ
-
case DMA1_STAT_REG:
r = dma[DMA1].status;
q_printf("DMA1: Read %u from Status reg\n", r);
@@ -328,60 +310,33 @@
switch (port) {

#define HANDLE_ADDR_WRITE(d_n, c_n) \
- case DMA##d_n##_ADDR_##c_n: \
- dma[d(d_n)].chans[d(c_n)].base_addr.byte[dma[d(d_n)].ff] = value; \
- dma[d(d_n)].chans[d(c_n)].cur_addr.byte[dma[d(d_n)].ff] = value; \
- q_printf("DMA%i: addr write: %#x to Channel %d byte %d\n", \
- d_n, value, d(c_n), dma[d(d_n)].ff); \
- dma[d(d_n)].ff ^= 1; \
- break
- HANDLE_ADDR_WRITE(1, 1);
- HANDLE_ADDR_WRITE(1, 2);
- HANDLE_ADDR_WRITE(1, 3);
- HANDLE_ADDR_WRITE(1, 4);
+ case DMA##d_n##_ADDR_##c_n: \
+ dma[d(d_n)].chans[d(c_n)].base_addr.byte[dma[d(d_n)].ff] = value; \
+ dma[d(d_n)].chans[d(c_n)].cur_addr.byte[dma[d(d_n)].ff] = value; \
+ q_printf("DMA%i: addr write: %#x to Channel %d byte %d\n", \
+ d_n, value, d(c_n), dma[d(d_n)].ff); \
+ dma[d(d_n)].ff ^= 1; \
+ break
+ HANDLE_X(ADDR_WRITE);

- HANDLE_ADDR_WRITE(2, 1);
- HANDLE_ADDR_WRITE(2, 2);
- HANDLE_ADDR_WRITE(2, 3);
- HANDLE_ADDR_WRITE(2, 4);
-#undef HANDLE_ADDR_WRITE
-
#define HANDLE_CNT_WRITE(d_n, c_n) \
- case DMA##d_n##_CNT_##c_n: \
- dma[d(d_n)].chans[d(c_n)].base_count.byte[dma[d(d_n)].ff] = value; \
- dma[d(d_n)].chans[d(c_n)].cur_count.byte[dma[d(d_n)].ff] = value; \
- q_printf("DMA%i: count write: %#x to Channel %d byte %d\n", \
- d_n, value, d(c_n), dma[d(d_n)].ff); \
- dma[d(d_n)].ff ^= 1; \
- break
- HANDLE_CNT_WRITE(1, 1);
- HANDLE_CNT_WRITE(1, 2);
- HANDLE_CNT_WRITE(1, 3);
- HANDLE_CNT_WRITE(1, 4);
+ case DMA##d_n##_CNT_##c_n: \
+ dma[d(d_n)].chans[d(c_n)].base_count.byte[dma[d(d_n)].ff] = value; \
+ dma[d(d_n)].chans[d(c_n)].cur_count.byte[dma[d(d_n)].ff] = value; \
+ q_printf("DMA%i: count write: %#x to Channel %d byte %d\n", \
+ d_n, value, d(c_n), dma[d(d_n)].ff); \
+ dma[d(d_n)].ff ^= 1; \
+ break
+ HANDLE_X(CNT_WRITE);

- HANDLE_CNT_WRITE(2, 1);
- HANDLE_CNT_WRITE(2, 2);
- HANDLE_CNT_WRITE(2, 3);
- HANDLE_CNT_WRITE(2, 4);
-#undef HANDLE_CNT_WRITE
-
#define HANDLE_PAGE_WRITE(d_n, c_n) \
- case DMA##d_n##_PAGE_##c_n: \
- dma[d(d_n)].chans[d(c_n)].page = value; \
- q_printf("DMA%i: page write: %#x to Channel %d\n", \
- d_n, value, d(c_n)); \
- break
- HANDLE_PAGE_WRITE(1, 1);
- HANDLE_PAGE_WRITE(1, 2);
- HANDLE_PAGE_WRITE(1, 3);
- HANDLE_PAGE_WRITE(1, 4);
+ case DMA##d_n##_PAGE_##c_n: \
+ dma[d(d_n)].chans[d(c_n)].page = value; \
+ q_printf("DMA%i: page write: %#x to Channel %d\n", \
+ d_n, value, d(c_n)); \
+ break
+ HANDLE_X(PAGE_WRITE);

- HANDLE_PAGE_WRITE(2, 1);
- HANDLE_PAGE_WRITE(2, 2);
- HANDLE_PAGE_WRITE(2, 3);
- HANDLE_PAGE_WRITE(2, 4);
-#undef HANDLE_PAGE_WRITE
-
case DMA1_MASK_REG:
if (value & 4) {
q_printf("DMA1: mask channel %i\n", value & 3);
@@ -489,9 +444,6 @@
dma_process(); // Not needed in fact
}

-#undef d
-
-
void dma_new_reset(void)
{
dma_soft_reset(DMA1);
--- /dev/null 2009-09-23 16:50:16.994007431 +0400
+++ src/base/dev/dma/dmaregs.h 2007-06-29 10:30:17.000000000 +0400
@@ -0,0 +1,74 @@
+/*
+ * (C) Copyright 1992, ..., 2005 the "DOSEMU-Development-Team".
+ *
+ * for details see file COPYING in the DOSEMU distribution
+ */
+
+#ifndef __DMAREGS_H__
+#define __DMAREGS_H__
+
+/* 8237 DMA controllers */
+#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
+#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */
+
+/* DMA controller registers */
+#define DMA1_CMD_REG 0x08 /* command register (w) */
+#define DMA1_STAT_REG 0x08 /* status register (r) */
+#define DMA1_REQ_REG 0x09 /* request register (w) */
+#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
+#define DMA1_MODE_REG 0x0B /* mode register (w) */
+#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
+#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
+#define DMA1_RESET_REG 0x0D /* Master Clear (w) */
+#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
+#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
+
+#define DMA2_CMD_REG 0xD0 /* command register (w) */
+#define DMA2_STAT_REG 0xD0 /* status register (r) */
+#define DMA2_REQ_REG 0xD2 /* request register (w) */
+#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
+#define DMA2_MODE_REG 0xD6 /* mode register (w) */
+#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
+#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
+#define DMA2_RESET_REG 0xDA /* Master Clear (w) */
+#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
+#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
+
+#define DMA1_ADDR_1 0x00 /* DMA address registers */
+#define DMA1_ADDR_2 0x02
+#define DMA1_ADDR_3 0x04
+#define DMA1_ADDR_4 0x06
+#define DMA2_ADDR_1 0xC0
+#define DMA2_ADDR_2 0xC4
+#define DMA2_ADDR_3 0xC8
+#define DMA2_ADDR_4 0xCC
+
+#define DMA1_CNT_1 0x01 /* DMA count registers */
+#define DMA1_CNT_2 0x03
+#define DMA1_CNT_3 0x05
+#define DMA1_CNT_4 0x07
+#define DMA2_CNT_1 0xC2
+#define DMA2_CNT_2 0xC6
+#define DMA2_CNT_3 0xCA
+#define DMA2_CNT_4 0xCE
+
+#define DMA1_PAGE_1 0x87 /* DMA page registers */
+#define DMA1_PAGE_2 0x83
+#define DMA1_PAGE_3 0x81
+#define DMA1_PAGE_4 0x82
+#define DMA2_PAGE_1 0x8F
+#define DMA2_PAGE_2 0x8B
+#define DMA2_PAGE_3 0x89
+#define DMA2_PAGE_4 0x8A
+
+#define DMA_TRANSFER_MODE(m) ((m >> 4) & 3)
+enum TRMODE { DEMAND, SINGLE, BLOCK, CASCADE };
+
+#define DMA_TRANSFER_OP(m) (m & 3)
+enum TROP { VERIFY, WRITE, READ, INVALID };
+
+#define DMA_ADDR_DEC(m) ((m >> 3) & 1)
+
+#define DMA_AUTOINIT(m) ((m >> 2) & 1)
+
+#endif
--- src/base/sound/nullsnd.c 2008-03-06 12:39:48.000000000 +0300
+++ src/base/sound/nullsnd.c 2008-03-06 12:35:50.000000000 +0300
@@ -37,7 +37,6 @@
static const char *nullsnd_name = "Sound Output: NULL device";
const int frag_size = 4096;
static struct player_params params;
-static struct player_callbacks calls;
static int running, locked;
static double last_time = 0;

@@ -83,7 +82,7 @@
time = GETusTIME(0);
while (time - last_time > frag_time) {
last_time += frag_time;
- calls.get_data(NULL, frag_size, &params);
+ pcm_data_get(NULL, frag_size, &params);
}
}

@@ -99,5 +98,5 @@
player.unlock = nullsnd_unlock;
player.timer = nullsnd_timer;
running = locked = 0;
- return pcm_register_clocked_player(player, &calls);
+ return pcm_register_clocked_player(player);
}
--- src/base/sound/sndpcm.c 2009-09-23 12:59:45.000000000 +0400
+++ src/base/sound/sndpcm.c 2008-03-06 12:47:18.000000000 +0300
@@ -39,7 +39,6 @@
#include <string.h>
#include <math.h>
#include <limits.h>
-#include <assert.h>

#define SND_BUFFER_SIZE 200000 /* enough to hold 2.2s of 44100/stereo */
@@ -206,6 +199,48 @@
}
}

+static int pcm_get_format8(int is_signed)
+{
+ return is_signed ? PCM_FORMAT_S8 : PCM_FORMAT_U8;
+}
+
+static int pcm_get_format16(int is_signed)
+{
+ return is_signed ? PCM_FORMAT_S16_LE : PCM_FORMAT_U16_LE;
+}
+
+int pcm_get_format(int is_16, int is_signed)
+{
+ return is_16 ? pcm_get_format16(is_signed) :
+ pcm_get_format8(is_signed);
+}
+
+static int cutoff(int val, int min, int max)
+{
+ if (val < min)
+ return min;
+ if (val > max)
+ return max;
+ return val;
+}
+
+int pcm_samp_cutoff(int val, int format)
+{
+ switch (format) {
+ case PCM_FORMAT_U8:
+ return cutoff(val, 0, UCHAR_MAX);
+ case PCM_FORMAT_S8:
+ return cutoff(val, SCHAR_MIN, SCHAR_MAX);
+ case PCM_FORMAT_U16_LE:
+ return cutoff(val, 0, USHRT_MAX);
+ case PCM_FORMAT_S16_LE:
+ return cutoff(val, SHRT_MIN, SHRT_MAX);
+ default:
+ error("PCM: format %i is not supported\n", format);
+ return 0;
+ }
+}
+
#define UC2SS(v) ((*(unsigned char *)(v) - 128) * 256)
#define SC2SS(v) (*(signed char *)(v) * 256)
#define US2SS(v) (*(unsigned short *)(v) - 32768)
@@ -402,7 +437,7 @@
return 1;
}

-double pcm_get_stream_time(int strm_idx)
+static double pcm_get_stream_time(int strm_idx)
{
struct sample samp;
long long now = GETusTIME(0);
@@ -412,7 +447,7 @@
return samp.tstamp;
}

-static double pcm_calc_tstamp(double rate, int strm_idx)
+double pcm_calc_tstamp(double rate, int strm_idx)
{
double time, period, tstamp;
if (rate == 0)
@@ -492,15 +527,14 @@
if (s.tstamp > time) {
// S_printf("PCM: stream %i time=%lli, req_time=%lli\n", i, s.tstamp, time);
if (samp)
- for (j = 0; j < pcm.stream[i].channels; j++)
- samp[i][j] = s2[j];
+ memcpy(samp[i], s2, sizeof(struct sample) *
+ pcm.stream[i].channels);
if (time >= pcm.stream[i].start_time)
ret++;
break;
}
if (shift && idxs[i] >= pcm.stream[i].channels) {
- for (j = 0; j < pcm.stream[i].channels; j++)
- rng_get(&pcm.stream[i].buffer, NULL);
+ rng_remove(&pcm.stream[i].buffer, pcm.stream[i].channels, NULL);
idxs[i] -= pcm.stream[i].channels;
}
for (j = 0; j < pcm.stream[i].channels; j++)
@@ -531,17 +565,14 @@
continue;
value[j] += sample_to_S16(in[i][j].data, in[i][j].format);
}
- if (value[j] > SHRT_MAX)
- value[j] = SHRT_MAX;
- if (value[j] < SHRT_MIN)
- value[j] = SHRT_MIN;
- S16_to_sample(value[j], out + j * pcm_format_size(format), format);
+ S16_to_sample(pcm_samp_cutoff(value[j], PCM_FORMAT_S16_LE),
+ out + j * pcm_format_size(format), format);
}
}

/* this is called by the clocked player. It prepares the data for
* him, and, just in case, feeds it to all the unclocked players too. */
-static size_t pcm_data_get(void *data, size_t size,
+size_t pcm_data_get(void *data, size_t size,
struct player_params *params)
{
int i, samp_sz, have_data, idxs[MAX_STREAMS], ret = 0;
@@ -567,7 +598,7 @@
start_time = now - BUFFER_DELAY * 2;
stop_time = start_time + frag_period;
}
- S_printf("PCM: going to process %zu bytes for %i players (st=%f stp=%f d=%f)\n",
+ S_printf("PCM: going to process %zi bytes for %i players (st=%f stp=%f d=%f)\n",
size, players.num_clocked + players.num_unclocked, start_time,
stop_time, now - start_time);

@@ -634,8 +665,7 @@
return ret;
}

-int pcm_register_clocked_player(struct clocked_player player,
- struct player_callbacks *callbacks)
+int pcm_register_clocked_player(struct clocked_player player)
{
S_printf("PCM: registering clocked player: %s\n", player.name);
if (players.num_clocked) {
@@ -643,7 +673,6 @@
return 0;
}
players.clocked.player = player;
- callbacks->get_data = pcm_data_get;
players.num_clocked++;
return 1;
}
@@ -665,8 +694,6 @@
{
int i;
for (i = 0; i < players.num_unclocked; i++)
- if (players.unclocked[i].player.timer)
- players.unclocked[i].player.timer();
if (players.clocked.player.timer)
players.clocked.player.timer();
}
@@ -689,8 +716,7 @@
pcm_flush(i);
if (pcm.playing)
pcm_stop_output();
- if (players.clocked.player.close)
- players.clocked.player.close();
+ players.clocked.player.close();
for (i = 0; i < players.num_unclocked; i++)
players.unclocked[i].player.close();
for (i = 0; i < pcm.num_streams; i++)
--- src/plugin/midimisc/mid_o_tmdty.c 2009-04-03 11:45:40.000000000 +0400
+++ src/plugin/midimisc/mid_o_tmdty.c 2008-03-06 10:54:34.000000000 +0300
@@ -52,7 +51,7 @@
#define TMDTY_BIN "timidity"
#define TMDTY_ARGS "-EFreverb=0 -EFchorus=0 -EFresamp=1 -EFvlpf=0 -EFns=0"

-static const char *midotmdty_name = "MIDI Output: midid plugin";
+static const char *midotmdty_name = "MIDI Output: TiMidity++ plugin";

static int ctrl_sock_in, ctrl_sock_out, data_sock, pcm_stream;
static pid_t tmdty_pid = -1;
@@ -71,7 +70,8 @@
while ((selret = select(data_sock + 1, &rfds, NULL, NULL, &tv)) > 0) {
n = RPT_SYSCALL(read(data_sock, buf, sizeof(buf)));
if (n > 0) {
- pcm_write_samples(buf, n, 44100, PCM_FORMAT_S16_LE,
+ pcm_write_samples(buf, n, TMDTY_FREQ, pcm_get_format(
+ TMDTY_8BIT ? 0 : 1, TMDTY_UNS ? 0 : 1),
pcm_stream);
} else {
break;
@@ -233,10 +225,10 @@
if (ret) {
const char *ver_str = "Server Version ";
char *ptr = strstr(buf, ver_str);
- int vmin, vmid, vmaj, ver;
if (!ptr) {
ret = FALSE;
} else {
+ int vmin, vmid, vmaj, ver;
ptr += strlen(ver_str);
sscanf(ptr, "%d.%d.%d", &vmaj, &vmid, &vmin);
ver = vmaj * 10000 + vmid * 100 + vmin;
@@ -311,7 +303,7 @@

if (TMDTY_CAPT) {
add_to_io_select(data_sock, 1, midotmdty_io);
- pcm_stream = pcm_allocate_stream(2, "MIDI");
+ pcm_stream = pcm_allocate_stream(TMDTY_MONO ? 1 : 2, "MIDI");
}

return TRUE;
--- src/plugin/sdl/snd_o_SDL.c 2008-03-06 12:39:48.000000000 +0300
+++ src/plugin/sdl/snd_o_SDL.c 2009-09-23 14:37:44.000000000 +0400
@@ -33,12 +33,11 @@
#include <SDL.h>

static const char *sdlsnd_name = "Sound Output: SDL device";
-static struct player_callbacks calls;
static struct player_params params;

static void sdlsnd_callback(void *userdata, Uint8 * stream, int len)
{
- calls.get_data(stream, len, &params);
+ pcm_data_get(stream, len, &params);
}

static void sdlsnd_start(void)
@@ -87,9 +86,8 @@
player.close = sdlsnd_close;
player.lock = SDL_LockAudio;
player.unlock = SDL_UnlockAudio;
- player.timer = NULL;
#if 1
- return pcm_register_clocked_player(player, &calls);
+ return pcm_register_clocked_player(player);
#else
return 0;
#endif
--- src/plugin/sndfile/snd_o_wav.c 2007-04-28 22:21:33.000000000 +0400
+++ src/plugin/sndfile/snd_o_wav.c 2006-12-11 18:07:05.000000000 +0300
@@ -34,7 +34,7 @@
#include <stdio.h>
#include <sndfile.h>

-static const char *wavsnd_name = "Sound Output: WAV writer";
+static const char *wavsnd_name = "Sound Output: WAV file writer";
static SNDFILE *wav;

static int wavsnd_open(struct player_params *par)
@@ -67,7 +67,6 @@
player.open = wavsnd_open;
player.close = wavsnd_close;
player.write = wavsnd_write;
- player.timer = NULL;
#if 0
return pcm_register_unclocked_player(player);
#else
--- src/include/sound/sndpcm.h 2007-04-28 22:21:23.000000000 +0400
+++ src/include/sound/sndpcm.h 2008-03-06 10:42:33.000000000 +0300
@@ -30,13 +30,15 @@
extern void pcm_set_flag(int strm_idx, int flag);
extern void pcm_set_mode(int strm_idx, int mode);
extern int pcm_flush(int strm_idx);
+extern int pcm_samp_cutoff(int val, int format);
+extern int pcm_get_format(int is_16, int is_signed);
extern double pcm_samp_period(double rate, int channels);
extern double pcm_frag_period(int size, struct player_params *params);
extern void pcm_write_samples(void *ptr, size_t size,
- double rate, int format, int strm_idx);
+ double rate, int format, int strm_idx);
extern int pcm_format_size(int format);
extern void pcm_timer(void);
-extern double pcm_get_stream_time(int strm_idx);
+extern double pcm_calc_tstamp(double rate, int strm_idx);

#define PCM_FLAG_RAW 1

--- src/include/sound/sound.h 2008-03-06 12:39:48.000000000 +0300
+++ src/include/sound/sound.h 2009-09-23 14:43:54.000000000 +0400
@@ -20,8 +20,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#ifndef _SOUND_H
-#define _SOUND_H
+#ifndef __SOUND_H__
+#define __SOUND_H__

/* This is the correct way to run an SB timer tick */
extern void run_new_sb(void);
@@ -36,9 +36,7 @@
int channels;
};

-struct player_callbacks {
- size_t (*get_data)(void *buf, size_t size, struct player_params *params);
-};
+size_t pcm_data_get(void *data, size_t size, struct player_params *params);

struct clocked_player {
const char *name;
@@ -55,12 +53,10 @@
const char *name;
int (*open)(struct player_params *params);
void (*close)(void);
- void (*timer)(void);
size_t (*write)(void *buf, size_t size);
};

-extern int pcm_register_clocked_player(struct clocked_player player,
- struct player_callbacks *callbacks);
+extern int pcm_register_clocked_player(struct clocked_player player);
extern int pcm_register_unclocked_player(struct unclocked_player player);

/** PCM sample format */
@@ -84,4 +80,4 @@
PCM_FORMAT_IMA_ADPCM,
};

-#endif /* EMU_SOUND_H */
+#endif
Index: dma.h
===================================================================
--- src/include/dma.h (revision 1964)
+++ src/include/dma.h (working copy)
@@ -9,12 +9,7 @@

void dma_init(void);
void dma_reset(void);
-void dma_new_init(void);
-void dma_new_reset(void);

-enum { DMA_NO_DACK, DMA_DACK };
-int dma_pulse_DRQ(int ch, Bit8u *buf);
-
/* 8237 DMA controllers */
#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */
--- /dev/null 2009-09-23 16:50:16.994007431 +0400
+++ src/include/dmanew.h 2009-09-23 14:54:16.000000000 +0400
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2006 Stas Sergeev <stsp@users.sourceforge.net>
+ *
+ * The below copyright strings have to be distributed unchanged together
+ * with this file. This prefix can not be modified or separated.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __DMA_H__
+#define __DMA_H__
+
+void dma_new_init(void);
+void dma_new_reset(void);
+
+enum { DMA_NO_DACK, DMA_DACK };
+int dma_pulse_DRQ(int ch, Bit8u *buf);
+
+#endif
Index: dma.c
===================================================================
--- src/base/dev/dma/dma.c (revision 1964)
+++ src/base/dev/dma/dma.c (working copy)
@@ -51,6 +51,7 @@
#include <sys/types.h>
#include <unistd.h>
#include "dma.h"
+#include "dmanew.h"
#include "pic.h"
#include "port.h"