sound patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

--- 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@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * 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"
 

[Index of Archives]     [Linux Console]     [Linux Audio]     [Linux for Hams]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite Camping]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Samba]     [Linux Media]     [Fedora Users]

  Powered by Linux