PATCH: Preliminary DMA and SOUNDBLASTER emulation
Christian Costa
titan.costa at wanadoo.fr
Fri May 10 19:31:27 CDT 2002
Changelog:
Add preliminary support for DMA and SOUNBLASTER emulation
Added files: dlls/winedos/dma.h
dlls/winedos/dma.c
dlls/winedos/soundblaster.h
dlls/winedos/soundblaster.c
Modified files: dlls/winedos/ioports.c
dlls/winedos/winedos.spec
dlls/winedos/Makefile.in
Christian Costa titan.costa at wanadoo.fr
-------------- next part --------------
Index: ioports.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/ioports.c,v
retrieving revision 1.2
diff -u -r1.2 ioports.c
--- ioports.c 9 Mar 2002 23:44:32 -0000 1.2
+++ ioports.c 10 May 2002 23:53:19 -0000
@@ -24,7 +24,8 @@
#include "windef.h"
#include "dosexe.h"
#include "vga.h"
-
+#include "soundblaster.h"
+#include "dma.h"
/**********************************************************************
* DOSVM_inport
@@ -36,10 +37,51 @@
case 0x60:
*res = DOSVM_Int09ReadScan(NULL);
break;
+ case 0x22a:
+ case 0x22c:
+ case 0x22e:
+ *res = (DWORD)SB_ioport_in( port );
+ break;
case 0x3ba:
case 0x3da:
*res = (DWORD)VGA_ioport_in( port );
break;
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0xC0:
+ case 0xC2:
+ case 0xC4:
+ case 0xC6:
+ case 0xC8:
+ case 0xCA:
+ case 0xCC:
+ case 0xCE:
+ case 0x87:
+ case 0x83:
+ case 0x81:
+ case 0x82:
+ case 0x8B:
+ case 0x89:
+ case 0x8A:
+ case 0x487:
+ case 0x483:
+ case 0x481:
+ case 0x482:
+ case 0x48B:
+ case 0x489:
+ case 0x48A:
+ case 0x08:
+ case 0xD0:
+ case 0x0D:
+ case 0xDA:
+ *res = (DWORD)DMA_ioport_in( port );
+ break;
default:
return FALSE; /* not handled */
}
@@ -57,9 +99,61 @@
case 0x20:
DOSVM_PIC_ioport_out( port, (BYTE)value );
break;
+ case 0x226:
+ case 0x22c:
+ SB_ioport_out( port, (BYTE)value );
+ break;
case 0x3c8:
case 0x3c9:
VGA_ioport_out( port, (BYTE)value );
+ break;
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0xC0:
+ case 0xC2:
+ case 0xC4:
+ case 0xC6:
+ case 0xC8:
+ case 0xCA:
+ case 0xCC:
+ case 0xCE:
+ case 0x87:
+ case 0x83:
+ case 0x81:
+ case 0x82:
+ case 0x8B:
+ case 0x89:
+ case 0x8A:
+ case 0x487:
+ case 0x483:
+ case 0x481:
+ case 0x482:
+ case 0x48B:
+ case 0x489:
+ case 0x48A:
+ case 0x08:
+ case 0xD0:
+ case 0x0B:
+ case 0xD6:
+ case 0x0A:
+ case 0xD4:
+ case 0x0F:
+ case 0xDE:
+ case 0x09:
+ case 0xD2:
+ case 0x0C:
+ case 0xD8:
+ case 0x0D:
+ case 0xDA:
+ case 0x0E:
+ case 0xDC:
+ DMA_ioport_out( port, (BYTE)value );
break;
default:
return FALSE; /* not handled */
Index: Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/winedos/Makefile.in,v
retrieving revision 1.9
diff -u -r1.9 Makefile.in
--- Makefile.in 9 May 2002 00:05:53 -0000 1.9
+++ Makefile.in 10 May 2002 23:53:19 -0000
@@ -24,6 +24,8 @@
ioports.c \
module.c \
vga.c \
+ soundblaster.c \
+ dma.c \
xms.c
@MAKE_DLL_RULES@
Index: winedos.spec
===================================================================
RCS file: /home/wine/wine/dlls/winedos/winedos.spec,v
retrieving revision 1.9
diff -u -r1.9 winedos.spec
--- winedos.spec 9 May 2002 00:05:53 -0000 1.9
+++ winedos.spec 10 May 2002 23:53:19 -0000
@@ -2,7 +2,7 @@
type win32
init DOSVM_Init
-debug_channels (aspi console ddraw int int21 int31 module relay)
+debug_channels (aspi console ddraw int int21 int31 module relay sblaster dma)
@ stdcall LoadDosExe(str long) MZ_LoadImage
-------------- next part --------------
/*
* DMA Emulation
*
* Copyright 2002 Christian Costa
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_DMA_H
#define __WINE_DMA_H
#include "winbase.h"
int DMA_Transfer(int channel,int reqlength,void* buffer);
void DMA_ioport_out( WORD port, BYTE val );
BYTE DMA_ioport_in( WORD port );
#endif /* __WINE_DMA_H */
-------------- next part --------------
/*
* DMA Emulation
*
* Copyright 2002 Christian Costa
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Note : This is preliminary, poorly documented and not cleaned up yet
*/
#include "config.h"
#include "windef.h"
#include "dosexe.h"
#include "dma.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dma);
static DWORD DMA_BaseAddress[8];
static WORD DMA_ByteCount[8];
static DWORD DMA_CurrentBaseAddress[8];
static WORD DMA_CurrentByteCount[8];
static BYTE DMA_Command[8];
static int toggle[2]={FALSE,FALSE};
int DMA_Transfer(int channel,int reqlen,void* buffer)
{
int size,ret=0;
TRACE("DMA_Command = %x reqlen=%d\n",DMA_Command[channel],reqlen);
size = (channel<4) ? 1 : 2;
switch((DMA_Command[channel]&0xC)>>2)
{
case 0:
/* Verification */
FIXME("Verification partially Implemented\n");
ret = min(DMA_CurrentByteCount[channel],reqlen) * size;
break;
case 1:
/* Write */
ret = min(DMA_CurrentByteCount[channel],reqlen) * size;
memcpy((void*)DMA_CurrentBaseAddress[channel],buffer,ret);
DMA_CurrentByteCount[channel]-=ret;
DMA_CurrentBaseAddress[channel]+=ret;
TRACE("Perform Read transfer of %d bytes\n",ret);
if (DMA_CurrentByteCount[channel]==0)
TRACE("DMA buffer empty\n");
break;
case 2:
/* Read */
ret = min(DMA_CurrentByteCount[channel],reqlen) * size;
TRACE("Perform Read transfer of %d bytes at %lx with count %x\n",ret,DMA_CurrentBaseAddress[channel],
DMA_CurrentByteCount[channel]);
memcpy(buffer,(void*)DMA_CurrentBaseAddress[channel],ret);
DMA_CurrentByteCount[channel]-=ret;
DMA_CurrentBaseAddress[channel]+=ret;
if (DMA_CurrentByteCount[channel]==0)
TRACE("DMA buffer empty\n");
break;
case 3:
/* Illegal */
ERR("Transfer Type Illegal\n");
break;
}
return ret;
}
void DMA_ioport_out( WORD port, BYTE val )
{
int channel,dmachip;
switch(port)
{
case 0x00:
case 0x02:
case 0x04:
case 0x06:
case 0xC0:
case 0xC4:
case 0xC8:
case 0xCC:
/* Base Address*/
channel = (port&0xC0)?((port-0xC0)>>2):(port>>1);
dmachip = (channel<4) ? 0 : 1;
if (!toggle[dmachip])
DMA_BaseAddress[channel]=(DMA_BaseAddress[channel] & ~0xFF)|(val & 0xFF);
else {
DMA_BaseAddress[channel]=(DMA_BaseAddress[channel] & (~(0xFF << 8)))|((val & 0xFF) << 8);
DMA_CurrentBaseAddress[channel] = DMA_BaseAddress[channel];
TRACE("Write Base Address = %lx\n",DMA_BaseAddress[channel]);
}
toggle[dmachip] = !toggle[dmachip];
break;
case 0x01:
case 0x03:
case 0x05:
case 0x07:
case 0xC2:
case 0xC6:
case 0xCA:
case 0xCE:
/* Count*/
channel = ((port-1)&0xC0)?(((port-1)-0xC0)>>2):(port>>1);
dmachip = (channel<4) ? 0 : 1;
if (!toggle[dmachip])
DMA_ByteCount[channel]=(DMA_ByteCount[channel] & ~0xFF)|((val+1) & 0xFF);
else {
DMA_ByteCount[channel]=(DMA_ByteCount[channel] & (~(0xFF << 8)))|(((val+1) & 0xFF) << 8);
DMA_CurrentByteCount[channel] = DMA_ByteCount[channel];
TRACE("Write Count = %x.\n",DMA_ByteCount[channel]);
}
toggle[dmachip] = !toggle[dmachip];
break;
case 0x87: DMA_BaseAddress[0]=(DMA_BaseAddress[0] & (~0xFF << 16))|((val & 0xFF) << 16); break;
case 0x83: DMA_BaseAddress[1]=(DMA_BaseAddress[1] & (~0xFF << 16))|((val & 0xFF) << 16); break;
case 0x81: DMA_BaseAddress[2]=(DMA_BaseAddress[2] & (~0xFF << 16))|((val & 0xFF) << 16); break;
case 0x82: DMA_BaseAddress[3]=(DMA_BaseAddress[3] & (~0xFF << 16))|((val & 0xFF) << 16); break;
case 0x8B: DMA_BaseAddress[5]=(DMA_BaseAddress[5] & (~0xFF << 16))|((val & 0xFF) << 16); break;
case 0x89: DMA_BaseAddress[6]=(DMA_BaseAddress[6] & (~0xFF << 16))|((val & 0xFF) << 16); break;
case 0x8A: DMA_BaseAddress[7]=(DMA_BaseAddress[7] & (~0xFF << 16))|((val & 0xFF) << 16); break;
/* Low Page Base Address*/
case 0x487: DMA_BaseAddress[0]=(DMA_BaseAddress[0] & (~0xFF << 24))|((val & 0x0F) << 24); break;
case 0x483: DMA_BaseAddress[1]=(DMA_BaseAddress[1] & (~0xFF << 24))|((val & 0x0F) << 24); break;
case 0x481: DMA_BaseAddress[2]=(DMA_BaseAddress[2] & (~0xFF << 24))|((val & 0x0F) << 24); break;
case 0x482: DMA_BaseAddress[3]=(DMA_BaseAddress[3] & (~0xFF << 24))|((val & 0x0F) << 24); break;
case 0x48B: DMA_BaseAddress[5]=(DMA_BaseAddress[5] & (~0xFF << 24))|((val & 0x0F) << 24); break;
case 0x489: DMA_BaseAddress[6]=(DMA_BaseAddress[6] & (~0xFF << 24))|((val & 0x0F) << 24); break;
case 0x48A: DMA_BaseAddress[7]=(DMA_BaseAddress[7] & (~0xFF << 24))|((val & 0x0F) << 24); break;
/* Low Page Base Address*/
case 0x08:
case 0xD0:
/* Command */
FIXME("Write Command (%x) - Not Implemented\n",val);
break;
case 0x0B:
case 0xD6:
/* Mode - FIXME partially implemented*/
TRACE("Write Mode (%x)\n",val);
DMA_Command[((port==0xD6)?4:0)+(val&0x3)]=val;
break;
case 0x0A:
case 0xD4:
/* Write Single Mask Bit - FIXME not implemented */
TRACE("Write Single Mask Bit (%x) - Not Implemented\n",val);
break;
case 0x0F:
case 0xDE:
/* Write All Mask Bits - FIXME not implemented*/
FIXME("Write All Mask Bits (%x)\n",val);
break;
case 0x09:
case 0xD2:
/* Software DRQx Request */
FIXME("Software DRQx Request (%x) - Not Implemented\n",val);
break;
case 0x0C:
case 0xD8:
/* Reset Pointer Flip-Flop DMA */
toggle[port==0xD8]=FALSE;
break;
case 0x0D:
case 0xDA:
/* Master Reset */
FIXME("Master Reset - Not Implemented !\n");
break;
case 0x0E:
case 0xDC:
/* Reset Mask Register */
FIXME("Reset Mask Register - Not Implemented !\n");
break;
}
}
BYTE DMA_ioport_in( WORD port )
{
int channel,dmachip;
BYTE res = 0;
switch(port)
{
case 0x00:
case 0x02:
case 0x04:
case 0x06:
case 0xC0:
case 0xC4:
case 0xC8:
case 0xCC:
/* Base Address*/
channel = (port&0xC0)?((port-0xC0)>>2):(port>>1);
dmachip = (channel<4) ? 0 : 1;
if (!toggle[dmachip])
res = DMA_CurrentBaseAddress[channel] & 0xFF;
else {
res = (DMA_CurrentBaseAddress[channel] & (0xFF << 8))>>8;
TRACE("Read Current Base Address = %lx\n",DMA_CurrentBaseAddress[channel]);
}
toggle[dmachip] = !toggle[dmachip];
break;
case 0x01:
case 0x03:
case 0x05:
case 0x07:
case 0xC2:
case 0xC6:
case 0xCA:
case 0xCE:
/* Count*/
channel = ((port-1)&0xC0)?(((port-1)-0xC0)>>2):(port>>1);
dmachip = (channel<4) ? 0 : 1;
if (!toggle[dmachip])
res = DMA_CurrentByteCount[channel] & 0xFF;
else {
res = (DMA_CurrentByteCount[channel] & (0xFF << 8))>>8;
TRACE("Read Current Count = %x.\n",DMA_CurrentByteCount[channel]);
}
toggle[dmachip] = !toggle[dmachip];
break;
case 0x87: res = (DMA_BaseAddress[0]&(0xFF<<16))>>16; break;
case 0x83: res = (DMA_BaseAddress[1]&(0xFF<<16))>>16; break;
case 0x81: res = (DMA_BaseAddress[2]&(0xFF<<16))>>16; break;
case 0x82: res = (DMA_BaseAddress[3]&(0xFF<<16))>>16; break;
case 0x8B: res = (DMA_BaseAddress[5]&(0xFF<<16))>>16; break;
case 0x89: res = (DMA_BaseAddress[6]&(0xFF<<16))>>16; break;
case 0x8A: res = (DMA_BaseAddress[7]&(0xFF<<16))>>16; break;
/* Low Page Base Address*/
case 0x487: res = (DMA_BaseAddress[0]&(0xFF<<24))>>24; break;
case 0x483: res = (DMA_BaseAddress[1]&(0xFF<<24))>>24; break;
case 0x481: res = (DMA_BaseAddress[2]&(0xFF<<24))>>24; break;
case 0x482: res = (DMA_BaseAddress[3]&(0xFF<<24))>>24; break;
case 0x48B: res = (DMA_BaseAddress[5]&(0xFF<<24))>>24; break;
case 0x489: res = (DMA_BaseAddress[6]&(0xFF<<24))>>24; break;
case 0x48A: res = (DMA_BaseAddress[7]&(0xFF<<24))>>24; break;
/* High Page Base Address*/
case 0x08:
case 0xD0:
/* Status */
case 0x0D:
case 0xDA:
/* Temporary */
break;
}
return res;
}
-------------- next part --------------
/*
* Soundblaster Emulation
*
* Copyright 2002 Christian Costa
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_SOUNDBLASTER_H
#define __WINE_SOUNDBLASTER_H
#include "winbase.h"
void SB_ioport_out( WORD port, BYTE val );
BYTE SB_ioport_in( WORD port );
#endif /* __WINE_SOUNDBLASTER_H */
-------------- next part --------------
/*
* Soundblaster Emulation
*
* Copyright 2002 Christian Costa
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Note : This is preliminary, poorly documented and not cleaned up yet
*/
#include "config.h"
#include "windef.h"
#include "dosexe.h"
#include "soundblaster.h"
#include "wine/debug.h"
#include "dsound.h"
#include "dma.h"
WINE_DEFAULT_DEBUG_CHANNEL(sblaster);
static int SampleRate;
static int SamplesCount;
static BYTE DSP_Command[256];
static BYTE DSP_Buffer[10];
static int data;
static int order = 0;
static int resval = 0;
static int end_loop = 0;
static int start = 0;
typedef HRESULT (WINAPI* fnDirectSoundCreate) (LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
fnDirectSoundCreate lpDirectSoundCreate;
static HANDLE SB_Thread;
static HMODULE hmodule;
static LPDIRECTSOUND lpdsound;
static LPDIRECTSOUNDBUFFER lpdsbuf;
static DSBUFFERDESC buf_desc;
static WAVEFORMATEX wav_fmt;
static UINT buf_off;
static BYTE dma_buffer[65536*2];
extern HWND vga_hwnd;
#define DSBUFLEN 4096
#define SB_IRQ 5
#define SB_IRQ_PRI 11
#define SB_DMA 1
static void SB_CleanBuffer()
{
HRESULT result;
LPBYTE lpbuf1 = NULL;
LPBYTE lpbuf2 = NULL;
DWORD dwsize1 = 0;
DWORD dwsize2 = 0;
DWORD dwbyteswritten1 = 0;
DWORD dwbyteswritten2 = 0;
int i;
result = IDirectSoundBuffer_Lock(lpdsbuf,0,DSBUFLEN,&lpbuf1,&dwsize1,&lpbuf2,&dwsize2,0);
for(i=0;i<dwsize1;i++)
*(lpbuf1+i) = 0;
for(i=0;i<dwsize2;i++)
*(lpbuf2+i) = 0;
result = IDirectSoundBuffer_Unlock(lpdsbuf,lpbuf1,dwbyteswritten1,lpbuf2,dwbyteswritten2);
}
static DWORD CALLBACK SB_Poll( void *dummy )
{
HRESULT result;
LPBYTE lpbuf1 = NULL;
LPBYTE lpbuf2 = NULL;
DWORD dwsize1 = 0;
DWORD dwsize2 = 0;
DWORD dwbyteswritten1 = 0;
DWORD dwbyteswritten2 = 0;
int size;
while(!end_loop)
{
Sleep(10);
#define B1
#ifdef B1
if (start) {
int reqsize;
reqsize = 1024;
size = DMA_Transfer(SB_DMA,reqsize,dma_buffer);
SamplesCount -= size;
if (!SamplesCount) {
DOSVM_QueueEvent(SB_IRQ,SB_IRQ_PRI,NULL,NULL);
start = 0;
}
} else
continue;
#else
if (!start) continue;
#endif
result = IDirectSoundBuffer_Lock(lpdsbuf,buf_off,size,&lpbuf1,&dwsize1,&lpbuf2,&dwsize2,0);
#ifndef B1
size = DMA_Transfer(SB_DMA,dwsize1+dwsize2,dma_buffer);
if (!size) goto end;
#endif
SamplesCount -= size;
if (!SamplesCount) {
DOSVM_QueueEvent(SB_IRQ,SB_IRQ_PRI,NULL,NULL);
start = 0;
}
dwbyteswritten1 = min(size,dwsize1);
memcpy(lpbuf1,dma_buffer,dwbyteswritten1);
if (size>dwsize1) {
dwbyteswritten2 = min(size - dwbyteswritten1,dwsize2);
memcpy(lpbuf2,dma_buffer+dwbyteswritten1,dwbyteswritten2);
}
buf_off = (buf_off + dwbyteswritten1 + dwbyteswritten2) % DSBUFLEN;
#ifndef B1
end:
#endif
result = IDirectSoundBuffer_Unlock(lpdsbuf,lpbuf1,dwbyteswritten1,lpbuf2,dwbyteswritten2);
}
return 0;
}
void SB_Init()
{
HRESULT result;
if (!lpdsound) {
hmodule = LoadLibraryA("dsound.dll");
if (!hmodule) {
ERR("Can't load dsound.dll !\n");
return;
}
lpDirectSoundCreate = (fnDirectSoundCreate)GetProcAddress(hmodule,"DirectSoundCreate");
if (!lpDirectSoundCreate) {
/* CloseHandle(hmodule); */
ERR("Can't find DirectSoundCreate function !\n");
return;
}
result = (*lpDirectSoundCreate)(NULL,&lpdsound,NULL);
if (result != DS_OK) {
ERR("Unable to initialize Sound Subsystem err = %lx !\n",result);
return;
}
result = IDirectSound_SetCooperativeLevel(lpdsound,vga_hwnd,DSSCL_EXCLUSIVE|DSSCL_PRIORITY);
if (result != DS_OK) {
ERR("Can't set cooperative level !\n");
return;
}
/* Default format */
wav_fmt.wFormatTag = WAVE_FORMAT_PCM;
wav_fmt.nChannels = 1;
wav_fmt.nSamplesPerSec = 22050;
wav_fmt.nAvgBytesPerSec = 22050;
wav_fmt.nBlockAlign = 1;
wav_fmt.wBitsPerSample = 8;
wav_fmt.cbSize = 0;
memset(&buf_desc,0,sizeof(DSBUFFERDESC));
buf_desc.dwSize = sizeof(DSBUFFERDESC);
buf_desc.dwBufferBytes = DSBUFLEN;
buf_desc.lpwfxFormat = &wav_fmt;
result = IDirectSound_CreateSoundBuffer(lpdsound,&buf_desc,&lpdsbuf,NULL);
if (result != DS_OK) {
ERR("Can't create sound buffer !\n");
return;
}
SB_CleanBuffer();
result = IDirectSoundBuffer_Play(lpdsbuf,0, 0, DSBPLAY_LOOPING);
if (result != DS_OK) {
ERR("Can't start playing !\n");
return;
}
buf_off = 0;
end_loop = 0;
SB_Thread = CreateThread(NULL, 0, SB_Poll, NULL, 0, NULL);
TRACE("thread\n");
if (!SB_Thread) {
ERR("Can't create thread !\n");
return;
}
}
resval = 0xaa;
}
void SB_Reset()
{
int i;
for(i=0;i<256;i++)
DSP_Command[i]=0;
/* Set Time Constant */
DSP_Command[0x40]=1;
/* Generate IRQ */
DSP_Command[0xf2]=0;
/* DMA DAC 8-bits */
DSP_Command[0x14]=2;
SB_Init();
}
int SB_StdSampleRate(int SampleRate)
{
if (SampleRate>((44100+48000)/2)) return 48000;
if (SampleRate>((32000+44100)/2)) return 44100;
if (SampleRate>((24000+32000)/2)) return 32000;
if (SampleRate>((22050+24000)/2)) return 24000;
if (SampleRate>((16000+22050)/2)) return 22050;
if (SampleRate>((12000+16000)/2)) return 16000;
if (SampleRate>((11025+12000)/2)) return 12000;
if (SampleRate>((8000+11025)/2)) return 11025;
return 8000;
}
void SB_ioport_out( WORD port, BYTE val )
{
switch(port)
{
case 0x226:
TRACE("Resetting DSP.\n");
SB_Reset();
break;
case 0x22c:
if (!order) {
order = val;
data = 0;
}
if (data!=DSP_Command[order])
DSP_Buffer[data++]=val;
else {
switch(order)
{
case 0x14:
SamplesCount = DSP_Buffer[1]+(val<<8)+1;
TRACE("DMA DAC 8-bits for %x samples - Not Implemented\n",SamplesCount);
start = 1;
break;
case 0x40:
SampleRate = 1000000/(256-val);
TRACE("Set Time Constant (%d <-> %d Hz => %d Hz)\n",DSP_Buffer[0],
SampleRate,SB_StdSampleRate(SampleRate));
SampleRate = SB_StdSampleRate(SampleRate);
wav_fmt.nSamplesPerSec = SampleRate;
wav_fmt.nAvgBytesPerSec = SampleRate;
IDirectSoundBuffer_SetFormat(lpdsbuf,&wav_fmt);
break;
case 0xD0:
TRACE("Halt DMA 8-bits operation\n");
start = 0;
break;
case 0xD1:
FIXME("Enable Speaker - Not Implemented\n");
break;
case 0xD3:
FIXME("Disable Speaker - Not Implemented\n");
break;
case 0xf2:
TRACE("Generate IRQ\n");
DOSVM_QueueEvent(SB_IRQ,SB_IRQ_PRI,NULL,NULL);
break;
default:
FIXME("DSP command %x not supported\n",val);
}
order = 0;
}
}
}
BYTE SB_ioport_in( WORD port )
{
BYTE res = 0;
switch(port)
{
case 0x22a:
/* Value after a RESET */
res = 0xaa; //resval;
break;
case 0x22c:
/* DSP always ready for writing */
res = 0x00;
break;
case 0x22e:
/* DSP data to read */
res = 0x80;
break;
}
return res;
}
More information about the wine-patches
mailing list