Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

750 lines
20 KiB

  1. /*--------------------------------------------------------------------------*\
  2. | RLECIF.C - Interface to RLE Comressor |
  3. |//@@BEGIN_MSINTERNAL |
  4. | History: |
  5. | 01/01/88 toddla Created |
  6. | 10/30/90 davidmay Reorganized, rewritten somewhat. |
  7. | 07/11/91 dannymi Un-hacked |
  8. | 09/15/91 ToddLa Re-hacked |
  9. | 09/18/91 DavidMay Separated from RLEC.C |
  10. | 06/01/92 ToddLa Moved into a installable compressor |
  11. |//@@END_MSINTERNAL |
  12. | |
  13. \*--------------------------------------------------------------------------*/
  14. /**************************************************************************
  15. *
  16. * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  17. * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  19. * PURPOSE.
  20. *
  21. * Copyright (c) 1991 - 1995 Microsoft Corporation. All Rights Reserved.
  22. *
  23. **************************************************************************/
  24. //@@BEGIN_MSINTERNAL |
  25. #ifndef _WIN32
  26. #include <win32.h>
  27. #endif
  28. //@@END_MSINTERNAL |
  29. #include <windows.h>
  30. #include <windowsx.h>
  31. #include <mmsystem.h>
  32. #ifndef _INC_COMPDDK
  33. #define _INC_COMPDDK 50 /* version number */
  34. #endif
  35. #include <vfw.h>
  36. #include "msrle.h"
  37. #include <stdarg.h>
  38. //@@BEGIN_MSINTERNAL |
  39. #ifdef UNICODE
  40. #include "profile.h" // map to registry for NT
  41. #endif
  42. //@@END_MSINTERNAL |
  43. RLESTATE DefaultRleState = {0, 0, -1, 187, 1500, 4};
  44. #define FOURCC_DIB mmioFOURCC('D','I','B',' ')
  45. #define FOURCC_RLE mmioFOURCC('M','R','L','E') //mmioFOURCC('R','L','E',' ')
  46. #define TWOCC_DIB aviTWOCC('d','b')
  47. #define TWOCC_RLE aviTWOCC('d','c')
  48. #define TWOCC_DIBX aviTWOCC('d','x')
  49. /****************************************************************************
  50. ****************************************************************************/
  51. #pragma optimize("", off)
  52. static BOOL NEAR PASCAL IsApp(LPTSTR szApp)
  53. {
  54. TCHAR ach[128];
  55. int i;
  56. HINSTANCE hInstance;
  57. #ifdef _WIN32
  58. hInstance = GetModuleHandle(NULL);
  59. #else
  60. _asm mov hInstance,ss
  61. #endif
  62. GetModuleFileName(hInstance, ach, sizeof(ach) / sizeof(ach[0]));
  63. for (i = lstrlen(ach);
  64. i > 0 && ach[i-1] != '\\' && ach[i-1] != '/' && ach[i] != ':';
  65. i--)
  66. ;
  67. return lstrcmpi(ach + i, szApp) == 0;
  68. }
  69. #pragma optimize("", on)
  70. /*****************************************************************************
  71. ****************************************************************************/
  72. //
  73. // RleLoad()
  74. //
  75. void NEAR PASCAL RleLoad()
  76. {
  77. }
  78. /*****************************************************************************
  79. ****************************************************************************/
  80. //
  81. // RleFree()
  82. //
  83. void NEAR PASCAL RleFree()
  84. {
  85. if (gRgbTol.hpTable)
  86. GlobalFreePtr(gRgbTol.hpTable);
  87. gRgbTol.hpTable = NULL;
  88. }
  89. /*****************************************************************************
  90. ****************************************************************************/
  91. //
  92. // RleOpen() - open a instance of the rle compressor
  93. //
  94. PRLEINST NEAR PASCAL RleOpen()
  95. {
  96. PRLEINST pri;
  97. //
  98. // VIDEDIT Hack
  99. //
  100. // we dont want to see two "Microsoft RLE" compressors.
  101. // so lie to VidEdit and fail to open.
  102. //
  103. if (GetModuleHandle(TEXT("MEDDIBS")) && IsApp(TEXT("VIDEDIT.EXE")))
  104. return NULL;
  105. pri = (PRLEINST)LocalAlloc(LPTR, sizeof(RLEINST));
  106. if (pri)
  107. {
  108. RleSetState(pri, NULL, 0);
  109. }
  110. return pri;
  111. }
  112. /*****************************************************************************
  113. ****************************************************************************/
  114. //
  115. // RleClose() - close a instance of the rle compressor
  116. //
  117. DWORD NEAR PASCAL RleClose(PRLEINST pri)
  118. {
  119. if (!pri)
  120. return FALSE;
  121. if (pri->lpbiPrev) {
  122. GlobalFreePtr(pri->lpbiPrev);
  123. pri->lpbiPrev = NULL;
  124. }
  125. LocalFree((LOCALHANDLE)pri);
  126. return TRUE;
  127. }
  128. /*****************************************************************************
  129. ****************************************************************************/
  130. //
  131. // RleGetState() - get the current state of the rle compressor
  132. //
  133. // will copy current state into passed buffer.
  134. // returns the size in bytes required to store the entire state.
  135. //
  136. DWORD NEAR PASCAL RleGetState(PRLEINST pri, LPVOID pv, DWORD dwSize)
  137. {
  138. if (pv == NULL || dwSize == 0)
  139. return sizeof(RLESTATE);
  140. if (pri == NULL || dwSize < sizeof(RLESTATE))
  141. return 0;
  142. *(LPRLESTATE)pv = pri->RleState;
  143. return sizeof(RLESTATE);
  144. }
  145. /*****************************************************************************
  146. ****************************************************************************/
  147. //
  148. // RleSetState() - sets the current state of the rle compressor
  149. //
  150. DWORD NEAR PASCAL RleSetState(PRLEINST pri, LPVOID pv, DWORD dwSize)
  151. {
  152. if (pv == NULL || dwSize == 0)
  153. {
  154. pv = &DefaultRleState;
  155. dwSize = sizeof(RLESTATE);
  156. }
  157. if (pri == NULL || dwSize < sizeof(RLESTATE))
  158. return 0;
  159. pri->RleState = *(LPRLESTATE)pv;
  160. return sizeof(RLESTATE);
  161. }
  162. #if !defined NUMELMS
  163. #define NUMELMS(aa) (sizeof(aa)/sizeof((aa)[0]))
  164. #endif
  165. #if defined _WIN32 && !defined UNICODE
  166. int LoadUnicodeString(HINSTANCE hinst, UINT wID, LPWSTR lpBuffer, int cchBuffer)
  167. {
  168. char ach[128];
  169. int i;
  170. i = LoadString(hinst, wID, ach, sizeof(ach));
  171. if (i > 0)
  172. MultiByteToWideChar(CP_ACP, 0, ach, -1, lpBuffer, cchBuffer);
  173. return i;
  174. }
  175. #else
  176. #define LoadUnicodeString LoadString
  177. #endif
  178. /*****************************************************************************
  179. ****************************************************************************/
  180. DWORD NEAR PASCAL RleGetInfo(PRLEINST pri, ICINFO FAR *icinfo, DWORD dwSize)
  181. {
  182. if (icinfo == NULL)
  183. return sizeof(ICINFO);
  184. if (dwSize < sizeof(ICINFO))
  185. return 0;
  186. icinfo->dwSize = sizeof(ICINFO);
  187. icinfo->fccType = ICTYPE_VIDEO;
  188. icinfo->fccHandler = FOURCC_RLE;
  189. icinfo->dwFlags = VIDCF_QUALITY | // supports quality
  190. VIDCF_TEMPORAL | // supports inter-frame
  191. VIDCF_CRUNCH; // can crunch to a data rate
  192. icinfo->dwVersion = ICVERSION;
  193. LoadUnicodeString(ghModule, IDS_DESCRIPTION, icinfo->szDescription, NUMELMS(icinfo->szDescription));
  194. LoadUnicodeString(ghModule, IDS_NAME, icinfo->szName, NUMELMS(icinfo->szName));
  195. return sizeof(ICINFO);
  196. }
  197. /*****************************************************************************
  198. ****************************************************************************/
  199. DWORD NEAR PASCAL RleCompressQuery(PRLEINST pri, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  200. {
  201. //
  202. // determine if the input DIB data is in a format we like.
  203. //
  204. if (lpbiIn == NULL ||
  205. lpbiIn->biBitCount != 8 ||
  206. lpbiIn->biCompression != BI_RGB)
  207. return (DWORD)ICERR_BADFORMAT;
  208. //
  209. // are we being asked to query just the input format?
  210. //
  211. if (lpbiOut == NULL)
  212. return ICERR_OK;
  213. //
  214. // make sure we can handle the format to compress to also.
  215. //
  216. if (lpbiOut->biCompression != BI_RLE8 || // must be rle format
  217. lpbiOut->biBitCount != 8 || // must be 8bpp
  218. lpbiOut->biWidth != lpbiIn->biWidth || // must be 1:1 (no stretch)
  219. lpbiOut->biHeight != lpbiIn->biHeight)
  220. return (DWORD)ICERR_BADFORMAT;
  221. return ICERR_OK;
  222. }
  223. /*****************************************************************************
  224. ****************************************************************************/
  225. DWORD NEAR PASCAL RleCompressGetFormat(PRLEINST pri, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  226. {
  227. DWORD dw;
  228. DWORD dwClrUsed;
  229. if (dw = RleCompressQuery(pri, lpbiIn, NULL))
  230. return dw;
  231. dwClrUsed = lpbiIn->biClrUsed;
  232. if (dwClrUsed == 0) {
  233. dwClrUsed = 256;
  234. }
  235. dw = lpbiIn->biSize + (int)dwClrUsed * sizeof(RGBQUAD);
  236. //
  237. // if lpbiOut == NULL then, return the size required to hold a output
  238. // format
  239. //
  240. if (lpbiOut == NULL)
  241. return dw;
  242. hmemcpy(lpbiOut, lpbiIn, dw);
  243. lpbiOut->biBitCount = 8;
  244. lpbiOut->biCompression = BI_RLE8;
  245. lpbiOut->biSizeImage = RleCompressGetSize(pri, lpbiIn, lpbiOut);
  246. return ICERR_OK;
  247. }
  248. /*****************************************************************************
  249. ****************************************************************************/
  250. DWORD NEAR PASCAL RleCompressBegin(PRLEINST pri, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  251. {
  252. DWORD dw;
  253. if (dw = RleCompressQuery(pri, lpbiIn, lpbiOut))
  254. return dw;
  255. if (pri->lpbiPrev) {
  256. GlobalFreePtr(pri->lpbiPrev);
  257. pri->lpbiPrev = NULL;
  258. }
  259. pri->iStart = 0;
  260. pri->lLastParm = 0L;
  261. pri->fCompressBegin = TRUE;
  262. MakeRgbTable(lpbiIn);
  263. return ICERR_OK;
  264. }
  265. /*****************************************************************************
  266. ****************************************************************************/
  267. DWORD NEAR PASCAL RleCompressGetSize(PRLEINST pri, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  268. {
  269. int dx,dy;
  270. //
  271. // we assume RLE data will never be twice the size of a full frame.
  272. //
  273. dx = (int)lpbiIn->biWidth;
  274. dy = (int)lpbiIn->biHeight;
  275. return (DWORD)(UINT)dx * (DWORD)(UINT)dy * 2;
  276. }
  277. /*****************************************************************************
  278. ****************************************************************************/
  279. DWORD NEAR PASCAL RleCompress(PRLEINST pri, ICCOMPRESS FAR *icinfo, DWORD dwSize)
  280. {
  281. DWORD dw;
  282. BOOL fFrameHalvingOccurred = FALSE;
  283. LPBITMAPINFOHEADER lpbi;
  284. if (!pri->fCompressBegin)
  285. {
  286. if (dw = RleCompressBegin(pri, icinfo->lpbiInput, icinfo->lpbiOutput))
  287. return dw;
  288. pri->fCompressBegin = FALSE;
  289. }
  290. //
  291. // we can compress in one of two ways:
  292. //
  293. // if a frame size is given (>0) then call CrunchDib using the passed
  294. // quality as the "frame half" setting.
  295. //
  296. // if a frame size is not given (==0) then use the passed quality
  297. // as the tolerance and do a normal RleDeltaFrame()
  298. //
  299. if (icinfo->dwQuality == ICQUALITY_DEFAULT)
  300. icinfo->dwQuality = QUALITY_DEFAULT;
  301. if (icinfo->dwFrameSize > 0)
  302. {
  303. dw = ICQUALITY_HIGH - icinfo->dwQuality;
  304. pri->RleState.lMaxFrameSize = icinfo->dwFrameSize;
  305. pri->RleState.lMinFrameSize = icinfo->dwFrameSize - 500;
  306. pri->RleState.tolMax = dw;
  307. pri->RleState.tolSpatial = dw / 8;
  308. pri->RleState.tolTemporal = ADAPTIVE;
  309. // SplitDib makes really ugly artifacts by splitting the frame into who knows
  310. // how many pieces which will be pieced together like a bad jigsaw puzzle where
  311. // each piece is from a different picture. I decided never to use this method
  312. // of compression.
  313. #if 0
  314. if (dw == 0)
  315. {
  316. pri->RleState.tolSpatial = 0;
  317. pri->RleState.tolTemporal = 0;
  318. SplitDib(pri,
  319. icinfo->lpbiOutput, icinfo->lpOutput,
  320. icinfo->lpbiPrev, icinfo->lpPrev,
  321. icinfo->lpbiInput, icinfo->lpInput);
  322. }
  323. else
  324. #endif
  325. {
  326. CrunchDib(pri,
  327. icinfo->lpbiOutput, icinfo->lpOutput,
  328. icinfo->lpbiPrev, icinfo->lpPrev,
  329. icinfo->lpbiInput, icinfo->lpInput);
  330. }
  331. lpbi = icinfo->lpbiOutput;
  332. if (lpbi->biCompression == BI_DIBX)
  333. fFrameHalvingOccurred = TRUE;
  334. if (icinfo->lpckid)
  335. {
  336. if (fFrameHalvingOccurred)
  337. *icinfo->lpckid = TWOCC_DIBX;
  338. else
  339. *icinfo->lpckid = TWOCC_RLE;
  340. }
  341. lpbi->biCompression = BI_RLE8; // biSizeImage is filled in
  342. }
  343. else
  344. {
  345. dw = ICQUALITY_HIGH - icinfo->dwQuality;
  346. pri->RleState.tolSpatial = dw;
  347. pri->RleState.tolTemporal = dw / 8;
  348. RleDeltaFrame(
  349. icinfo->lpbiOutput, icinfo->lpOutput,
  350. icinfo->lpbiPrev, icinfo->lpPrev,
  351. icinfo->lpbiInput, icinfo->lpInput,
  352. 0,-1,
  353. pri->RleState.tolTemporal,
  354. pri->RleState.tolSpatial,
  355. pri->RleState.iMaxRunLen,4);
  356. if (icinfo->lpckid)
  357. *icinfo->lpckid = TWOCC_RLE;
  358. }
  359. //
  360. // set the AVI index flags,
  361. //
  362. // make it a keyframe, if no previous frame
  363. //
  364. if (icinfo->lpdwFlags) {
  365. if (icinfo->lpbiPrev == NULL && !fFrameHalvingOccurred)
  366. *icinfo->lpdwFlags |= AVIIF_TWOCC | AVIIF_KEYFRAME;
  367. else
  368. *icinfo->lpdwFlags |= AVIIF_TWOCC;
  369. }
  370. return ICERR_OK;
  371. }
  372. /*****************************************************************************
  373. ****************************************************************************/
  374. DWORD NEAR PASCAL RleCompressEnd(PRLEINST pri)
  375. {
  376. pri->fCompressBegin = FALSE;
  377. return ICERR_OK;
  378. }
  379. /*****************************************************************************
  380. ****************************************************************************/
  381. DWORD NEAR PASCAL RleDecompressQuery(RLEINST * pri, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  382. {
  383. //
  384. // determine if the input DIB data is in a format we like.
  385. // We like all RGB. We like 8bit RLE.
  386. //
  387. if (lpbiIn == NULL ||
  388. (lpbiIn->biBitCount != 8 && lpbiIn->biCompression == BI_RLE8) ||
  389. (lpbiIn->biCompression != BI_RGB && lpbiIn->biCompression != BI_RLE8))
  390. return (DWORD)ICERR_BADFORMAT;
  391. //
  392. // are we being asked to query just the input format?
  393. //
  394. if (lpbiOut == NULL)
  395. return ICERR_OK;
  396. //
  397. // make sure we can handle the format to decompress too.
  398. //
  399. if (lpbiOut->biCompression != BI_RGB || // must be full dib
  400. lpbiOut->biBitCount != lpbiIn->biBitCount ||// must match
  401. lpbiOut->biWidth != lpbiIn->biWidth || // must be 1:1 (no stretch)
  402. lpbiOut->biHeight != lpbiIn->biHeight)
  403. return (DWORD)ICERR_BADFORMAT;
  404. return ICERR_OK;
  405. }
  406. /*****************************************************************************
  407. ****************************************************************************/
  408. DWORD NEAR PASCAL RleDecompressGetFormat(RLEINST * pri, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  409. {
  410. DWORD dw;
  411. if (dw = RleDecompressQuery(pri, lpbiIn, NULL))
  412. return dw;
  413. dw = lpbiIn->biSize + (int)lpbiIn->biClrUsed * sizeof(RGBQUAD);
  414. //
  415. // if lpbiOut == NULL then, return the size required to hold a output
  416. // format
  417. //
  418. if (lpbiOut == NULL)
  419. return dw;
  420. hmemcpy(lpbiOut, lpbiIn, dw);
  421. lpbiOut->biBitCount = lpbiIn->biBitCount;
  422. lpbiOut->biCompression = BI_RGB;
  423. lpbiOut->biSizeImage = lpbiIn->biHeight * DibWidthBytes(lpbiIn);
  424. return ICERR_OK;
  425. }
  426. /*****************************************************************************
  427. ****************************************************************************/
  428. DWORD NEAR PASCAL RleDecompressBegin(RLEINST * pri, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  429. {
  430. DWORD dw;
  431. if (dw = RleDecompressQuery(pri, lpbiIn, lpbiOut))
  432. return dw;
  433. pri->fDecompressBegin = TRUE;
  434. // Make sure we know the size of an uncompressed DIB
  435. if (lpbiOut->biSizeImage == 0)
  436. lpbiOut->biSizeImage = lpbiOut->biHeight * DibWidthBytes(lpbiOut);
  437. return ICERR_OK;
  438. }
  439. /*****************************************************************************
  440. ****************************************************************************/
  441. DWORD NEAR PASCAL RleDecompress(RLEINST * pri, ICDECOMPRESS FAR *icinfo, DWORD dwSize)
  442. {
  443. DWORD dw;
  444. if (!pri->fDecompressBegin)
  445. {
  446. if (dw = RleDecompressBegin(pri, icinfo->lpbiInput, icinfo->lpbiOutput))
  447. return dw;
  448. pri->fDecompressBegin = FALSE;
  449. }
  450. //
  451. // handle a decompress of 'DIB ' (ie full frame) data. Just return it.
  452. // It may be disguised an an RLE. We can tell by how big it is
  453. //
  454. if (icinfo->lpbiInput->biCompression == BI_RGB ||
  455. icinfo->lpbiInput->biSizeImage == icinfo->lpbiOutput->biSizeImage)
  456. {
  457. hmemcpy(icinfo->lpOutput, icinfo->lpInput,
  458. icinfo->lpbiInput->biSizeImage);
  459. return ICERR_OK;
  460. }
  461. DecodeRle(icinfo->lpbiOutput, icinfo->lpOutput, icinfo->lpInput, icinfo->lpbiInput->biSizeImage);
  462. return ICERR_OK;
  463. }
  464. /*****************************************************************************
  465. ****************************************************************************/
  466. DWORD NEAR PASCAL RleDecompressEnd(RLEINST * pri)
  467. {
  468. pri->fDecompressBegin = FALSE;
  469. return ICERR_OK;
  470. }
  471. /***************************************************************************
  472. DecodeRle - 'C' version
  473. Play back a RLE buffer into a DIB buffer
  474. returns
  475. none
  476. ***************************************************************************/
  477. void NEAR PASCAL DecodeRle(LPBITMAPINFOHEADER lpbi, LPVOID lp, LPVOID lpRle, DWORD dwInSize)
  478. {
  479. UINT cnt;
  480. BYTE b;
  481. UINT x;
  482. UINT dx,dy;
  483. UINT wWidthBytes;
  484. DWORD dwOutSize;
  485. DWORD dwJump;
  486. #define RLE_ESCAPE 0
  487. #define RLE_EOL 0
  488. #define RLE_EOF 1
  489. #define RLE_JMP 2
  490. #define RLE_RUN 3
  491. #ifndef _WIN32
  492. extern FAR PASCAL __WinFlags;
  493. #define WinFlags (UINT)(&__WinFlags)
  494. //
  495. // this uses ASM code found in RLEA.ASM
  496. //
  497. if (!(WinFlags & WF_CPU286))
  498. DecodeRle386(lpbi, lp, lpRle);
  499. else if (lpbi->biSizeImage < 65536l)
  500. DecodeRle286(lpbi, lp, lpRle);
  501. else
  502. #endif
  503. {
  504. BYTE _huge *pb = lp;
  505. BYTE _huge *prle = lpRle;
  506. #define EatOutput(_x_) \
  507. { \
  508. if (dwOutSize < (_x_)) { \
  509. return; \
  510. } \
  511. dwOutSize -= (_x_); \
  512. }
  513. #define EatInput(_x_) \
  514. { \
  515. if (dwInSize < (_x_)) { \
  516. return; \
  517. } \
  518. dwInSize -= (_x_); \
  519. }
  520. if (lpbi->biHeight <= 0) {
  521. return;
  522. }
  523. wWidthBytes = (UINT)lpbi->biWidth+3 & ~3;
  524. dwOutSize = wWidthBytes * (DWORD)lpbi->biHeight;
  525. x = 0;
  526. for (;;)
  527. {
  528. EatInput(2);
  529. cnt = (UINT)*prle++;
  530. b = *prle++;
  531. if (cnt == RLE_ESCAPE)
  532. {
  533. switch (b)
  534. {
  535. case RLE_EOF:
  536. return;
  537. case RLE_EOL:
  538. EatOutput(wWidthBytes - x);
  539. pb += wWidthBytes - x;
  540. x = 0;
  541. break;
  542. case RLE_JMP:
  543. EatInput(2);
  544. dx = (UINT)*prle++;
  545. dy = (UINT)*prle++;
  546. dwJump = (DWORD)wWidthBytes * dy + dx;
  547. EatOutput(dwJump);
  548. pb += dwJump;
  549. x += dx;
  550. break;
  551. default:
  552. cnt = b;
  553. EatOutput(cnt);
  554. EatInput(cnt);
  555. x += cnt;
  556. // If the count was sufficiently large it would be worthwhile
  557. // using an inline memcpy function. The code could
  558. // be faster. Even doing this as a series of word
  559. // moves would be quicker. However, RLE is not the highest
  560. // priority.
  561. while (cnt-- > 0)
  562. *pb++ = *prle++; // copy
  563. if (b & 1) {
  564. EatInput(1);
  565. prle++;
  566. }
  567. break;
  568. }
  569. }
  570. else
  571. {
  572. x += cnt;
  573. // If the count was sufficiently large it would be worthwhile
  574. // using an inline memset function. The code could
  575. // be faster. Even doing this as a series of word
  576. // moves would be quicker. However, RLE is not the highest
  577. // priority.
  578. #if 1
  579. // at least on the x86... this way persuades the compiler
  580. // to use registers more effectively through the whole of
  581. // the decode routine
  582. EatOutput(cnt);
  583. while (cnt-- > 0) {
  584. *pb++ = b; // set
  585. }
  586. #else // the alternative
  587. memset(pb, b, cnt);
  588. pb += cnt;
  589. #endif
  590. }
  591. }
  592. }
  593. }
  594. #ifdef DEBUG
  595. void FAR cdecl dprintf(LPSTR szFormat, ...)
  596. {
  597. char ach[256];
  598. va_list va;
  599. static BOOL fDebug = -1;
  600. if (fDebug == -1)
  601. fDebug = GetProfileIntA("Debug", "MSRLE", FALSE);
  602. if (!fDebug)
  603. return;
  604. lstrcpyA(ach, "MSRLE: ");
  605. va_start(va, szFormat);
  606. wvsprintfA(ach+7, szFormat, va);
  607. va_end(va);
  608. lstrcatA(ach, "\r\n");
  609. OutputDebugStringA(ach);
  610. }
  611. #endif