diff --git a/reactos/baseaddress.rbuild b/reactos/baseaddress.rbuild
index 2036254cac9..567666925f2 100644
--- a/reactos/baseaddress.rbuild
+++ b/reactos/baseaddress.rbuild
@@ -18,6 +18,8 @@
+
+
@@ -119,17 +121,20 @@
+
+
+
diff --git a/reactos/boot/bootdata/hivesft_arm.inf b/reactos/boot/bootdata/hivesft_arm.inf
index b4c43a0cecd..4838fdbd198 100644
--- a/reactos/boot/bootdata/hivesft_arm.inf
+++ b/reactos/boot/bootdata/hivesft_arm.inf
@@ -60,6 +60,23 @@ HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","midimapper",0x000
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","wavemapper",0x00000000,"c:\reactos\system32\msacm32.dll"
;HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","wave",0x00000000,"sndblst.dll"
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","midi",0x00000000,"c:\reactos\system32\beepmidi.dll"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","msacm.msadpcm",0x00000000,"c:\reactos\system32\msadp32.acm"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","msacm.msg711",0x00000000,"c:\reactos\system32\msg711.acm"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","msacm.imaadpcm",0x00000000,"c:\reactos\system32\imaadp32.acm"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","vidc.cvid",0x00000000,"c:\reactos\system32\iccvid.dll"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","vidc.mrle",0x00000000,"c:\reactos\system32\msrle32.dll"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","vidc.msvc",0x00000000,"c:\reactos\system32\msvidc32.dll"
+
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","AVIVideo",0x00000002,"c:\reactos\system32\mciavi32.dll"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","CDAudio",0x00000002,"c:\reactos\system32\mcicda.dll"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","Sequencer",0x00000002,"c:\reactos\system32\mciseq.dll"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","WaveAudio",0x00000002,"c:\reactos\system32\mciwave.dll"
+
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","avi",0x00000002,"avivideo"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","cda",0x00000002,"CDAudio"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","mid",0x00000002,"Sequencer"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","rmi",0x00000002,"Sequencer"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","wav",0x00000002,"WaveAudio"
; Mesa OpenGL Driver
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers","DefaultDriver",0x00000000,"Mesa"
diff --git a/reactos/boot/bootdata/hivesft_i386.inf b/reactos/boot/bootdata/hivesft_i386.inf
index 9c969e1ba27..bc45bfa6ec3 100644
--- a/reactos/boot/bootdata/hivesft_i386.inf
+++ b/reactos/boot/bootdata/hivesft_i386.inf
@@ -65,6 +65,23 @@ HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","midimapper",0x000
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","wavemapper",0x00000000,"c:\reactos\system32\msacm32.dll"
;HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","wave",0x00000000,"sndblst.dll"
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","midi",0x00000000,"c:\reactos\system32\beepmidi.dll"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","msacm.msadpcm",0x00000000,"c:\reactos\system32\msadp32.acm"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","msacm.msg711",0x00000000,"c:\reactos\system32\msg711.acm"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","msacm.imaadpcm",0x00000000,"c:\reactos\system32\imaadp32.acm"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","vidc.cvid",0x00000000,"c:\reactos\system32\iccvid.dll"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","vidc.mrle",0x00000000,"c:\reactos\system32\msrle32.dll"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","vidc.msvc",0x00000000,"c:\reactos\system32\msvidc32.dll"
+
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","AVIVideo",0x00000002,"c:\reactos\system32\mciavi32.dll"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","CDAudio",0x00000002,"c:\reactos\system32\mcicda.dll"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","Sequencer",0x00000002,"c:\reactos\system32\mciseq.dll"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","WaveAudio",0x00000002,"c:\reactos\system32\mciwave.dll"
+
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","avi",0x00000002,"avivideo"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","cda",0x00000002,"CDAudio"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","mid",0x00000002,"Sequencer"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","rmi",0x00000002,"Sequencer"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","wav",0x00000002,"WaveAudio"
; Mesa OpenGL Driver
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers","DefaultDriver",0x00000000,"Mesa"
diff --git a/reactos/boot/bootdata/packages/reactos.dff b/reactos/boot/bootdata/packages/reactos.dff
index b578b6ebbf8..a433806d8d4 100644
--- a/reactos/boot/bootdata/packages/reactos.dff
+++ b/reactos/boot/bootdata/packages/reactos.dff
@@ -276,7 +276,9 @@ dll\win32\glu32\glu32.dll 1
dll\win32\hhctrl.ocx\hhctrl.ocx 1
dll\win32\hid\hid.dll 1
dll\win32\hlink\hlink.dll 1
+dll\win32\iccvid\iccvid.dll 1
dll\win32\icmp\icmp.dll 1
+dll\win32\imaadp32.acm\imaadp32.acm 1
dll\win32\imagehlp\imagehlp.dll 1
dll\win32\imm32\imm32.dll 1
dll\win32\inetcomm\inetcomm.dll 1
@@ -303,12 +305,14 @@ dll\win32\modemui\modemui.dll 1
dll\win32\mpr\mpr.dll 1
dll\win32\mprapi\mprapi.dll 1
dll\win32\msacm32\msacm32.dll 1
+dll\win32\msadp32.acm\msadp32.acm 1
dll\win32\msafd\msafd.dll 1
dll\win32\mscat32\mscat32.dll 1
dll\win32\mscms\mscms.dll 1
dll\win32\mscoree\mscoree.dll 1
dll\win32\msctf\msctf.dll 1
dll\win32\msftedit\msftedit.dll 1
+dll\win32\msg711.acm\msg711.acm 1
dll\win32\msgina\msgina.dll 1
dll\win32\mshtml\mshtml.dll 1
dll\win32\mshtml.tlb\mshtml.tlb 1
@@ -321,6 +325,7 @@ dll\win32\msvcrt\msvcrt.dll 1
dll\win32\msvcrt20\msvcrt20.dll 1
dll\win32\msvcrt40\msvcrt40.dll 1
dll\win32\msvfw32\msvfw32.dll 1
+dll\win32\msvidc32\msvidc32.dll 1
dll\win32\mswsock\mswsock.dll 1
dll\win32\msxml3\msxml3.dll 1
dll\win32\nddeapi\nddeapi.dll 1
diff --git a/reactos/dll/win32/iccvid/iccvid.c b/reactos/dll/win32/iccvid/iccvid.c
new file mode 100644
index 00000000000..77328eabcda
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid.c
@@ -0,0 +1,1042 @@
+/*
+ * Radius Cinepak Video Decoder
+ *
+ * Copyright 2001 Dr. Tim Ferguson (see below)
+ * Portions Copyright 2003 Mike McCormack for CodeWeavers
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/* Copyright notice from original source:
+ * ------------------------------------------------------------------------
+ * Radius Cinepak Video Decoder
+ *
+ * Dr. Tim Ferguson, 2001.
+ * For more details on the algorithm:
+ * http://www.csse.monash.edu.au/~timf/videocodec.html
+ *
+ * This is basically a vector quantiser with adaptive vector density. The
+ * frame is segmented into 4x4 pixel blocks, and each block is coded using
+ * either 1 or 4 vectors.
+ *
+ * There are still some issues with this code yet to be resolved. In
+ * particular with decoding in the strip boundaries. However, I have not
+ * yet found a sequence it doesn't work on. Ill keep trying :)
+ *
+ * You may freely use this source code. I only ask that you reference its
+ * source in your projects documentation:
+ * Tim Ferguson: http://www.csse.monash.edu.au/~timf/
+ * ------------------------------------------------------------------------ */
+
+#include
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "commdlg.h"
+#include "vfw.h"
+#include "mmsystem.h"
+#include "iccvid_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(iccvid);
+
+static HINSTANCE ICCVID_hModule;
+
+#define ICCVID_MAGIC mmioFOURCC('c', 'v', 'i', 'd')
+
+#define DBUG 0
+#define MAX_STRIPS 32
+
+/* ------------------------------------------------------------------------ */
+typedef struct
+{
+ unsigned char y0, y1, y2, y3;
+ char u, v;
+ unsigned char r[4], g[4], b[4];
+} cvid_codebook;
+
+typedef struct {
+ cvid_codebook *v4_codebook[MAX_STRIPS];
+ cvid_codebook *v1_codebook[MAX_STRIPS];
+ unsigned int strip_num;
+} cinepak_info;
+
+typedef struct _ICCVID_Info
+{
+ DWORD dwMagic;
+ int bits_per_pixel;
+ cinepak_info *cvinfo;
+} ICCVID_Info;
+
+static inline LPVOID heap_alloc( size_t size )
+{
+ return HeapAlloc( GetProcessHeap(), 0, size );
+}
+
+static inline BOOL heap_free( LPVOID ptr )
+{
+ return HeapFree( GetProcessHeap(), 0, ptr );
+}
+
+
+/* ------------------------------------------------------------------------ */
+static unsigned char *in_buffer, uiclip[1024], *uiclp = NULL;
+
+#define get_byte() *(in_buffer++)
+#define skip_byte() in_buffer++
+#define get_word() ((unsigned short)(in_buffer += 2, \
+ (in_buffer[-2] << 8 | in_buffer[-1])))
+#define get_long() ((unsigned long)(in_buffer += 4, \
+ (in_buffer[-4] << 24 | in_buffer[-3] << 16 | in_buffer[-2] << 8 | in_buffer[-1])))
+
+
+/* ---------------------------------------------------------------------- */
+static inline void read_codebook(cvid_codebook *c, int mode)
+{
+int uvr, uvg, uvb;
+
+ if(mode) /* black and white */
+ {
+ c->y0 = get_byte();
+ c->y1 = get_byte();
+ c->y2 = get_byte();
+ c->y3 = get_byte();
+ c->u = c->v = 0;
+
+ c->r[0] = c->g[0] = c->b[0] = c->y0;
+ c->r[1] = c->g[1] = c->b[1] = c->y1;
+ c->r[2] = c->g[2] = c->b[2] = c->y2;
+ c->r[3] = c->g[3] = c->b[3] = c->y3;
+ }
+ else /* colour */
+ {
+ c->y0 = get_byte(); /* luma */
+ c->y1 = get_byte();
+ c->y2 = get_byte();
+ c->y3 = get_byte();
+ c->u = get_byte(); /* chroma */
+ c->v = get_byte();
+
+ uvr = c->v << 1;
+ uvg = -((c->u+1) >> 1) - c->v;
+ uvb = c->u << 1;
+
+ c->r[0] = uiclp[c->y0 + uvr]; c->g[0] = uiclp[c->y0 + uvg]; c->b[0] = uiclp[c->y0 + uvb];
+ c->r[1] = uiclp[c->y1 + uvr]; c->g[1] = uiclp[c->y1 + uvg]; c->b[1] = uiclp[c->y1 + uvb];
+ c->r[2] = uiclp[c->y2 + uvr]; c->g[2] = uiclp[c->y2 + uvg]; c->b[2] = uiclp[c->y2 + uvb];
+ c->r[3] = uiclp[c->y3 + uvr]; c->g[3] = uiclp[c->y3 + uvg]; c->b[3] = uiclp[c->y3 + uvb];
+ }
+}
+
+
+#define MAKECOLOUR32(r,g,b) (((r) << 16) | ((g) << 8) | (b))
+/*#define MAKECOLOUR24(r,g,b) (((r) << 16) | ((g) << 8) | (b))*/
+#define MAKECOLOUR16(r,g,b) (((r) >> 3) << 11)| (((g) >> 2) << 5)| (((b) >> 3) << 0)
+#define MAKECOLOUR15(r,g,b) (((r) >> 3) << 10)| (((g) >> 3) << 5)| (((b) >> 3) << 0)
+
+/* ------------------------------------------------------------------------ */
+static void cvid_v1_32(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb)
+{
+unsigned long *vptr = (unsigned long *)frm;
+#ifndef ORIGINAL
+int row_inc = -stride/4;
+#else
+int row_inc = stride/4;
+#endif
+int x, y;
+
+ /* fill 4x4 block of pixels with colour values from codebook */
+ for (y = 0; y < 4; y++)
+ {
+ if (&vptr[y*row_inc] < (unsigned long *)limit) return;
+ for (x = 0; x < 4; x++)
+ vptr[y*row_inc + x] = MAKECOLOUR32(cb->r[x/2+(y/2)*2], cb->g[x/2+(y/2)*2], cb->b[x/2+(y/2)*2]);
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+static void cvid_v4_32(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0,
+ cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
+{
+unsigned long *vptr = (unsigned long *)frm;
+#ifndef ORIGINAL
+int row_inc = -stride/4;
+#else
+int row_inc = stride/4;
+#endif
+int x, y;
+cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
+
+ /* fill 4x4 block of pixels with colour values from codebooks */
+ for (y = 0; y < 4; y++)
+ {
+ if (&vptr[y*row_inc] < (unsigned long *)limit) return;
+ for (x = 0; x < 4; x++)
+ vptr[y*row_inc + x] = MAKECOLOUR32(cb[x/2+(y/2)*2]->r[x%2+(y%2)*2], cb[x/2+(y/2)*2]->g[x%2+(y%2)*2], cb[x/2+(y/2)*2]->b[x%2+(y%2)*2]);
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+static void cvid_v1_24(unsigned char *vptr, unsigned char *limit, int stride, cvid_codebook *cb)
+{
+#ifndef ORIGINAL
+int row_inc = -stride;
+#else
+int row_inc = stride;
+#endif
+int x, y;
+
+ /* fill 4x4 block of pixels with colour values from codebook */
+ for (y = 0; y < 4; y++)
+ {
+ if (&vptr[y*row_inc] < limit) return;
+ for (x = 0; x < 4; x++)
+ {
+ vptr[y*row_inc + x*3 + 0] = cb->b[x/2+(y/2)*2];
+ vptr[y*row_inc + x*3 + 1] = cb->g[x/2+(y/2)*2];
+ vptr[y*row_inc + x*3 + 2] = cb->r[x/2+(y/2)*2];
+ }
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+static void cvid_v4_24(unsigned char *vptr, unsigned char *limit, int stride, cvid_codebook *cb0,
+ cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
+{
+#ifndef ORIGINAL
+int row_inc = -stride;
+#else
+int row_inc = stride;
+#endif
+cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
+int x, y;
+
+ /* fill 4x4 block of pixels with colour values from codebooks */
+ for (y = 0; y < 4; y++)
+ {
+ if (&vptr[y*row_inc] < limit) return;
+ for (x = 0; x < 4; x++)
+ {
+ vptr[y*row_inc + x*3 + 0] = cb[x/2+(y/2)*2]->b[x%2+(y%2)*2];
+ vptr[y*row_inc + x*3 + 1] = cb[x/2+(y/2)*2]->g[x%2+(y%2)*2];
+ vptr[y*row_inc + x*3 + 2] = cb[x/2+(y/2)*2]->r[x%2+(y%2)*2];
+ }
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+static void cvid_v1_16(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb)
+{
+unsigned short *vptr = (unsigned short *)frm;
+#ifndef ORIGINAL
+int row_inc = -stride/2;
+#else
+int row_inc = stride/2;
+#endif
+int x, y;
+
+ /* fill 4x4 block of pixels with colour values from codebook */
+ for (y = 0; y < 4; y++)
+ {
+ if (&vptr[y*row_inc] < (unsigned short *)limit) return;
+ for (x = 0; x < 4; x++)
+ vptr[y*row_inc + x] = MAKECOLOUR16(cb->r[x/2+(y/2)*2], cb->g[x/2+(y/2)*2], cb->b[x/2+(y/2)*2]);
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+static void cvid_v4_16(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0,
+ cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
+{
+unsigned short *vptr = (unsigned short *)frm;
+#ifndef ORIGINAL
+int row_inc = -stride/2;
+#else
+int row_inc = stride/2;
+#endif
+cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
+int x, y;
+
+ /* fill 4x4 block of pixels with colour values from codebooks */
+ for (y = 0; y < 4; y++)
+ {
+ if (&vptr[y*row_inc] < (unsigned short *)limit) return;
+ for (x = 0; x < 4; x++)
+ vptr[y*row_inc + x] = MAKECOLOUR16(cb[x/2+(y/2)*2]->r[x%2+(y%2)*2], cb[x/2+(y/2)*2]->g[x%2+(y%2)*2], cb[x/2+(y/2)*2]->b[x%2+(y%2)*2]);
+ }
+}
+
+/* ------------------------------------------------------------------------ */
+static void cvid_v1_15(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb)
+{
+unsigned short *vptr = (unsigned short *)frm;
+#ifndef ORIGINAL
+int row_inc = -stride/2;
+#else
+int row_inc = stride/2;
+#endif
+int x, y;
+
+ /* fill 4x4 block of pixels with colour values from codebook */
+ for (y = 0; y < 4; y++)
+ {
+ if (&vptr[y*row_inc] < (unsigned short *)limit) return;
+ for (x = 0; x < 4; x++)
+ vptr[y*row_inc + x] = MAKECOLOUR15(cb->r[x/2+(y/2)*2], cb->g[x/2+(y/2)*2], cb->b[x/2+(y/2)*2]);
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+static void cvid_v4_15(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0,
+ cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
+{
+unsigned short *vptr = (unsigned short *)frm;
+#ifndef ORIGINAL
+int row_inc = -stride/2;
+#else
+int row_inc = stride/2;
+#endif
+cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
+int x, y;
+
+ /* fill 4x4 block of pixels with colour values from codebooks */
+ for (y = 0; y < 4; y++)
+ {
+ if (&vptr[y*row_inc] < (unsigned short *)limit) return;
+ for (x = 0; x < 4; x++)
+ vptr[y*row_inc + x] = MAKECOLOUR15(cb[x/2+(y/2)*2]->r[x%2+(y%2)*2], cb[x/2+(y/2)*2]->g[x%2+(y%2)*2], cb[x/2+(y/2)*2]->b[x%2+(y%2)*2]);
+ }
+}
+
+
+/* ------------------------------------------------------------------------
+ * Call this function once at the start of the sequence and save the
+ * returned context for calls to decode_cinepak().
+ */
+static cinepak_info *decode_cinepak_init(void)
+{
+ cinepak_info *cvinfo;
+ int i;
+
+ cvinfo = heap_alloc( sizeof (cinepak_info) );
+ if( !cvinfo )
+ return NULL;
+ cvinfo->strip_num = 0;
+
+ if(uiclp == NULL)
+ {
+ uiclp = uiclip+512;
+ for(i = -512; i < 512; i++)
+ uiclp[i] = (i < 0 ? 0 : (i > 255 ? 255 : i));
+ }
+
+ return cvinfo;
+}
+
+static void free_cvinfo( cinepak_info *cvinfo )
+{
+ unsigned int i;
+
+ for( i=0; istrip_num; i++ )
+ {
+ heap_free(cvinfo->v4_codebook[i]);
+ heap_free(cvinfo->v1_codebook[i]);
+ }
+ heap_free( cvinfo );
+}
+
+typedef void (*fn_cvid_v1)(unsigned char *frm, unsigned char *limit,
+ int stride, cvid_codebook *cb);
+typedef void (*fn_cvid_v4)(unsigned char *frm, unsigned char *limit, int stride,
+ cvid_codebook *cb0, cvid_codebook *cb1,
+ cvid_codebook *cb2, cvid_codebook *cb3);
+
+/* ------------------------------------------------------------------------
+ * This function decodes a buffer containing a Cinepak encoded frame.
+ *
+ * context - the context created by decode_cinepak_init().
+ * buf - the input buffer to be decoded
+ * size - the size of the input buffer
+ * frame - the output frame buffer (24 or 32 bit per pixel)
+ * width - the width of the output frame
+ * height - the height of the output frame
+ * bit_per_pixel - the number of bits per pixel allocated to the output
+ * frame (only 24 or 32 bpp are supported)
+ */
+static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
+ unsigned char *frame, unsigned int width, unsigned int height, int bit_per_pixel)
+{
+ cvid_codebook *v4_codebook, *v1_codebook, *codebook = NULL;
+ unsigned long x, y, y_bottom, frame_flags, strips, cv_width, cv_height,
+ cnum, strip_id, chunk_id, x0, y0, x1, y1, ci, flag, mask;
+ long len, top_size, chunk_size;
+ unsigned char *frm_ptr;
+ unsigned int i, cur_strip;
+ int d0, d1, d2, d3, frm_stride, bpp = 3;
+ fn_cvid_v1 cvid_v1 = cvid_v1_24;
+ fn_cvid_v4 cvid_v4 = cvid_v4_24;
+
+ y = 0;
+ y_bottom = 0;
+ in_buffer = buf;
+
+ frame_flags = get_byte();
+ len = get_byte() << 16;
+ len |= get_byte() << 8;
+ len |= get_byte();
+
+ switch(bit_per_pixel)
+ {
+ case 15:
+ bpp = 2;
+ cvid_v1 = cvid_v1_15;
+ cvid_v4 = cvid_v4_15;
+ break;
+ case 16:
+ bpp = 2;
+ cvid_v1 = cvid_v1_16;
+ cvid_v4 = cvid_v4_16;
+ break;
+ case 24:
+ bpp = 3;
+ cvid_v1 = cvid_v1_24;
+ cvid_v4 = cvid_v4_24;
+ break;
+ case 32:
+ bpp = 4;
+ cvid_v1 = cvid_v1_32;
+ cvid_v4 = cvid_v4_32;
+ break;
+ }
+
+ frm_stride = width * bpp;
+ frm_ptr = frame;
+
+ if(len != size)
+ {
+ if(len & 0x01) len++; /* AVIs tend to have a size mismatch */
+ if(len != size)
+ {
+ ERR("CVID: corruption %d (QT/AVI) != %ld (CV)\n", size, len);
+ /* return; */
+ }
+ }
+
+ cv_width = get_word();
+ cv_height = get_word();
+ strips = get_word();
+
+ if(strips > cvinfo->strip_num)
+ {
+ if(strips >= MAX_STRIPS)
+ {
+ ERR("CVID: strip overflow (more than %d)\n", MAX_STRIPS);
+ return;
+ }
+
+ for(i = cvinfo->strip_num; i < strips; i++)
+ {
+ if((cvinfo->v4_codebook[i] = heap_alloc(sizeof(cvid_codebook) * 260)) == NULL)
+ {
+ ERR("CVID: codebook v4 alloc err\n");
+ return;
+ }
+
+ if((cvinfo->v1_codebook[i] = heap_alloc(sizeof(cvid_codebook) * 260)) == NULL)
+ {
+ ERR("CVID: codebook v1 alloc err\n");
+ return;
+ }
+ }
+ }
+ cvinfo->strip_num = strips;
+
+ TRACE("CVID: <%ld,%ld> strips %ld\n", cv_width, cv_height, strips);
+
+ for(cur_strip = 0; cur_strip < strips; cur_strip++)
+ {
+ v4_codebook = cvinfo->v4_codebook[cur_strip];
+ v1_codebook = cvinfo->v1_codebook[cur_strip];
+
+ if((cur_strip > 0) && (!(frame_flags & 0x01)))
+ {
+ memcpy(cvinfo->v4_codebook[cur_strip], cvinfo->v4_codebook[cur_strip-1], 260 * sizeof(cvid_codebook));
+ memcpy(cvinfo->v1_codebook[cur_strip], cvinfo->v1_codebook[cur_strip-1], 260 * sizeof(cvid_codebook));
+ }
+
+ strip_id = get_word(); /* 1000 = key strip, 1100 = iter strip */
+ top_size = get_word();
+ y0 = get_word(); /* FIXME: most of these are ignored at the moment */
+ x0 = get_word();
+ y1 = get_word();
+ x1 = get_word();
+
+ y_bottom += y1;
+ top_size -= 12;
+ x = 0;
+ if(x1 != width)
+ WARN("CVID: Warning x1 (%ld) != width (%d)\n", x1, width);
+
+ TRACE(" %d) %04lx %04ld <%ld,%ld> <%ld,%ld> yt %ld\n",
+ cur_strip, strip_id, top_size, x0, y0, x1, y1, y_bottom);
+
+ while(top_size > 0)
+ {
+ chunk_id = get_word();
+ chunk_size = get_word();
+
+ TRACE(" %04lx %04ld\n", chunk_id, chunk_size);
+ top_size -= chunk_size;
+ chunk_size -= 4;
+
+ switch(chunk_id)
+ {
+ /* -------------------- Codebook Entries -------------------- */
+ case 0x2000:
+ case 0x2200:
+ codebook = (chunk_id == 0x2200 ? v1_codebook : v4_codebook);
+ cnum = chunk_size/6;
+ for(i = 0; i < cnum; i++) read_codebook(codebook+i, 0);
+ break;
+
+ case 0x2400:
+ case 0x2600: /* 8 bit per pixel */
+ codebook = (chunk_id == 0x2600 ? v1_codebook : v4_codebook);
+ cnum = chunk_size/4;
+ for(i = 0; i < cnum; i++) read_codebook(codebook+i, 1);
+ break;
+
+ case 0x2100:
+ case 0x2300:
+ codebook = (chunk_id == 0x2300 ? v1_codebook : v4_codebook);
+
+ ci = 0;
+ while(chunk_size > 0)
+ {
+ flag = get_long();
+ chunk_size -= 4;
+
+ for(i = 0; i < 32; i++)
+ {
+ if(flag & 0x80000000)
+ {
+ chunk_size -= 6;
+ read_codebook(codebook+ci, 0);
+ }
+
+ ci++;
+ flag <<= 1;
+ }
+ }
+ while(chunk_size > 0) { skip_byte(); chunk_size--; }
+ break;
+
+ case 0x2500:
+ case 0x2700: /* 8 bit per pixel */
+ codebook = (chunk_id == 0x2700 ? v1_codebook : v4_codebook);
+
+ ci = 0;
+ while(chunk_size > 0)
+ {
+ flag = get_long();
+ chunk_size -= 4;
+
+ for(i = 0; i < 32; i++)
+ {
+ if(flag & 0x80000000)
+ {
+ chunk_size -= 4;
+ read_codebook(codebook+ci, 1);
+ }
+
+ ci++;
+ flag <<= 1;
+ }
+ }
+ while(chunk_size > 0) { skip_byte(); chunk_size--; }
+ break;
+
+ /* -------------------- Frame -------------------- */
+ case 0x3000:
+ while((chunk_size > 0) && (y < y_bottom))
+ {
+ flag = get_long();
+ chunk_size -= 4;
+
+ for(i = 0; i < 32; i++)
+ {
+ if(y >= y_bottom) break;
+ if(flag & 0x80000000) /* 4 bytes per block */
+ {
+ d0 = get_byte();
+ d1 = get_byte();
+ d2 = get_byte();
+ d3 = get_byte();
+ chunk_size -= 4;
+#ifdef ORIGINAL
+ cvid_v4(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
+#else
+ cvid_v4(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
+#endif
+ }
+ else /* 1 byte per block */
+ {
+#ifdef ORIGINAL
+ cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte());
+#else
+ cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte());
+#endif
+ chunk_size--;
+ }
+
+ x += 4;
+ if(x >= width)
+ {
+ x = 0;
+ y += 4;
+ }
+ flag <<= 1;
+ }
+ }
+ while(chunk_size > 0) { skip_byte(); chunk_size--; }
+ break;
+
+ case 0x3100:
+ while((chunk_size > 0) && (y < y_bottom))
+ {
+ /* ---- flag bits: 0 = SKIP, 10 = V1, 11 = V4 ---- */
+ flag = get_long();
+ chunk_size -= 4;
+ mask = 0x80000000;
+
+ while((mask) && (y < y_bottom))
+ {
+ if(flag & mask)
+ {
+ if(mask == 1)
+ {
+ if(chunk_size < 0) break;
+ flag = get_long();
+ chunk_size -= 4;
+ mask = 0x80000000;
+ }
+ else mask >>= 1;
+
+ if(flag & mask) /* V4 */
+ {
+ d0 = get_byte();
+ d1 = get_byte();
+ d2 = get_byte();
+ d3 = get_byte();
+ chunk_size -= 4;
+#ifdef ORIGINAL
+ cvid_v4(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
+#else
+ cvid_v4(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
+#endif
+ }
+ else /* V1 */
+ {
+ chunk_size--;
+#ifdef ORIGINAL
+ cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte());
+#else
+ cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte());
+#endif
+ }
+ } /* else SKIP */
+
+ mask >>= 1;
+ x += 4;
+ if(x >= width)
+ {
+ x = 0;
+ y += 4;
+ }
+ }
+ }
+
+ while(chunk_size > 0) { skip_byte(); chunk_size--; }
+ break;
+
+ case 0x3200: /* each byte is a V1 codebook */
+ while((chunk_size > 0) && (y < y_bottom))
+ {
+#ifdef ORIGINAL
+ cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte());
+#else
+ cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte());
+#endif
+ chunk_size--;
+ x += 4;
+ if(x >= width)
+ {
+ x = 0;
+ y += 4;
+ }
+ }
+ while(chunk_size > 0) { skip_byte(); chunk_size--; }
+ break;
+
+ default:
+ ERR("CVID: unknown chunk_id %08lx\n", chunk_id);
+ while(chunk_size > 0) { skip_byte(); chunk_size--; }
+ break;
+ }
+ }
+ }
+
+ if(len != size)
+ {
+ if(len & 0x01) len++; /* AVIs tend to have a size mismatch */
+ if(len != size)
+ {
+ long xlen;
+ skip_byte();
+ xlen = get_byte() << 16;
+ xlen |= get_byte() << 8;
+ xlen |= get_byte(); /* Read Len */
+ WARN("CVID: END INFO chunk size %d cvid size1 %ld cvid size2 %ld\n",
+ size, len, xlen);
+ }
+ }
+}
+
+static void ICCVID_dump_BITMAPINFO(const BITMAPINFO * bmi)
+{
+ TRACE(
+ "planes = %d\n"
+ "bpp = %d\n"
+ "height = %d\n"
+ "width = %d\n"
+ "compr = %s\n",
+ bmi->bmiHeader.biPlanes,
+ bmi->bmiHeader.biBitCount,
+ bmi->bmiHeader.biHeight,
+ bmi->bmiHeader.biWidth,
+ debugstr_an( (const char *)&bmi->bmiHeader.biCompression, 4 ) );
+}
+
+static inline int ICCVID_CheckMask(RGBQUAD bmiColors[3], COLORREF redMask, COLORREF blueMask, COLORREF greenMask)
+{
+ COLORREF realRedMask = MAKECOLOUR32(bmiColors[0].rgbRed, bmiColors[0].rgbGreen, bmiColors[0].rgbBlue);
+ COLORREF realBlueMask = MAKECOLOUR32(bmiColors[1].rgbRed, bmiColors[1].rgbGreen, bmiColors[1].rgbBlue);
+ COLORREF realGreenMask = MAKECOLOUR32(bmiColors[2].rgbRed, bmiColors[2].rgbGreen, bmiColors[2].rgbBlue);
+
+ TRACE("\nbmiColors[0] = 0x%08x\nbmiColors[1] = 0x%08x\nbmiColors[2] = 0x%08x\n",
+ realRedMask, realBlueMask, realGreenMask);
+
+ if ((realRedMask == redMask) &&
+ (realBlueMask == blueMask) &&
+ (realGreenMask == greenMask))
+ return TRUE;
+ return FALSE;
+}
+
+static LRESULT ICCVID_DecompressQuery( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out )
+{
+ TRACE("ICM_DECOMPRESS_QUERY %p %p %p\n", info, in, out);
+
+ if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
+ return ICERR_BADPARAM;
+
+ TRACE("in: ");
+ ICCVID_dump_BITMAPINFO(in);
+
+ if( in->bmiHeader.biCompression != ICCVID_MAGIC )
+ return ICERR_BADFORMAT;
+
+ if( out )
+ {
+ TRACE("out: ");
+ ICCVID_dump_BITMAPINFO(out);
+
+ if( in->bmiHeader.biPlanes != out->bmiHeader.biPlanes )
+ return ICERR_BADFORMAT;
+ if( in->bmiHeader.biHeight != out->bmiHeader.biHeight )
+ return ICERR_BADFORMAT;
+ if( in->bmiHeader.biWidth != out->bmiHeader.biWidth )
+ return ICERR_BADFORMAT;
+
+ switch( out->bmiHeader.biBitCount )
+ {
+ case 16:
+ if ( out->bmiHeader.biCompression == BI_BITFIELDS )
+ {
+ if ( !ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) &&
+ !ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) )
+ {
+ TRACE("unsupported output bit field(s) for 16-bit colors\n");
+ return ICERR_BADFORMAT;
+ }
+ }
+ break;
+ case 24:
+ case 32:
+ break;
+ default:
+ TRACE("unsupported output bitcount = %d\n", out->bmiHeader.biBitCount );
+ return ICERR_BADFORMAT;
+ }
+ }
+
+ return ICERR_OK;
+}
+
+static LRESULT ICCVID_DecompressGetFormat( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out )
+{
+ DWORD size;
+
+ TRACE("ICM_DECOMPRESS_GETFORMAT %p %p %p\n", info, in, out);
+
+ if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
+ return ICERR_BADPARAM;
+
+ size = in->bmiHeader.biSize;
+ if (in->bmiHeader.biBitCount <= 8)
+ size += in->bmiHeader.biClrUsed * sizeof(RGBQUAD);
+
+ if( out )
+ {
+ memcpy( out, in, size );
+ out->bmiHeader.biCompression = BI_RGB;
+ out->bmiHeader.biSizeImage = in->bmiHeader.biHeight
+ * in->bmiHeader.biWidth *4;
+ return ICERR_OK;
+ }
+ return size;
+}
+
+static LRESULT ICCVID_DecompressBegin( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out )
+{
+ TRACE("ICM_DECOMPRESS_BEGIN %p %p %p\n", info, in, out);
+
+ if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
+ return ICERR_BADPARAM;
+
+ info->bits_per_pixel = out->bmiHeader.biBitCount;
+
+ if (info->bits_per_pixel == 16)
+ {
+ if ( out->bmiHeader.biCompression == BI_BITFIELDS )
+ {
+ if ( ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) )
+ info->bits_per_pixel = 15;
+ else if ( ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) )
+ info->bits_per_pixel = 16;
+ else
+ {
+ TRACE("unsupported output bit field(s) for 16-bit colors\n");
+ return ICERR_UNSUPPORTED;
+ }
+ }
+ else
+ info->bits_per_pixel = 15;
+ }
+
+ TRACE("bit_per_pixel = %d\n", info->bits_per_pixel);
+
+ if( info->cvinfo )
+ free_cvinfo( info->cvinfo );
+ info->cvinfo = decode_cinepak_init();
+
+ return ICERR_OK;
+}
+
+static LRESULT ICCVID_Decompress( ICCVID_Info *info, ICDECOMPRESS *icd, DWORD size )
+{
+ LONG width, height;
+
+ TRACE("ICM_DECOMPRESS %p %p %d\n", info, icd, size);
+
+ if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
+ return ICERR_BADPARAM;
+ if (info->cvinfo==NULL)
+ {
+ ERR("ICM_DECOMPRESS sent after ICM_DECOMPRESS_END\n");
+ return ICERR_BADPARAM;
+ }
+
+ width = icd->lpbiInput->biWidth;
+ height = icd->lpbiInput->biHeight;
+
+ decode_cinepak(info->cvinfo, icd->lpInput, icd->lpbiInput->biSizeImage,
+ icd->lpOutput, width, height, info->bits_per_pixel);
+
+ return ICERR_OK;
+}
+
+static LRESULT ICCVID_DecompressEx( ICCVID_Info *info, ICDECOMPRESSEX *icd, DWORD size )
+{
+ LONG width, height;
+
+ TRACE("ICM_DECOMPRESSEX %p %p %d\n", info, icd, size);
+
+ if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
+ return ICERR_BADPARAM;
+ if (info->cvinfo==NULL)
+ {
+ ERR("ICM_DECOMPRESSEX sent after ICM_DECOMPRESS_END\n");
+ return ICERR_BADPARAM;
+ }
+
+ /* FIXME: flags are ignored */
+
+ width = icd->lpbiSrc->biWidth;
+ height = icd->lpbiSrc->biHeight;
+
+ decode_cinepak(info->cvinfo, icd->lpSrc, icd->lpbiSrc->biSizeImage,
+ icd->lpDst, width, height, info->bits_per_pixel);
+
+ return ICERR_OK;
+}
+
+static LRESULT ICCVID_Close( ICCVID_Info *info )
+{
+ if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) )
+ return 0;
+ if( info->cvinfo )
+ free_cvinfo( info->cvinfo );
+ heap_free( info );
+ return 1;
+}
+
+static LRESULT ICCVID_GetInfo( ICCVID_Info *info, ICINFO *icinfo, DWORD dwSize )
+{
+ if (!icinfo) return sizeof(ICINFO);
+ if (dwSize < sizeof(ICINFO)) return 0;
+
+ icinfo->dwSize = sizeof(ICINFO);
+ icinfo->fccType = ICTYPE_VIDEO;
+ icinfo->fccHandler = info ? info->dwMagic : ICCVID_MAGIC;
+ icinfo->dwFlags = 0;
+ icinfo->dwVersion = ICVERSION;
+ icinfo->dwVersionICM = ICVERSION;
+
+ LoadStringW(ICCVID_hModule, IDS_NAME, icinfo->szName, sizeof(icinfo->szName)/sizeof(WCHAR));
+ LoadStringW(ICCVID_hModule, IDS_DESCRIPTION, icinfo->szDescription, sizeof(icinfo->szDescription)/sizeof(WCHAR));
+ /* msvfw32 will fill icinfo->szDriver for us */
+
+ return sizeof(ICINFO);
+}
+
+static LRESULT ICCVID_DecompressEnd( ICCVID_Info *info )
+{
+ if( info->cvinfo )
+ {
+ free_cvinfo( info->cvinfo );
+ info->cvinfo = NULL;
+ }
+ return ICERR_OK;
+}
+
+LRESULT WINAPI ICCVID_DriverProc( DWORD_PTR dwDriverId, HDRVR hdrvr, UINT msg,
+ LPARAM lParam1, LPARAM lParam2)
+{
+ ICCVID_Info *info = (ICCVID_Info *) dwDriverId;
+
+ TRACE("%ld %p %d %ld %ld\n", dwDriverId, hdrvr, msg, lParam1, lParam2);
+
+ switch( msg )
+ {
+ case DRV_LOAD:
+ TRACE("Loaded\n");
+ return 1;
+ case DRV_ENABLE:
+ return 0;
+ case DRV_DISABLE:
+ return 0;
+ case DRV_FREE:
+ return 0;
+
+ case DRV_OPEN:
+ {
+ ICINFO *icinfo = (ICINFO *)lParam2;
+
+ TRACE("Opened\n");
+
+ if (icinfo && icinfo->fccType != ICTYPE_VIDEO) return 0;
+
+ info = heap_alloc( sizeof (ICCVID_Info) );
+ if( info )
+ {
+ info->dwMagic = ICCVID_MAGIC;
+ info->cvinfo = NULL;
+ }
+ return (LRESULT) info;
+ }
+
+ case DRV_CLOSE:
+ return ICCVID_Close( info );
+
+ case ICM_GETINFO:
+ return ICCVID_GetInfo( info, (ICINFO *)lParam1, (DWORD)lParam2 );
+
+ case ICM_DECOMPRESS_QUERY:
+ return ICCVID_DecompressQuery( info, (LPBITMAPINFO) lParam1,
+ (LPBITMAPINFO) lParam2 );
+ case ICM_DECOMPRESS_GET_FORMAT:
+ return ICCVID_DecompressGetFormat( info, (LPBITMAPINFO) lParam1,
+ (LPBITMAPINFO) lParam2 );
+ case ICM_DECOMPRESS_BEGIN:
+ return ICCVID_DecompressBegin( info, (LPBITMAPINFO) lParam1,
+ (LPBITMAPINFO) lParam2 );
+ case ICM_DECOMPRESS:
+ return ICCVID_Decompress( info, (ICDECOMPRESS*) lParam1,
+ (DWORD) lParam2 );
+ case ICM_DECOMPRESSEX:
+ return ICCVID_DecompressEx( info, (ICDECOMPRESSEX*) lParam1,
+ (DWORD) lParam2 );
+
+ case ICM_DECOMPRESS_END:
+ return ICCVID_DecompressEnd( info );
+
+ case ICM_COMPRESS_QUERY:
+ FIXME("compression not implemented\n");
+ return ICERR_BADFORMAT;
+
+ case ICM_CONFIGURE:
+ return ICERR_UNSUPPORTED;
+
+ default:
+ FIXME("Unknown message: %04x %ld %ld\n", msg, lParam1, lParam2);
+ }
+ return ICERR_UNSUPPORTED;
+}
+
+BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
+{
+ TRACE("(%p,%d,%p)\n", hModule, dwReason, lpReserved);
+
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hModule);
+ ICCVID_hModule = hModule;
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
diff --git a/reactos/dll/win32/iccvid/iccvid.rbuild b/reactos/dll/win32/iccvid/iccvid.rbuild
new file mode 100644
index 00000000000..8c73f6f6771
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid.rbuild
@@ -0,0 +1,12 @@
+
+
+ .
+ include/reactos/wine
+
+ iccvid.c
+ rsrc.rc
+ wine
+ user32
+ kernel32
+ ntdll
+
\ No newline at end of file
diff --git a/reactos/dll/win32/iccvid/iccvid.spec b/reactos/dll/win32/iccvid/iccvid.spec
new file mode 100644
index 00000000000..e77601d46db
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid.spec
@@ -0,0 +1 @@
+@ stdcall -private DriverProc(long long long long long) ICCVID_DriverProc
diff --git a/reactos/dll/win32/iccvid/iccvid_Da.rc b/reactos/dll/win32/iccvid/iccvid_Da.rc
new file mode 100644
index 00000000000..185b1bb92ab
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_Da.rc
@@ -0,0 +1,27 @@
+/*
+ * Danish resources for iccvid
+ *
+ * Copyright 2008 Jens Albretsen
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_DANISH, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "Cinepak videokodeks"
+ IDS_DESCRIPTION "Cinepak videokodeks"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_De.rc b/reactos/dll/win32/iccvid/iccvid_De.rc
new file mode 100644
index 00000000000..c101f3ad714
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_De.rc
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ * Copyright 2005 Henning Gerhardt
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "Cinepak Video Codec"
+ IDS_DESCRIPTION "Cinepak Video Codec"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_En.rc b/reactos/dll/win32/iccvid/iccvid_En.rc
new file mode 100644
index 00000000000..c71b0a449a0
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_En.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "Cinepak Video codec"
+ IDS_DESCRIPTION "Cinepak Video codec"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_Fr.rc b/reactos/dll/win32/iccvid/iccvid_Fr.rc
new file mode 100644
index 00000000000..4d276e68a15
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_Fr.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2006 Jonathan Ernst
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "codec vidéo Cinepak"
+ IDS_DESCRIPTION "codec vidéo Cinepak"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_Hu.rc b/reactos/dll/win32/iccvid/iccvid_Hu.rc
new file mode 100644
index 00000000000..b24cf8eaf25
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_Hu.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2006 Andras Kovacs
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "Cinepak Video kodek"
+ IDS_DESCRIPTION "Cinepak Video kodek"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_Ko.rc b/reactos/dll/win32/iccvid/iccvid_Ko.rc
new file mode 100644
index 00000000000..0cfbe3ea95d
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_Ko.rc
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ * Copyright 2005 YunSomg Hwang
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "½Ã³×ÆÑ ºñµð¿À ÄÚµ¦"
+ IDS_DESCRIPTION "½Ã³×ÆÑ ºñµð¿À ÄÚµ¦"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_Nl.rc b/reactos/dll/win32/iccvid/iccvid_Nl.rc
new file mode 100644
index 00000000000..0c58dd16d85
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_Nl.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2008 Frans Kool
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "Cinepak Video codec"
+ IDS_DESCRIPTION "Cinepak Video codec"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_No.rc b/reactos/dll/win32/iccvid/iccvid_No.rc
new file mode 100644
index 00000000000..dd64108523b
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_No.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2005 Alexander N. Sørnes
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "Cinepak-videokodek"
+ IDS_DESCRIPTION "Cinepak-videokodek"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_Pl.rc b/reactos/dll/win32/iccvid/iccvid_Pl.rc
new file mode 100644
index 00000000000..e276e8703a1
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_Pl.rc
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ * Copyright 2006 Mikolaj Zalewski
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "Kodek Cinepak Video"
+ IDS_DESCRIPTION "Kodek Cinepak Video"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_Pt.rc b/reactos/dll/win32/iccvid/iccvid_Pt.rc
new file mode 100644
index 00000000000..5e4ad5cabd3
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_Pt.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2008 Ricardo Filipe
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "Codec Video Cinepak"
+ IDS_DESCRIPTION "Codec Video Cinepak"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_Ro.rc b/reactos/dll/win32/iccvid/iccvid_Ro.rc
new file mode 100644
index 00000000000..85cb1da2d38
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_Ro.rc
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ * Copyright 2008 Michael Stefaniuc
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "Codecul Cinepak Video"
+ IDS_DESCRIPTION "Codecul Cinepak Video"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_Ru.rc b/reactos/dll/win32/iccvid/iccvid_Ru.rc
new file mode 100644
index 00000000000..c78ee72ff16
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_Ru.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2008 Vitaliy Margolen
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "Âèäåî êîäåð-äåêîäåð Cinepak"
+ IDS_DESCRIPTION "Âèäåî êîäåð-äåêîäåð Cinepak"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_Si.rc b/reactos/dll/win32/iccvid/iccvid_Si.rc
new file mode 100644
index 00000000000..82bbd05fee4
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_Si.rc
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 Rok Mandeljc
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#pragma code_page(65001)
+
+LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "Cinepak Video kodek"
+ IDS_DESCRIPTION "Cinepak Video kodek"
+}
+
+#pragma code_page(default)
diff --git a/reactos/dll/win32/iccvid/iccvid_Sv.rc b/reactos/dll/win32/iccvid/iccvid_Sv.rc
new file mode 100644
index 00000000000..55eb468125b
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_Sv.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2007 Daniel Nylander
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "Cinepak videokodek"
+ IDS_DESCRIPTION "Cinepak videokodek"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_Tr.rc b/reactos/dll/win32/iccvid/iccvid_Tr.rc
new file mode 100644
index 00000000000..929f44fcbb2
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_Tr.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2006 Fatih Aþýcý
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "Cinepak Vidyo çözücü"
+ IDS_DESCRIPTION "Cinepak Vidyo çözücü"
+}
diff --git a/reactos/dll/win32/iccvid/iccvid_private.h b/reactos/dll/win32/iccvid/iccvid_private.h
new file mode 100644
index 00000000000..8400e775207
--- /dev/null
+++ b/reactos/dll/win32/iccvid/iccvid_private.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __ICCVID_PRIVATE_H
+#define __ICCVID_PRIVATE_H
+
+#define IDS_NAME 100
+#define IDS_DESCRIPTION 101
+
+#endif /* __ICCVID_PRIVATE_H */
diff --git a/reactos/dll/win32/iccvid/rsrc.rc b/reactos/dll/win32/iccvid/rsrc.rc
new file mode 100644
index 00000000000..e7512207c82
--- /dev/null
+++ b/reactos/dll/win32/iccvid/rsrc.rc
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "windef.h"
+#include "iccvid_private.h"
+
+#include "iccvid_Da.rc"
+#include "iccvid_De.rc"
+#include "iccvid_En.rc"
+#include "iccvid_Fr.rc"
+#include "iccvid_Hu.rc"
+#include "iccvid_Ko.rc"
+#include "iccvid_Nl.rc"
+#include "iccvid_No.rc"
+#include "iccvid_Pl.rc"
+#include "iccvid_Pt.rc"
+#include "iccvid_Ro.rc"
+#include "iccvid_Ru.rc"
+#include "iccvid_Si.rc"
+#include "iccvid_Sv.rc"
+#include "iccvid_Tr.rc"
diff --git a/reactos/dll/win32/imaadp32.acm/imaadp32.acm.rbuild b/reactos/dll/win32/imaadp32.acm/imaadp32.acm.rbuild
new file mode 100644
index 00000000000..8f24f00fda5
--- /dev/null
+++ b/reactos/dll/win32/imaadp32.acm/imaadp32.acm.rbuild
@@ -0,0 +1,12 @@
+
+
+ .
+ include/reactos/wine
+
+ imaadp32.c
+ wine
+ winmm
+ user32
+ kernel32
+ ntdll
+
diff --git a/reactos/dll/win32/imaadp32.acm/imaadp32.acm.spec b/reactos/dll/win32/imaadp32.acm/imaadp32.acm.spec
new file mode 100644
index 00000000000..09473e9d6a6
--- /dev/null
+++ b/reactos/dll/win32/imaadp32.acm/imaadp32.acm.spec
@@ -0,0 +1 @@
+@ stdcall -private DriverProc (long long long long long) ADPCM_DriverProc
diff --git a/reactos/dll/win32/imaadp32.acm/imaadp32.c b/reactos/dll/win32/imaadp32.acm/imaadp32.c
new file mode 100644
index 00000000000..dd3cc5d108e
--- /dev/null
+++ b/reactos/dll/win32/imaadp32.acm/imaadp32.c
@@ -0,0 +1,926 @@
+/*
+ * IMA ADPCM handling
+ *
+ * Copyright (C) 2001,2002 Eric Pouech
+ *
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include
+#include
+#include
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "mmsystem.h"
+#include "mmreg.h"
+#include "msacm.h"
+#include "msacmdrv.h"
+#include "wine/debug.h"
+
+/* see http://www.pcisys.net/~melanson/codecs/adpcm.txt for the details */
+
+WINE_DEFAULT_DEBUG_CHANNEL(adpcm);
+
+/***********************************************************************
+ * ADPCM_drvOpen
+ */
+static LRESULT ADPCM_drvOpen(LPCSTR str)
+{
+ return 1;
+}
+
+/***********************************************************************
+ * ADPCM_drvClose
+ */
+static LRESULT ADPCM_drvClose(DWORD_PTR dwDevID)
+{
+ return 1;
+}
+
+typedef struct tagAcmAdpcmData
+{
+ void (*convert)(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
+ /* IMA encoding only */
+ BYTE stepIndexL;
+ BYTE stepIndexR;
+ /* short sample; */
+} AcmAdpcmData;
+
+/* table to list all supported formats... those are the basic ones. this
+ * also helps given a unique index to each of the supported formats
+ */
+typedef struct
+{
+ int nChannels;
+ int nBits;
+ int rate;
+} Format;
+
+static const Format PCM_Formats[] =
+{
+ {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000},
+ {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025},
+ {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050},
+ {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100},
+};
+
+static const Format ADPCM_Formats[] =
+{
+ {1, 4, 8000}, {2, 4, 8000}, {1, 4, 11025}, {2, 4, 11025},
+ {1, 4, 22050}, {2, 4, 22050}, {1, 4, 44100}, {2, 4, 44100},
+};
+
+#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
+#define NUM_ADPCM_FORMATS (sizeof(ADPCM_Formats) / sizeof(ADPCM_Formats[0]))
+
+/***********************************************************************
+ * ADPCM_GetFormatIndex
+ */
+static DWORD ADPCM_GetFormatIndex(const WAVEFORMATEX *wfx)
+{
+ int i, hi;
+ const Format* fmts;
+
+ switch (wfx->wFormatTag)
+ {
+ case WAVE_FORMAT_PCM:
+ hi = NUM_PCM_FORMATS;
+ fmts = PCM_Formats;
+ break;
+ case WAVE_FORMAT_IMA_ADPCM:
+ hi = NUM_ADPCM_FORMATS;
+ fmts = ADPCM_Formats;
+ break;
+ default:
+ return 0xFFFFFFFF;
+ }
+
+ for (i = 0; i < hi; i++)
+ {
+ if (wfx->nChannels == fmts[i].nChannels &&
+ wfx->nSamplesPerSec == fmts[i].rate &&
+ wfx->wBitsPerSample == fmts[i].nBits)
+ return i;
+ }
+
+ return 0xFFFFFFFF;
+}
+
+/***********************************************************************
+ * R16
+ *
+ * Read a 16 bit sample (correctly handles endianess)
+ */
+static inline short R16(const unsigned char* src)
+{
+ return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
+}
+
+/***********************************************************************
+ * W16
+ *
+ * Write a 16 bit sample (correctly handles endianess)
+ */
+static inline void W16(unsigned char* dst, short s)
+{
+ dst[0] = LOBYTE(s);
+ dst[1] = HIBYTE(s);
+}
+
+/* IMA (or DVI) APDCM codec routines */
+
+static const unsigned IMA_StepTable[89] =
+{
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 16, 17, 19, 21, 23, 25, 28, 31,
+ 34, 37, 41, 45, 50, 55, 60, 66,
+ 73, 80, 88, 97, 107, 118, 130, 143,
+ 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658,
+ 724, 796, 876, 963, 1060, 1166, 1282, 1411,
+ 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
+ 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
+ 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
+ 32767
+};
+
+static const int IMA_IndexTable[16] =
+{
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8
+};
+
+static inline void clamp_step_index(int* stepIndex)
+{
+ if (*stepIndex < 0 ) *stepIndex = 0;
+ if (*stepIndex > 88) *stepIndex = 88;
+}
+
+static inline void clamp_sample(int* sample)
+{
+ if (*sample < -32768) *sample = -32768;
+ if (*sample > 32767) *sample = 32767;
+}
+
+static inline void process_nibble(unsigned char code, int* stepIndex, int* sample)
+{
+ unsigned step;
+ int diff;
+
+ code &= 0x0F;
+
+ step = IMA_StepTable[*stepIndex];
+ diff = step >> 3;
+ if (code & 1) diff += step >> 2;
+ if (code & 2) diff += step >> 1;
+ if (code & 4) diff += step;
+ if (code & 8) *sample -= diff;
+ else *sample += diff;
+ clamp_sample(sample);
+ *stepIndex += IMA_IndexTable[code];
+ clamp_step_index(stepIndex);
+}
+
+static inline unsigned char generate_nibble(int in, int* stepIndex, int* sample)
+{
+ int effdiff, diff = in - *sample;
+ unsigned step;
+ unsigned char code;
+
+ if (diff < 0)
+ {
+ diff = -diff;
+ code = 8;
+ }
+ else
+ {
+ code = 0;
+ }
+
+ step = IMA_StepTable[*stepIndex];
+ effdiff = (step >> 3);
+ if (diff >= step)
+ {
+ code |= 4;
+ diff -= step;
+ effdiff += step;
+ }
+ step >>= 1;
+ if (diff >= step)
+ {
+ code |= 2;
+ diff -= step;
+ effdiff += step;
+ }
+ step >>= 1;
+ if (diff >= step)
+ {
+ code |= 1;
+ effdiff += step;
+ }
+ if (code & 8) *sample -= effdiff;
+ else *sample += effdiff;
+ clamp_sample(sample);
+ *stepIndex += IMA_IndexTable[code];
+ clamp_step_index(stepIndex);
+ return code;
+}
+
+static void cvtSSima16K(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char* src, LPDWORD nsrc,
+ unsigned char* dst, LPDWORD ndst)
+{
+ int i;
+ int sampleL, sampleR;
+ int stepIndexL, stepIndexR;
+ int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
+ int nsamp;
+ /* compute the number of entire blocks we can decode...
+ * it's the min of the number of entire blocks in source buffer and the number
+ * of entire blocks in destination buffer
+ */
+ DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
+ *ndst / (nsamp_blk * 2 * 2));
+
+ *nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
+ *ndst = nblock * (nsamp_blk * 2 * 2);
+
+ nsamp_blk--; /* remove the sample in block header */
+ for (; nblock > 0; nblock--)
+ {
+ const unsigned char* in_src = src;
+
+ /* handle headers first */
+ sampleL = R16(src);
+ stepIndexL = (unsigned)*(src + 2);
+ clamp_step_index(&stepIndexL);
+ src += 4;
+ W16(dst, sampleL); dst += 2;
+
+ sampleR = R16(src);
+ stepIndexR = (unsigned)*(src + 2);
+ clamp_step_index(&stepIndexR);
+ src += 4;
+ W16(dst, sampleR); dst += 2;
+
+ for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ process_nibble(*src, &stepIndexL, &sampleL);
+ W16(dst + (2 * i + 0) * 4 + 0, sampleL);
+ process_nibble(*src++ >> 4, &stepIndexL, &sampleL);
+ W16(dst + (2 * i + 1) * 4 + 0, sampleL);
+ }
+ for (i = 0; i < 4; i++)
+ {
+ process_nibble(*src , &stepIndexR, &sampleR);
+ W16(dst + (2 * i + 0) * 4 + 2, sampleR);
+ process_nibble(*src++ >>4, &stepIndexR, &sampleR);
+ W16(dst + (2 * i + 1) * 4 + 2, sampleR);
+ }
+ dst += 32;
+ }
+ /* we have now to realign the source pointer on block */
+ src = in_src + adsi->pwfxSrc->nBlockAlign;
+ }
+}
+
+static void cvtMMima16K(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char* src, LPDWORD nsrc,
+ unsigned char* dst, LPDWORD ndst)
+{
+ int sample;
+ int stepIndex;
+ int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
+ int nsamp;
+ /* compute the number of entire blocks we can decode...
+ * it's the min of the number of entire blocks in source buffer and the number
+ * of entire blocks in destination buffer
+ */
+ DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
+ *ndst / (nsamp_blk * 2));
+
+ *nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
+ *ndst = nblock * nsamp_blk * 2;
+
+ nsamp_blk--; /* remove the sample in block header */
+ for (; nblock > 0; nblock--)
+ {
+ const unsigned char* in_src = src;
+
+ /* handle header first */
+ sample = R16(src);
+ stepIndex = (unsigned)*(src + 2);
+ clamp_step_index(&stepIndex);
+ src += 4;
+ W16(dst, sample); dst += 2;
+
+ for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
+ {
+ process_nibble(*src, &stepIndex, &sample);
+ W16(dst, sample); dst += 2;
+ process_nibble(*src++ >> 4, &stepIndex, &sample);
+ W16(dst, sample); dst += 2;
+ }
+ /* we have now to realign the source pointer on block */
+ src = in_src + adsi->pwfxSrc->nBlockAlign;
+ }
+}
+
+static void cvtSS16imaK(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char* src, LPDWORD nsrc,
+ unsigned char* dst, LPDWORD ndst)
+{
+ int stepIndexL, stepIndexR;
+ int sampleL, sampleR;
+ BYTE code1, code2;
+ int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
+ int i, nsamp;
+ /* compute the number of entire blocks we can decode...
+ * it's the min of the number of entire blocks in source buffer and the number
+ * of entire blocks in destination buffer
+ */
+ DWORD nblock = min(*nsrc / (nsamp_blk * 2 * 2),
+ *ndst / adsi->pwfxDst->nBlockAlign);
+
+ *nsrc = nblock * (nsamp_blk * 2 * 2);
+ *ndst = nblock * adsi->pwfxDst->nBlockAlign;
+
+ stepIndexL = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL;
+ stepIndexR = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexR;
+
+ nsamp_blk--; /* so that we won't count the sample in header while filling the block */
+
+ for (; nblock > 0; nblock--)
+ {
+ unsigned char* in_dst = dst;
+
+ /* generate header */
+ sampleL = R16(src); src += 2;
+ W16(dst, sampleL); dst += 2;
+ *dst = (unsigned char)(unsigned)stepIndexL;
+ dst += 2;
+
+ sampleR = R16(src); src += 2;
+ W16(dst, sampleR); dst += 2;
+ *dst = (unsigned char)(unsigned)stepIndexR;
+ dst += 2;
+
+ for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 0),
+ &stepIndexL, &sampleL);
+ code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 0),
+ &stepIndexL, &sampleL);
+ *dst++ = (code1 << 4) | code2;
+ }
+ for (i = 0; i < 4; i++)
+ {
+ code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 1),
+ &stepIndexR, &sampleR);
+ code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 1),
+ &stepIndexR, &sampleR);
+ *dst++ = (code1 << 4) | code2;
+ }
+ src += 32;
+ }
+ dst = in_dst + adsi->pwfxDst->nBlockAlign;
+ }
+ ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndexL;
+ ((AcmAdpcmData*)adsi->dwDriver)->stepIndexR = stepIndexR;
+}
+
+static void cvtMM16imaK(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char* src, LPDWORD nsrc,
+ unsigned char* dst, LPDWORD ndst)
+{
+ int stepIndex;
+ int sample;
+ BYTE code1, code2;
+ int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
+ int nsamp;
+ /* compute the number of entire blocks we can decode...
+ * it's the min of the number of entire blocks in source buffer and the number
+ * of entire blocks in destination buffer
+ */
+ DWORD nblock = min(*nsrc / (nsamp_blk * 2),
+ *ndst / adsi->pwfxDst->nBlockAlign);
+
+ *nsrc = nblock * (nsamp_blk * 2);
+ *ndst = nblock * adsi->pwfxDst->nBlockAlign;
+
+ stepIndex = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL;
+ nsamp_blk--; /* so that we won't count the sample in header while filling the block */
+
+ for (; nblock > 0; nblock--)
+ {
+ unsigned char* in_dst = dst;
+
+ /* generate header */
+ /* FIXME: what about the last effective sample from previous block ??? */
+ /* perhaps something like:
+ * sample += R16(src);
+ * clamp_sample(sample);
+ * and with :
+ * + saving the sample in adsi->dwDriver when all blocks are done
+ + + reset should set the field in adsi->dwDriver to 0 too
+ */
+ sample = R16(src); src += 2;
+ W16(dst, sample); dst += 2;
+ *dst = (unsigned char)(unsigned)stepIndex;
+ dst += 2;
+
+ for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
+ {
+ code1 = generate_nibble(R16(src), &stepIndex, &sample);
+ src += 2;
+ code2 = generate_nibble(R16(src), &stepIndex, &sample);
+ src += 2;
+ *dst++ = (code1 << 4) | code2;
+ }
+ dst = in_dst + adsi->pwfxDst->nBlockAlign;
+ }
+ ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndex;
+}
+
+/***********************************************************************
+ * ADPCM_DriverDetails
+ *
+ */
+static LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add)
+{
+ add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
+ add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
+ add->wMid = 0x1;
+ add->wPid = 0x22;
+ add->vdwACM = 0x3320000;
+ add->vdwDriver = 0x04000000;
+ add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
+ add->cFormatTags = 2; /* PCM, IMA ADPCM */
+ add->cFilterTags = 0;
+ add->hicon = NULL;
+ MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM", -1,
+ add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM CODEC", -1,
+ add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
+ add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
+ add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
+ add->szFeatures[0] = 0;
+
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * ADPCM_FormatTagDetails
+ *
+ */
+static LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
+{
+ static const WCHAR szPcm[]={'P','C','M',0};
+ static const WCHAR szImaAdPcm[]={'I','M','A',' ','A','D','P','C','M',0};
+
+ switch (dwQuery)
+ {
+ case ACM_FORMATTAGDETAILSF_INDEX:
+ if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE;
+ break;
+ case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
+ if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
+ {
+ aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_IMA_ADPCM is bigger than PCM */
+ break;
+ }
+ /* fall thru */
+ case ACM_FORMATTAGDETAILSF_FORMATTAG:
+ switch (aftd->dwFormatTag)
+ {
+ case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
+ case WAVE_FORMAT_IMA_ADPCM: aftd->dwFormatTagIndex = 1; break;
+ default: return ACMERR_NOTPOSSIBLE;
+ }
+ break;
+ default:
+ WARN("Unsupported query %08x\n", dwQuery);
+ return MMSYSERR_NOTSUPPORTED;
+ }
+
+ aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
+ switch (aftd->dwFormatTagIndex)
+ {
+ case 0:
+ aftd->dwFormatTag = WAVE_FORMAT_PCM;
+ aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
+ aftd->cStandardFormats = NUM_PCM_FORMATS;
+ lstrcpyW(aftd->szFormatTag, szPcm);
+ break;
+ case 1:
+ aftd->dwFormatTag = WAVE_FORMAT_IMA_ADPCM;
+ aftd->cbFormatSize = sizeof(IMAADPCMWAVEFORMAT);
+ aftd->cStandardFormats = NUM_ADPCM_FORMATS;
+ lstrcpyW(aftd->szFormatTag, szImaAdPcm);
+ break;
+ }
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * ADPCM_FormatDetails
+ *
+ */
+static LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
+{
+ switch (dwQuery)
+ {
+ case ACM_FORMATDETAILSF_FORMAT:
+ if (ADPCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
+ break;
+ case ACM_FORMATDETAILSF_INDEX:
+ afd->pwfx->wFormatTag = afd->dwFormatTag;
+ switch (afd->dwFormatTag)
+ {
+ case WAVE_FORMAT_PCM:
+ if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
+ afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
+ afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
+ afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
+ /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
+ * afd->pwfx->cbSize = 0;
+ */
+ afd->pwfx->nBlockAlign =
+ (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
+ afd->pwfx->nAvgBytesPerSec =
+ afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
+ break;
+ case WAVE_FORMAT_IMA_ADPCM:
+ if (afd->dwFormatIndex >= NUM_ADPCM_FORMATS) return ACMERR_NOTPOSSIBLE;
+ afd->pwfx->nChannels = ADPCM_Formats[afd->dwFormatIndex].nChannels;
+ afd->pwfx->nSamplesPerSec = ADPCM_Formats[afd->dwFormatIndex].rate;
+ afd->pwfx->wBitsPerSample = ADPCM_Formats[afd->dwFormatIndex].nBits;
+ afd->pwfx->nBlockAlign = 1024;
+ /* we got 4 bits per sample */
+ afd->pwfx->nAvgBytesPerSec =
+ (afd->pwfx->nSamplesPerSec * 4) / 8;
+ if (afd->cbwfx >= sizeof(WAVEFORMATEX))
+ afd->pwfx->cbSize = sizeof(WORD);
+ if (afd->cbwfx >= sizeof(IMAADPCMWAVEFORMAT))
+ ((IMAADPCMWAVEFORMAT*)afd->pwfx)->wSamplesPerBlock = (1024 - 4 * afd->pwfx->nChannels) * (2 / afd->pwfx->nChannels) + 1;
+ break;
+ default:
+ WARN("Unsupported tag %08x\n", afd->dwFormatTag);
+ return MMSYSERR_INVALPARAM;
+ }
+ break;
+ default:
+ WARN("Unsupported query %08x\n", dwQuery);
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
+ afd->szFormat[0] = 0; /* let MSACM format this for us... */
+
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * ADPCM_FormatSuggest
+ *
+ */
+static LRESULT ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
+{
+ /* some tests ... */
+ if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
+ adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
+ ADPCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
+ /* FIXME: should do those tests against the real size (according to format tag */
+
+ /* If no suggestion for destination, then copy source value */
+ if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
+ adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
+ if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
+ adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
+
+ if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
+ {
+ if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
+ adfs->pwfxDst->wBitsPerSample = 4;
+ else
+ adfs->pwfxDst->wBitsPerSample = 16;
+ }
+ if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
+ {
+ if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
+ adfs->pwfxDst->wFormatTag = WAVE_FORMAT_IMA_ADPCM;
+ else
+ adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
+ }
+
+ /* check if result is ok */
+ if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
+
+ /* recompute other values */
+ switch (adfs->pwfxDst->wFormatTag)
+ {
+ case WAVE_FORMAT_PCM:
+ adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
+ adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
+ break;
+ case WAVE_FORMAT_IMA_ADPCM:
+ adfs->pwfxDst->nBlockAlign = 1024;
+ /* FIXME: not handling header overhead */
+ adfs->pwfxDst->nAvgBytesPerSec = ((adfs->pwfxDst->nSamplesPerSec * 4) / 8) * adfs->pwfxSrc->nChannels;
+ ((IMAADPCMWAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock = (1024 - 4 * adfs->pwfxSrc->nChannels) * (2 / adfs->pwfxSrc->nChannels) + 1;
+ TRACE("setting spb=%u\n", ((IMAADPCMWAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock);
+ break;
+ default:
+ FIXME("\n");
+ break;
+ }
+
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * ADPCM_Reset
+ *
+ */
+static void ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi, AcmAdpcmData* aad)
+{
+ aad->stepIndexL = aad->stepIndexR = 0;
+}
+
+/***********************************************************************
+ * ADPCM_StreamOpen
+ *
+ */
+static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
+{
+ AcmAdpcmData* aad;
+ unsigned nspb;
+
+ assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
+
+ if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
+ ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
+ return ACMERR_NOTPOSSIBLE;
+
+ aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData));
+ if (aad == 0) return MMSYSERR_NOMEM;
+
+ adsi->dwDriver = (DWORD_PTR)aad;
+
+ if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
+ {
+ goto theEnd;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
+ {
+ /* resampling or mono <=> stereo not available
+ * ADPCM algo only define 16 bit per sample output
+ */
+ if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
+ adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
+ adsi->pwfxDst->wBitsPerSample != 16)
+ goto theEnd;
+
+ nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
+ TRACE("spb=%u\n", nspb);
+
+ /* we check that in a block, after the header, samples are present on
+ * 4-sample packet pattern
+ * we also check that the block alignment is bigger than the expected size
+ */
+ if (((nspb - 1) & 3) != 0) goto theEnd;
+ if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign)
+ goto theEnd;
+
+ /* adpcm decoding... */
+ if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 2)
+ aad->convert = cvtSSima16K;
+ if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 1)
+ aad->convert = cvtMMima16K;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
+ {
+ if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
+ adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
+ adsi->pwfxSrc->wBitsPerSample != 16)
+ goto theEnd;
+
+ nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
+ TRACE("spb=%u\n", nspb);
+
+ /* we check that in a block, after the header, samples are present on
+ * 4-sample packet pattern
+ * we also check that the block alignment is bigger than the expected size
+ */
+ if (((nspb - 1) & 3) != 0) goto theEnd;
+ if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign)
+ goto theEnd;
+
+ /* adpcm coding... */
+ if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2)
+ aad->convert = cvtSS16imaK;
+ if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1)
+ aad->convert = cvtMM16imaK;
+ }
+ else goto theEnd;
+ ADPCM_Reset(adsi, aad);
+
+ return MMSYSERR_NOERROR;
+
+ theEnd:
+ HeapFree(GetProcessHeap(), 0, aad);
+ adsi->dwDriver = 0L;
+ return MMSYSERR_NOTSUPPORTED;
+}
+
+/***********************************************************************
+ * ADPCM_StreamClose
+ *
+ */
+static LRESULT ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
+{
+ HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * ADPCM_StreamSize
+ *
+ */
+static LRESULT ADPCM_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss)
+{
+ switch (adss->fdwSize)
+ {
+ case ACM_STREAMSIZEF_DESTINATION:
+ /* cbDstLength => cbSrcLength */
+ if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
+ {
+ /* don't take block overhead into account, doesn't matter too much */
+ adss->cbSrcLength = adss->cbDstLength * 4;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
+ {
+ FIXME("misses the block header overhead\n");
+ adss->cbSrcLength = 256 + adss->cbDstLength / 4;
+ }
+ else
+ {
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ break;
+ case ACM_STREAMSIZEF_SOURCE:
+ /* cbSrcLength => cbDstLength */
+ if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
+ {
+ FIXME("misses the block header overhead\n");
+ adss->cbDstLength = 256 + adss->cbSrcLength / 4;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
+ {
+ /* don't take block overhead into account, doesn't matter too much */
+ adss->cbDstLength = adss->cbSrcLength * 4;
+ }
+ else
+ {
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ break;
+ default:
+ WARN("Unsupported query %08x\n", adss->fdwSize);
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * ADPCM_StreamConvert
+ *
+ */
+static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
+{
+ AcmAdpcmData* aad = (AcmAdpcmData*)adsi->dwDriver;
+ DWORD nsrc = adsh->cbSrcLength;
+ DWORD ndst = adsh->cbDstLength;
+
+ if (adsh->fdwConvert &
+ ~(ACM_STREAMCONVERTF_BLOCKALIGN|
+ ACM_STREAMCONVERTF_END|
+ ACM_STREAMCONVERTF_START))
+ {
+ FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
+ }
+ /* ACM_STREAMCONVERTF_BLOCKALIGN
+ * currently all conversions are block aligned, so do nothing for this flag
+ * ACM_STREAMCONVERTF_END
+ * no pending data, so do nothing for this flag
+ */
+ if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
+ {
+ ADPCM_Reset(adsi, aad);
+ }
+
+ aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
+ adsh->cbSrcLengthUsed = nsrc;
+ adsh->cbDstLengthUsed = ndst;
+
+ return MMSYSERR_NOERROR;
+}
+
+/**************************************************************************
+ * ADPCM_DriverProc [exported]
+ */
+LRESULT CALLBACK ADPCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
+ LPARAM dwParam1, LPARAM dwParam2)
+{
+ TRACE("(%08lx %p %04x %08lx %08lx);\n",
+ dwDevID, hDriv, wMsg, dwParam1, dwParam2);
+
+ switch (wMsg)
+ {
+ case DRV_LOAD: return 1;
+ case DRV_FREE: return 1;
+ case DRV_OPEN: return ADPCM_drvOpen((LPSTR)dwParam1);
+ case DRV_CLOSE: return ADPCM_drvClose(dwDevID);
+ case DRV_ENABLE: return 1;
+ case DRV_DISABLE: return 1;
+ case DRV_QUERYCONFIGURE: return 1;
+ case DRV_CONFIGURE: MessageBoxA(0, "MSACM IMA ADPCM filter !", "Wine Driver", MB_OK); return 1;
+ case DRV_INSTALL: return DRVCNF_RESTART;
+ case DRV_REMOVE: return DRVCNF_RESTART;
+
+ case ACMDM_DRIVER_NOTIFY:
+ /* no caching from other ACM drivers is done so far */
+ return MMSYSERR_NOERROR;
+
+ case ACMDM_DRIVER_DETAILS:
+ return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
+
+ case ACMDM_FORMATTAG_DETAILS:
+ return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
+
+ case ACMDM_FORMAT_DETAILS:
+ return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
+
+ case ACMDM_FORMAT_SUGGEST:
+ return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
+
+ case ACMDM_STREAM_OPEN:
+ return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
+
+ case ACMDM_STREAM_CLOSE:
+ return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
+
+ case ACMDM_STREAM_SIZE:
+ return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
+
+ case ACMDM_STREAM_CONVERT:
+ return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
+
+ case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
+ case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
+ /* this converter is not a hardware driver */
+ case ACMDM_FILTERTAG_DETAILS:
+ case ACMDM_FILTER_DETAILS:
+ /* this converter is not a filter */
+ case ACMDM_STREAM_RESET:
+ /* only needed for asynchronous driver... we aren't, so just say it */
+ return MMSYSERR_NOTSUPPORTED;
+ case ACMDM_STREAM_PREPARE:
+ case ACMDM_STREAM_UNPREPARE:
+ /* nothing special to do here... so don't do anything */
+ return MMSYSERR_NOERROR;
+
+ default:
+ return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
+ }
+}
diff --git a/reactos/dll/win32/msadp32.acm/msadp32.acm.rbuild b/reactos/dll/win32/msadp32.acm/msadp32.acm.rbuild
new file mode 100644
index 00000000000..1be0196a9ee
--- /dev/null
+++ b/reactos/dll/win32/msadp32.acm/msadp32.acm.rbuild
@@ -0,0 +1,12 @@
+
+
+ .
+ include/reactos/wine
+
+ msadp32.c
+ wine
+ winmm
+ user32
+ kernel32
+ ntdll
+
diff --git a/reactos/dll/win32/msadp32.acm/msadp32.acm.spec b/reactos/dll/win32/msadp32.acm/msadp32.acm.spec
new file mode 100644
index 00000000000..09473e9d6a6
--- /dev/null
+++ b/reactos/dll/win32/msadp32.acm/msadp32.acm.spec
@@ -0,0 +1 @@
+@ stdcall -private DriverProc (long long long long long) ADPCM_DriverProc
diff --git a/reactos/dll/win32/msadp32.acm/msadp32.c b/reactos/dll/win32/msadp32.acm/msadp32.c
new file mode 100644
index 00000000000..1c0c840ae83
--- /dev/null
+++ b/reactos/dll/win32/msadp32.acm/msadp32.c
@@ -0,0 +1,811 @@
+/*
+ * MS ADPCM handling
+ *
+ * Copyright (C) 2002 Eric Pouech
+ *
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include
+#include
+#include
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "mmsystem.h"
+#include "mmreg.h"
+#include "msacm.h"
+#include "msacmdrv.h"
+#include "wine/debug.h"
+
+/* see http://www.pcisys.net/~melanson/codecs/adpcm.txt for the details */
+
+WINE_DEFAULT_DEBUG_CHANNEL(adpcm);
+
+/***********************************************************************
+ * ADPCM_drvOpen
+ */
+static LRESULT ADPCM_drvOpen(LPCSTR str)
+{
+ return 1;
+}
+
+/***********************************************************************
+ * ADPCM_drvClose
+ */
+static LRESULT ADPCM_drvClose(DWORD_PTR dwDevID)
+{
+ return 1;
+}
+
+typedef struct tagAcmAdpcmData
+{
+ void (*convert)(const ACMDRVSTREAMINSTANCE *adsi,
+ const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
+} AcmAdpcmData;
+
+/* table to list all supported formats... those are the basic ones. this
+ * also helps given a unique index to each of the supported formats
+ */
+typedef struct
+{
+ int nChannels;
+ int nBits;
+ int rate;
+} Format;
+
+static const Format PCM_Formats[] =
+{
+ {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000},
+ {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025},
+ {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050},
+ {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100},
+};
+
+static const Format ADPCM_Formats[] =
+{
+ {1, 4, 8000}, {2, 4, 8000}, {1, 4, 11025}, {2, 4, 11025},
+ {1, 4, 22050}, {2, 4, 22050}, {1, 4, 44100}, {2, 4, 44100},
+};
+
+#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
+#define NUM_ADPCM_FORMATS (sizeof(ADPCM_Formats) / sizeof(ADPCM_Formats[0]))
+
+static int MS_Delta[] =
+{
+ 230, 230, 230, 230, 307, 409, 512, 614,
+ 768, 614, 512, 409, 307, 230, 230, 230
+};
+
+
+static ADPCMCOEFSET MSADPCM_CoeffSet[] =
+{
+ {256, 0}, {512, -256}, {0, 0}, {192, 64}, {240, 0}, {460, -208}, {392, -232}
+};
+
+/***********************************************************************
+ * ADPCM_GetFormatIndex
+ */
+static DWORD ADPCM_GetFormatIndex(const WAVEFORMATEX* wfx)
+{
+ int i, hi;
+ const Format* fmts;
+
+ switch (wfx->wFormatTag)
+ {
+ case WAVE_FORMAT_PCM:
+ hi = NUM_PCM_FORMATS;
+ fmts = PCM_Formats;
+ break;
+ case WAVE_FORMAT_ADPCM:
+ hi = NUM_ADPCM_FORMATS;
+ fmts = ADPCM_Formats;
+ break;
+ default:
+ return 0xFFFFFFFF;
+ }
+
+ for (i = 0; i < hi; i++)
+ {
+ if (wfx->nChannels == fmts[i].nChannels &&
+ wfx->nSamplesPerSec == fmts[i].rate &&
+ wfx->wBitsPerSample == fmts[i].nBits)
+ return i;
+ }
+
+ switch (wfx->wFormatTag)
+ {
+ case WAVE_FORMAT_PCM:
+ if(3 > wfx->nChannels &&
+ wfx->nChannels > 0 &&
+ wfx->nAvgBytesPerSec == 2 * wfx->nSamplesPerSec * wfx->nChannels &&
+ wfx->nBlockAlign == 2 * wfx->nChannels &&
+ wfx->wBitsPerSample == 16)
+ return hi;
+ break;
+ case WAVE_FORMAT_ADPCM:
+ if(3 > wfx->nChannels &&
+ wfx->nChannels > 0 &&
+ wfx->wBitsPerSample == 4 &&
+ wfx->cbSize == 32)
+ return hi;
+ break;
+ }
+
+ return 0xFFFFFFFF;
+}
+
+static void init_wfx_adpcm(ADPCMWAVEFORMAT* awfx)
+{
+ register WAVEFORMATEX* pwfx = &awfx->wfx;
+
+ /* we assume wFormatTag, nChannels, nSamplesPerSec and wBitsPerSample
+ * have been initialized... */
+
+ if (pwfx->wFormatTag != WAVE_FORMAT_ADPCM) {FIXME("wrong FT\n"); return;}
+ if (ADPCM_GetFormatIndex(pwfx) == 0xFFFFFFFF) {FIXME("wrong fmt\n"); return;}
+
+ switch (pwfx->nSamplesPerSec)
+ {
+ case 8000: pwfx->nBlockAlign = 256 * pwfx->nChannels; break;
+ case 11025: pwfx->nBlockAlign = 256 * pwfx->nChannels; break;
+ case 22050: pwfx->nBlockAlign = 512 * pwfx->nChannels; break;
+ case 44100: pwfx->nBlockAlign = 1024 * pwfx->nChannels; break;
+ default: break;
+ }
+ pwfx->cbSize = 2 * sizeof(WORD) + 7 * sizeof(ADPCMCOEFSET);
+ /* 7 is the size of the block head (which contains two samples) */
+
+ awfx->wSamplesPerBlock = pwfx->nBlockAlign * 2 / pwfx->nChannels - 12;
+ pwfx->nAvgBytesPerSec = (pwfx->nSamplesPerSec * pwfx->nBlockAlign) / awfx->wSamplesPerBlock;
+ awfx->wNumCoef = 7;
+ memcpy(awfx->aCoef, MSADPCM_CoeffSet, 7 * sizeof(ADPCMCOEFSET));
+}
+
+/***********************************************************************
+ * R16
+ *
+ * Read a 16 bit sample (correctly handles endianess)
+ */
+static inline short R16(const unsigned char* src)
+{
+ return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
+}
+
+/***********************************************************************
+ * W16
+ *
+ * Write a 16 bit sample (correctly handles endianess)
+ */
+static inline void W16(unsigned char* dst, short s)
+{
+ dst[0] = LOBYTE(s);
+ dst[1] = HIBYTE(s);
+}
+
+static inline void clamp_sample(int* sample)
+{
+ if (*sample < -32768) *sample = -32768;
+ if (*sample > 32767) *sample = 32767;
+}
+
+static inline void process_nibble(unsigned nibble, int* idelta,
+ int* sample1, int* sample2,
+ const ADPCMCOEFSET* coeff)
+{
+ int sample;
+ int snibble;
+
+ /* nibble is in fact a signed 4 bit integer => propagate sign if needed */
+ snibble = (nibble & 0x08) ? (nibble - 16) : nibble;
+ sample = ((*sample1 * coeff->iCoef1) + (*sample2 * coeff->iCoef2)) / 256 +
+ snibble * *idelta;
+ clamp_sample(&sample);
+
+ *sample2 = *sample1;
+ *sample1 = sample;
+ *idelta = ((MS_Delta[nibble] * *idelta) / 256);
+ if (*idelta < 16) *idelta = 16;
+}
+
+static void cvtSSms16K(const ACMDRVSTREAMINSTANCE *adsi,
+ const unsigned char* src, LPDWORD nsrc,
+ unsigned char* dst, LPDWORD ndst)
+{
+ int ideltaL, ideltaR;
+ int sample1L, sample2L;
+ int sample1R, sample2R;
+ ADPCMCOEFSET coeffL, coeffR;
+ int nsamp;
+ int nsamp_blk = ((ADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock;
+ DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
+ *ndst / (nsamp_blk * 2 * 2));
+
+ *nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
+ *ndst = nblock * nsamp_blk * 2 * 2;
+
+ nsamp_blk -= 2; /* see below for samples from block head */
+ for (; nblock > 0; nblock--)
+ {
+ const unsigned char* in_src = src;
+
+ assert(*src <= 6);
+ coeffL = MSADPCM_CoeffSet[*src++];
+ assert(*src <= 6);
+ coeffR = MSADPCM_CoeffSet[*src++];
+
+ ideltaL = R16(src); src += 2;
+ ideltaR = R16(src); src += 2;
+ sample1L = R16(src); src += 2;
+ sample1R = R16(src); src += 2;
+ sample2L = R16(src); src += 2;
+ sample2R = R16(src); src += 2;
+
+ /* store samples from block head */
+ W16(dst, sample2L); dst += 2;
+ W16(dst, sample2R); dst += 2;
+ W16(dst, sample1L); dst += 2;
+ W16(dst, sample1R); dst += 2;
+
+ for (nsamp = nsamp_blk; nsamp > 0; nsamp--)
+ {
+ process_nibble(*src >> 4, &ideltaL, &sample1L, &sample2L, &coeffL);
+ W16(dst, sample1L); dst += 2;
+ process_nibble(*src++ & 0x0F, &ideltaR, &sample1R, &sample2R, &coeffR);
+ W16(dst, sample1R); dst += 2;
+ }
+ src = in_src + adsi->pwfxSrc->nBlockAlign;
+ }
+}
+
+static void cvtMMms16K(const ACMDRVSTREAMINSTANCE *adsi,
+ const unsigned char* src, LPDWORD nsrc,
+ unsigned char* dst, LPDWORD ndst)
+{
+ int idelta;
+ int sample1, sample2;
+ ADPCMCOEFSET coeff;
+ int nsamp;
+ int nsamp_blk = ((ADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock;
+ DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
+ *ndst / (nsamp_blk * 2));
+
+ *nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
+ *ndst = nblock * nsamp_blk * 2;
+
+ nsamp_blk -= 2; /* see below for samples from block head */
+ for (; nblock > 0; nblock--)
+ {
+ const unsigned char* in_src = src;
+
+ assert(*src <= 6);
+ coeff = MSADPCM_CoeffSet[*src++];
+
+ idelta = R16(src); src += 2;
+ sample1 = R16(src); src += 2;
+ sample2 = R16(src); src += 2;
+
+ /* store samples from block head */
+ W16(dst, sample2); dst += 2;
+ W16(dst, sample1); dst += 2;
+
+ for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
+ {
+ process_nibble(*src >> 4, &idelta, &sample1, &sample2, &coeff);
+ W16(dst, sample1); dst += 2;
+ process_nibble(*src++ & 0x0F, &idelta, &sample1, &sample2, &coeff);
+ W16(dst, sample1); dst += 2;
+ }
+ src = in_src + adsi->pwfxSrc->nBlockAlign;
+ }
+}
+
+#if 0
+static void cvtSS16msK(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char* src, LPDWORD nsrc,
+ unsigned char* dst, LPDWORD ndst)
+{
+}
+
+static void cvtMM16msK(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char* src, LPDWORD nsrc,
+ unsigned char* dst, LPDWORD ndst)
+{
+}
+#endif
+
+/***********************************************************************
+ * ADPCM_DriverDetails
+ *
+ */
+static LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add)
+{
+ add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
+ add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
+ add->wMid = 0xFF;
+ add->wPid = 0x00;
+ add->vdwACM = 0x01000000;
+ add->vdwDriver = 0x01000000;
+ add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
+ add->cFormatTags = 2; /* PCM, MS ADPCM */
+ add->cFilterTags = 0;
+ add->hicon = NULL;
+ MultiByteToWideChar( CP_ACP, 0, "MS-ADPCM", -1,
+ add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, "Wine MS ADPCM converter", -1,
+ add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
+ add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
+ add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
+ add->szFeatures[0] = 0;
+
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * ADPCM_FormatTagDetails
+ *
+ */
+static LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
+{
+ static const WCHAR szPcm[]={'P','C','M',0};
+ static const WCHAR szMsAdPcm[]={'M','i','c','r','o','s','o','f','t',' ','A','D','P','C','M',0};
+
+ switch (dwQuery)
+ {
+ case ACM_FORMATTAGDETAILSF_INDEX:
+ if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE;
+ break;
+ case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
+ if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
+ {
+ aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_ADPCM is bigger than PCM */
+ break;
+ }
+ /* fall thru */
+ case ACM_FORMATTAGDETAILSF_FORMATTAG:
+ switch (aftd->dwFormatTag)
+ {
+ case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
+ case WAVE_FORMAT_ADPCM: aftd->dwFormatTagIndex = 1; break;
+ default: return ACMERR_NOTPOSSIBLE;
+ }
+ break;
+ default:
+ WARN("Unsupported query %08x\n", dwQuery);
+ return MMSYSERR_NOTSUPPORTED;
+ }
+
+ aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
+ switch (aftd->dwFormatTagIndex)
+ {
+ case 0:
+ aftd->dwFormatTag = WAVE_FORMAT_PCM;
+ aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
+ aftd->cStandardFormats = NUM_PCM_FORMATS;
+ lstrcpyW(aftd->szFormatTag, szPcm);
+ break;
+ case 1:
+ aftd->dwFormatTag = WAVE_FORMAT_ADPCM;
+ aftd->cbFormatSize = sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET);
+ aftd->cStandardFormats = NUM_ADPCM_FORMATS;
+ lstrcpyW(aftd->szFormatTag, szMsAdPcm);
+ break;
+ }
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * ADPCM_FormatDetails
+ *
+ */
+static LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
+{
+ switch (dwQuery)
+ {
+ case ACM_FORMATDETAILSF_FORMAT:
+ if (ADPCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
+ break;
+ case ACM_FORMATDETAILSF_INDEX:
+ afd->pwfx->wFormatTag = afd->dwFormatTag;
+ switch (afd->dwFormatTag)
+ {
+ case WAVE_FORMAT_PCM:
+ if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
+ afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
+ afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
+ afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
+ /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
+ * afd->pwfx->cbSize = 0;
+ */
+ afd->pwfx->nBlockAlign =
+ (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
+ afd->pwfx->nAvgBytesPerSec =
+ afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
+ break;
+ case WAVE_FORMAT_ADPCM:
+ if (afd->dwFormatIndex >= NUM_ADPCM_FORMATS) return ACMERR_NOTPOSSIBLE;
+ if (afd->cbwfx < sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET))
+ return ACMERR_NOTPOSSIBLE;
+ afd->pwfx->nChannels = ADPCM_Formats[afd->dwFormatIndex].nChannels;
+ afd->pwfx->nSamplesPerSec = ADPCM_Formats[afd->dwFormatIndex].rate;
+ afd->pwfx->wBitsPerSample = ADPCM_Formats[afd->dwFormatIndex].nBits;
+ init_wfx_adpcm((ADPCMWAVEFORMAT*)afd->pwfx);
+ break;
+ default:
+ WARN("Unsupported tag %08x\n", afd->dwFormatTag);
+ return MMSYSERR_INVALPARAM;
+ }
+ break;
+ default:
+ WARN("Unsupported query %08x\n", dwQuery);
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
+ afd->szFormat[0] = 0; /* let MSACM format this for us... */
+
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * ADPCM_FormatSuggest
+ *
+ */
+static LRESULT ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
+{
+ /* some tests ... */
+ if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
+ adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
+ adfs->pwfxSrc->wFormatTag == adfs->pwfxDst->wFormatTag ||
+ ADPCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
+ /* FIXME: should do those tests against the real size (according to format tag */
+
+ /* If no suggestion for destination, then copy source value */
+ if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
+ adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
+ if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
+ adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
+
+ if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
+ {
+ if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
+ adfs->pwfxDst->wBitsPerSample = 4;
+ else
+ adfs->pwfxDst->wBitsPerSample = 16;
+ }
+ if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
+ {
+ if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
+ adfs->pwfxDst->wFormatTag = WAVE_FORMAT_ADPCM;
+ else
+ adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
+ }
+
+ /* recompute other values */
+ switch (adfs->pwfxDst->wFormatTag)
+ {
+ case WAVE_FORMAT_PCM:
+ adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
+ adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
+ /* check if result is ok */
+ if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
+ break;
+ case WAVE_FORMAT_ADPCM:
+ init_wfx_adpcm((ADPCMWAVEFORMAT*)adfs->pwfxDst);
+ /* check if result is ok */
+ if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
+ break;
+ default:
+ FIXME("\n");
+ break;
+ }
+
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * ADPCM_Reset
+ *
+ */
+static void ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi, AcmAdpcmData* aad)
+{
+}
+
+/***********************************************************************
+ * ADPCM_StreamOpen
+ *
+ */
+static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
+{
+ AcmAdpcmData* aad;
+
+ assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
+
+ if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
+ ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
+ return ACMERR_NOTPOSSIBLE;
+
+ aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData));
+ if (aad == 0) return MMSYSERR_NOMEM;
+
+ adsi->dwDriver = (DWORD_PTR)aad;
+
+ if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
+ {
+ goto theEnd;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
+ {
+ /* resampling or mono <=> stereo not available
+ * ADPCM algo only define 16 bit per sample output
+ */
+ if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
+ adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
+ adsi->pwfxDst->wBitsPerSample != 16)
+ goto theEnd;
+
+#if 0
+ {
+ unsigned int nspb = ((IMAADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock;
+ FIXME("spb=%u\n", nspb);
+
+ /* we check that in a block, after the header, samples are present on
+ * 4-sample packet pattern
+ * we also check that the block alignment is bigger than the expected size
+ */
+ if (((nspb - 1) & 3) != 0) goto theEnd;
+ if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign)
+ goto theEnd;
+ }
+#endif
+
+ /* adpcm decoding... */
+ if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 2)
+ aad->convert = cvtSSms16K;
+ if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 1)
+ aad->convert = cvtMMms16K;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ADPCM)
+ {
+ if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
+ adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
+ adsi->pwfxSrc->wBitsPerSample != 16)
+ goto theEnd;
+#if 0
+ nspb = ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock;
+ FIXME("spb=%u\n", nspb);
+
+ /* we check that in a block, after the header, samples are present on
+ * 4-sample packet pattern
+ * we also check that the block alignment is bigger than the expected size
+ */
+ if (((nspb - 1) & 3) != 0) goto theEnd;
+ if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign)
+ goto theEnd;
+#endif
+#if 0
+ /* adpcm coding... */
+ if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2)
+ aad->convert = cvtSS16msK;
+ if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1)
+ aad->convert = cvtMM16msK;
+#endif
+ FIXME("We don't support encoding yet\n");
+ goto theEnd;
+ }
+ else goto theEnd;
+ ADPCM_Reset(adsi, aad);
+
+ return MMSYSERR_NOERROR;
+
+ theEnd:
+ HeapFree(GetProcessHeap(), 0, aad);
+ adsi->dwDriver = 0L;
+ return MMSYSERR_NOTSUPPORTED;
+}
+
+/***********************************************************************
+ * ADPCM_StreamClose
+ *
+ */
+static LRESULT ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
+{
+ HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * ADPCM_StreamSize
+ *
+ */
+static LRESULT ADPCM_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss)
+{
+ DWORD nblocks;
+ WORD wSamplesPerBlock;
+ /* wSamplesPerBlock formula comes from MSDN ADPCMWAVEFORMAT page.*/
+ switch (adss->fdwSize)
+ {
+ case ACM_STREAMSIZEF_DESTINATION:
+ /* cbDstLength => cbSrcLength */
+ if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ADPCM)
+ {
+ wSamplesPerBlock = adsi->pwfxDst->nBlockAlign * 2 / adsi->pwfxDst->nChannels - 12;
+ nblocks = adss->cbDstLength / adsi->pwfxDst->nBlockAlign;
+ if (nblocks == 0)
+ return ACMERR_NOTPOSSIBLE;
+ adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
+ {
+ wSamplesPerBlock = adsi->pwfxSrc->nBlockAlign * 2 / adsi->pwfxSrc->nChannels - 12;
+ nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * wSamplesPerBlock);
+ if (nblocks == 0)
+ return ACMERR_NOTPOSSIBLE;
+ adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign;
+ }
+ else
+ {
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ break;
+ case ACM_STREAMSIZEF_SOURCE:
+ /* cbSrcLength => cbDstLength */
+ if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ADPCM)
+ {
+ wSamplesPerBlock = adsi->pwfxDst->nBlockAlign * 2 / adsi->pwfxDst->nChannels - 12;
+ nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock);
+ if (nblocks == 0)
+ return ACMERR_NOTPOSSIBLE;
+ if (adss->cbSrcLength % (adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock))
+ /* Round block count up. */
+ nblocks++;
+ adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
+ {
+ wSamplesPerBlock = adsi->pwfxSrc->nBlockAlign * 2 / adsi->pwfxSrc->nChannels - 12;
+ nblocks = adss->cbSrcLength / adsi->pwfxSrc->nBlockAlign;
+ if (nblocks == 0)
+ return ACMERR_NOTPOSSIBLE;
+ if (adss->cbSrcLength % adsi->pwfxSrc->nBlockAlign)
+ /* Round block count up. */
+ nblocks++;
+ adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign * wSamplesPerBlock;
+ }
+ else
+ {
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ break;
+ default:
+ WARN("Unsupported query %08x\n", adss->fdwSize);
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * ADPCM_StreamConvert
+ *
+ */
+static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
+{
+ AcmAdpcmData* aad = (AcmAdpcmData*)adsi->dwDriver;
+ DWORD nsrc = adsh->cbSrcLength;
+ DWORD ndst = adsh->cbDstLength;
+
+ if (adsh->fdwConvert &
+ ~(ACM_STREAMCONVERTF_BLOCKALIGN|
+ ACM_STREAMCONVERTF_END|
+ ACM_STREAMCONVERTF_START))
+ {
+ FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
+ }
+ /* ACM_STREAMCONVERTF_BLOCKALIGN
+ * currently all conversions are block aligned, so do nothing for this flag
+ * ACM_STREAMCONVERTF_END
+ * no pending data, so do nothing for this flag
+ */
+ if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
+ {
+ ADPCM_Reset(adsi, aad);
+ }
+
+ aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
+ adsh->cbSrcLengthUsed = nsrc;
+ adsh->cbDstLengthUsed = ndst;
+
+ return MMSYSERR_NOERROR;
+}
+
+/**************************************************************************
+ * ADPCM_DriverProc [exported]
+ */
+LRESULT CALLBACK ADPCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
+ LPARAM dwParam1, LPARAM dwParam2)
+{
+ TRACE("(%08lx %p %04x %08lx %08lx);\n",
+ dwDevID, hDriv, wMsg, dwParam1, dwParam2);
+
+ switch (wMsg)
+ {
+ case DRV_LOAD: return 1;
+ case DRV_FREE: return 1;
+ case DRV_OPEN: return ADPCM_drvOpen((LPSTR)dwParam1);
+ case DRV_CLOSE: return ADPCM_drvClose(dwDevID);
+ case DRV_ENABLE: return 1;
+ case DRV_DISABLE: return 1;
+ case DRV_QUERYCONFIGURE: return 1;
+ case DRV_CONFIGURE: MessageBoxA(0, "MSACM MS ADPCM filter !", "Wine Driver", MB_OK); return 1;
+ case DRV_INSTALL: return DRVCNF_RESTART;
+ case DRV_REMOVE: return DRVCNF_RESTART;
+
+ case ACMDM_DRIVER_NOTIFY:
+ /* no caching from other ACM drivers is done so far */
+ return MMSYSERR_NOERROR;
+
+ case ACMDM_DRIVER_DETAILS:
+ return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
+
+ case ACMDM_FORMATTAG_DETAILS:
+ return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
+
+ case ACMDM_FORMAT_DETAILS:
+ return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
+
+ case ACMDM_FORMAT_SUGGEST:
+ return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
+
+ case ACMDM_STREAM_OPEN:
+ return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
+
+ case ACMDM_STREAM_CLOSE:
+ return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
+
+ case ACMDM_STREAM_SIZE:
+ return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
+
+ case ACMDM_STREAM_CONVERT:
+ return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
+
+ case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
+ case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
+ /* this converter is not a hardware driver */
+ case ACMDM_FILTERTAG_DETAILS:
+ case ACMDM_FILTER_DETAILS:
+ /* this converter is not a filter */
+ case ACMDM_STREAM_RESET:
+ /* only needed for asynchronous driver... we aren't, so just say it */
+ return MMSYSERR_NOTSUPPORTED;
+ case ACMDM_STREAM_PREPARE:
+ case ACMDM_STREAM_UNPREPARE:
+ /* nothing special to do here... so don't do anything */
+ return MMSYSERR_NOERROR;
+
+ default:
+ return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
+ }
+}
diff --git a/reactos/dll/win32/msg711.acm/msg711.acm.rbuild b/reactos/dll/win32/msg711.acm/msg711.acm.rbuild
new file mode 100644
index 00000000000..a9297bd3812
--- /dev/null
+++ b/reactos/dll/win32/msg711.acm/msg711.acm.rbuild
@@ -0,0 +1,12 @@
+
+
+ .
+ include/reactos/wine
+
+ msg711.c
+ wine
+ winmm
+ user32
+ kernel32
+ ntdll
+
diff --git a/reactos/dll/win32/msg711.acm/msg711.acm.spec b/reactos/dll/win32/msg711.acm/msg711.acm.spec
new file mode 100644
index 00000000000..e351c5879a5
--- /dev/null
+++ b/reactos/dll/win32/msg711.acm/msg711.acm.spec
@@ -0,0 +1 @@
+@ stdcall -private DriverProc(long long long long long) G711_DriverProc
diff --git a/reactos/dll/win32/msg711.acm/msg711.c b/reactos/dll/win32/msg711.acm/msg711.c
new file mode 100644
index 00000000000..203942ddcb1
--- /dev/null
+++ b/reactos/dll/win32/msg711.acm/msg711.c
@@ -0,0 +1,1151 @@
+/*
+ * G711 handling (includes A-Law & MU-Law)
+ *
+ * Copyright (C) 2002 Eric Pouech
+ *
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include
+#include
+#include
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "mmsystem.h"
+#include "mmreg.h"
+#include "msacm.h"
+#include "msacmdrv.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(g711);
+
+/***********************************************************************
+ * G711_drvOpen
+ */
+static LRESULT G711_drvOpen(LPCSTR str)
+{
+ return 1;
+}
+
+/***********************************************************************
+ * G711_drvClose
+ */
+static LRESULT G711_drvClose(DWORD_PTR dwDevID)
+{
+ return 1;
+}
+
+typedef struct tagAcmG711Data
+{
+ void (*convert)(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
+} AcmG711Data;
+
+/* table to list all supported formats... those are the basic ones. this
+ * also helps given a unique index to each of the supported formats
+ */
+typedef struct
+{
+ int nChannels;
+ int nBits;
+ int rate;
+} Format;
+
+static const Format PCM_Formats[] =
+{
+ /*{1, 8, 8000}, {2, 8, 8000}, */{1, 16, 8000}, {2, 16, 8000},
+ /*{1, 8, 11025}, {2, 8, 11025}, */{1, 16, 11025}, {2, 16, 11025},
+ /*{1, 8, 22050}, {2, 8, 22050}, */{1, 16, 22050}, {2, 16, 22050},
+ /*{1, 8, 44100}, {2, 8, 44100}, */{1, 16, 44100}, {2, 16, 44100},
+};
+
+static const Format ALaw_Formats[] =
+{
+ {1, 8, 8000}, {2, 8, 8000}, {1, 8, 11025}, {2, 8, 11025},
+ {1, 8, 22050}, {2, 8, 22050}, {1, 8, 44100}, {2, 8, 44100},
+};
+
+static const Format ULaw_Formats[] =
+{
+ {1, 8, 8000}, {2, 8, 8000}, {1, 8, 11025}, {2, 8, 11025},
+ {1, 8, 22050}, {2, 8, 22050}, {1, 8, 44100}, {2, 8, 44100},
+};
+
+#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
+#define NUM_ALAW_FORMATS (sizeof(ALaw_Formats) / sizeof(ALaw_Formats[0]))
+#define NUM_ULAW_FORMATS (sizeof(ULaw_Formats) / sizeof(ULaw_Formats[0]))
+
+/***********************************************************************
+ * G711_GetFormatIndex
+ */
+static DWORD G711_GetFormatIndex(const WAVEFORMATEX *wfx)
+{
+ int i, hi;
+ const Format* fmts;
+
+ switch (wfx->wFormatTag)
+ {
+ case WAVE_FORMAT_PCM:
+ hi = NUM_PCM_FORMATS;
+ fmts = PCM_Formats;
+ break;
+ case WAVE_FORMAT_ALAW:
+ hi = NUM_ALAW_FORMATS;
+ fmts = ALaw_Formats;
+ break;
+ case WAVE_FORMAT_MULAW:
+ hi = NUM_ULAW_FORMATS;
+ fmts = ULaw_Formats;
+ break;
+ default:
+ return 0xFFFFFFFF;
+ }
+
+ for (i = 0; i < hi; i++)
+ {
+ if (wfx->nChannels == fmts[i].nChannels &&
+ wfx->nSamplesPerSec == fmts[i].rate &&
+ wfx->wBitsPerSample == fmts[i].nBits)
+ return i;
+ }
+
+ return 0xFFFFFFFF;
+}
+
+/***********************************************************************
+ * R16
+ *
+ * Read a 16 bit sample (correctly handles endianess)
+ */
+static inline short R16(const unsigned char* src)
+{
+ return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
+}
+
+/***********************************************************************
+ * W16
+ *
+ * Write a 16 bit sample (correctly handles endianess)
+ */
+static inline void W16(unsigned char* dst, short s)
+{
+ dst[0] = LOBYTE(s);
+ dst[1] = HIBYTE(s);
+}
+
+/* You can uncomment this if you don't want the statically generated conversion
+ * table, but rather recompute the Xlaw => PCM conversion for each sample
+#define NO_FASTDECODE
+ * Since the conversion tables are rather small (2k), I don't think it's really
+ * interesting not to use them, but keeping the actual conversion code around
+ * is helpful to regenerate the tables when needed.
+ */
+
+/* -------------------------------------------------------------------------------*/
+
+/*
+ * This source code is a product of Sun Microsystems, Inc. and is provided
+ * for unrestricted use. Users may copy or modify this source code without
+ * charge.
+ *
+ * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
+ * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun source code is provided with no support and without any obligation on
+ * the part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * g711.c
+ *
+ * u-law, A-law and linear PCM conversions.
+ */
+
+/*
+ * December 30, 1994:
+ * Functions linear2alaw, linear2ulaw have been updated to correctly
+ * convert unquantized 16 bit values.
+ * Tables for direct u- to A-law and A- to u-law conversions have been
+ * corrected.
+ * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
+ * bli@cpk.auc.dk
+ *
+ */
+
+#define SIGN_BIT (0x80) /* Sign bit for an A-law byte. */
+#define QUANT_MASK (0xf) /* Quantization field mask. */
+#define NSEGS (8) /* Number of A-law segments. */
+#define SEG_SHIFT (4) /* Left shift for segment number. */
+#define SEG_MASK (0x70) /* Segment field mask. */
+
+static const short seg_aend[8] = {0x1F, 0x3F, 0x7F, 0x0FF, 0x1FF, 0x3FF, 0x7FF, 0x0FFF};
+static const short seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF};
+
+/* copy from CCITT G.711 specifications */
+static const unsigned char _u2a[128] = { /* u- to A-law conversions */
+ 1, 1, 2, 2, 3, 3, 4, 4,
+ 5, 5, 6, 6, 7, 7, 8, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 27, 29, 31, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44,
+ 46, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62,
+ 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+/* corrected:
+ 81, 82, 83, 84, 85, 86, 87, 88,
+ should be: */
+ 80, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120,
+ 121, 122, 123, 124, 125, 126, 127, 128};
+
+static const unsigned char _a2u[128] = { /* A- to u-law conversions */
+ 1, 3, 5, 7, 9, 11, 13, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 32, 33, 33, 34, 34, 35, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 48, 49, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72,
+/* corrected:
+ 73, 74, 75, 76, 77, 78, 79, 79,
+ should be: */
+ 73, 74, 75, 76, 77, 78, 79, 80,
+
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127};
+
+static short
+search(
+ int val, /* changed from "short" *drago* */
+ const short *table,
+ int size) /* changed from "short" *drago* */
+{
+ int i; /* changed from "short" *drago* */
+
+ for (i = 0; i < size; i++) {
+ if (val <= *table++)
+ return (i);
+ }
+ return (size);
+}
+
+/*
+ * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
+ *
+ * linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
+ *
+ * Linear Input Code Compressed Code
+ * ------------------------ ---------------
+ * 0000000wxyza 000wxyz
+ * 0000001wxyza 001wxyz
+ * 000001wxyzab 010wxyz
+ * 00001wxyzabc 011wxyz
+ * 0001wxyzabcd 100wxyz
+ * 001wxyzabcde 101wxyz
+ * 01wxyzabcdef 110wxyz
+ * 1wxyzabcdefg 111wxyz
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+static inline unsigned char
+linear2alaw(int pcm_val) /* 2's complement (16-bit range) */
+ /* changed from "short" *drago* */
+{
+ int mask; /* changed from "short" *drago* */
+ int seg; /* changed from "short" *drago* */
+ unsigned char aval;
+
+ pcm_val = pcm_val >> 3;
+
+ if (pcm_val >= 0) {
+ mask = 0xD5; /* sign (7th) bit = 1 */
+ } else {
+ mask = 0x55; /* sign bit = 0 */
+ pcm_val = -pcm_val - 1;
+ }
+
+ /* Convert the scaled magnitude to segment number. */
+ seg = search(pcm_val, seg_aend, 8);
+
+ /* Combine the sign, segment, and quantization bits. */
+
+ if (seg >= 8) /* out of range, return maximum value. */
+ return (unsigned char) (0x7F ^ mask);
+ else {
+ aval = (unsigned char) seg << SEG_SHIFT;
+ if (seg < 2)
+ aval |= (pcm_val >> 1) & QUANT_MASK;
+ else
+ aval |= (pcm_val >> seg) & QUANT_MASK;
+ return (aval ^ mask);
+ }
+}
+
+#ifdef NO_FASTDECODE
+/*
+ * alaw2linear() - Convert an A-law value to 16-bit linear PCM
+ *
+ */
+static inline int
+alaw2linear(unsigned char a_val)
+{
+ int t; /* changed from "short" *drago* */
+ int seg; /* changed from "short" *drago* */
+
+ a_val ^= 0x55;
+
+ t = (a_val & QUANT_MASK) << 4;
+ seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
+ switch (seg) {
+ case 0:
+ t += 8;
+ break;
+ case 1:
+ t += 0x108;
+ break;
+ default:
+ t += 0x108;
+ t <<= seg - 1;
+ }
+ return ((a_val & SIGN_BIT) ? t : -t);
+}
+#else
+/* EPP (for Wine):
+ * this array has been statically generated from the above routine
+ */
+static const unsigned short _a2l[] = {
+0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80,
+0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
+0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0,
+0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
+0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600,
+0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
+0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00,
+0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
+0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8,
+0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
+0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8,
+0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
+0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60,
+0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
+0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0,
+0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
+0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280,
+0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
+0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940,
+0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
+0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00,
+0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
+0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500,
+0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
+0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128,
+0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
+0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028,
+0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
+0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0,
+0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
+0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250,
+0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350,
+};
+static inline int
+alaw2linear(unsigned char a_val)
+{
+ return (short)_a2l[a_val];
+}
+#endif
+
+#define BIAS (0x84) /* Bias for linear code. */
+#define CLIP 8159
+
+/*
+ * linear2ulaw() - Convert a linear PCM value to u-law
+ *
+ * In order to simplify the encoding process, the original linear magnitude
+ * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
+ * (33 - 8191). The result can be seen in the following encoding table:
+ *
+ * Biased Linear Input Code Compressed Code
+ * ------------------------ ---------------
+ * 00000001wxyza 000wxyz
+ * 0000001wxyzab 001wxyz
+ * 000001wxyzabc 010wxyz
+ * 00001wxyzabcd 011wxyz
+ * 0001wxyzabcde 100wxyz
+ * 001wxyzabcdef 101wxyz
+ * 01wxyzabcdefg 110wxyz
+ * 1wxyzabcdefgh 111wxyz
+ *
+ * Each biased linear code has a leading 1 which identifies the segment
+ * number. The value of the segment number is equal to 7 minus the number
+ * of leading 0's. The quantization interval is directly available as the
+ * four bits wxyz. * The trailing bits (a - h) are ignored.
+ *
+ * Ordinarily the complement of the resulting code word is used for
+ * transmission, and so the code word is complemented before it is returned.
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+static inline unsigned char
+linear2ulaw(short pcm_val) /* 2's complement (16-bit range) */
+{
+ short mask;
+ short seg;
+ unsigned char uval;
+
+ /* Get the sign and the magnitude of the value. */
+ pcm_val = pcm_val >> 2;
+ if (pcm_val < 0) {
+ pcm_val = -pcm_val;
+ mask = 0x7F;
+ } else {
+ mask = 0xFF;
+ }
+ if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */
+ pcm_val += (BIAS >> 2);
+
+ /* Convert the scaled magnitude to segment number. */
+ seg = search(pcm_val, seg_uend, 8);
+
+ /*
+ * Combine the sign, segment, quantization bits;
+ * and complement the code word.
+ */
+ if (seg >= 8) /* out of range, return maximum value. */
+ return (unsigned char) (0x7F ^ mask);
+ else {
+ uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
+ return (uval ^ mask);
+ }
+}
+
+#ifdef NO_FASTDECODE
+/*
+ * ulaw2linear() - Convert a u-law value to 16-bit linear PCM
+ *
+ * First, a biased linear code is derived from the code word. An unbiased
+ * output can then be obtained by subtracting 33 from the biased code.
+ *
+ * Note that this function expects to be passed the complement of the
+ * original code word. This is in keeping with ISDN conventions.
+ */
+static inline short
+ulaw2linear(unsigned char u_val)
+{
+ short t;
+
+ /* Complement to obtain normal u-law value. */
+ u_val = ~u_val;
+
+ /*
+ * Extract and bias the quantization bits. Then
+ * shift up by the segment number and subtract out the bias.
+ */
+ t = ((u_val & QUANT_MASK) << 3) + BIAS;
+ t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
+
+ return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
+}
+#else
+/* EPP (for Wine):
+ * this array has been statically generated from the above routine
+ */
+static const unsigned short _u2l[] = {
+0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84,
+0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
+0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84,
+0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
+0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804,
+0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
+0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444,
+0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
+0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64,
+0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
+0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74,
+0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
+0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC,
+0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
+0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0,
+0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
+0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C,
+0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
+0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C,
+0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
+0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC,
+0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
+0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC,
+0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
+0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C,
+0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
+0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C,
+0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
+0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
+0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
+0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
+0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000,
+};
+static inline short ulaw2linear(unsigned char u_val)
+{
+ return (short)_u2l[u_val];
+}
+#endif
+
+/* A-law to u-law conversion */
+static inline unsigned char
+alaw2ulaw(unsigned char aval)
+{
+ aval &= 0xff;
+ return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
+ (0x7F ^ _a2u[aval ^ 0x55]));
+}
+
+/* u-law to A-law conversion */
+static inline unsigned char
+ulaw2alaw(unsigned char uval)
+{
+ uval &= 0xff;
+ return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
+ (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
+}
+
+/* -------------------------------------------------------------------------------*/
+
+static void cvtXXalaw16K(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char* src, LPDWORD srcsize,
+ unsigned char* dst, LPDWORD dstsize)
+{
+ DWORD len = min(*srcsize, *dstsize / 2);
+ DWORD i;
+ short w;
+
+ *srcsize = len;
+ *dstsize = len * 2;
+ for (i = 0; i < len; i++)
+ {
+ w = alaw2linear(*src++);
+ W16(dst, w); dst += 2;
+ }
+}
+
+static void cvtXX16alawK(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char* src, LPDWORD srcsize,
+ unsigned char* dst, LPDWORD dstsize)
+{
+ DWORD len = min(*srcsize / 2, *dstsize);
+ DWORD i;
+
+ *srcsize = len * 2;
+ *dstsize = len;
+ for (i = 0; i < len; i++)
+ {
+ *dst++ = linear2alaw(R16(src)); src += 2;
+ }
+}
+
+static void cvtXXulaw16K(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char* src, LPDWORD srcsize,
+ unsigned char* dst, LPDWORD dstsize)
+{
+ DWORD len = min(*srcsize, *dstsize / 2);
+ DWORD i;
+ short w;
+
+ *srcsize = len;
+ *dstsize = len * 2;
+ for (i = 0; i < len; i++)
+ {
+ w = ulaw2linear(*src++);
+ W16(dst, w); dst += 2;
+ }
+}
+
+static void cvtXX16ulawK(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char* src, LPDWORD srcsize,
+ unsigned char* dst, LPDWORD dstsize)
+{
+ DWORD len = min(*srcsize / 2, *dstsize);
+ DWORD i;
+
+ *srcsize = len * 2;
+ *dstsize = len;
+ for (i = 0; i < len; i++)
+ {
+ *dst++ = linear2ulaw(R16(src)); src += 2;
+ }
+}
+
+static void cvtXXalawulawK(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char* src, LPDWORD srcsize,
+ unsigned char* dst, LPDWORD dstsize)
+{
+ DWORD len = min(*srcsize, *dstsize);
+ DWORD i;
+
+ *srcsize = len;
+ *dstsize = len;
+
+ for (i = 0; i < len; i++)
+ *dst++ = alaw2ulaw(*src++);
+}
+
+
+static void cvtXXulawalawK(PACMDRVSTREAMINSTANCE adsi,
+ const unsigned char* src, LPDWORD srcsize,
+ unsigned char* dst, LPDWORD dstsize)
+{
+ DWORD len = min(*srcsize, *dstsize);
+ DWORD i;
+
+ *srcsize = len;
+ *dstsize = len;
+
+ for (i = 0; i < len; i++)
+ *dst++ = ulaw2alaw(*src++);
+}
+
+/***********************************************************************
+ * G711_DriverDetails
+ *
+ */
+static LRESULT G711_DriverDetails(PACMDRIVERDETAILSW add)
+{
+ add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
+ add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
+ add->wMid = 0xFF;
+ add->wPid = 0x00;
+ add->vdwACM = 0x01000000;
+ add->vdwDriver = 0x01000000;
+ add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
+ add->cFormatTags = 3; /* PCM, G711 A-LAW & MU-LAW */
+ add->cFilterTags = 0;
+ add->hicon = NULL;
+ MultiByteToWideChar( CP_ACP, 0, "WINE-G711", -1,
+ add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, "Wine G711 converter", -1,
+ add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
+ add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
+ add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
+ add->szFeatures[0] = 0;
+
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * G711_FormatTagDetails
+ *
+ */
+static LRESULT G711_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
+{
+ static const WCHAR szPcm[]={'P','C','M',0};
+ static const WCHAR szALaw[]={'A','-','L','a','w',0};
+ static const WCHAR szULaw[]={'U','-','L','a','w',0};
+
+ switch (dwQuery)
+ {
+ case ACM_FORMATTAGDETAILSF_INDEX:
+ if (aftd->dwFormatTagIndex >= 3) return ACMERR_NOTPOSSIBLE;
+ break;
+ case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
+ if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
+ {
+ aftd->dwFormatTagIndex = 1;
+ break;
+ }
+ /* fall thru */
+ case ACM_FORMATTAGDETAILSF_FORMATTAG:
+ switch (aftd->dwFormatTag)
+ {
+ case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
+ case WAVE_FORMAT_ALAW: aftd->dwFormatTagIndex = 1; break;
+ case WAVE_FORMAT_MULAW: aftd->dwFormatTagIndex = 2; break;
+ default: return ACMERR_NOTPOSSIBLE;
+ }
+ break;
+ default:
+ WARN("Unsupported query %08x\n", dwQuery);
+ return MMSYSERR_NOTSUPPORTED;
+ }
+
+ aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
+ switch (aftd->dwFormatTagIndex)
+ {
+ case 0:
+ aftd->dwFormatTag = WAVE_FORMAT_PCM;
+ aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
+ aftd->cStandardFormats = NUM_PCM_FORMATS;
+ lstrcpyW(aftd->szFormatTag, szPcm);
+ break;
+ case 1:
+ aftd->dwFormatTag = WAVE_FORMAT_ALAW;
+ aftd->cbFormatSize = sizeof(WAVEFORMATEX);
+ aftd->cStandardFormats = NUM_ALAW_FORMATS;
+ lstrcpyW(aftd->szFormatTag, szALaw);
+ break;
+ case 2:
+ aftd->dwFormatTag = WAVE_FORMAT_MULAW;
+ aftd->cbFormatSize = sizeof(WAVEFORMATEX);
+ aftd->cStandardFormats = NUM_ULAW_FORMATS;
+ lstrcpyW(aftd->szFormatTag, szULaw);
+ break;
+ }
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * G711_FormatDetails
+ *
+ */
+static LRESULT G711_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
+{
+ switch (dwQuery)
+ {
+ case ACM_FORMATDETAILSF_FORMAT:
+ if (G711_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
+ break;
+ case ACM_FORMATDETAILSF_INDEX:
+ afd->pwfx->wFormatTag = afd->dwFormatTag;
+ switch (afd->dwFormatTag)
+ {
+ case WAVE_FORMAT_PCM:
+ if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
+ afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
+ afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
+ afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
+ afd->pwfx->nBlockAlign = afd->pwfx->nChannels * 2;
+ afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
+ break;
+ case WAVE_FORMAT_ALAW:
+ if (afd->dwFormatIndex >= NUM_ALAW_FORMATS) return ACMERR_NOTPOSSIBLE;
+ afd->pwfx->nChannels = ALaw_Formats[afd->dwFormatIndex].nChannels;
+ afd->pwfx->nSamplesPerSec = ALaw_Formats[afd->dwFormatIndex].rate;
+ afd->pwfx->wBitsPerSample = ALaw_Formats[afd->dwFormatIndex].nBits;
+ afd->pwfx->nBlockAlign = ALaw_Formats[afd->dwFormatIndex].nChannels;
+ afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels;
+ afd->pwfx->cbSize = 0;
+ break;
+ case WAVE_FORMAT_MULAW:
+ if (afd->dwFormatIndex >= NUM_ULAW_FORMATS) return ACMERR_NOTPOSSIBLE;
+ afd->pwfx->nChannels = ULaw_Formats[afd->dwFormatIndex].nChannels;
+ afd->pwfx->nSamplesPerSec = ULaw_Formats[afd->dwFormatIndex].rate;
+ afd->pwfx->wBitsPerSample = ULaw_Formats[afd->dwFormatIndex].nBits;
+ afd->pwfx->nBlockAlign = ULaw_Formats[afd->dwFormatIndex].nChannels;
+ afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels;
+ afd->pwfx->cbSize = 0;
+ break;
+ default:
+ WARN("Unsupported tag %08x\n", afd->dwFormatTag);
+ return MMSYSERR_INVALPARAM;
+ }
+ break;
+ default:
+ WARN("Unsupported query %08x\n", dwQuery);
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
+ afd->szFormat[0] = 0; /* let MSACM format this for us... */
+
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * G711_FormatSuggest
+ *
+ */
+static LRESULT G711_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
+{
+ /* some tests ... */
+ if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
+ adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
+ G711_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
+ /* FIXME: should do those tests against the real size (according to format tag */
+
+ /* If no suggestion for destination, then copy source value */
+ if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
+ adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
+ if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
+ adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
+
+ if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
+ {
+ if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
+ adfs->pwfxDst->wBitsPerSample = 8;
+ else
+ adfs->pwfxDst->wBitsPerSample = 16;
+ }
+ if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
+ {
+ switch (adfs->pwfxSrc->wFormatTag)
+ {
+ case WAVE_FORMAT_PCM: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_ALAW; break;
+ case WAVE_FORMAT_ALAW: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; break;
+ case WAVE_FORMAT_MULAW: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; break;
+ }
+ }
+ /* check if result is ok */
+ if (G711_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
+
+ /* recompute other values */
+ switch (adfs->pwfxDst->wFormatTag)
+ {
+ case WAVE_FORMAT_PCM:
+ adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels;
+ adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
+ break;
+ case WAVE_FORMAT_ALAW:
+ adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels * 2;
+ adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels * 2;
+ break;
+ case WAVE_FORMAT_MULAW:
+ adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels * 2;
+ adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels * 2;
+ break;
+ default:
+ FIXME("\n");
+ break;
+ }
+
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * G711_Reset
+ *
+ */
+static void G711_Reset(PACMDRVSTREAMINSTANCE adsi, AcmG711Data* aad)
+{
+}
+
+/***********************************************************************
+ * G711_StreamOpen
+ *
+ */
+static LRESULT G711_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
+{
+ AcmG711Data* aad;
+
+ assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
+
+ if (G711_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
+ G711_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
+ return ACMERR_NOTPOSSIBLE;
+
+ aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmG711Data));
+ if (aad == 0) return MMSYSERR_NOMEM;
+
+ adsi->dwDriver = (DWORD_PTR)aad;
+
+ if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
+ {
+ goto theEnd;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
+ {
+ /* resampling or mono <=> stereo not available
+ * G711 algo only define 16 bit per sample output
+ */
+ if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
+ adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
+ adsi->pwfxDst->wBitsPerSample != 16)
+ goto theEnd;
+
+ /* g711 A-Law decoding... */
+ if (adsi->pwfxDst->wBitsPerSample == 16)
+ aad->convert = cvtXXalaw16K;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW)
+ {
+ if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
+ adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
+ adsi->pwfxSrc->wBitsPerSample != 16)
+ goto theEnd;
+
+ /* g711 coding... */
+ if (adsi->pwfxSrc->wBitsPerSample == 16)
+ aad->convert = cvtXX16alawK;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
+ {
+ /* resampling or mono <=> stereo not available
+ * G711 algo only define 16 bit per sample output
+ */
+ if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
+ adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
+ adsi->pwfxDst->wBitsPerSample != 16)
+ goto theEnd;
+
+ /* g711 MU-Law decoding... */
+ if (adsi->pwfxDst->wBitsPerSample == 16)
+ aad->convert = cvtXXulaw16K;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)
+ {
+ if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
+ adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
+ adsi->pwfxSrc->wBitsPerSample != 16)
+ goto theEnd;
+
+ /* g711 coding... */
+ if (adsi->pwfxSrc->wBitsPerSample == 16)
+ aad->convert = cvtXX16ulawK;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW)
+ {
+ if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
+ adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels)
+ goto theEnd;
+
+ /* MU-Law => A-Law... */
+ aad->convert = cvtXXulawalawK;
+ }
+ else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)
+ {
+ if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
+ adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels)
+ goto theEnd;
+
+ /* A-Law => MU-Law... */
+ aad->convert = cvtXXalawulawK;
+ }
+ else goto theEnd;
+
+ G711_Reset(adsi, aad);
+
+ return MMSYSERR_NOERROR;
+
+ theEnd:
+ HeapFree(GetProcessHeap(), 0, aad);
+ adsi->dwDriver = 0L;
+ return MMSYSERR_NOTSUPPORTED;
+}
+
+/***********************************************************************
+ * G711_StreamClose
+ *
+ */
+static LRESULT G711_StreamClose(PACMDRVSTREAMINSTANCE adsi)
+{
+ HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * G711_StreamSize
+ *
+ */
+static LRESULT G711_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss)
+{
+ switch (adss->fdwSize)
+ {
+ case ACM_STREAMSIZEF_DESTINATION:
+ /* cbDstLength => cbSrcLength */
+ if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
+ (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
+ {
+ adss->cbSrcLength = adss->cbDstLength / 2;
+ }
+ else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
+ adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
+ {
+ adss->cbSrcLength = adss->cbDstLength * 2;
+ }
+ else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
+ adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
+ (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
+ {
+ adss->cbSrcLength = adss->cbDstLength;
+ }
+ else
+ {
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ break;
+ case ACM_STREAMSIZEF_SOURCE:
+ /* cbSrcLength => cbDstLength */
+ if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
+ (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
+ {
+ adss->cbDstLength = adss->cbSrcLength * 2;
+ }
+ else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
+ adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
+ {
+ adss->cbDstLength = adss->cbSrcLength / 2;
+ }
+ else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
+ adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
+ (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
+ adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
+ {
+ adss->cbDstLength = adss->cbSrcLength;
+ }
+ else
+ {
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ break;
+ default:
+ WARN("Unsupported query %08x\n", adss->fdwSize);
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ FIXME("\n");
+ return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ * G711_StreamConvert
+ *
+ */
+static LRESULT G711_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
+{
+ AcmG711Data* aad = (AcmG711Data*)adsi->dwDriver;
+ DWORD nsrc = adsh->cbSrcLength;
+ DWORD ndst = adsh->cbDstLength;
+
+ if (adsh->fdwConvert &
+ ~(ACM_STREAMCONVERTF_BLOCKALIGN|
+ ACM_STREAMCONVERTF_END|
+ ACM_STREAMCONVERTF_START))
+ {
+ FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
+ }
+ /* ACM_STREAMCONVERTF_BLOCKALIGN
+ * currently all conversions are block aligned, so do nothing for this flag
+ * ACM_STREAMCONVERTF_END
+ * no pending data, so do nothing for this flag
+ */
+ if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
+ {
+ G711_Reset(adsi, aad);
+ }
+
+ aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
+ adsh->cbSrcLengthUsed = nsrc;
+ adsh->cbDstLengthUsed = ndst;
+
+ return MMSYSERR_NOERROR;
+}
+
+/**************************************************************************
+ * G711_DriverProc [exported]
+ */
+LRESULT CALLBACK G711_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
+ LPARAM dwParam1, LPARAM dwParam2)
+{
+ TRACE("(%08lx %p %04x %08lx %08lx);\n",
+ dwDevID, hDriv, wMsg, dwParam1, dwParam2);
+
+ switch (wMsg)
+ {
+ case DRV_LOAD: return 1;
+ case DRV_FREE: return 1;
+ case DRV_OPEN: return G711_drvOpen((LPSTR)dwParam1);
+ case DRV_CLOSE: return G711_drvClose(dwDevID);
+ case DRV_ENABLE: return 1;
+ case DRV_DISABLE: return 1;
+ case DRV_QUERYCONFIGURE: return 1;
+ case DRV_CONFIGURE: MessageBoxA(0, "MS G711 (a-Law & mu-Law) filter !", "Wine Driver", MB_OK); return 1;
+ case DRV_INSTALL: return DRVCNF_RESTART;
+ case DRV_REMOVE: return DRVCNF_RESTART;
+
+ case ACMDM_DRIVER_NOTIFY:
+ /* no caching from other ACM drivers is done so far */
+ return MMSYSERR_NOERROR;
+
+ case ACMDM_DRIVER_DETAILS:
+ return G711_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
+
+ case ACMDM_FORMATTAG_DETAILS:
+ return G711_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
+
+ case ACMDM_FORMAT_DETAILS:
+ return G711_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
+
+ case ACMDM_FORMAT_SUGGEST:
+ return G711_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
+
+ case ACMDM_STREAM_OPEN:
+ return G711_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
+
+ case ACMDM_STREAM_CLOSE:
+ return G711_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
+
+ case ACMDM_STREAM_SIZE:
+ return G711_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
+
+ case ACMDM_STREAM_CONVERT:
+ return G711_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
+
+ case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
+ case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
+ /* this converter is not a hardware driver */
+ case ACMDM_FILTERTAG_DETAILS:
+ case ACMDM_FILTER_DETAILS:
+ /* this converter is not a filter */
+ case ACMDM_STREAM_RESET:
+ /* only needed for asynchronous driver... we aren't, so just say it */
+ return MMSYSERR_NOTSUPPORTED;
+ case ACMDM_STREAM_PREPARE:
+ case ACMDM_STREAM_UNPREPARE:
+ /* nothing special to do here... so don't do anything */
+ return MMSYSERR_NOERROR;
+
+ default:
+ return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
+ }
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32.rbuild b/reactos/dll/win32/msvidc32/msvidc32.rbuild
new file mode 100644
index 00000000000..7ebb98a3381
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32.rbuild
@@ -0,0 +1,12 @@
+
+
+ .
+ include/reactos/wine
+
+ msvideo1.c
+ rsrc.rc
+ wine
+ user32
+ kernel32
+ ntdll
+
diff --git a/reactos/dll/win32/msvidc32/msvidc32.spec b/reactos/dll/win32/msvidc32/msvidc32.spec
new file mode 100644
index 00000000000..e93470adea9
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32.spec
@@ -0,0 +1 @@
+@ stdcall -private DriverProc(long long long long long) CRAM_DriverProc
diff --git a/reactos/dll/win32/msvidc32/msvidc32_Da.rc b/reactos/dll/win32/msvidc32/msvidc32_Da.rc
new file mode 100644
index 00000000000..50ae3f6f5a0
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_Da.rc
@@ -0,0 +1,27 @@
+/*
+ * Danish language support
+ *
+ * Copyright (C) 2008 Jens Albretsen
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_DANISH, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "Wine Video 1 videokodeks"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_De.rc b/reactos/dll/win32/msvidc32/msvidc32_De.rc
new file mode 100644
index 00000000000..1d0de70d0db
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_De.rc
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ * Copyright 2005 Henning Gerhardt
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "Wine Video 1 Video Codec"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_En.rc b/reactos/dll/win32/msvidc32/msvidc32_En.rc
new file mode 100644
index 00000000000..93c8518ec9d
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_En.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "Wine Video 1 video codec"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_Fr.rc b/reactos/dll/win32/msvidc32/msvidc32_Fr.rc
new file mode 100644
index 00000000000..3592f31331c
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_Fr.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2006 Jonathan Ernst
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "codec vidéo Wine Video 1"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_Hu.rc b/reactos/dll/win32/msvidc32/msvidc32_Hu.rc
new file mode 100644
index 00000000000..c031963f495
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_Hu.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2006 Andras Kovacs
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "Wine Video 1 video kodek"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_Ko.rc b/reactos/dll/win32/msvidc32/msvidc32_Ko.rc
new file mode 100644
index 00000000000..11c18c1134f
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_Ko.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "Wine ºñµð¿À 1 ºñµð¿À ÄÚµ¦"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_Nl.rc b/reactos/dll/win32/msvidc32/msvidc32_Nl.rc
new file mode 100644
index 00000000000..b68d3eff7a0
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_Nl.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2008 Frans Kool
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "Wine Video 1 video codec"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_No.rc b/reactos/dll/win32/msvidc32/msvidc32_No.rc
new file mode 100644
index 00000000000..6d27778dfcc
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_No.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2005 Alexander N. Sørnes
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "Wine Video 1-videokodek"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_Pl.rc b/reactos/dll/win32/msvidc32/msvidc32_Pl.rc
new file mode 100644
index 00000000000..af39271d3b1
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_Pl.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "Kodek Wine Video 1"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_Pt.rc b/reactos/dll/win32/msvidc32/msvidc32_Pt.rc
new file mode 100644
index 00000000000..8dcda922a39
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_Pt.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2008 Ricardo Filipe
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "codec video Wine Video 1"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_Ro.rc b/reactos/dll/win32/msvidc32/msvidc32_Ro.rc
new file mode 100644
index 00000000000..fa7584a7dfd
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_Ro.rc
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ * Copyright 2008 Michael Stefaniuc
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "Codecul video Wine Video 1"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_Ru.rc b/reactos/dll/win32/msvidc32/msvidc32_Ru.rc
new file mode 100644
index 00000000000..2c84bff4da4
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_Ru.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2008 Vitaliy Margolen
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "Âèäåî êîäåð Wine Video 1"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_Si.rc b/reactos/dll/win32/msvidc32/msvidc32_Si.rc
new file mode 100644
index 00000000000..060ad082142
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_Si.rc
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 Rok Mandeljc
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#pragma code_page(65001)
+
+LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "Wine Video 1 video kodek"
+}
+
+#pragma code_page(default)
diff --git a/reactos/dll/win32/msvidc32/msvidc32_Sv.rc b/reactos/dll/win32/msvidc32/msvidc32_Sv.rc
new file mode 100644
index 00000000000..1f4770d7a80
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_Sv.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2007 Daniel Nylander
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "Wine Video 1 videokodek"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_Tr.rc b/reactos/dll/win32/msvidc32/msvidc32_Tr.rc
new file mode 100644
index 00000000000..2353b0c542e
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_Tr.rc
@@ -0,0 +1,27 @@
+/*
+ * Turkish Resources
+ *
+ * Copyright 2006 Fatih Aþýcý
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_NAME "MS-CRAM"
+ IDS_DESCRIPTION "Wine Vidyo 1 vidyo çözücü"
+}
diff --git a/reactos/dll/win32/msvidc32/msvidc32_private.h b/reactos/dll/win32/msvidc32/msvidc32_private.h
new file mode 100644
index 00000000000..b47c6e6f556
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvidc32_private.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __MSVIDC32_PRIVATE_H
+#define __MSVIDC32_PRIVATE_H
+
+#define IDS_NAME 100
+#define IDS_DESCRIPTION 101
+
+#endif /* __MSVIDC32_PRIVATE_H */
diff --git a/reactos/dll/win32/msvidc32/msvideo1.c b/reactos/dll/win32/msvidc32/msvideo1.c
new file mode 100644
index 00000000000..9de2a2d35e9
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/msvideo1.c
@@ -0,0 +1,598 @@
+/*
+ * Microsoft Video-1 Decoder
+ * Copyright (C) 2003 the ffmpeg project
+ *
+ * Portions Copyright (C) 2004 Mike McCormack for CodeWeavers
+ *
+ * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ */
+
+/**
+ * @file msvideo1.c
+ * Microsoft Video-1 Decoder by Mike Melanson (melanson@pcisys.net)
+ * For more information about the MS Video-1 format, visit:
+ * http://www.pcisys.net/~melanson/codecs/
+ *
+ * This decoder outputs either PAL8 or RGB555 data, depending on the
+ * whether a RGB palette was passed through palctrl;
+ * if it's present, then the data is PAL8; RGB555 otherwise.
+ */
+
+#include
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "commdlg.h"
+#include "vfw.h"
+#include "mmsystem.h"
+#include "msvidc32_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msvidc32);
+
+static HINSTANCE MSVIDC32_hModule;
+
+#define CRAM_MAGIC mmioFOURCC('C', 'R', 'A', 'M')
+#define MSVC_MAGIC mmioFOURCC('M', 'S', 'V', 'C')
+#define WHAM_MAGIC mmioFOURCC('W', 'H', 'A', 'M')
+
+#define PALETTE_COUNT 256
+#define LE_16(x) ((((const uint8_t *)(x))[1] << 8) | ((const uint8_t *)(x))[0])
+
+/* FIXME - check the stream size */
+#define CHECK_STREAM_PTR(n) \
+ if ((stream_ptr + n) > buf_size ) { \
+ WARN("stream_ptr out of bounds (%d >= %d)\n", \
+ stream_ptr + n, buf_size); \
+ return; \
+ }
+
+typedef BYTE uint8_t;
+
+typedef struct Msvideo1Context {
+ DWORD dwMagic;
+ int mode_8bit; /* if it's not 8-bit, it's 16-bit */
+} Msvideo1Context;
+
+static void
+msvideo1_decode_8bit( int width, int height, const unsigned char *buf, int buf_size,
+ unsigned char *pixels, int stride)
+{
+ int block_ptr, pixel_ptr;
+ int total_blocks;
+ int pixel_x, pixel_y; /* pixel width and height iterators */
+ int block_x, block_y; /* block width and height iterators */
+ int blocks_wide, blocks_high; /* width and height in 4x4 blocks */
+ int block_inc;
+ int row_dec;
+
+ /* decoding parameters */
+ int stream_ptr;
+ unsigned char byte_a, byte_b;
+ unsigned short flags;
+ int skip_blocks;
+ unsigned char colors[8];
+
+ stream_ptr = 0;
+ skip_blocks = 0;
+ blocks_wide = width / 4;
+ blocks_high = height / 4;
+ total_blocks = blocks_wide * blocks_high;
+ block_inc = 4;
+ row_dec = stride + 4;
+
+ for (block_y = blocks_high; block_y > 0; block_y--) {
+ block_ptr = ((block_y * 4) - 1) * stride;
+ for (block_x = blocks_wide; block_x > 0; block_x--) {
+ /* check if this block should be skipped */
+ if (skip_blocks) {
+ block_ptr += block_inc;
+ skip_blocks--;
+ total_blocks--;
+ continue;
+ }
+
+ pixel_ptr = block_ptr;
+
+ /* get the next two bytes in the encoded data stream */
+ CHECK_STREAM_PTR(2);
+ byte_a = buf[stream_ptr++];
+ byte_b = buf[stream_ptr++];
+
+ /* check if the decode is finished */
+ if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0))
+ return;
+ else if ((byte_b & 0xFC) == 0x84) {
+ /* skip code, but don't count the current block */
+ skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
+ } else if (byte_b < 0x80) {
+ /* 2-color encoding */
+ flags = (byte_b << 8) | byte_a;
+
+ CHECK_STREAM_PTR(2);
+ colors[0] = buf[stream_ptr++];
+ colors[1] = buf[stream_ptr++];
+
+ for (pixel_y = 0; pixel_y < 4; pixel_y++) {
+ for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
+ {
+#if ORIGINAL
+ pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
+#else
+ pixels[width*(height-(pixel_ptr/width)-1) +
+ pixel_ptr%width] =
+ colors[(flags & 0x1) ^ 1];
+ pixel_ptr++;
+#endif
+ }
+ pixel_ptr -= row_dec;
+ }
+ } else if (byte_b >= 0x90) {
+ /* 8-color encoding */
+ flags = (byte_b << 8) | byte_a;
+
+ CHECK_STREAM_PTR(8);
+ memcpy(colors, &buf[stream_ptr], 8);
+ stream_ptr += 8;
+
+ for (pixel_y = 0; pixel_y < 4; pixel_y++) {
+ for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
+ {
+#if ORIGINAL
+ pixels[pixel_ptr++] =
+ colors[((pixel_y & 0x2) << 1) +
+ (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
+#else
+ pixels[width*(height-(pixel_ptr/width)-1) +
+ pixel_ptr%width] =
+ colors[((pixel_y & 0x2) << 1) +
+ (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
+ pixel_ptr++;
+#endif
+ }
+ pixel_ptr -= row_dec;
+ }
+ } else {
+ /* 1-color encoding */
+ colors[0] = byte_a;
+
+ for (pixel_y = 0; pixel_y < 4; pixel_y++) {
+ for (pixel_x = 0; pixel_x < 4; pixel_x++)
+ {
+#if ORIGINAL
+ pixels[pixel_ptr++] = colors[0];
+#else
+ pixels[width*(height-(pixel_ptr/width)-1) +
+ pixel_ptr%width] = colors[0];
+ pixel_ptr++;
+#endif
+ }
+ pixel_ptr -= row_dec;
+ }
+ }
+
+ block_ptr += block_inc;
+ total_blocks--;
+ }
+ }
+}
+
+static void
+msvideo1_decode_16bit( int width, int height, const unsigned char *buf, int buf_size,
+ unsigned short *pixels, int stride)
+{
+ int block_ptr, pixel_ptr;
+ int total_blocks;
+ int pixel_x, pixel_y; /* pixel width and height iterators */
+ int block_x, block_y; /* block width and height iterators */
+ int blocks_wide, blocks_high; /* width and height in 4x4 blocks */
+ int block_inc;
+ int row_dec;
+
+ /* decoding parameters */
+ int stream_ptr;
+ unsigned char byte_a, byte_b;
+ unsigned short flags;
+ int skip_blocks;
+ unsigned short colors[8];
+
+ stream_ptr = 0;
+ skip_blocks = 0;
+ blocks_wide = width / 4;
+ blocks_high = height / 4;
+ total_blocks = blocks_wide * blocks_high;
+ block_inc = 4;
+ row_dec = stride + 4;
+
+ for (block_y = blocks_high; block_y > 0; block_y--) {
+ block_ptr = ((block_y * 4) - 1) * stride;
+ for (block_x = blocks_wide; block_x > 0; block_x--) {
+ /* check if this block should be skipped */
+ if (skip_blocks) {
+ block_ptr += block_inc;
+ skip_blocks--;
+ total_blocks--;
+ continue;
+ }
+
+ pixel_ptr = block_ptr;
+
+ /* get the next two bytes in the encoded data stream */
+ CHECK_STREAM_PTR(2);
+ byte_a = buf[stream_ptr++];
+ byte_b = buf[stream_ptr++];
+
+ /* check if the decode is finished */
+ if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0)) {
+ return;
+ } else if ((byte_b & 0xFC) == 0x84) {
+ /* skip code, but don't count the current block */
+ skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
+ } else if (byte_b < 0x80) {
+ /* 2- or 8-color encoding modes */
+ flags = (byte_b << 8) | byte_a;
+
+ CHECK_STREAM_PTR(4);
+ colors[0] = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ colors[1] = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+
+ if (colors[0] & 0x8000) {
+ /* 8-color encoding */
+ CHECK_STREAM_PTR(12);
+ colors[2] = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ colors[3] = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ colors[4] = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ colors[5] = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ colors[6] = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ colors[7] = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+
+ for (pixel_y = 0; pixel_y < 4; pixel_y++) {
+ for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
+ pixels[pixel_ptr++] =
+ colors[((pixel_y & 0x2) << 1) +
+ (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
+ pixel_ptr -= row_dec;
+ }
+ } else {
+ /* 2-color encoding */
+ for (pixel_y = 0; pixel_y < 4; pixel_y++) {
+ for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
+ pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
+ pixel_ptr -= row_dec;
+ }
+ }
+ } else {
+ /* otherwise, it's a 1-color block */
+ colors[0] = (byte_b << 8) | byte_a;
+
+ for (pixel_y = 0; pixel_y < 4; pixel_y++) {
+ for (pixel_x = 0; pixel_x < 4; pixel_x++)
+ pixels[pixel_ptr++] = colors[0];
+ pixel_ptr -= row_dec;
+ }
+ }
+
+ block_ptr += block_inc;
+ total_blocks--;
+ }
+ }
+}
+
+static LRESULT
+CRAM_DecompressQuery( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO out )
+{
+ TRACE("ICM_DECOMPRESS_QUERY %p %p %p\n", info, in, out);
+
+ if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
+ return ICERR_BADPARAM;
+
+ TRACE("planes = %d\n", in->bmiHeader.biPlanes );
+ TRACE("bpp = %d\n", in->bmiHeader.biBitCount );
+ TRACE("height = %d\n", in->bmiHeader.biHeight );
+ TRACE("width = %d\n", in->bmiHeader.biWidth );
+ TRACE("compr = %x\n", in->bmiHeader.biCompression );
+
+ if( ( in->bmiHeader.biCompression != CRAM_MAGIC ) &&
+ ( in->bmiHeader.biCompression != MSVC_MAGIC ) &&
+ ( in->bmiHeader.biCompression != WHAM_MAGIC ) )
+ return ICERR_UNSUPPORTED;
+
+ if( ( in->bmiHeader.biBitCount != 16 ) &&
+ ( in->bmiHeader.biBitCount != 8 ) )
+ {
+ TRACE("can't do %d bpp\n", in->bmiHeader.biBitCount );
+ return ICERR_UNSUPPORTED;
+ }
+
+ /* output must be same dimensions as input */
+ if( out )
+ {
+ if( in->bmiHeader.biBitCount != out->bmiHeader.biBitCount )
+ return ICERR_UNSUPPORTED;
+ if( in->bmiHeader.biPlanes != out->bmiHeader.biPlanes )
+ return ICERR_UNSUPPORTED;
+ if( in->bmiHeader.biHeight != out->bmiHeader.biHeight )
+ return ICERR_UNSUPPORTED;
+ if( in->bmiHeader.biWidth != out->bmiHeader.biWidth )
+ return ICERR_UNSUPPORTED;
+ }
+
+ TRACE("OK!\n");
+
+ return ICERR_OK;
+}
+
+static LRESULT
+CRAM_DecompressGetFormat( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO out )
+{
+ DWORD size;
+
+ TRACE("ICM_DECOMPRESS_GETFORMAT %p %p %p\n", info, in, out);
+
+ if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
+ return ICERR_BADPARAM;
+
+ size = in->bmiHeader.biSize;
+ if (in->bmiHeader.biBitCount <= 8)
+ size += in->bmiHeader.biClrUsed * sizeof(RGBQUAD);
+
+ if( out )
+ {
+ memcpy( out, in, size );
+ out->bmiHeader.biCompression = BI_RGB;
+ out->bmiHeader.biSizeImage = in->bmiHeader.biHeight
+ * in->bmiHeader.biWidth *4;
+ return ICERR_OK;
+ }
+
+ return size;
+}
+
+static LRESULT CRAM_DecompressBegin( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO out )
+{
+ TRACE("ICM_DECOMPRESS_BEGIN %p %p %p\n", info, in, out);
+
+ if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
+ return ICERR_BADPARAM;
+
+ TRACE("bitmap is %d bpp\n", in->bmiHeader.biBitCount);
+ if( in->bmiHeader.biBitCount == 8 )
+ info->mode_8bit = 1;
+ else if( in->bmiHeader.biBitCount == 16 )
+ info->mode_8bit = 0;
+ else
+ {
+ ERR("Bad output format\n");
+ return ICERR_BADPARAM;
+ }
+
+ return ICERR_OK;
+}
+
+static LRESULT CRAM_Decompress( Msvideo1Context *info, ICDECOMPRESS *icd, DWORD size )
+{
+ LONG width, height, stride, sz;
+ WORD bit_per_pixel;
+
+ TRACE("ICM_DECOMPRESS %p %p %d\n", info, icd, size);
+
+ if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
+ return ICERR_BADPARAM;
+
+ /* FIXME: flags are ignored */
+
+ width = icd->lpbiInput->biWidth;
+ height = icd->lpbiInput->biHeight;
+ bit_per_pixel = icd->lpbiInput->biBitCount;
+ stride = width*bit_per_pixel/8;
+ sz = icd->lpbiInput->biSizeImage;
+
+ if (info->mode_8bit)
+ {
+ msvideo1_decode_8bit( width, height, icd->lpInput, sz,
+ icd->lpOutput, stride);
+ }
+ else
+ {
+ msvideo1_decode_16bit( width, height, icd->lpInput, sz,
+ icd->lpOutput, stride);
+ }
+
+ return ICERR_OK;
+}
+
+static LRESULT CRAM_DecompressEx( Msvideo1Context *info, ICDECOMPRESSEX *icd, DWORD size )
+{
+ LONG width, height, stride, sz;
+ WORD bit_per_pixel;
+
+ TRACE("ICM_DECOMPRESSEX %p %p %d\n", info, icd, size);
+
+ if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) )
+ return ICERR_BADPARAM;
+
+ /* FIXME: flags are ignored */
+
+ width = icd->lpbiSrc->biWidth;
+ height = icd->lpbiSrc->biHeight;
+ bit_per_pixel = icd->lpbiSrc->biBitCount;
+ stride = width*bit_per_pixel/8;
+ sz = icd->lpbiSrc->biSizeImage;
+
+ if (info->mode_8bit)
+ {
+ msvideo1_decode_8bit( width, height, icd->lpSrc, sz,
+ icd->lpDst, stride);
+ }
+ else
+ {
+ msvideo1_decode_16bit( width, height, icd->lpSrc, sz,
+ icd->lpDst, stride);
+ }
+
+ return ICERR_OK;
+}
+
+static LRESULT CRAM_GetInfo( const Msvideo1Context *info, ICINFO *icinfo, DWORD dwSize )
+{
+ if (!icinfo) return sizeof(ICINFO);
+ if (dwSize < sizeof(ICINFO)) return 0;
+
+ icinfo->dwSize = sizeof(ICINFO);
+ icinfo->fccType = ICTYPE_VIDEO;
+ icinfo->fccHandler = info ? info->dwMagic : CRAM_MAGIC;
+ icinfo->dwFlags = 0;
+ icinfo->dwVersion = ICVERSION;
+ icinfo->dwVersionICM = ICVERSION;
+
+ LoadStringW(MSVIDC32_hModule, IDS_NAME, icinfo->szName, sizeof(icinfo->szName)/sizeof(WCHAR));
+ LoadStringW(MSVIDC32_hModule, IDS_DESCRIPTION, icinfo->szDescription, sizeof(icinfo->szDescription)/sizeof(WCHAR));
+ /* msvfw32 will fill icinfo->szDriver for us */
+
+ return sizeof(ICINFO);
+}
+
+/***********************************************************************
+ * DriverProc (MSVIDC32.@)
+ */
+LRESULT WINAPI CRAM_DriverProc( DWORD_PTR dwDriverId, HDRVR hdrvr, UINT msg,
+ LPARAM lParam1, LPARAM lParam2 )
+{
+ Msvideo1Context *info = (Msvideo1Context *) dwDriverId;
+ LRESULT r = ICERR_UNSUPPORTED;
+
+ TRACE("%ld %p %04x %08lx %08lx\n", dwDriverId, hdrvr, msg, lParam1, lParam2);
+
+ switch( msg )
+ {
+ case DRV_LOAD:
+ TRACE("Loaded\n");
+ r = 1;
+ break;
+
+ case DRV_ENABLE:
+ break;
+
+ case DRV_OPEN:
+ {
+ ICINFO *icinfo = (ICINFO *)lParam2;
+
+ TRACE("Opened\n");
+
+ if (icinfo && icinfo->fccType != ICTYPE_VIDEO) return 0;
+
+ info = HeapAlloc( GetProcessHeap(), 0, sizeof (Msvideo1Context) );
+ if( info )
+ {
+ memset( info, 0, sizeof info );
+ info->dwMagic = CRAM_MAGIC;
+ }
+ r = (LRESULT) info;
+ break;
+ }
+
+ case DRV_CLOSE:
+ HeapFree( GetProcessHeap(), 0, info );
+ break;
+
+ case DRV_DISABLE:
+ break;
+
+ case DRV_FREE:
+ break;
+
+ case ICM_GETINFO:
+ r = CRAM_GetInfo( info, (ICINFO *)lParam1, (DWORD)lParam2 );
+ break;
+
+ case ICM_DECOMPRESS_QUERY:
+ r = CRAM_DecompressQuery( info, (LPBITMAPINFO) lParam1,
+ (LPBITMAPINFO) lParam2 );
+ break;
+
+ case ICM_DECOMPRESS_GET_FORMAT:
+ r = CRAM_DecompressGetFormat( info, (LPBITMAPINFO) lParam1,
+ (LPBITMAPINFO) lParam2 );
+ break;
+
+ case ICM_DECOMPRESS_GET_PALETTE:
+ FIXME("ICM_DECOMPRESS_GET_PALETTE\n");
+ break;
+
+ case ICM_DECOMPRESSEX_QUERY:
+ FIXME("ICM_DECOMPRESSEX_QUERY\n");
+ break;
+
+ case ICM_DECOMPRESS:
+ r = CRAM_Decompress( info, (ICDECOMPRESS*) lParam1,
+ (DWORD) lParam2 );
+ break;
+
+ case ICM_DECOMPRESS_BEGIN:
+ r = CRAM_DecompressBegin( info, (LPBITMAPINFO) lParam1,
+ (LPBITMAPINFO) lParam2 );
+ break;
+
+ case ICM_DECOMPRESSEX:
+ r = CRAM_DecompressEx( info, (ICDECOMPRESSEX*) lParam1,
+ (DWORD) lParam2 );
+ break;
+
+ case ICM_COMPRESS_QUERY:
+ FIXME("compression not implemented\n");
+ r = ICERR_BADFORMAT;
+ break;
+
+ case ICM_CONFIGURE:
+ r = ICERR_UNSUPPORTED;
+ break;
+
+ default:
+ FIXME("Unknown message: %04x %ld %ld\n", msg, lParam1, lParam2);
+ }
+
+ return r;
+}
+
+/***********************************************************************
+ * DllMain
+ */
+BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
+{
+ TRACE("(%p,%d,%p)\n", hModule, dwReason, lpReserved);
+
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hModule);
+ MSVIDC32_hModule = hModule;
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
diff --git a/reactos/dll/win32/msvidc32/rsrc.rc b/reactos/dll/win32/msvidc32/rsrc.rc
new file mode 100644
index 00000000000..f7f7630c9a9
--- /dev/null
+++ b/reactos/dll/win32/msvidc32/rsrc.rc
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2005 Dmitry Timoshkov
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "windef.h"
+#include "msvidc32_private.h"
+
+#include "msvidc32_Da.rc"
+#include "msvidc32_De.rc"
+#include "msvidc32_Fr.rc"
+#include "msvidc32_En.rc"
+#include "msvidc32_Hu.rc"
+#include "msvidc32_Ko.rc"
+#include "msvidc32_Nl.rc"
+#include "msvidc32_No.rc"
+#include "msvidc32_Pl.rc"
+#include "msvidc32_Pt.rc"
+#include "msvidc32_Ro.rc"
+#include "msvidc32_Ru.rc"
+#include "msvidc32_Si.rc"
+#include "msvidc32_Sv.rc"
+#include "msvidc32_Tr.rc"
diff --git a/reactos/dll/win32/win32.rbuild b/reactos/dll/win32/win32.rbuild
index 57aa44a5a89..657de9b9563 100644
--- a/reactos/dll/win32/win32.rbuild
+++ b/reactos/dll/win32/win32.rbuild
@@ -124,9 +124,15 @@
+
+
+
+
+
+
@@ -208,6 +214,9 @@
+
+
+
@@ -226,6 +235,9 @@
+
+
+
@@ -262,6 +274,9 @@
+
+
+
diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE
index 128c43048a8..5cd8f4d92b2 100644
--- a/reactos/media/doc/README.WINE
+++ b/reactos/media/doc/README.WINE
@@ -50,7 +50,9 @@ reactos/dll/win32/dciman32 # Synced to Wine-1_0-rc2
reactos/dll/win32/gdiplus # Autosync
reactos/dll/win32/hhctrl.ocx # Autosync
reactos/dll/win32/hlink # Autosync
+reactos/dll/win32/iccvid # Autosync
reactos/dll/win32/icmp # Synced to Wine-0_9_10
+reactos/dll/win32/imaadp32.acm # Autosync
reactos/dll/win32/imm32 # Autosync
reactos/dll/win32/imagehlp # Patches for BindImage need review and submission to winehq.
reactos/dll/win32/inetcomm # Autosync
@@ -71,11 +73,13 @@ reactos/dll/win32/mciwave # Autosync
reactos/dll/win32/mlang # Autosync
reactos/dll/win32/mpr # Autosync
reactos/dll/win32/msacm32 # Out of sync
+reactos/dll/win32/msadp32.acm # Autosync
reactos/dll/win32/mscat32 # Autosync
reactos/dll/win32/mscms # Autosync
reactos/dll/win32/mscoree # Autosync
reactos/dll/win32/msctf # Autosync
reactos/dll/win32/msftedit # Autosync
+reactos/dll/win32/msg711.acm # Autosync
reactos/dll/win32/mshtml # Autosync
reactos/dll/win32/msimg32 # Autosync
reactos/dll/win32/msi # Autosync
@@ -84,6 +88,7 @@ reactos/dll/win32/msrle32 # Autosync
reactos/dll/win32/mstask # Autosync
reactos/dll/win32/msvcrt20 # Autosync
reactos/dll/win32/msvfw32 # Autosync
+reactos/dll/win32/msvidc32 # Autosync
reactos/dll/win32/msxml3 # Synced to Wine-20071230
reactos/dll/win32/nddeapi # Autosync
reactos/dll/win32/netapi32 # Autosync