Merged ffmpeg's MS Video 1 decoder by Mike Melanson.
diff --git a/configure b/configure index b46f600..f820d0e 100755 --- a/configure +++ b/configure
@@ -19070,7 +19070,7 @@ MAKE_PROG_RULES=programs/Makeprog.rules - ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules dlls/Maketest.rules libs/Makelib.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/capi2032/Makefile dlls/cfgmgr32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/comctl32/tests/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/ctl3d/Makefile dlls/wined3d/Makefile dlls/d3d8/Makefile dlls/d3d9/Makefile dlls/d3dim/Makefile dlls/d3dx8/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/ddraw/tests/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/dswave/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/glut32/Makefile dlls/iccvid/Makefile dlls/icmp/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/iphlpapi/Makefile dlls/iphlpapi/tests/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/mshtml/Makefile dlls/msi/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrt40/Makefile dlls/msvcrtd/Makefile dlls/msvideo/Makefile dlls/msvideo/msrle32/Makefile dlls/mswsock/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/newdev/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleacc/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/unicows/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/uxtheme/Makefile dlls/version/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio/Makefile dlls/winmm/winenas/Makefile dlls/winmm/winejack/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/uuid/Makefile libs/wine/Makefile libs/wpp/Makefile loader/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/progman/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winebrowser/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemenubuilder/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/winegcc/Makefile tools/wmc/Makefile tools/wrc/Makefile" + ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules dlls/Maketest.rules libs/Makelib.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/capi2032/Makefile dlls/cfgmgr32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/comctl32/tests/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/ctl3d/Makefile dlls/wined3d/Makefile dlls/d3d8/Makefile dlls/d3d9/Makefile dlls/d3dim/Makefile dlls/d3dx8/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/ddraw/tests/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/dswave/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/glut32/Makefile dlls/iccvid/Makefile dlls/icmp/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/iphlpapi/Makefile dlls/iphlpapi/tests/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/mshtml/Makefile dlls/msi/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrt40/Makefile dlls/msvcrtd/Makefile dlls/msvidc32/Makefile dlls/msvideo/Makefile dlls/msvideo/msrle32/Makefile dlls/mswsock/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/newdev/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleacc/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/unicows/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/uxtheme/Makefile dlls/version/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio/Makefile dlls/winmm/winenas/Makefile dlls/winmm/winejack/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/uuid/Makefile libs/wine/Makefile libs/wpp/Makefile loader/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/progman/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winebrowser/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemenubuilder/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/winegcc/Makefile tools/wmc/Makefile tools/wrc/Makefile" cat >confcache <<\_ACEOF @@ -19679,6 +19679,7 @@ "dlls/msvcrt20/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/msvcrt20/Makefile" ;; "dlls/msvcrt40/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/msvcrt40/Makefile" ;; "dlls/msvcrtd/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/msvcrtd/Makefile" ;; + "dlls/msvidc32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/msvidc32/Makefile" ;; "dlls/msvideo/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/msvideo/Makefile" ;; "dlls/msvideo/msrle32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/msvideo/msrle32/Makefile" ;; "dlls/mswsock/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/mswsock/Makefile" ;;
diff --git a/configure.ac b/configure.ac index 181e379..5c363e9 100644 --- a/configure.ac +++ b/configure.ac
@@ -1530,6 +1530,7 @@ dlls/msvcrt20/Makefile dlls/msvcrt40/Makefile dlls/msvcrtd/Makefile +dlls/msvidc32/Makefile dlls/msvideo/Makefile dlls/msvideo/msrle32/Makefile dlls/mswsock/Makefile
diff --git a/dlls/Makefile.in b/dlls/Makefile.in index aea4045..8db5ebc 100644 --- a/dlls/Makefile.in +++ b/dlls/Makefile.in
@@ -72,6 +72,7 @@ msvcrt20 \ msvcrt40 \ msvcrtd \ + msvidc32 \ msvideo \ msvideo/msrle32 \ mswsock \ @@ -275,6 +276,7 @@ msvcrt40.dll$(DLLEXT) \ msvcrtd.dll$(DLLEXT) \ msvfw32.dll$(DLLEXT) \ + msvidc32.dll$(DLLEXT) \ mswsock.dll$(DLLEXT) \ netapi32.dll$(DLLEXT) \ newdev.dll$(DLLEXT) \ @@ -579,6 +581,9 @@ msvideo.dll$(DLLEXT) : msvfw32.dll$(DLLEXT) $(RM) $@ && $(LN_S) msvfw32.dll$(DLLEXT) $@ +msvidc32.dll$(DLLEXT): msvidc32/msvidc32.dll$(DLLEXT) + $(RM) $@ && $(LN_S) msvidc32/msvidc32.dll$(DLLEXT) $@ + mswsock.dll$(DLLEXT): mswsock/mswsock.dll$(DLLEXT) $(RM) $@ && $(LN_S) mswsock/mswsock.dll$(DLLEXT) $@ @@ -870,6 +875,7 @@ libmsvcrt40 \ libmsvcrtd \ libmsvfw32 \ + libmsvidc32 \ libmswsock \ libnetapi32 \ libnewdev \ @@ -1217,6 +1223,11 @@ libmsvfw32.a: msvideo/msvfw32.spec.def $(DLLTOOL) -k -l $@ -d msvideo/msvfw32.spec.def +libmsvidc32.def: msvidc32/msvidc32.spec.def + $(RM) $@ && $(LN_S) msvidc32/msvidc32.spec.def $@ +libmsvidc32.a: msvidc32/msvidc32.spec.def + $(DLLTOOL) -k -l $@ -d msvidc32/msvidc32.spec.def + libmswsock.def: mswsock/mswsock.spec.def $(RM) $@ && $(LN_S) mswsock/mswsock.spec.def $@ libmswsock.a: mswsock/mswsock.spec.def @@ -1531,6 +1542,7 @@ msvcrt40/msvcrt40.spec.def: $(WINEBUILD) msvcrtd/msvcrtd.spec.def: $(WINEBUILD) msvideo/msvfw32.spec.def: $(WINEBUILD) +msvidc32/msvidc32.spec.def: $(WINEBUILD) mswsock/mswsock.spec.def: $(WINEBUILD) netapi32/netapi32.spec.def: $(WINEBUILD) newdev/newdev.spec.def: $(WINEBUILD) @@ -1660,6 +1672,7 @@ msvcrt40/msvcrt40.dll$(DLLEXT): msvcrt40 msvcrtd/msvcrtd.dll$(DLLEXT): msvcrtd msvideo/msvfw32.dll$(DLLEXT): msvideo +msvidc32/msvidc32.dll$(DLLEXT): msvidc32 mswsock/mswsock.dll$(DLLEXT): mswsock netapi32/netapi32.dll$(DLLEXT): netapi32 newdev/newdev.dll$(DLLEXT): newdev
diff --git a/dlls/msvidc32/.cvsignore b/dlls/msvidc32/.cvsignore new file mode 100644 index 0000000..5420b8c --- /dev/null +++ b/dlls/msvidc32/.cvsignore
@@ -0,0 +1,4 @@ +Makefile +msvidc32.dll.dbg.c +msvidc32.spec.c +msvidc32.spec.def
diff --git a/dlls/msvidc32/Makefile.in b/dlls/msvidc32/Makefile.in new file mode 100644 index 0000000..cc0e0a5 --- /dev/null +++ b/dlls/msvidc32/Makefile.in
@@ -0,0 +1,13 @@ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = msvidc32.dll +IMPORTS = kernel32 + +C_SRCS = \ + msvideo1.c + +@MAKE_DLL_RULES@ + +### Dependencies:
diff --git a/dlls/msvidc32/msvidc32.spec b/dlls/msvidc32/msvidc32.spec new file mode 100644 index 0000000..85ec15b --- /dev/null +++ b/dlls/msvidc32/msvidc32.spec
@@ -0,0 +1 @@ +@ stdcall DriverProc(long ptr long long long) CRAM_DriverProc
diff --git a/dlls/msvidc32/msvideo1.c b/dlls/msvidc32/msvideo1.c new file mode 100644 index 0000000..e184dfd --- /dev/null +++ b/dlls/msvidc32/msvideo1.c
@@ -0,0 +1,528 @@ +/* + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 <stdarg.h> +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "commdlg.h" +#include "vfw.h" + +#include "mmsystem.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msvidc32); + +#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) ((((uint8_t*)(x))[1] << 8) | ((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, 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, 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 = %ld\n", in->bmiHeader.biHeight ); + TRACE("width = %ld\n", in->bmiHeader.biWidth ); + TRACE("compr = %lx\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 ) +{ + TRACE("ICM_DECOMPRESS_GETFORMAT %p %p %p\n", info, in, out); + + if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) ) + return ICERR_BADPARAM; + + if( out ) + { + memcpy( out, in, sizeof (BITMAPINFO) ); + out->bmiHeader.biCompression = BI_RGB; + out->bmiHeader.biSizeImage = in->bmiHeader.biHeight + * in->bmiHeader.biWidth *4; + out->bmiHeader.biBitCount = in->bmiHeader.biBitCount; + } + + return sizeof (BITMAPINFO); +} + +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; +} + +LRESULT CRAM_Decompress( Msvideo1Context *info, ICDECOMPRESS *icd, DWORD size ) +{ + LONG width, height, stride, sz; + WORD bit_per_pixel; + + TRACE("ICM_DECOMPRESS %p %p %ld\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; +} + +LRESULT CRAM_DecompressEx( Msvideo1Context *info, ICDECOMPRESSEX *icd, DWORD size ) +{ + LONG width, height, stride, sz; + WORD bit_per_pixel; + + TRACE("ICM_DECOMPRESSEX %p %p %ld\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; +} + +LRESULT WINAPI CRAM_DriverProc( DWORD dwDriverId, HDRVR hdrvr, UINT msg, + LONG lParam1, LONG lParam2) +{ + Msvideo1Context *info = (Msvideo1Context *) dwDriverId; + LRESULT r = 0; + + TRACE("%ld %p %d %ld %ld\n", dwDriverId, hdrvr, msg, lParam1, lParam2); + + switch( msg ) + { + case DRV_LOAD: + TRACE("Loaded\n"); + r = 1; + break; + + case DRV_ENABLE: + break; + + case DRV_OPEN: + TRACE("Opened\n"); + info = HeapAlloc( GetProcessHeap(), 0, sizeof (Msvideo1Context) ); + if( info ) + { + memset( info, 0, sizeof info ); + info->dwMagic = CRAM_MAGIC; + } + r = (LRESULT) info; + 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 DRV_CLOSE: + HeapFree( GetProcessHeap(), 0, info ); + break; + + case DRV_DISABLE: + break; + + case DRV_FREE: + break; + + default: + FIXME("Unknown message: %04x %ld %ld\n", msg, lParam1, lParam2); + } + + return r; +}