From: Stas Sergeev <stsp@aknet.ru>
To: dosemu <linux-msdos@vger.kernel.org>
Cc: Stas Sergeev <stsp@aknet.ru>
Subject: sound patch
Date: Wed, 23 Sep 2009 17:40:37 +0400 [thread overview]
Message-ID: <4ABA2555.6010100@aknet.ru> (raw)
[-- 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, ¶ms);
+ pcm_data_get(NULL, frag_size, ¶ms);
}
}
@@ -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, ¶ms);
+ pcm_data_get(stream, len, ¶ms);
}
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"
next reply other threads:[~2009-09-23 13:40 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-09-23 13:40 Stas Sergeev [this message]
2009-09-23 18:28 ` sound patch Bart Oldeman
2009-09-23 19:10 ` Stas Sergeev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4ABA2555.6010100@aknet.ru \
--to=stsp@aknet.ru \
--cc=linux-msdos@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.